diff --git a/imap_processing/glows/l2/glows_l2.py b/imap_processing/glows/l2/glows_l2.py index 29aa589d0..041bf1582 100644 --- a/imap_processing/glows/l2/glows_l2.py +++ b/imap_processing/glows/l2/glows_l2.py @@ -1,6 +1,7 @@ """Module for GLOWS Level 2 processing.""" import dataclasses +import logging import numpy as np import xarray as xr @@ -13,6 +14,8 @@ from imap_processing.glows.l2.glows_l2_data import HistogramL2 from imap_processing.spice.time import et_to_datetime64, ttj2000ns_to_et +logger = logging.getLogger(__name__) + def glows_l2( input_dataset: xr.Dataset, @@ -47,8 +50,11 @@ def glows_l2( ) l2 = HistogramL2(input_dataset, pipeline_settings) - - return [create_l2_dataset(l2, cdf_attrs)] + if l2.number_of_good_l1b_inputs == 0: + logger.warning("No good data found in L1B dataset. Returning empty list.") + return [] + else: + return [create_l2_dataset(l2, cdf_attrs)] def create_l2_dataset( diff --git a/imap_processing/glows/l2/glows_l2_data.py b/imap_processing/glows/l2/glows_l2_data.py index 52a7510b3..bbed51984 100644 --- a/imap_processing/glows/l2/glows_l2_data.py +++ b/imap_processing/glows/l2/glows_l2_data.py @@ -228,13 +228,13 @@ def __init__(self, l1b_dataset: xr.Dataset, pipeline_settings: PipelineSettings) good_data = l1b_dataset.isel( epoch=self.return_good_times(l1b_dataset["flags"], active_flags) ) - # todo: bad angle filter - # TODO filter bad bins out. Needs to happen here while everything is still - # per-timestamp. + # TODO: bad angle filter + # TODO: filter bad bins out. Needs to happen here while everything is still + # per-timestamp. self.daily_lightcurve = DailyLightcurve(good_data) - self.total_l1b_inputs = len(good_data["epoch"]) + self.total_l1b_inputs = len(l1b_dataset["epoch"]) self.number_of_good_l1b_inputs = len(good_data["epoch"]) self.identifier = -1 # TODO: retrieve from spin table # TODO fill this in @@ -372,7 +372,7 @@ def return_good_times(flags: xr.DataArray, active_flags: NDArray) -> NDArray: An array of indices for good times. """ if len(active_flags) != flags.shape[1]: - print("Active flags don't matched expected length") + print("Active flags don't match expected length") # A good time is where all the active flags are equal to one. # Here, we mask the active indices using active_flags, and then return the times diff --git a/imap_processing/tests/glows/test_glows_l2.py b/imap_processing/tests/glows/test_glows_l2.py index d4df5fda3..a20b4cc96 100644 --- a/imap_processing/tests/glows/test_glows_l2.py +++ b/imap_processing/tests/glows/test_glows_l2.py @@ -44,6 +44,7 @@ def test_glows_l2( mock_ancillary_exclusions, mock_pipeline_settings, mock_conversion_table_dict, + caplog, ): mock_spice_function.side_effect = mock_update_spice_parameters @@ -56,11 +57,19 @@ def test_glows_l2( mock_pipeline_settings, mock_conversion_table_dict, ) + + # Test case 1: L1B dataset has good times l2 = glows_l2(l1b_hist_dataset, mock_pipeline_settings)[0] assert l2.attrs["Logical_source"] == "imap_glows_l2_hist" - assert np.allclose(l2["filter_temperature_average"].values, [57.6], rtol=0.1) + # Test case 2: L1B dataset has no good times (all flags 0) + l1b_hist_dataset["flags"].values = np.zeros(l1b_hist_dataset.flags.shape) + caplog.set_level("WARNING") + result = glows_l2(l1b_hist_dataset, mock_pipeline_settings) + assert result == [] + assert any(record.levelname == "WARNING" for record in caplog.records) + @patch.object(HistogramL1B, "flag_uv_source", return_value=np.zeros(3600, dtype=bool)) @patch.object(HistogramL1B, "update_spice_parameters", autospec=True) @@ -87,6 +96,8 @@ def test_generate_l2( pipeline_settings = PipelineSettings( mock_pipeline_settings.sel(epoch=day, method="nearest") ) + + # Test case 1: L1B dataset has good times l2 = HistogramL2(l1b_hist_dataset, pipeline_settings) expected_values = { @@ -113,6 +124,12 @@ def test_generate_l2( l2.hv_voltage_std_dev, expected_values["hv_voltage_std_dev"], 0.01 ) + # Test case 2: L1B dataset has no good times (all flags 0) + l1b_hist_dataset["flags"].values = np.zeros(l1b_hist_dataset.flags.shape) + ds = HistogramL2(l1b_hist_dataset, pipeline_settings) + expected_number_of_good_l1b_inputs = 0 + assert ds.number_of_good_l1b_inputs == expected_number_of_good_l1b_inputs + def test_bin_exclusions(l1b_hists): # TODO test excluding bins as well