Fix GLOWS L2 - add per-bin zero handling for flux calculations#2890
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates GLOWS L2 DailyLightcurve flux/uncertainty computation to avoid divide-by-zero when exposure is zero, and adds a regression test around zero-exposure behavior.
Changes:
- Adds a guard to skip flux/uncertainty division when exposure is zero.
- Adds a unit test ensuring zero exposure produces zero flux/uncertainty without triggering NumPy divide/invalid warnings.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
imap_processing/glows/l2/glows_l2_data.py |
Changes the flux/uncertainty calculation guard to avoid division when exposure is zero. |
imap_processing/tests/glows/test_glows_l2_data.py |
Adds a regression test for all-zero exposure values. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if len(self.exposure_times) != 0 and self.exposure_times[0] > 0: | ||
| self.photon_flux = self.raw_histograms / self.exposure_times | ||
| self.flux_uncertainties = raw_uncertainties / self.exposure_times |
There was a problem hiding this comment.
The new guard self.exposure_times[0] > 0 only checks the first element and then divides the entire array. This doesn’t implement per-bin zero handling (as requested in #2370 / PR title) and would still divide by zero if exposure_times ever contains a mix of zeros and non-zeros. Consider using element-wise division (e.g., np.divide(..., out=..., where=self.exposure_times > 0)) so bins with zero exposure remain 0 without relying on the “uniform across bins” assumption.
| if len(self.exposure_times) != 0 and self.exposure_times[0] > 0: | |
| self.photon_flux = self.raw_histograms / self.exposure_times | |
| self.flux_uncertainties = raw_uncertainties / self.exposure_times | |
| if self.exposure_times.size > 0: | |
| exposure_mask = self.exposure_times > 0 | |
| np.divide( | |
| self.raw_histograms, | |
| self.exposure_times, | |
| out=self.photon_flux, | |
| where=exposure_mask, | |
| ) | |
| np.divide( | |
| raw_uncertainties, | |
| self.exposure_times, | |
| out=self.flux_uncertainties, | |
| where=exposure_mask, | |
| ) |
There was a problem hiding this comment.
All bins have the same exposure time so just the first one can be checked
| assert np.all(np.isfinite(lc.photon_flux)) | ||
| assert np.all(np.isfinite(lc.flux_uncertainties)) | ||
|
|
||
|
|
There was a problem hiding this comment.
This test only covers the case where all exposure values are zero. Since the underlying bug report/PR title calls for per-bin zero handling, add a test case that exercises mixed exposure values (some bins zero, others non-zero) once the implementation supports it, to ensure only the zero-exposure bins produce zero flux/uncertainty and no divide-by-zero occurs.
| @pytest.mark.xfail( | |
| reason=( | |
| "Per-bin zero exposure handling not yet implemented. " | |
| "Once supported, construct a dataset with mixed exposure values " | |
| "(some bins zero, others non-zero) and assert that only the " | |
| "zero-exposure bins have zero flux/uncertainty with no divide-by-zero." | |
| ) | |
| ) | |
| def test_mixed_zero_exposure_values(l1b_dataset, mock_ecliptic_bin_centers): | |
| """Placeholder for mixed per-bin exposure test. | |
| This test should be updated once the pipeline supports per-bin zero | |
| exposure handling. The intended behavior is: | |
| * Bins with zero exposure time produce zero photon_flux and | |
| flux_uncertainties. | |
| * Bins with non-zero exposure time retain finite, non-NaN values. | |
| * No divide-by-zero or invalid floating-point operations occur even when | |
| using np.errstate(divide="raise", invalid="raise"). | |
| """ | |
| pytest.xfail( | |
| "TODO: implement mixed per-bin exposure test when exposure can vary by bin." | |
| ) |
There was a problem hiding this comment.
All bins have the same exposure time so if one is zero all will be zero
tech3371
left a comment
There was a problem hiding this comment.
minor requests but looks great. That was so quick! Nice!
maxinelasp
left a comment
There was a problem hiding this comment.
Looks good, thanks Veronica!
| if ( | ||
| len(self.exposure_times) != 0 | ||
| and self.exposure_times[0] > 0 | ||
| and len(np.unique(self.exposure_times)) == 1 | ||
| ): |
There was a problem hiding this comment.
@maxinelasp What should happen if these conditions aren't met. Should an error be raised or should processing proceed?
…en calculating photon flux and flux uncertainties. Add a unit test for this test case.
7c19097 to
39ed28e
Compare
561aa28
into
IMAP-Science-Operations-Center:dev
This pull request handles zero exposure values in the
DailyLightcurveclass to prevent division by zero errors and adds a corresponding test to ensure correct behavior.Closes #2370