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
…Science-Operations-Center#2890) * Check that exposure times are not zero to prevent division by zero when calculating photon flux and flux uncertainties. Add testing for this case. * Address PR comments - check that all exposure times are the same value * Add handling for dataset with zero flux and exposure times to return an empty dataset
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