Fix polchisq psi parametrization and gmst_to_utc inverse#251
Merged
Conversation
Two latent bugs in obsdata.py + obs_helpers.py, plus an explicit warning for the multi-day aliasing limitation: * Obsdata.polchisq packed psi = arcsin(V/I), but pol_imager_utils.make_v_image defines V = I*rho*sin(psi). The imager and the chisq disagreed on what psi meant, producing an O(1e-2) self-consistency residue when the chisq was evaluated on the generating image. Pack psi = arcsin(V/(I*rho)). * obs_helpers.gmst_to_utc used a hardcoded constant solar/sidereal ratio (0.99726956...) for a linear inverse, while utc_to_gmst called astropy per-sample. The mismatched rate accumulated to several minutes over a 24h obs. Replace with astropy-derived local sidereal rate (sample at mjd and mjd+1) plus a [0, 24) wrap on the sidereal delta so utc lands in the canonical solar day of mjd. Roundtrip is now 1e-11 hr for any obs that fits in one sidereal day (~23.93 solar hours). * The >23.93h aliasing limit is pre-existing and fundamental (sidereal time mod 24 is many-to-one in solar UTC). Add a UserWarning in Obsdata.switch_timetype on the UTC->GMST branch -- the only direction where the unaliased span is still visible in the input. The inverse GMST->UTC has no signal to detect this (GMST is already wrapped to [0, 24)), so no warning there. Regression tests added to tests/test_obsdata.py.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev-backend #251 +/- ##
===============================================
+ Coverage 26.85% 26.87% +0.02%
===============================================
Files 50 50
Lines 25321 25328 +7
Branches 4261 4262 +1
===============================================
+ Hits 6800 6807 +7
Misses 17821 17821
Partials 700 700 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
rohandahale
previously approved these changes
May 15, 2026
Collaborator
There was a problem hiding this comment.
@achael Looks good!
One trivial CI fix: lint is red on tests/test_obsdata.py:11:1: I001 Import block is un-sorted. The new import warnings needs to go above import numpy as np. ruff check --fix tests/test_obsdata.py closes it.
Two minor suggestions:
psivec = np.arcsin(...)is exact mathematically (V/(I·rho) ∈ [-1, 1]by construction) but a defensivenp.arcsin(np.clip(..., -1, 1))guards against floating-point overshoot at the boundary.- At fully unpolarized pixels (
rho = 0), the fixed expression hits0/0 → NaN. The old code dodged it by computingarcsin(0) = 0.
psivec = np.where(rhovec > 0, np.arcsin(np.clip(imstokes.vvec / (ivec * rhovec), -1, 1)), 0.0).
Returns the old arcsin(0) = 0
Owner
Author
|
updated following your review suggestions @rohandahale , merging now |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two latent bugs in
obsdata.py+obs_helpers.py, plus an explicit warning for the multi-day aliasing limit. The twoxfail(strict=True)regression tests landed via #249/#250 are now passing and have had their decorators dropped.Bug 1 —
Obsdata.polchisqpsi parametrizationobsdata.py:1188packedpsi = arcsin(V/I), butpol_imager_utils.make_v_imagedefinesV = I*rho*sin(psi). The imager and the chisq disagreed on whatpsimeant, producing an O(1e-2) self-consistency residue when evaluated on the generating image. Fixed topsi = arcsin(V/(I*rho)).Bug 2 —
obs_helpers.gmst_to_utcinverseobs_helpers.py:976used a hardcoded constant solar/sidereal ratio (0.99726956...) for a linear inverse, whileutc_to_gmstcalled astropy per-sample. The mismatched rate accumulated to several minutes over a 24h obs.Replaced with astropy-derived local sidereal rate (sample at
mjdandmjd+1), plus a[0, 24)wrap on the sidereal delta so UTC lands in the canonical solar day ofmjd. Roundtrip is now ~1e-11 hr for any obs that fits in one sidereal day (~23.93 solar hours).Companion warning — multi-day aliasing
The
>23.93haliasing limit is fundamental: GMST mod 24 is many-to-one in solar UTC, and once data is in GMST the diagnostic signal is gone. Added aUserWarninginObsdata.switch_timetypeon the UTC->GMST branch only — the only direction where the unaliased span is still visible in the input. The inverse GMST->UTC has no signal to detect this, so no warning there.Test plan
pytest tests/test_obsdata.py→ 169 passed, 1 skippedpytest tests/(full suite, on prior unrebased commit) → 730 passed, 91 skippedxfail(strict=True)tests (test_switch_timetype_roundtrip_utc_gmst,test_polchisq_self_consistency) now pass; their decorators are removed.test_switch_timetype_warns_on_multi_day_to_gmst,test_switch_timetype_no_warn_on_single_day,test_switch_timetype_no_warn_on_gmst_to_utc).utc_to_gmsthandles negative / >24 / multi-day inputs;gmst_to_utcreturns UTC in [0, 24) ofmjdwith <1e-9 hr roundtrip for any single-sidereal-day obs.