From dc47ad78ff1eceb41fdb6a1eae165d7925f5fa37 Mon Sep 17 00:00:00 2001 From: Vineet Bansal Date: Mon, 8 Jun 2026 16:19:26 -0400 Subject: [PATCH 1/6] get_star_bin_offset guided by STAR_BIN_OFFSET_BY_SYNC dict; pulled out 2 constants - STAR_END_BINS_TO_EXCLUDE, STAR_MIN_COUNT_THRESHOLD. lo_angle_offset gone --- imap_processing/lo/constants.py | 21 ++++++- imap_processing/lo/l1b/lo_l1b.py | 77 ++++++++++++++++++++----- imap_processing/tests/lo/test_lo_l1b.py | 58 ++++++++++++++++++- 3 files changed, 138 insertions(+), 18 deletions(-) diff --git a/imap_processing/lo/constants.py b/imap_processing/lo/constants.py index 25cea7b72..7220566c9 100644 --- a/imap_processing/lo/constants.py +++ b/imap_processing/lo/constants.py @@ -58,9 +58,9 @@ class LoConstants: # The first matching open interval (low < pivot < high) is used; if none matches, # THRESHOLD_BG_RATE_RAM_DEFAULT / THRESHOLD_BG_RATE_ANTI_RAM_DEFAULT apply. PIVOT_ANGLE_THRESHOLDS: ClassVar[dict[tuple[float, float], tuple[float, float]]] = { - (88.0, 92.0): (0.014, 0.007), - (73.0, 77.0): (0.0175, 0.00875), - (103.0, 107.0): (0.0112, 0.0056), + (88.0, 92.0): (0.028, 0.014), + (73.0, 77.0): (0.035, 0.0175), + (103.0, 107.0): (0.0224, 0.0112), } # Default background-rate thresholds [counts/s] when no pivot range matches. @@ -75,3 +75,18 @@ class LoConstants: # Padding [s] added to begin/end of each goodtime interval to ensure complete # cycles are covered at interval edges. GOODTIME_PADDING: float = 2.0 + + # Star-sensor spin-angle binning offset (fractional bin-index shift used when + # computing sample centers), keyed by the IFB star-sync housekeeping state + # (ifb_ctrl_star_sync). Flight software 4.8 enabled star sync ("EN"), + # switching from binning to the bin center (+0.5) to the left edge (+0.0). + STAR_BIN_OFFSET_BY_SYNC: ClassVar[dict[str | None, float]] = { + "DS": 0.5, # star sync disabled (pre FSW 4.8) + "EN": 0.0, # star sync enabled (FSW 4.8+) + None: 0.5, # default value + } + + # Number of ending bins to exclude from each star-sensor profile average. + STAR_END_BINS_TO_EXCLUDE: int = 2 + # Minimum COUNT value for a star-sensor record to be considered valid. + STAR_MIN_COUNT_THRESHOLD: int = 700 diff --git a/imap_processing/lo/l1b/lo_l1b.py b/imap_processing/lo/l1b/lo_l1b.py index a085a5b36..b9a0bf06e 100644 --- a/imap_processing/lo/l1b/lo_l1b.py +++ b/imap_processing/lo/l1b/lo_l1b.py @@ -1986,7 +1986,7 @@ def split_rate_dataset( def filter_valid_star_records( l1a_star: xr.Dataset, - min_count: int = 700, + min_count: int = c.STAR_MIN_COUNT_THRESHOLD, time_window_offset: float = 0.0, time_window_duration: float | None = None, ) -> np.ndarray: @@ -2014,7 +2014,7 @@ def filter_valid_star_records( valid_mask : np.ndarray Boolean array indicating valid records. """ - # Section 5: Acceptance Criteria - COUNT >= 700 + # Section 5: Acceptance Criteria - COUNT >= min_count count_mask = l1a_star["count"].values >= min_count # shcoarse is already in MET seconds @@ -2049,7 +2049,7 @@ def filter_valid_star_records( def calculate_star_sensor_profile_for_group( data: np.ndarray, counts: np.ndarray, - end_bins_to_exclude: int = 2, + end_bins_to_exclude: int = c.STAR_END_BINS_TO_EXCLUDE, ) -> tuple[np.ndarray, np.ndarray]: """ Calculate averaged star sensor amplitude profile for a group of records. @@ -2098,14 +2098,58 @@ def calculate_star_sensor_profile_for_group( return avg_amplitude, count_array +def get_star_bin_offset(l1b_nhk: xr.Dataset, reference_epoch: int) -> float: + """ + Determine the star-sensor binning offset from the IFB star-sync state. + + Reads ``ifb_ctrl_star_sync`` from the NHK housekeeping at the record nearest + on or before ``reference_epoch`` and maps it to a binning offset via + ``LoConstants.STAR_BIN_OFFSET_BY_SYNC``. + + Parameters + ---------- + l1b_nhk : xr.Dataset + L1B NHK dataset containing ``ifb_ctrl_star_sync`` and an ``epoch`` + coordinate (TT2000 nanoseconds since J2000). + reference_epoch : int + Epoch at which to evaluate the sync state, in TT2000 nanoseconds since + J2000. The NHK record in effect at or before this time is used. + + Returns + ------- + bin_offset : float + Fractional bin-index offset to use when computing sample spin-angle + centers. + """ + if "ifb_ctrl_star_sync" not in l1b_nhk: + raise KeyError( + "ifb_ctrl_star_sync field not found in L1B NHK dataset. " + "Cannot determine star-sensor binning offset." + ) + + nhk_epoch = l1b_nhk["epoch"].values + sync_state = l1b_nhk["ifb_ctrl_star_sync"].values + + # Use the housekeeping record in effect at the star data end time (the last + # NHK sample at or before it), clamping to the first sample if star data + # ends before NHK coverage. + idx = max(int(np.searchsorted(nhk_epoch, reference_epoch, side="right")) - 1, 0) + state = str(sync_state[idx]) + + offset = c.STAR_BIN_OFFSET_BY_SYNC.get(state, c.STAR_BIN_OFFSET_BY_SYNC[None]) + logger.info(f"Star sync state '{state}' -> bin offset {offset}") + return offset + + def calculate_star_sensor_profiles_by_group( l1a_star: xr.Dataset, sampling_cadence: float, spin_period: float, group_size: int = 64, start_angle_offset: float = 62.0, - end_bins_to_exclude: int = 2, - min_count_threshold: int = 700, + end_bins_to_exclude: int = c.STAR_END_BINS_TO_EXCLUDE, + min_count_threshold: int = c.STAR_MIN_COUNT_THRESHOLD, + bin_offset: float = 0.5, ) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: """ Calculate averaged star sensor amplitude profiles for groups of records. @@ -2129,6 +2173,10 @@ def calculate_star_sensor_profiles_by_group( Number of ending bins to exclude from each average (default: 2). min_count_threshold : int Minimum COUNT value for valid record (default: 700). + bin_offset : float + Fractional offset applied to bin indices when computing sample + spin-angle centers (default: 0.5). Use 0.5 to bin to the bin center + (pre-FSW 4.8) and 0.0 to bin to the left edge (FSW 4.8 and later). Returns ------- @@ -2152,7 +2200,7 @@ def calculate_star_sensor_profiles_by_group( # Calculate spin angles (same for all groups) deg_per_bin = 360.0 * (sampling_cadence / 1000.0) / spin_period bin_indices = np.arange(720) - sample_centers = (bin_indices + 0.5) * deg_per_bin + sample_centers = (bin_indices + bin_offset) * deg_per_bin spin_angle = (start_angle_offset + sample_centers) % 360.0 if n_valid == 0: @@ -2282,13 +2330,16 @@ def l1b_star( logger.info(f"Using spin duration from spin data: {spin_duration:.6f} s") # TODO: Read from ancillary config file when available - lo_angle_offset = 2.0 - sc_to_inst_angle_offset = ( - 360 * get_spacecraft_to_instrument_spin_phase_offset(SpiceFrame.IMAP_LO) - + lo_angle_offset + sc_to_inst_angle_offset = 360 * get_spacecraft_to_instrument_spin_phase_offset( + SpiceFrame.IMAP_LO ) - end_bins_to_exclude = 2 - min_count_threshold = 700 + end_bins_to_exclude = c.STAR_END_BINS_TO_EXCLUDE + min_count_threshold = c.STAR_MIN_COUNT_THRESHOLD + + # Select the star-sensor binning convention from the IFB star-sync state in + # housekeeping. Evaluate at the latest star record's epoch so a pointing that + # spans the `EN` event uses the value corresponding to `EN`. + bin_offset = get_star_bin_offset(l1b_nhk, int(l1a_star["epoch"].values.max())) # Calculate profiles for each 64-spin group ( @@ -2304,6 +2355,7 @@ def l1b_star( start_angle_offset=sc_to_inst_angle_offset, end_bins_to_exclude=end_bins_to_exclude, min_count_threshold=min_count_threshold, + bin_offset=bin_offset, ) # Get global epoch times from L1A data for start_doy and end_doy @@ -2375,7 +2427,6 @@ def l1b_star( l1b_star_ds.attrs["pointing_mid_met"] = pointing_mid_met l1b_star_ds.attrs["sampling_cadence_ms"] = sampling_cadence l1b_star_ds.attrs["spin_duration_sec"] = spin_duration - l1b_star_ds.attrs["lo_angle_offset_deg"] = lo_angle_offset l1b_star_ds.attrs["end_bins_excluded"] = end_bins_to_exclude l1b_star_ds.attrs["min_count_threshold"] = min_count_threshold l1b_star_ds.attrs["group_size"] = group_size diff --git a/imap_processing/tests/lo/test_lo_l1b.py b/imap_processing/tests/lo/test_lo_l1b.py index 17d0ae3db..1999549c0 100644 --- a/imap_processing/tests/lo/test_lo_l1b.py +++ b/imap_processing/tests/lo/test_lo_l1b.py @@ -27,6 +27,7 @@ get_pivot_angle_from_nhk, get_sampling_cadence_from_nhk, get_spin_start_times, + get_star_bin_offset, identify_species, initialize_l1b_de, l1b_bgrates_and_goodtimes, @@ -1836,6 +1837,57 @@ def test_profiles_by_group_angle_wrapping(self, mock_repoint): assert np.any(spin_angle < 100) # Some angles wrapped to lower range +class TestStarBinOffset: + """Tests for the star-sensor binning offset derived from HK star-sync state.""" + + @staticmethod + def _nhk(states): + """Build a minimal NHK dataset with ifb_ctrl_star_sync at 1 Hz.""" + n = len(states) + return xr.Dataset( + {"ifb_ctrl_star_sync": ("epoch", list(states))}, + coords={"epoch": met_to_ttj2000ns(np.arange(n, dtype=np.float64))}, + ) + + @pytest.mark.parametrize("state, expected", [("DS", 0.5), ("EN", 0.0)]) + def test_offset_maps_sync_state(self, state, expected): + """DS (sync disabled) -> 0.5; EN (sync enabled) -> 0.0.""" + nhk = self._nhk([state] * 3) + star_end = int(nhk["epoch"].values[1]) + assert get_star_bin_offset(nhk, star_end) == expected + + def test_uses_state_at_or_before_star_end(self): + """Offset reflects the NHK record in effect at the star end time.""" + # Sync flips DS->EN at index 2. + nhk = self._nhk(["DS", "DS", "EN", "EN"]) + before = int(nhk["epoch"].values[1]) + at = int(nhk["epoch"].values[2]) + assert get_star_bin_offset(nhk, before) == 0.5 + assert get_star_bin_offset(nhk, at) == 0.0 + + def test_straddling_pointing_uses_en(self): + """A pointing whose data ends after the enable event uses EN (left edge).""" + # Star data starts under DS but ends under EN: evaluating at the end + # (as l1b_star does) yields EN. + nhk = self._nhk(["DS", "DS", "EN", "EN"]) + star_end = int(nhk["epoch"].values[-1]) + assert get_star_bin_offset(nhk, star_end) == 0.0 + + def test_missing_field_raises(self): + """A clear error is raised if the star-sync field is absent.""" + nhk = xr.Dataset( + {"ifb_data_interval": ("epoch", [21.0])}, + coords={"epoch": met_to_ttj2000ns([0.0])}, + ) + with pytest.raises(KeyError, match="ifb_ctrl_star_sync"): + get_star_bin_offset(nhk, int(nhk["epoch"].values[0])) + + def test_unexpected_state_defaults(self): + """An unrecognized star-sync state falls back to the default offset (0.5).""" + nhk = self._nhk(["??"]) + assert get_star_bin_offset(nhk, int(nhk["epoch"].values[0])) == 0.5 + + class TestL1bStar: """Tests for l1b_star function.""" @@ -1873,6 +1925,7 @@ def test_initializes_with_spin_data( l1b_nhk = xr.Dataset( { "ifb_data_interval": ("epoch", [21.0] * n_records), + "ifb_ctrl_star_sync": ("epoch", ["DS"] * n_records), }, coords={"epoch": list(range(n_records))}, ) @@ -1953,6 +2006,7 @@ def test_dataset_structure_and_attributes( l1b_nhk = xr.Dataset( { "ifb_data_interval": ("epoch", [21.0]), + "ifb_ctrl_star_sync": ("epoch", ["DS"]), }, coords={"epoch": [0]}, ) @@ -1998,10 +2052,8 @@ def test_dataset_structure_and_attributes( assert l1b_star_ds["count_per_bin"].attrs["VALIDMAX"] == 100000 # Assert - Check processing parameter attributes - assert "lo_angle_offset_deg" in l1b_star_ds.attrs assert "end_bins_excluded" in l1b_star_ds.attrs assert "min_count_threshold" in l1b_star_ds.attrs - assert l1b_star_ds.attrs["lo_angle_offset_deg"] == 2.0 assert l1b_star_ds.attrs["end_bins_excluded"] == 2 assert l1b_star_ds.attrs["min_count_threshold"] == 700 @@ -2035,6 +2087,7 @@ def test_start_and_end_doy_variables( l1b_nhk = xr.Dataset( { "ifb_data_interval": ("epoch", [21.0, 21.0, 21.0]), + "ifb_ctrl_star_sync": ("epoch", ["DS", "DS", "DS"]), }, coords={"epoch": [0, 1, 2]}, ) @@ -2103,6 +2156,7 @@ def test_multiple_groups_created( l1b_nhk = xr.Dataset( { "ifb_data_interval": ("epoch", [21.0] * n_records), + "ifb_ctrl_star_sync": ("epoch", ["DS"] * n_records), }, coords={"epoch": list(range(n_records))}, ) From 1e488f53fa798df9200e2babd52d47fac3d1aa23 Mon Sep 17 00:00:00 2001 From: Vineet Bansal Date: Tue, 9 Jun 2026 10:11:57 -0400 Subject: [PATCH 2/6] A pointing that straddles the star-sensor enable event now takes the state at its start. --- imap_processing/lo/l1b/lo_l1b.py | 25 +++++++++++++++---------- imap_processing/tests/lo/test_lo_l1b.py | 16 ++++++++-------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/imap_processing/lo/l1b/lo_l1b.py b/imap_processing/lo/l1b/lo_l1b.py index b9a0bf06e..021ffb6a5 100644 --- a/imap_processing/lo/l1b/lo_l1b.py +++ b/imap_processing/lo/l1b/lo_l1b.py @@ -2120,6 +2120,11 @@ def get_star_bin_offset(l1b_nhk: xr.Dataset, reference_epoch: int) -> float: bin_offset : float Fractional bin-index offset to use when computing sample spin-angle centers. + + Raises + ------ + KeyError + If ``ifb_ctrl_star_sync`` is not present in ``l1b_nhk``. """ if "ifb_ctrl_star_sync" not in l1b_nhk: raise KeyError( @@ -2130,9 +2135,9 @@ def get_star_bin_offset(l1b_nhk: xr.Dataset, reference_epoch: int) -> float: nhk_epoch = l1b_nhk["epoch"].values sync_state = l1b_nhk["ifb_ctrl_star_sync"].values - # Use the housekeeping record in effect at the star data end time (the last - # NHK sample at or before it), clamping to the first sample if star data - # ends before NHK coverage. + # Use the housekeeping record in effect at the reference epoch (the last + # NHK sample at or before it), clamping to the first sample if the reference + # epoch falls before NHK coverage. idx = max(int(np.searchsorted(nhk_epoch, reference_epoch, side="right")) - 1, 0) state = str(sync_state[idx]) @@ -2336,10 +2341,14 @@ def l1b_star( end_bins_to_exclude = c.STAR_END_BINS_TO_EXCLUDE min_count_threshold = c.STAR_MIN_COUNT_THRESHOLD + # Global epoch times from L1A data (used for start_doy/end_doy below). + global_start_epoch = l1a_star["epoch"].values[0] + global_end_epoch = l1a_star["epoch"].values[-1] + # Select the star-sensor binning convention from the IFB star-sync state in - # housekeeping. Evaluate at the latest star record's epoch so a pointing that - # spans the `EN` event uses the value corresponding to `EN`. - bin_offset = get_star_bin_offset(l1b_nhk, int(l1a_star["epoch"].values.max())) + # housekeeping. Evaluate at the earliest star record's epoch so a pointing that + # spans the `EN` event uses the value corresponding to the state at its start. + bin_offset = get_star_bin_offset(l1b_nhk, int(global_start_epoch)) # Calculate profiles for each 64-spin group ( @@ -2358,10 +2367,6 @@ def l1b_star( bin_offset=bin_offset, ) - # Get global epoch times from L1A data for start_doy and end_doy - global_start_epoch = l1a_star["epoch"].values[0] - global_end_epoch = l1a_star["epoch"].values[-1] - # Create dataset with spin_angle as coordinate and multiple epochs group_epochs = met_to_ttj2000ns(group_mets) l1b_star_ds = xr.Dataset( diff --git a/imap_processing/tests/lo/test_lo_l1b.py b/imap_processing/tests/lo/test_lo_l1b.py index 1999549c0..2a8f23039 100644 --- a/imap_processing/tests/lo/test_lo_l1b.py +++ b/imap_processing/tests/lo/test_lo_l1b.py @@ -1856,8 +1856,8 @@ def test_offset_maps_sync_state(self, state, expected): star_end = int(nhk["epoch"].values[1]) assert get_star_bin_offset(nhk, star_end) == expected - def test_uses_state_at_or_before_star_end(self): - """Offset reflects the NHK record in effect at the star end time.""" + def test_uses_state_at_or_before_reference(self): + """Offset reflects the NHK record in effect at the reference epoch.""" # Sync flips DS->EN at index 2. nhk = self._nhk(["DS", "DS", "EN", "EN"]) before = int(nhk["epoch"].values[1]) @@ -1865,13 +1865,13 @@ def test_uses_state_at_or_before_star_end(self): assert get_star_bin_offset(nhk, before) == 0.5 assert get_star_bin_offset(nhk, at) == 0.0 - def test_straddling_pointing_uses_en(self): - """A pointing whose data ends after the enable event uses EN (left edge).""" - # Star data starts under DS but ends under EN: evaluating at the end - # (as l1b_star does) yields EN. + def test_straddling_pointing_uses_start_state(self): + """A pointing that begins before the enable event uses DS (bin center).""" + # Star data starts under DS but ends under EN: evaluating at the start + # (as l1b_star does) yields DS. nhk = self._nhk(["DS", "DS", "EN", "EN"]) - star_end = int(nhk["epoch"].values[-1]) - assert get_star_bin_offset(nhk, star_end) == 0.0 + star_start = int(nhk["epoch"].values[0]) + assert get_star_bin_offset(nhk, star_start) == 0.5 def test_missing_field_raises(self): """A clear error is raised if the star-sync field is absent.""" From cec5c6facf9657069d63f96be486fb631b57ebd9 Mon Sep 17 00:00:00 2001 From: Vineet Bansal Date: Tue, 16 Jun 2026 15:26:00 -0400 Subject: [PATCH 3/6] Reading lower/upper uncertainty factors, and generating lower/upper systematic errors, but saving the mean in the existing variable. Updated ancillary files. --- ...imap_enamaps_l2-common_variable_attrs.yaml | 48 ++++++++++++ imap_processing/ena_maps/utils/naming.py | 4 + ...imap_lo_hydrogen-geometric-factor_v001.csv | 75 ------------------- ...imap_lo_hydrogen-geometric-factor_v004.csv | 16 ++++ .../imap_lo_oxygen-geometric-factor_v001.csv | 75 ------------------- .../imap_lo_oxygen-geometric-factor_v004.csv | 16 ++++ imap_processing/lo/l1b/lo_l1b.py | 2 +- imap_processing/lo/l2/lo_l2.py | 58 +++++++++----- imap_processing/lo/lo_ancillary.py | 24 +++--- imap_processing/tests/lo/test_lo_l2.py | 72 ++++++++++++------ 10 files changed, 191 insertions(+), 199 deletions(-) delete mode 100644 imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv create mode 100644 imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v004.csv delete mode 100644 imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv create mode 100644 imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v004.csv diff --git a/imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml b/imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml index 8d5a10823..ec6ef36a2 100644 --- a/imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml @@ -239,6 +239,30 @@ bg_rate_sys_err: VAR_NOTES: Systematic error in the background count rate from non-ENA (non-heliospheric) sources. VAR_TYPE: support_data +bg_rate_sys_err_minus: + <<: *default_float32 + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Background Rate Sys Error Lower + FORMAT: F6.3 + LABLAXIS: Rate Error Lower + UNITS: count s-1 + VAR_NOTES: Lower bound of the systematic error in the background count rate from non-ENA (non-heliospheric) sources. + VAR_TYPE: support_data + +bg_rate_sys_err_plus: + <<: *default_float32 + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Background Rate Sys Error Upper + FORMAT: F6.3 + LABLAXIS: Rate Error Upper + UNITS: count s-1 + VAR_NOTES: Upper bound of the systematic error in the background count rate from non-ENA (non-heliospheric) sources. + VAR_TYPE: support_data + bg_intensity: <<: *default_float32 DEPEND_0: epoch @@ -275,6 +299,30 @@ bg_intensity_sys_err: VAR_NOTES: Non-statistical error in the background intensity from non-ENA (non-heliospheric) sources. VAR_TYPE: support_data +bg_intensity_sys_err_minus: + <<: *default_float32 + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Background Intensity Non-statistical Error Lower + FORMAT: F8.3 + LABLAXIS: Intensity Non-statistical Error Lower + UNITS: cm -2 s -1 sr -1 keV -1 + VAR_NOTES: Lower bound of the non-statistical error in the background intensity from non-ENA (non-heliospheric) sources. + VAR_TYPE: support_data + +bg_intensity_sys_err_plus: + <<: *default_float32 + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Background Intensity Non-statistical Error Upper + FORMAT: F8.3 + LABLAXIS: Intensity Non-statistical Error Upper + UNITS: cm -2 s -1 sr -1 keV -1 + VAR_NOTES: Upper bound of the non-statistical error in the background intensity from non-ENA (non-heliospheric) sources. + VAR_TYPE: support_data + ena_count: <<: *default_float32 DEPEND_0: epoch diff --git a/imap_processing/ena_maps/utils/naming.py b/imap_processing/ena_maps/utils/naming.py index 4eddbafda..191239d2c 100644 --- a/imap_processing/ena_maps/utils/naming.py +++ b/imap_processing/ena_maps/utils/naming.py @@ -203,9 +203,13 @@ def build_map_var_catdesc(self, support_var_name: str) -> str | None: "bg_intensity": "Background Inten", "bg_intensity_stat_uncert": "Background Inten Stat. Unc.", "bg_intensity_sys_err": "Background Inten Sys. Err.", + "bg_intensity_sys_err_minus": "Background Inten Sys. Err. Lower", + "bg_intensity_sys_err_plus": "Background Inten Sys. Err. Upper", "bg_rate": "Background Count Rate", "bg_rate_stat_uncert": "Background Count Rate Stat. Unc.", "bg_rate_sys_err": "Background Count Rate Sys. Err.", + "bg_rate_sys_err_minus": "Background Count Rate Sys. Err. Lower", + "bg_rate_sys_err_plus": "Background Count Rate Sys. Err. Upper", "ena_count_rate": "ENA Count Rate", "ena_count_rate_stat_uncert": "ENA Count Rate Stat. Unc.", "obs_date": "Mean Observation Date", diff --git a/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv b/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv deleted file mode 100644 index 3c4b9996d..000000000 --- a/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv +++ /dev/null @@ -1,75 +0,0 @@ -incident_E-Step,Observed_E-Step,Cntr_E,Cntr_E_unc,GF_Dbl_all,GF_Dbl_all_unc,GF_Trpl_all,GF_Trpl_all_unc,GF_Dbl_H,GF_Dbl_H_unc,GF_Trpl_H,GF_Trpl_H_unc -Hi_Res,,[keV],[keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV] -1,1,0.01633,0.00028,5.35E-05,4.82E-06,2.20E-05,1.87E-06,5.32E-05,4.26E-06,7.00E-05,4.90E-05 -2,1,0.01633,0.00028,3.10E-05,2.79E-06,1.25E-05,1.06E-06,3.09E-05,2.47E-06,1.27E-05,1.08E-06 -2,2,0.03047,0.00043,1.04E-04,9.36E-06,4.27E-05,3.63E-06,1.03E-04,8.26E-06,7.90E-05,5.50E-05 -3,1,0.01633,0.00028,4.13E-05,3.72E-06,1.68E-05,1.43E-06,4.16E-05,3.33E-06,1.71E-05,1.45E-06 -3,2,0.03047,0.00043,1.28E-04,1.15E-05,5.02E-05,4.26E-06,1.30E-04,1.04E-05,5.35E-05,4.55E-06 -3,3,0.05576,0.00089,1.59E-04,1.43E-05,6.54E-05,5.56E-06,1.59E-04,1.27E-05,9.70E-05,6.80E-05 -4,1,0.01633,0.00028,9.85E-06,8.86E-07,3.73E-06,3.17E-07,7.97E-06,6.38E-07,3.28E-06,2.79E-07 -4,2,0.03047,0.00043,1.71E-05,1.54E-06,6.54E-06,5.56E-07,1.68E-05,1.34E-06,6.89E-06,5.86E-07 -4,3,0.05576,0.00089,6.72E-05,6.05E-06,2.58E-05,2.19E-06,6.92E-05,5.53E-06,2.84E-05,2.42E-06 -4,4,0.1063,0.0019,1.79E-04,1.61E-05,7.36E-05,6.25E-06,1.78E-04,1.42E-05,1.12E-04,3.00E-05 -5,1,0.01633,0.00028,1.62E-05,1.46E-06,5.05E-06,4.29E-07,7.86E-06,6.29E-07,3.23E-06,2.75E-07 -5,2,0.03047,0.00043,1.57E-05,1.41E-06,5.16E-06,4.39E-07,9.72E-06,7.77E-07,3.99E-06,3.39E-07 -5,3,0.05576,0.00089,1.45E-05,1.31E-06,4.98E-06,4.24E-07,1.49E-05,1.20E-06,6.14E-06,5.22E-07 -5,4,0.1063,0.0019,5.81E-05,5.23E-06,2.15E-05,1.83E-06,6.00E-05,4.80E-06,2.47E-05,2.10E-06 -5,5,0.2,0.0034,1.77E-04,1.59E-05,7.26E-05,6.17E-06,1.76E-04,1.41E-05,1.40E-04,4.50E-05 -6,1,0.01633,0.00028,1.34E-05,1.21E-06,4.33E-06,3.68E-07,9.40E-06,7.52E-07,3.86E-06,3.28E-07 -6,2,0.03047,0.00043,1.61E-05,1.45E-06,4.64E-06,3.94E-07,1.11E-05,8.92E-07,4.58E-06,3.89E-07 -6,3,0.05576,0.00089,1.74E-05,1.57E-06,5.02E-06,4.27E-07,1.42E-05,1.14E-06,5.84E-06,4.96E-07 -6,4,0.1063,0.0019,1.45E-05,1.30E-06,4.28E-06,3.64E-07,1.56E-05,1.25E-06,6.40E-06,5.44E-07 -6,5,0.2,0.0034,5.81E-05,5.23E-06,2.06E-05,1.75E-06,6.01E-05,4.81E-06,2.47E-05,2.10E-06 -6,6,0.405,0.0073,2.06E-04,1.85E-05,8.46E-05,7.19E-06,2.06E-04,1.64E-05,1.77E-04,2.00E-05 -7,1,0.01633,0.00028,5.32E-06,4.79E-07,1.51E-06,1.29E-07,5.05E-06,4.04E-07,2.08E-06,1.76E-07 -7,2,0.03047,0.00043,1.61E-05,1.45E-06,5.15E-06,4.38E-07,1.39E-05,1.11E-06,5.70E-06,4.85E-07 -7,3,0.05576,0.00089,1.96E-05,1.77E-06,6.10E-06,5.19E-07,1.42E-05,1.14E-06,5.84E-06,4.96E-07 -7,4,0.1063,0.0019,2.08E-05,1.87E-06,6.43E-06,5.46E-07,1.65E-05,1.32E-06,6.78E-06,5.77E-07 -7,5,0.2,0.0034,2.52E-05,2.27E-06,8.69E-06,7.39E-07,2.61E-05,2.09E-06,1.07E-05,9.11E-07 -7,6,0.405,0.0073,1.93E-04,1.74E-05,6.94E-05,5.90E-06,1.98E-04,1.59E-05,8.15E-05,6.93E-06 -7,7,0.7873,0.022,3.82E-04,3.44E-05,1.57E-04,1.33E-05,3.82E-04,3.05E-05,2.25E-04,1.40E-05 -8,1,0.01633,0.00028,5.28E-05,4.75E-06,2.25E-05,1.91E-06,4.10E-05,3.28E-06,1.68E-05,1.43E-06 -8,2,0.03047,0.00043,6.14E-06,5.53E-07,1.96E-06,1.66E-07,5.25E-06,4.20E-07,2.16E-06,1.83E-07 -8,3,0.05576,0.00089,1.13E-05,1.02E-06,3.39E-06,2.88E-07,9.37E-06,7.50E-07,3.85E-06,3.27E-07 -8,4,0.1063,0.0019,1.16E-05,1.04E-06,3.83E-06,3.25E-07,8.69E-06,6.95E-07,3.57E-06,3.03E-07 -8,5,0.2,0.0034,1.09E-05,9.78E-07,3.55E-06,3.02E-07,8.41E-06,6.73E-07,3.46E-06,2.94E-07 -8,6,0.405,0.0073,3.29E-05,2.96E-06,1.28E-05,1.08E-06,3.28E-05,2.62E-06,1.35E-05,1.15E-06 -8,7,0.7873,0.022,3.95E-04,3.56E-05,1.44E-04,1.23E-05,4.04E-04,3.23E-05,1.66E-04,1.41E-05 -8,8,1.821,0.16389,5.41E-04,4.87E-05,2.22E-04,1.89E-05,5.41E-04,4.33E-05,2.22E-04,1.89E-05 -Hi_Thr,,,,,,,,,,, -1,1,0.01719,0.00022,8.92E-05,8.03E-06,3.67E-05,3.12E-06,8.87E-05,7.10E-06,1.66E-04,1.01E-04 -2,1,0.01719,0.00022,5.16E-05,4.65E-06,2.08E-05,1.76E-06,5.15E-05,4.12E-06,2.12E-05,1.80E-06 -2,2,0.03236,0.00036,1.73E-04,1.56E-05,7.12E-05,6.06E-06,1.72E-04,1.38E-05,1.92E-04,1.17E-04 -3,1,0.01719,0.00022,6.88E-05,6.19E-06,2.80E-05,2.38E-06,6.94E-05,5.55E-06,2.85E-05,2.42E-06 -3,2,0.03236,0.00036,2.13E-04,1.91E-05,8.36E-05,7.11E-06,2.17E-04,1.74E-05,8.92E-05,7.58E-06 -3,3,0.05948,0.00077,2.65E-04,2.39E-05,1.09E-04,9.26E-06,2.64E-04,2.11E-05,2.27E-04,1.38E-04 -4,1,0.01719,0.00022,1.64E-05,1.48E-06,6.22E-06,5.29E-07,1.33E-05,1.06E-06,5.46E-06,4.64E-07 -4,2,0.03236,0.00036,2.84E-05,2.56E-06,1.09E-05,9.27E-07,2.80E-05,2.24E-06,1.15E-05,9.77E-07 -4,3,0.05948,0.00077,1.12E-04,1.01E-05,4.30E-05,3.66E-06,1.15E-04,9.22E-06,4.74E-05,4.03E-06 -4,4,0.1144,0.0013,2.98E-04,2.68E-05,1.23E-04,1.04E-05,2.96E-04,2.37E-05,2.73E-04,9.80E-05 -5,1,0.01719,0.00022,2.70E-05,2.43E-06,8.42E-06,7.15E-07,1.31E-05,1.05E-06,5.38E-06,4.58E-07 -5,2,0.03236,0.00036,2.61E-05,2.35E-06,8.61E-06,7.31E-07,1.62E-05,1.30E-06,6.65E-06,5.66E-07 -5,3,0.05948,0.00077,2.42E-05,2.18E-06,8.30E-06,7.06E-07,2.49E-05,1.99E-06,1.02E-05,8.70E-07 -5,4,0.1144,0.0013,9.69E-05,8.72E-06,3.58E-05,3.04E-06,1.00E-04,8.00E-06,4.11E-05,3.49E-06 -5,5,0.2137,0.003,2.94E-04,2.65E-05,1.21E-04,1.03E-05,2.93E-04,2.34E-05,3.38E-04,9.50E-05 -6,1,0.01719,0.00022,2.24E-05,2.01E-06,7.22E-06,6.14E-07,1.57E-05,1.25E-06,6.44E-06,5.47E-07 -6,2,0.03236,0.00036,2.68E-05,2.41E-06,7.73E-06,6.57E-07,1.86E-05,1.49E-06,7.64E-06,6.49E-07 -6,3,0.05948,0.00077,2.91E-05,2.61E-06,8.37E-06,7.12E-07,2.37E-05,1.89E-06,9.73E-06,8.27E-07 -6,4,0.1144,0.0013,2.41E-05,2.17E-06,7.13E-06,6.06E-07,2.60E-05,2.08E-06,1.07E-05,9.07E-07 -6,5,0.2137,0.003,9.68E-05,8.71E-06,3.44E-05,2.92E-06,1.00E-04,8.02E-06,4.12E-05,3.50E-06 -6,6,0.4374,0.0053,3.43E-04,3.09E-05,1.41E-04,1.20E-05,3.43E-04,2.74E-05,4.44E-04,4.90E-05 -7,1,0.01719,0.00022,8.87E-06,7.98E-07,2.52E-06,2.14E-07,8.42E-06,6.73E-07,3.46E-06,2.94E-07 -7,2,0.03236,0.00036,2.68E-05,2.41E-06,8.59E-06,7.30E-07,2.31E-05,1.85E-06,9.50E-06,8.08E-07 -7,3,0.05948,0.00077,3.27E-05,2.95E-06,1.02E-05,8.64E-07,2.37E-05,1.89E-06,9.73E-06,8.27E-07 -7,4,0.1144,0.0013,3.47E-05,3.12E-06,1.07E-05,9.10E-07,2.75E-05,2.20E-06,1.13E-05,9.61E-07 -7,5,0.2137,0.003,4.20E-05,3.78E-06,1.45E-05,1.23E-06,4.35E-05,3.48E-06,1.79E-05,1.52E-06 -7,6,0.4374,0.0053,3.21E-04,2.89E-05,1.16E-04,9.84E-06,3.31E-04,2.65E-05,1.36E-04,1.16E-05 -7,7,0.8389,0.00117,6.36E-04,5.73E-05,2.61E-04,2.22E-05,6.36E-04,5.09E-05,5.69E-04,2.90E-05 -8,1,0.01719,0.00022,8.79E-05,7.91E-06,3.75E-05,3.19E-06,6.83E-05,5.46E-06,2.81E-05,2.39E-06 -8,2,0.03236,0.00036,1.02E-05,9.21E-07,3.26E-06,2.77E-07,8.75E-06,7.00E-07,3.60E-06,3.06E-07 -8,3,0.05948,0.00077,1.88E-05,1.70E-06,5.65E-06,4.80E-07,1.56E-05,1.25E-06,6.42E-06,5.46E-07 -8,4,0.1144,0.0013,1.93E-05,1.73E-06,6.38E-06,5.42E-07,1.45E-05,1.16E-06,5.95E-06,5.06E-07 -8,5,0.2137,0.003,1.81E-05,1.63E-06,5.92E-06,5.03E-07,1.40E-05,1.12E-06,5.76E-06,4.90E-07 -8,6,0.4374,0.0053,5.48E-05,4.93E-06,2.13E-05,1.81E-06,5.46E-05,4.37E-06,2.25E-05,1.91E-06 -8,7,0.8389,0.00117,6.59E-04,5.93E-05,2.40E-04,2.04E-05,6.74E-04,5.39E-05,2.77E-04,2.35E-05 -8,8,1.822,0.16398,9.01E-04,8.11E-05,3.70E-04,3.15E-05,9.01E-04,7.21E-05,3.70E-04,3.15E-05 \ No newline at end of file diff --git a/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v004.csv b/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v004.csv new file mode 100644 index 000000000..bcfc4cf1d --- /dev/null +++ b/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v004.csv @@ -0,0 +1,16 @@ +esa_mode,incident_E-Step,Observed_E-Step,Cntr_E,Cntr_E_unc,GF_Trpl_H,GF_Trpl_H_unc_minus,GF_Trpl_H_unc_plus +# [1],[1],[1],[keV],[keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV] +0,1,1,0.01633,0.28,4.45E-05,4.03E-05,4.20E-05 +0,2,2,0.03047,0.43,5.02E-05,4.53E-05,4.72E-05 +0,3,3,0.05576,0.89,6.16E-05,5.58E-05,5.82E-05 +0,4,4,0.10626,1.9,7.12E-05,4.51E-05,4.89E-05 +0,5,5,0.20004,3.4,8.89E-05,5.85E-05,6.31E-05 +0,6,6,0.40496,7.3,1.12E-04,6.58E-05,7.23E-05 +0,7,7,0.78729,22,1.43E-04,8.25E-05,9.09E-05 +1,1,1,0.01719,0.22,1.05E-04,8.82E-05,9.26E-05 +1,2,2,0.03236,0.36,1.22E-04,1.02E-04,1.07E-04 +1,3,3,0.05948,0.77,1.44E-04,1.21E-04,1.27E-04 +1,4,4,0.11441,1.3,1.73E-04,1.17E-04,1.26E-04 +1,5,5,0.2137,3,2.15E-04,1.37E-04,1.49E-04 +1,6,6,0.43736,5.3,2.82E-04,1.65E-04,1.81E-04 +1,7,7,0.83888,11.7,3.61E-04,2.08E-04,2.29E-04 diff --git a/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv b/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv deleted file mode 100644 index a72e122e4..000000000 --- a/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv +++ /dev/null @@ -1,75 +0,0 @@ -incident_E-Step,Observed_E-Step,Cntr_E,Cntr_E_unc,GF_Dbl_all,GF_Dbl_all_unc,GF_Trpl_all,GF_Trpl_all_unc,GF_Dbl_O,GF_Dbl_O_unc,GF_Trpl_O,GF_Trpl_O_unc -Hi_Res,,[keV],[keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV] -1,1,0.016,0.00144,3.8700E-04,3.4400E-04,8.9100E-05,8.0200E-05,4.2600E-04,3.4100E-04,1.0600E-04,9.1500E-05 -2,1,0.016,0.00144,2.8700E-04,2.5600E-04,6.6100E-05,5.9500E-05,2.7700E-04,2.2100E-04,6.9200E-05,5.9500E-05 -2,2,0.032,0.00288,4.4800E-04,3.9900E-04,9.6700E-05,8.7000E-05,4.7800E-04,3.8200E-04,1.2000E-04,1.0300E-04 -3,1,0.016,0.00144,5.2900E-04,4.7100E-04,1.3200E-04,1.1900E-04,4.1800E-04,3.3400E-04,1.0400E-04,8.9800E-05 -3,2,0.032,0.00288,5.9300E-04,5.2800E-04,1.4100E-04,1.2700E-04,6.3000E-04,5.0400E-04,1.5800E-04,1.3600E-04 -3,3,0.065,0.00585,6.9900E-04,6.2200E-04,1.6600E-04,1.5000E-04,7.6400E-04,6.1100E-04,1.9100E-04,1.6400E-04 -4,1,0.016,0.00144,6.6400E-04,5.9100E-04,1.7700E-04,1.5900E-04,4.1600E-04,3.3300E-04,1.0400E-04,8.9400E-05 -4,2,0.032,0.00288,1.1500E-03,1.0200E-03,2.6900E-04,2.4200E-04,1.0900E-03,8.7300E-04,2.7300E-04,2.3500E-04 -4,3,0.065,0.00585,2.3600E-03,2.1000E-03,5.1700E-04,4.6500E-04,2.5200E-03,2.0100E-03,6.2900E-04,5.4100E-04 -4,4,0.135,0.01215,8.1500E-04,7.2600E-04,1.9100E-04,1.7200E-04,8.7400E-04,7.0000E-04,2.1900E-04,1.8800E-04 -5,1,0.016,0.00144,2.8100E-04,2.5000E-04,8.8400E-05,7.9600E-05,1.2500E-04,9.9900E-05,3.1200E-05,2.6800E-05 -5,2,0.032,0.00288,3.8100E-04,3.4000E-04,1.0800E-04,9.7300E-05,2.0800E-04,1.6600E-04,5.1900E-05,4.4600E-05 -5,3,0.065,0.00585,5.8000E-04,5.1600E-04,1.3800E-04,1.2400E-04,5.7100E-04,4.5700E-04,1.4300E-04,1.2300E-04 -5,4,0.135,0.01215,5.4100E-04,4.8100E-04,1.2100E-04,1.0800E-04,5.6900E-04,4.5500E-04,1.4200E-04,1.2200E-04 -5,5,0.279,0.02511,8.4100E-04,7.4900E-04,2.0500E-04,1.8500E-04,8.6900E-04,6.9500E-04,2.1700E-04,1.8700E-04 -6,1,0.016,0.00144,2.2100E-04,1.9700E-04,7.1000E-05,6.3900E-05,4.7600E-05,3.8100E-05,1.1900E-05,1.0200E-05 -6,2,0.032,0.00288,3.1900E-04,2.8400E-04,9.7800E-05,8.8000E-05,1.3800E-04,1.1100E-04,3.4600E-05,2.9800E-05 -6,3,0.065,0.00585,4.4900E-04,4.0000E-04,1.2400E-04,1.1100E-04,1.7000E-04,1.3600E-04,4.2500E-05,3.6500E-05 -6,4,0.135,0.01215,6.7700E-04,6.0300E-04,1.5400E-04,1.3800E-04,5.1000E-04,4.0800E-04,1.2700E-04,1.1000E-04 -6,5,0.279,0.02511,1.2800E-03,1.1400E-03,2.9100E-04,2.6200E-04,1.1700E-03,9.3300E-04,2.9100E-04,2.5100E-04 -6,6,0.601,0.05409,8.3600E-04,7.4400E-04,1.9800E-04,1.7800E-04,8.2700E-04,6.6100E-04,2.0700E-04,1.7800E-04 -7,1,0.016,0.00144,1.8500E-04,1.6500E-04,5.9600E-05,5.3700E-05,5.6700E-05,4.5400E-05,1.4200E-05,1.2200E-05 -7,2,0.032,0.00288,2.3400E-04,2.0800E-04,7.3700E-05,6.6300E-05,9.2100E-05,7.3700E-05,2.3000E-05,1.9800E-05 -7,3,0.065,0.00585,3.2000E-04,2.8500E-04,9.2000E-05,8.2800E-05,1.0600E-04,8.5000E-05,2.6600E-05,2.2800E-05 -7,4,0.135,0.01215,4.4900E-04,4.0000E-04,1.2000E-04,1.0800E-04,1.7800E-04,1.4200E-04,4.4400E-05,3.8200E-05 -7,5,0.279,0.02511,7.1800E-04,6.3900E-04,1.7600E-04,1.5800E-04,6.1600E-04,4.9300E-04,1.5400E-04,1.3200E-04 -7,6,0.601,0.05409,1.0300E-03,9.1800E-04,2.4500E-04,2.2000E-04,9.9900E-04,7.9900E-04,2.5000E-04,2.1500E-04 -7,7,1.206,0.10854,9.6000E-04,8.5400E-04,2.4400E-04,2.1900E-04,9.6100E-04,7.6900E-04,2.4000E-04,2.0700E-04 -8,1,0.016,0.00144,2.8900E-04,2.5800E-04,9.1800E-05,8.2700E-05,4.4800E-05,3.5800E-05,1.1200E-05,9.6300E-06 -8,2,0.032,0.00288,3.4200E-04,3.0500E-04,1.0500E-04,9.4300E-05,6.8300E-05,5.4600E-05,1.7100E-05,1.4700E-05 -8,3,0.065,0.00585,1.9300E-04,1.7200E-04,5.6900E-05,5.1200E-05,4.9700E-05,3.9800E-05,1.2400E-05,1.0700E-05 -8,4,0.135,0.01215,2.7000E-04,2.4000E-04,7.2300E-05,6.5000E-05,6.1300E-05,4.9000E-05,1.5300E-05,1.3200E-05 -8,5,0.279,0.02511,3.7600E-04,3.3500E-04,9.7400E-05,8.7700E-05,1.5500E-04,1.2400E-04,3.8800E-05,3.3300E-05 -8,6,0.601,0.05409,7.3600E-04,6.5500E-04,1.8400E-04,1.6600E-04,6.0000E-04,4.8000E-04,1.5000E-04,1.2900E-04 -8,7,1.206,0.10854,1.0600E-03,9.4100E-04,2.5600E-04,2.3100E-04,9.7300E-04,7.7900E-04,2.4300E-04,2.0900E-04 -8,8,2.361,0.21249,9.8400E-04,8.7500E-04,2.5500E-04,2.2900E-04,9.3600E-04,7.4900E-04,2.3400E-04,2.0100E-04 -Hi_Thr,,,,,,,,,,, -1,1,0.017,0.00153,6.4500E-04,5.7400E-04,1.4900E-04,1.3400E-04,7.1000E-04,5.6800E-04,1.7700E-04,1.5300E-04 -2,1,0.017,0.00153,4.7900E-04,4.2600E-04,1.1000E-04,9.9200E-05,4.6100E-04,3.6900E-04,1.1500E-04,9.9200E-05 -2,2,0.033,0.00297,7.4600E-04,6.6400E-04,1.6100E-04,1.4500E-04,7.9700E-04,6.3700E-04,1.9900E-04,1.7100E-04 -3,1,0.017,0.00153,8.8200E-04,7.8500E-04,2.2000E-04,1.9800E-04,6.9600E-04,5.5700E-04,1.7400E-04,1.5000E-04 -3,2,0.033,0.00297,9.8800E-04,8.7900E-04,2.3500E-04,2.1100E-04,1.0500E-03,8.4100E-04,2.6300E-04,2.2600E-04 -3,3,0.066,0.00594,1.1700E-03,1.0400E-03,2.7700E-04,2.4900E-04,1.2700E-03,1.0200E-03,3.1800E-04,2.7400E-04 -4,1,0.017,0.00153,1.1100E-03,9.8600E-04,2.9500E-04,2.6600E-04,6.9300E-04,5.5400E-04,1.7300E-04,1.4900E-04 -4,2,0.033,0.00297,1.9200E-03,1.7100E-03,4.4800E-04,4.0300E-04,1.8200E-03,1.4600E-03,4.5500E-04,3.9100E-04 -4,3,0.066,0.00594,3.9300E-03,3.4900E-03,8.6100E-04,7.7500E-04,4.1900E-03,3.3500E-03,1.0500E-03,9.0100E-04 -4,4,0.136,0.01224,1.3600E-03,1.2100E-03,3.1800E-04,2.8600E-04,1.4600E-03,1.1700E-03,3.6400E-04,3.1300E-04 -5,1,0.017,0.00153,4.6800E-04,4.1700E-04,1.4700E-04,1.3300E-04,2.0800E-04,1.6700E-04,5.2000E-05,4.4700E-05 -5,2,0.033,0.00297,6.3600E-04,5.6600E-04,1.8000E-04,1.6200E-04,3.4600E-04,2.7700E-04,8.6500E-05,7.4400E-05 -5,3,0.066,0.00594,9.6600E-04,8.6000E-04,2.3000E-04,2.0700E-04,9.5100E-04,7.6100E-04,2.3800E-04,2.0400E-04 -5,4,0.136,0.01224,9.0100E-04,8.0200E-04,2.0100E-04,1.8100E-04,9.4800E-04,7.5800E-04,2.3700E-04,2.0400E-04 -5,5,0.28,0.0252,1.4000E-03,1.2500E-03,3.4200E-04,3.0800E-04,1.4500E-03,1.1600E-03,3.6200E-04,3.1100E-04 -6,1,0.017,0.00153,3.6800E-04,3.2800E-04,1.1800E-04,1.0700E-04,7.9400E-05,6.3500E-05,1.9800E-05,1.7100E-05 -6,2,0.033,0.00297,5.3200E-04,4.7300E-04,1.6300E-04,1.4700E-04,2.3100E-04,1.8500E-04,5.7700E-05,4.9600E-05 -6,3,0.066,0.00594,7.4800E-04,6.6600E-04,2.0600E-04,1.8500E-04,2.8300E-04,2.2600E-04,7.0800E-05,6.0900E-05 -6,4,0.136,0.01224,1.1300E-03,1.0000E-03,2.5600E-04,2.3000E-04,8.4900E-04,6.8000E-04,2.1200E-04,1.8300E-04 -6,5,0.28,0.0252,2.1400E-03,1.9100E-03,4.8500E-04,4.3700E-04,1.9400E-03,1.5500E-03,4.8600E-04,4.1800E-04 -6,6,0.602,0.05418,1.3900E-03,1.2400E-03,3.3000E-04,2.9700E-04,1.3800E-03,1.1000E-03,3.4400E-04,2.9600E-04 -7,1,0.017,0.00153,3.0900E-04,2.7500E-04,9.9400E-05,8.9500E-05,9.4500E-05,7.5600E-05,2.3600E-05,2.0300E-05 -7,2,0.033,0.00297,3.9000E-04,3.4700E-04,1.2300E-04,1.1100E-04,1.5400E-04,1.2300E-04,3.8400E-05,3.3000E-05 -7,3,0.066,0.00594,5.3400E-04,4.7500E-04,1.5300E-04,1.3800E-04,1.7700E-04,1.4200E-04,4.4300E-05,3.8100E-05 -7,4,0.136,0.01224,7.4900E-04,6.6700E-04,2.0000E-04,1.8000E-04,2.9600E-04,2.3700E-04,7.4000E-05,6.3700E-05 -7,5,0.28,0.0252,1.2000E-03,1.0700E-03,2.9300E-04,2.6400E-04,1.0300E-03,8.2100E-04,2.5700E-04,2.2100E-04 -7,6,0.602,0.05418,1.7200E-03,1.5300E-03,4.0800E-04,3.6700E-04,1.6700E-03,1.3300E-03,4.1600E-04,3.5800E-04 -7,7,1.207,0.10863,1.6000E-03,1.4200E-03,4.0600E-04,3.6500E-04,1.6000E-03,1.2800E-03,4.0000E-04,3.4400E-04 -8,1,0.017,0.00153,4.8200E-04,4.2900E-04,1.5300E-04,1.3800E-04,7.4700E-05,5.9700E-05,1.8700E-05,1.6100E-05 -8,2,0.033,0.00297,5.7000E-04,5.0800E-04,1.7500E-04,1.5700E-04,1.1400E-04,9.1100E-05,2.8500E-05,2.4500E-05 -8,3,0.066,0.00594,3.2100E-04,2.8600E-04,9.4800E-05,8.5300E-05,8.2900E-05,6.6300E-05,2.0700E-05,1.7800E-05 -8,4,0.136,0.01224,4.5000E-04,4.0100E-04,1.2000E-04,1.0800E-04,1.0200E-04,8.1700E-05,2.5500E-05,2.2000E-05 -8,5,0.28,0.0252,6.2700E-04,5.5800E-04,1.6200E-04,1.4600E-04,2.5800E-04,2.0700E-04,6.4600E-05,5.5600E-05 -8,6,0.602,0.05418,1.2300E-03,1.0900E-03,3.0700E-04,2.7600E-04,1.0000E-03,8.0000E-04,2.5000E-04,2.1500E-04 -8,7,1.207,0.10863,1.7600E-03,1.5700E-03,4.2700E-04,3.8400E-04,1.6200E-03,1.3000E-03,4.0600E-04,3.4900E-04 -8,8,2.362,0.21258,1.6400E-03,1.4600E-03,4.2500E-04,3.8200E-04,1.5600E-03,1.2500E-03,3.9000E-04,3.3500E-04 \ No newline at end of file diff --git a/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v004.csv b/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v004.csv new file mode 100644 index 000000000..f494346c1 --- /dev/null +++ b/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v004.csv @@ -0,0 +1,16 @@ +esa_mode,incident_E-Step,Observed_E-Step,Cntr_E,Cntr_E_unc,GF_Trpl_O,GF_Trpl_O_unc_minus,GF_Trpl_O_unc_plus +# [1],[1],[1],[keV],[keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV] +0,1,1,0.01919,1.372344105,1.98E-05,1.74E-05,1.81E-05 +0,2,2,0.03675,2.537963082,3.18E-05,2.39E-05,2.53E-05 +0,3,3,0.07121,6.591339559,5.34E-05,4.05E-05,4.29E-05 +0,4,4,0.14141,17.43990907,8.64E-05,6.14E-05,6.56E-05 +0,5,5,0.274,35.83900763,1.32E-04,9.07E-05,9.72E-05 +0,6,6,0.58503,98.06681395,2.46E-04,1.53E-04,1.67E-04 +0,7,7,1.13506,238.1076888,3.81E-04,2.23E-04,2.45E-04 +1,1,1,0.02043303552,1.575924599,5.02E-05,4.41E-05,4.61E-05 +1,2,2,0.03972,2.953020557,8.13E-05,6.09E-05,6.47E-05 +1,3,3,0.07648,7.476494389,1.33E-04,1.01E-04,1.07E-04 +1,4,4,0.15353,14.87953071,2.38E-04,1.69E-04,1.80E-04 +1,5,5,0.29846,41.48950349,3.87E-04,2.67E-04,2.86E-04 +1,6,6,0.61524,83.57629594,6.61E-04,4.11E-04,4.47E-04 +1,7,7,1.24282,212.0806857,1.02E-03,6.10E-04,6.67E-04 diff --git a/imap_processing/lo/l1b/lo_l1b.py b/imap_processing/lo/l1b/lo_l1b.py index 021ffb6a5..d51df8133 100644 --- a/imap_processing/lo/l1b/lo_l1b.py +++ b/imap_processing/lo/l1b/lo_l1b.py @@ -2181,7 +2181,7 @@ def calculate_star_sensor_profiles_by_group( bin_offset : float Fractional offset applied to bin indices when computing sample spin-angle centers (default: 0.5). Use 0.5 to bin to the bin center - (pre-FSW 4.8) and 0.0 to bin to the left edge (FSW 4.8 and later). + and 0.0 to bin to the left edge. Returns ------- diff --git a/imap_processing/lo/l2/lo_l2.py b/imap_processing/lo/l2/lo_l2.py index b6af437d9..2160a3edd 100644 --- a/imap_processing/lo/l2/lo_l2.py +++ b/imap_processing/lo/l2/lo_l2.py @@ -710,9 +710,9 @@ def load_geometric_factor_data(species: str) -> pd.DataFrame: anc_path = Path(__file__).parent.parent / "ancillary_data" if species == "h": - gf_file = anc_path / "imap_lo_hydrogen-geometric-factor_v001.csv" + gf_file = sorted(anc_path.glob("*hydrogen-geometric-factor*"))[-1] else: # species == "o" - gf_file = anc_path / "imap_lo_oxygen-geometric-factor_v001.csv" + gf_file = sorted(anc_path.glob("*oxygen-geometric-factor*"))[-1] return lo_ancillary.read_ancillary_file(gf_file) @@ -776,7 +776,8 @@ def initialize_geometric_factor_variables( "energy_delta_minus", "energy_delta_plus", "geometric_factor", - "geometric_factor_stat_uncert", + "geometric_factor_stat_uncert_minus", + "geometric_factor_stat_uncert_plus", ] # Initialize variables with proper dimensions (energy only) @@ -817,7 +818,8 @@ def populate_geometric_factors( gf_coords = {"energy": "Cntr_E"} gf_vars = { "geometric_factor": f"GF_Trpl_{species.upper()}", - "geometric_factor_stat_uncert": f"GF_Trpl_{species.upper()}_unc", + "geometric_factor_stat_uncert_minus": f"GF_Trpl_{species.upper()}_unc_minus", + "geometric_factor_stat_uncert_plus": f"GF_Trpl_{species.upper()}_unc_plus", } if species == "h": # NOTE: From an e-mail from Nathan on 2025-09-11 (values converted to keV) @@ -1007,11 +1009,16 @@ def calculate_intensities(dataset: xr.Dataset) -> xr.Dataset: dataset["counts_over_eff_squared"] ) / (dataset["geometric_factor"] * dataset["energy"] * dataset["exposure_factor"]) - # Equation 5 from mapping document (systematic uncertainty) - dataset["ena_intensity_sys_err"] = ( - dataset["ena_intensity"] - * dataset["geometric_factor_stat_uncert"] - / dataset["geometric_factor"] + for suffix in ("minus", "plus"): + dataset[f"ena_intensity_sys_err_{suffix}"] = ( + dataset["ena_intensity"] + * dataset[f"geometric_factor_stat_uncert_{suffix}"] + / dataset["geometric_factor"] + ) + + # Symmetric systematic error (mean of the asymmetric minus/plus bounds) + dataset["ena_intensity_sys_err"] = 0.5 * ( + dataset["ena_intensity_sys_err_minus"] + dataset["ena_intensity_sys_err_plus"] ) return dataset @@ -1040,11 +1047,17 @@ def calculate_backgrounds(dataset: xr.Dataset) -> xr.Dataset: dataset["bg_rate_stat_uncert_exposure_factor2"] / dataset["exposure_factor"] ** 2 ) - # Equation 8 from mapping document (background systematic uncertainty) - dataset["bg_rate_sys_err"] = ( - dataset["bg_rate"] - * dataset["geometric_factor_stat_uncert"] - / dataset["geometric_factor"] + + for suffix in ("minus", "plus"): + dataset[f"bg_rate_sys_err_{suffix}"] = ( + dataset["bg_rate"] + * dataset[f"geometric_factor_stat_uncert_{suffix}"] + / dataset["geometric_factor"] + ) + + # Symmetric systematic error (mean of the asymmetric minus/plus bounds) + dataset["bg_rate_sys_err"] = 0.5 * ( + dataset["bg_rate_sys_err_minus"] + dataset["bg_rate_sys_err_plus"] ) # Background intensity @@ -1054,10 +1067,17 @@ def calculate_backgrounds(dataset: xr.Dataset) -> xr.Dataset: dataset["bg_intensity_stat_uncert"] = dataset["bg_rate_stat_uncert"] / ( dataset["geometric_factor"] * dataset["energy"] ) - dataset["bg_intensity_sys_err"] = ( - dataset["bg_intensity"] - * dataset["geometric_factor_stat_uncert"] - / dataset["geometric_factor"] + + for suffix in ("minus", "plus"): + dataset[f"bg_intensity_sys_err_{suffix}"] = ( + dataset["bg_intensity"] + * dataset[f"geometric_factor_stat_uncert_{suffix}"] + / dataset["geometric_factor"] + ) + + # Symmetric systematic error (mean of the asymmetric minus/plus bounds) + dataset["bg_intensity_sys_err"] = 0.5 * ( + dataset["bg_intensity_sys_err_minus"] + dataset["bg_intensity_sys_err_plus"] ) return dataset @@ -1401,6 +1421,8 @@ def cleanup_intermediate_variables(dataset: xr.Dataset) -> xr.Dataset: potential_vars = [ "geometric_factor", "geometric_factor_stat_uncert", + "geometric_factor_stat_uncert_minus", + "geometric_factor_stat_uncert_plus", "counts_over_eff", "counts_over_eff_squared", "bg_rate_exposure_factor", diff --git a/imap_processing/lo/lo_ancillary.py b/imap_processing/lo/lo_ancillary.py index 994b03f30..939779747 100644 --- a/imap_processing/lo/lo_ancillary.py +++ b/imap_processing/lo/lo_ancillary.py @@ -36,20 +36,26 @@ def read_ancillary_file(ancillary_file: str | Path) -> pd.DataFrame: pd.DataFrame DataFrame containing the ancillary data. """ - skiprows = None + legacy_format = False + read_csv_kwargs = {} if "esa-mode-lut" in str(ancillary_file): # skip the first row which is a comment - skiprows = [0] + read_csv_kwargs["skiprows"] = [0] elif "geometric-factor" in str(ancillary_file): - # skip the rows with comment headers indicating Hi_Res and Hi_Thr - skiprows = [1, 38] - df = pd.read_csv(ancillary_file, converters=_CONVERTERS, skiprows=skiprows) + # legacy format - rows with comment headers indicating Hi_Res and Hi_Thr + legacy_format = "Hi_Thr,,," in Path(ancillary_file).read_text() + if legacy_format: + read_csv_kwargs["skiprows"] = [1, 38] + else: + read_csv_kwargs["comment"] = "#" + df = pd.read_csv(ancillary_file, converters=_CONVERTERS, **read_csv_kwargs) df = df.rename(columns=_RENAME_COLUMNS) if "geometric-factor" in str(ancillary_file): - # Add an ESA mode column based on the known structure of the file. - # The first 36 rows are ESA mode 0 (HiRes), the second 36 are ESA mode 1 (HiThr) - df["esa_mode"] = 0 - df.loc[36:, "esa_mode"] = 1 + if legacy_format and "esa_mode" not in df.columns: + # Add an ESA mode column based on the known structure of the file. + # The first 36 rows are ESA mode 0 (HiRes), the second 36 are ESA mode 1 (HiThr) + df["esa_mode"] = 0 + df.loc[36:, "esa_mode"] = 1 return df diff --git a/imap_processing/tests/lo/test_lo_l2.py b/imap_processing/tests/lo/test_lo_l2.py index 3422f2070..f4868791b 100644 --- a/imap_processing/tests/lo/test_lo_l2.py +++ b/imap_processing/tests/lo/test_lo_l2.py @@ -278,7 +278,8 @@ def sample_geometric_factor_data(): "Cntr_E": 0.01 * (i + 1), # Simple energy values "Cntr_E_unc": 0.001 * (i + 1), "GF_Trpl_H": 1e-4 * (i + 1), - "GF_Trpl_H_unc": 1e-5 * (i + 1), + "GF_Trpl_H_unc_minus": 1e-5 * (i + 1), + "GF_Trpl_H_unc_plus": 2e-5 * (i + 1), "GF_Dbl_all": 2e-4 * (i + 1), "GF_Dbl_all_unc": 2e-5 * (i + 1), "GF_Trpl_all": 3e-4 * (i + 1), @@ -294,7 +295,8 @@ def sample_geometric_factor_data(): "Cntr_E": 0.015 * (i + 1), # Slightly different for oxygen "Cntr_E_unc": 0.0015 * (i + 1), "GF_Trpl_O": 1.5e-4 * (i + 1), - "GF_Trpl_O_unc": 1.5e-5 * (i + 1), + "GF_Trpl_O_unc_minus": 1.5e-5 * (i + 1), + "GF_Trpl_O_unc_plus": 3e-5 * (i + 1), } ) @@ -358,7 +360,8 @@ def sample_dataset_with_geometric_factors(): dataset["exposure_factor"] = (("epoch", "energy"), np.ones((1, 7)) * 1.0) dataset["geometric_factor"] = (("energy",), np.ones(7) * 1e-4) dataset["energy"] = (("energy",), np.ones(7) * 0.1) # Energy values - dataset["geometric_factor_stat_uncert"] = (("energy",), np.ones(7) * 1e-5) + dataset["geometric_factor_stat_uncert_minus"] = (("energy",), np.ones(7) * 1e-5) + dataset["geometric_factor_stat_uncert_plus"] = (("energy",), np.ones(7) * 3e-5) return dataset @@ -393,7 +396,14 @@ def sample_dataset_with_background_intermediates(): # Add geometric factors for systematic uncertainty calculation dataset["geometric_factor"] = (("energy",), np.ones(n_energy) * 1e-4) - dataset["geometric_factor_stat_uncert"] = (("energy",), np.ones(n_energy) * 1e-5) + dataset["geometric_factor_stat_uncert_minus"] = ( + ("energy",), + np.ones(n_energy) * 1e-5, + ) + dataset["geometric_factor_stat_uncert_plus"] = ( + ("energy",), + np.ones(n_energy) * 3e-5, + ) return dataset @@ -705,7 +715,8 @@ def test_reduce_geometric_factor_dataset_hydrogen( # Check that hydrogen-specific columns are present assert "Cntr_E" in result.data_vars assert "GF_Trpl_H" in result.data_vars - assert "GF_Trpl_H_unc" in result.data_vars + assert "GF_Trpl_H_unc_minus" in result.data_vars + assert "GF_Trpl_H_unc_plus" in result.data_vars # Verify energy values match expected for hydrogen expected_energies = [0.01 * (i + 1) for i in range(7)] @@ -724,7 +735,8 @@ def test_reduce_geometric_factor_dataset_oxygen( # Check that oxygen-specific columns are present assert "Cntr_E" in result.data_vars assert "GF_Trpl_O" in result.data_vars - assert "GF_Trpl_O_unc" in result.data_vars + assert "GF_Trpl_O_unc_minus" in result.data_vars + assert "GF_Trpl_O_unc_plus" in result.data_vars # Verify energy values match expected for oxygen expected_energies = [0.015 * (i + 1) for i in range(7)] @@ -854,9 +866,9 @@ def test_normalize_coordinates_basic(self, species): # Check that energy coordinate is present assert "energy" in result.coords expected_energies = ( - np.array([0.01633, 0.03047, 0.05576, 0.1063, 0.2, 0.405, 0.7873]) + np.array([0.01633, 0.03047, 0.05576, 0.10626, 0.20004, 0.40496, 0.78729]) if species == "h" - else np.array([0.016, 0.032, 0.065, 0.135, 0.279, 0.601, 1.206]) + else np.array([0.01919, 0.03675, 0.07121, 0.14141, 0.274, 0.58503, 1.13506]) ) np.testing.assert_array_equal(result.coords["energy"], expected_energies) @@ -1122,10 +1134,15 @@ def test_calculate_intensities_basic(self, sample_dataset_with_geometric_factors result["ena_intensity_stat_uncert"], expected_stat_uncert ) - # Check systematic uncertainty calculation + # Check systematic uncertainty calculation. The single `_sys_err` is the + # mean of the asymmetric minus/plus bounds. + mean_gf_stat_uncert = 0.5 * ( + sample_dataset_with_geometric_factors["geometric_factor_stat_uncert_minus"] + + sample_dataset_with_geometric_factors["geometric_factor_stat_uncert_plus"] + ) expected_sys_err = ( result["ena_intensity"] - * sample_dataset_with_geometric_factors["geometric_factor_stat_uncert"] + * mean_gf_stat_uncert / sample_dataset_with_geometric_factors["geometric_factor"] ) xr.testing.assert_allclose(result["ena_intensity_sys_err"], expected_sys_err) @@ -1180,11 +1197,13 @@ def test_calculate_backgrounds_basic( xr.testing.assert_allclose(result["bg_rate_stat_uncert"], expected_stat_uncert) # Check systematic uncertainty calculation - # (geometric_factor_stat_uncert / geometric_factor) * bg_rate + # (mean(geometric_factor_stat_uncert bounds) / geometric_factor) * bg_rate + mean_gf_stat_uncert = 0.5 * ( + dataset["geometric_factor_stat_uncert_minus"] + + dataset["geometric_factor_stat_uncert_plus"] + ) expected_sys_err = ( - result["bg_rate"] - * dataset["geometric_factor_stat_uncert"] - / dataset["geometric_factor"] + result["bg_rate"] * mean_gf_stat_uncert / dataset["geometric_factor"] ) xr.testing.assert_allclose(result["bg_rate_sys_err"], expected_sys_err) @@ -1202,7 +1221,8 @@ def test_calculate_backgrounds_zero_exposure(self): ), "exposure_factor": (("epoch", "energy"), np.zeros((1, 7))), "geometric_factor": (("energy",), np.ones(7) * 1e-4), - "geometric_factor_stat_uncert": (("energy",), np.ones(7) * 1e-5), + "geometric_factor_stat_uncert_minus": (("energy",), np.ones(7) * 1e-5), + "geometric_factor_stat_uncert_plus": (("energy",), np.ones(7) * 3e-5), }, coords={"epoch": [8.1794907049e17], "energy": list(range(7))}, ) @@ -1733,7 +1753,8 @@ def test_initialize_geometric_factor_variables(self): "energy_delta_minus", "energy_delta_plus", "geometric_factor", - "geometric_factor_stat_uncert", + "geometric_factor_stat_uncert_minus", + "geometric_factor_stat_uncert_plus", ] for var in expected_vars: @@ -1773,15 +1794,21 @@ def test_populate_geometric_factors( # Check hydrogen values assert result["energy"].values[i] == 0.01 * (i + 1) assert result["geometric_factor"].values[i] == 1e-4 * (i + 1) - assert result["geometric_factor_stat_uncert"].values[i] == ( + assert result["geometric_factor_stat_uncert_minus"].values[i] == ( 1e-5 * (i + 1) ) + assert result["geometric_factor_stat_uncert_plus"].values[i] == ( + 2e-5 * (i + 1) + ) else: # oxygen assert result["energy"].values[i] == 0.015 * (i + 1) assert result["geometric_factor"].values[i] == 1.5e-4 * (i + 1) - assert result["geometric_factor_stat_uncert"].values[i] == ( + assert result["geometric_factor_stat_uncert_minus"].values[i] == ( 1.5e-5 * (i + 1) ) + assert result["geometric_factor_stat_uncert_plus"].values[i] == ( + 3e-5 * (i + 1) + ) # Ensure that energy_deltas are in units of keV assert np.all(result["energy_delta_plus"].values < 1) assert np.all(result["energy_delta_minus"].values < 1) @@ -2292,7 +2319,8 @@ def test_calculate_all_rates_and_intensities_complete(self): "exposure_factor": (("energy",), np.ones(7) * 1.0), "geometric_factor": (("energy",), np.ones(7) * 1e-4), "energy": (("energy",), np.ones(7) * 0.1), - "geometric_factor_stat_uncert": (("energy",), np.ones(7) * 1e-5), + "geometric_factor_stat_uncert_minus": (("energy",), np.ones(7) * 1e-5), + "geometric_factor_stat_uncert_plus": (("energy",), np.ones(7) * 3e-5), # Background intermediate data "bg_rate_exposure_factor": (("energy",), np.ones(7) * 0.3), "bg_rate_stat_uncert_exposure_factor2": ( @@ -2335,7 +2363,8 @@ def test_calculate_all_rates_with_cg_correction( dataset["counts_over_eff_squared"] = (("epoch", "energy"), np.ones((1, 7)) * 12) dataset["exposure_factor"] = (("epoch", "energy"), np.ones((1, 7)) * 1.0) dataset["geometric_factor"] = (("energy",), np.ones(7) * 1e-4) - dataset["geometric_factor_stat_uncert"] = (("energy",), np.ones(7) * 1e-5) + dataset["geometric_factor_stat_uncert_minus"] = (("energy",), np.ones(7) * 1e-5) + dataset["geometric_factor_stat_uncert_plus"] = (("energy",), np.ones(7) * 3e-5) dataset["bg_rate_exposure_factor"] = ( ("epoch", "energy"), np.ones((1, 7)) * 0.3, @@ -2386,7 +2415,8 @@ def test_calculate_all_rates_cg_with_other_corrections( dataset["counts_over_eff_squared"] = (("epoch", "energy"), np.ones((1, 7)) * 12) dataset["exposure_factor"] = (("epoch", "energy"), np.ones((1, 7)) * 1.0) dataset["geometric_factor"] = (("energy",), np.ones(7) * 1e-4) - dataset["geometric_factor_stat_uncert"] = (("energy",), np.ones(7) * 1e-5) + dataset["geometric_factor_stat_uncert_minus"] = (("energy",), np.ones(7) * 1e-5) + dataset["geometric_factor_stat_uncert_plus"] = (("energy",), np.ones(7) * 3e-5) dataset["bg_rate_exposure_factor"] = ( ("epoch", "energy"), np.ones((1, 7)) * 0.3, From 400eecfb30b7e0eef0b6017561edba13589817b3 Mon Sep 17 00:00:00 2001 From: Vineet Bansal Date: Wed, 17 Jun 2026 13:35:41 -0400 Subject: [PATCH 4/6] failing loudly on unexpected ifb_ctrl_star_sync value in NHK data (should be DS/EN); pre-commit checked --- imap_processing/lo/constants.py | 1 - imap_processing/lo/l1b/lo_l1b.py | 2 +- imap_processing/lo/lo_ancillary.py | 6 ++++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/imap_processing/lo/constants.py b/imap_processing/lo/constants.py index 7220566c9..aa0e6e4a6 100644 --- a/imap_processing/lo/constants.py +++ b/imap_processing/lo/constants.py @@ -83,7 +83,6 @@ class LoConstants: STAR_BIN_OFFSET_BY_SYNC: ClassVar[dict[str | None, float]] = { "DS": 0.5, # star sync disabled (pre FSW 4.8) "EN": 0.0, # star sync enabled (FSW 4.8+) - None: 0.5, # default value } # Number of ending bins to exclude from each star-sensor profile average. diff --git a/imap_processing/lo/l1b/lo_l1b.py b/imap_processing/lo/l1b/lo_l1b.py index d51df8133..f375388ad 100644 --- a/imap_processing/lo/l1b/lo_l1b.py +++ b/imap_processing/lo/l1b/lo_l1b.py @@ -2141,7 +2141,7 @@ def get_star_bin_offset(l1b_nhk: xr.Dataset, reference_epoch: int) -> float: idx = max(int(np.searchsorted(nhk_epoch, reference_epoch, side="right")) - 1, 0) state = str(sync_state[idx]) - offset = c.STAR_BIN_OFFSET_BY_SYNC.get(state, c.STAR_BIN_OFFSET_BY_SYNC[None]) + offset = c.STAR_BIN_OFFSET_BY_SYNC[state] logger.info(f"Star sync state '{state}' -> bin offset {offset}") return offset diff --git a/imap_processing/lo/lo_ancillary.py b/imap_processing/lo/lo_ancillary.py index 939779747..0a90ddc17 100644 --- a/imap_processing/lo/lo_ancillary.py +++ b/imap_processing/lo/lo_ancillary.py @@ -1,6 +1,7 @@ """Ancillary file reading for IMAP-Lo processing.""" from pathlib import Path +from typing import Any import pandas as pd @@ -37,7 +38,7 @@ def read_ancillary_file(ancillary_file: str | Path) -> pd.DataFrame: DataFrame containing the ancillary data. """ legacy_format = False - read_csv_kwargs = {} + read_csv_kwargs: dict[str, Any] = {} if "esa-mode-lut" in str(ancillary_file): # skip the first row which is a comment read_csv_kwargs["skiprows"] = [0] @@ -54,7 +55,8 @@ def read_ancillary_file(ancillary_file: str | Path) -> pd.DataFrame: if "geometric-factor" in str(ancillary_file): if legacy_format and "esa_mode" not in df.columns: # Add an ESA mode column based on the known structure of the file. - # The first 36 rows are ESA mode 0 (HiRes), the second 36 are ESA mode 1 (HiThr) + # The first 36 rows are ESA mode 0 (HiRes), the second 36 are ESA mode 1 + # (HiThr) df["esa_mode"] = 0 df.loc[36:, "esa_mode"] = 1 From 2cd063cbbc277604c30ad15860c47fcae849e551 Mon Sep 17 00:00:00 2001 From: Vineet Bansal Date: Wed, 17 Jun 2026 13:45:29 -0400 Subject: [PATCH 5/6] testing for KeyError; reintroduced old ancillaries since some tests depend on it --- ...imap_lo_hydrogen-geometric-factor_v001.csv | 75 +++++++++++++++++++ .../imap_lo_oxygen-geometric-factor_v001.csv | 75 +++++++++++++++++++ imap_processing/tests/lo/test_lo_l1b.py | 7 +- 3 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv create mode 100644 imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv diff --git a/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv b/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv new file mode 100644 index 000000000..3c4b9996d --- /dev/null +++ b/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv @@ -0,0 +1,75 @@ +incident_E-Step,Observed_E-Step,Cntr_E,Cntr_E_unc,GF_Dbl_all,GF_Dbl_all_unc,GF_Trpl_all,GF_Trpl_all_unc,GF_Dbl_H,GF_Dbl_H_unc,GF_Trpl_H,GF_Trpl_H_unc +Hi_Res,,[keV],[keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV] +1,1,0.01633,0.00028,5.35E-05,4.82E-06,2.20E-05,1.87E-06,5.32E-05,4.26E-06,7.00E-05,4.90E-05 +2,1,0.01633,0.00028,3.10E-05,2.79E-06,1.25E-05,1.06E-06,3.09E-05,2.47E-06,1.27E-05,1.08E-06 +2,2,0.03047,0.00043,1.04E-04,9.36E-06,4.27E-05,3.63E-06,1.03E-04,8.26E-06,7.90E-05,5.50E-05 +3,1,0.01633,0.00028,4.13E-05,3.72E-06,1.68E-05,1.43E-06,4.16E-05,3.33E-06,1.71E-05,1.45E-06 +3,2,0.03047,0.00043,1.28E-04,1.15E-05,5.02E-05,4.26E-06,1.30E-04,1.04E-05,5.35E-05,4.55E-06 +3,3,0.05576,0.00089,1.59E-04,1.43E-05,6.54E-05,5.56E-06,1.59E-04,1.27E-05,9.70E-05,6.80E-05 +4,1,0.01633,0.00028,9.85E-06,8.86E-07,3.73E-06,3.17E-07,7.97E-06,6.38E-07,3.28E-06,2.79E-07 +4,2,0.03047,0.00043,1.71E-05,1.54E-06,6.54E-06,5.56E-07,1.68E-05,1.34E-06,6.89E-06,5.86E-07 +4,3,0.05576,0.00089,6.72E-05,6.05E-06,2.58E-05,2.19E-06,6.92E-05,5.53E-06,2.84E-05,2.42E-06 +4,4,0.1063,0.0019,1.79E-04,1.61E-05,7.36E-05,6.25E-06,1.78E-04,1.42E-05,1.12E-04,3.00E-05 +5,1,0.01633,0.00028,1.62E-05,1.46E-06,5.05E-06,4.29E-07,7.86E-06,6.29E-07,3.23E-06,2.75E-07 +5,2,0.03047,0.00043,1.57E-05,1.41E-06,5.16E-06,4.39E-07,9.72E-06,7.77E-07,3.99E-06,3.39E-07 +5,3,0.05576,0.00089,1.45E-05,1.31E-06,4.98E-06,4.24E-07,1.49E-05,1.20E-06,6.14E-06,5.22E-07 +5,4,0.1063,0.0019,5.81E-05,5.23E-06,2.15E-05,1.83E-06,6.00E-05,4.80E-06,2.47E-05,2.10E-06 +5,5,0.2,0.0034,1.77E-04,1.59E-05,7.26E-05,6.17E-06,1.76E-04,1.41E-05,1.40E-04,4.50E-05 +6,1,0.01633,0.00028,1.34E-05,1.21E-06,4.33E-06,3.68E-07,9.40E-06,7.52E-07,3.86E-06,3.28E-07 +6,2,0.03047,0.00043,1.61E-05,1.45E-06,4.64E-06,3.94E-07,1.11E-05,8.92E-07,4.58E-06,3.89E-07 +6,3,0.05576,0.00089,1.74E-05,1.57E-06,5.02E-06,4.27E-07,1.42E-05,1.14E-06,5.84E-06,4.96E-07 +6,4,0.1063,0.0019,1.45E-05,1.30E-06,4.28E-06,3.64E-07,1.56E-05,1.25E-06,6.40E-06,5.44E-07 +6,5,0.2,0.0034,5.81E-05,5.23E-06,2.06E-05,1.75E-06,6.01E-05,4.81E-06,2.47E-05,2.10E-06 +6,6,0.405,0.0073,2.06E-04,1.85E-05,8.46E-05,7.19E-06,2.06E-04,1.64E-05,1.77E-04,2.00E-05 +7,1,0.01633,0.00028,5.32E-06,4.79E-07,1.51E-06,1.29E-07,5.05E-06,4.04E-07,2.08E-06,1.76E-07 +7,2,0.03047,0.00043,1.61E-05,1.45E-06,5.15E-06,4.38E-07,1.39E-05,1.11E-06,5.70E-06,4.85E-07 +7,3,0.05576,0.00089,1.96E-05,1.77E-06,6.10E-06,5.19E-07,1.42E-05,1.14E-06,5.84E-06,4.96E-07 +7,4,0.1063,0.0019,2.08E-05,1.87E-06,6.43E-06,5.46E-07,1.65E-05,1.32E-06,6.78E-06,5.77E-07 +7,5,0.2,0.0034,2.52E-05,2.27E-06,8.69E-06,7.39E-07,2.61E-05,2.09E-06,1.07E-05,9.11E-07 +7,6,0.405,0.0073,1.93E-04,1.74E-05,6.94E-05,5.90E-06,1.98E-04,1.59E-05,8.15E-05,6.93E-06 +7,7,0.7873,0.022,3.82E-04,3.44E-05,1.57E-04,1.33E-05,3.82E-04,3.05E-05,2.25E-04,1.40E-05 +8,1,0.01633,0.00028,5.28E-05,4.75E-06,2.25E-05,1.91E-06,4.10E-05,3.28E-06,1.68E-05,1.43E-06 +8,2,0.03047,0.00043,6.14E-06,5.53E-07,1.96E-06,1.66E-07,5.25E-06,4.20E-07,2.16E-06,1.83E-07 +8,3,0.05576,0.00089,1.13E-05,1.02E-06,3.39E-06,2.88E-07,9.37E-06,7.50E-07,3.85E-06,3.27E-07 +8,4,0.1063,0.0019,1.16E-05,1.04E-06,3.83E-06,3.25E-07,8.69E-06,6.95E-07,3.57E-06,3.03E-07 +8,5,0.2,0.0034,1.09E-05,9.78E-07,3.55E-06,3.02E-07,8.41E-06,6.73E-07,3.46E-06,2.94E-07 +8,6,0.405,0.0073,3.29E-05,2.96E-06,1.28E-05,1.08E-06,3.28E-05,2.62E-06,1.35E-05,1.15E-06 +8,7,0.7873,0.022,3.95E-04,3.56E-05,1.44E-04,1.23E-05,4.04E-04,3.23E-05,1.66E-04,1.41E-05 +8,8,1.821,0.16389,5.41E-04,4.87E-05,2.22E-04,1.89E-05,5.41E-04,4.33E-05,2.22E-04,1.89E-05 +Hi_Thr,,,,,,,,,,, +1,1,0.01719,0.00022,8.92E-05,8.03E-06,3.67E-05,3.12E-06,8.87E-05,7.10E-06,1.66E-04,1.01E-04 +2,1,0.01719,0.00022,5.16E-05,4.65E-06,2.08E-05,1.76E-06,5.15E-05,4.12E-06,2.12E-05,1.80E-06 +2,2,0.03236,0.00036,1.73E-04,1.56E-05,7.12E-05,6.06E-06,1.72E-04,1.38E-05,1.92E-04,1.17E-04 +3,1,0.01719,0.00022,6.88E-05,6.19E-06,2.80E-05,2.38E-06,6.94E-05,5.55E-06,2.85E-05,2.42E-06 +3,2,0.03236,0.00036,2.13E-04,1.91E-05,8.36E-05,7.11E-06,2.17E-04,1.74E-05,8.92E-05,7.58E-06 +3,3,0.05948,0.00077,2.65E-04,2.39E-05,1.09E-04,9.26E-06,2.64E-04,2.11E-05,2.27E-04,1.38E-04 +4,1,0.01719,0.00022,1.64E-05,1.48E-06,6.22E-06,5.29E-07,1.33E-05,1.06E-06,5.46E-06,4.64E-07 +4,2,0.03236,0.00036,2.84E-05,2.56E-06,1.09E-05,9.27E-07,2.80E-05,2.24E-06,1.15E-05,9.77E-07 +4,3,0.05948,0.00077,1.12E-04,1.01E-05,4.30E-05,3.66E-06,1.15E-04,9.22E-06,4.74E-05,4.03E-06 +4,4,0.1144,0.0013,2.98E-04,2.68E-05,1.23E-04,1.04E-05,2.96E-04,2.37E-05,2.73E-04,9.80E-05 +5,1,0.01719,0.00022,2.70E-05,2.43E-06,8.42E-06,7.15E-07,1.31E-05,1.05E-06,5.38E-06,4.58E-07 +5,2,0.03236,0.00036,2.61E-05,2.35E-06,8.61E-06,7.31E-07,1.62E-05,1.30E-06,6.65E-06,5.66E-07 +5,3,0.05948,0.00077,2.42E-05,2.18E-06,8.30E-06,7.06E-07,2.49E-05,1.99E-06,1.02E-05,8.70E-07 +5,4,0.1144,0.0013,9.69E-05,8.72E-06,3.58E-05,3.04E-06,1.00E-04,8.00E-06,4.11E-05,3.49E-06 +5,5,0.2137,0.003,2.94E-04,2.65E-05,1.21E-04,1.03E-05,2.93E-04,2.34E-05,3.38E-04,9.50E-05 +6,1,0.01719,0.00022,2.24E-05,2.01E-06,7.22E-06,6.14E-07,1.57E-05,1.25E-06,6.44E-06,5.47E-07 +6,2,0.03236,0.00036,2.68E-05,2.41E-06,7.73E-06,6.57E-07,1.86E-05,1.49E-06,7.64E-06,6.49E-07 +6,3,0.05948,0.00077,2.91E-05,2.61E-06,8.37E-06,7.12E-07,2.37E-05,1.89E-06,9.73E-06,8.27E-07 +6,4,0.1144,0.0013,2.41E-05,2.17E-06,7.13E-06,6.06E-07,2.60E-05,2.08E-06,1.07E-05,9.07E-07 +6,5,0.2137,0.003,9.68E-05,8.71E-06,3.44E-05,2.92E-06,1.00E-04,8.02E-06,4.12E-05,3.50E-06 +6,6,0.4374,0.0053,3.43E-04,3.09E-05,1.41E-04,1.20E-05,3.43E-04,2.74E-05,4.44E-04,4.90E-05 +7,1,0.01719,0.00022,8.87E-06,7.98E-07,2.52E-06,2.14E-07,8.42E-06,6.73E-07,3.46E-06,2.94E-07 +7,2,0.03236,0.00036,2.68E-05,2.41E-06,8.59E-06,7.30E-07,2.31E-05,1.85E-06,9.50E-06,8.08E-07 +7,3,0.05948,0.00077,3.27E-05,2.95E-06,1.02E-05,8.64E-07,2.37E-05,1.89E-06,9.73E-06,8.27E-07 +7,4,0.1144,0.0013,3.47E-05,3.12E-06,1.07E-05,9.10E-07,2.75E-05,2.20E-06,1.13E-05,9.61E-07 +7,5,0.2137,0.003,4.20E-05,3.78E-06,1.45E-05,1.23E-06,4.35E-05,3.48E-06,1.79E-05,1.52E-06 +7,6,0.4374,0.0053,3.21E-04,2.89E-05,1.16E-04,9.84E-06,3.31E-04,2.65E-05,1.36E-04,1.16E-05 +7,7,0.8389,0.00117,6.36E-04,5.73E-05,2.61E-04,2.22E-05,6.36E-04,5.09E-05,5.69E-04,2.90E-05 +8,1,0.01719,0.00022,8.79E-05,7.91E-06,3.75E-05,3.19E-06,6.83E-05,5.46E-06,2.81E-05,2.39E-06 +8,2,0.03236,0.00036,1.02E-05,9.21E-07,3.26E-06,2.77E-07,8.75E-06,7.00E-07,3.60E-06,3.06E-07 +8,3,0.05948,0.00077,1.88E-05,1.70E-06,5.65E-06,4.80E-07,1.56E-05,1.25E-06,6.42E-06,5.46E-07 +8,4,0.1144,0.0013,1.93E-05,1.73E-06,6.38E-06,5.42E-07,1.45E-05,1.16E-06,5.95E-06,5.06E-07 +8,5,0.2137,0.003,1.81E-05,1.63E-06,5.92E-06,5.03E-07,1.40E-05,1.12E-06,5.76E-06,4.90E-07 +8,6,0.4374,0.0053,5.48E-05,4.93E-06,2.13E-05,1.81E-06,5.46E-05,4.37E-06,2.25E-05,1.91E-06 +8,7,0.8389,0.00117,6.59E-04,5.93E-05,2.40E-04,2.04E-05,6.74E-04,5.39E-05,2.77E-04,2.35E-05 +8,8,1.822,0.16398,9.01E-04,8.11E-05,3.70E-04,3.15E-05,9.01E-04,7.21E-05,3.70E-04,3.15E-05 \ No newline at end of file diff --git a/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv b/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv new file mode 100644 index 000000000..a72e122e4 --- /dev/null +++ b/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv @@ -0,0 +1,75 @@ +incident_E-Step,Observed_E-Step,Cntr_E,Cntr_E_unc,GF_Dbl_all,GF_Dbl_all_unc,GF_Trpl_all,GF_Trpl_all_unc,GF_Dbl_O,GF_Dbl_O_unc,GF_Trpl_O,GF_Trpl_O_unc +Hi_Res,,[keV],[keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV] +1,1,0.016,0.00144,3.8700E-04,3.4400E-04,8.9100E-05,8.0200E-05,4.2600E-04,3.4100E-04,1.0600E-04,9.1500E-05 +2,1,0.016,0.00144,2.8700E-04,2.5600E-04,6.6100E-05,5.9500E-05,2.7700E-04,2.2100E-04,6.9200E-05,5.9500E-05 +2,2,0.032,0.00288,4.4800E-04,3.9900E-04,9.6700E-05,8.7000E-05,4.7800E-04,3.8200E-04,1.2000E-04,1.0300E-04 +3,1,0.016,0.00144,5.2900E-04,4.7100E-04,1.3200E-04,1.1900E-04,4.1800E-04,3.3400E-04,1.0400E-04,8.9800E-05 +3,2,0.032,0.00288,5.9300E-04,5.2800E-04,1.4100E-04,1.2700E-04,6.3000E-04,5.0400E-04,1.5800E-04,1.3600E-04 +3,3,0.065,0.00585,6.9900E-04,6.2200E-04,1.6600E-04,1.5000E-04,7.6400E-04,6.1100E-04,1.9100E-04,1.6400E-04 +4,1,0.016,0.00144,6.6400E-04,5.9100E-04,1.7700E-04,1.5900E-04,4.1600E-04,3.3300E-04,1.0400E-04,8.9400E-05 +4,2,0.032,0.00288,1.1500E-03,1.0200E-03,2.6900E-04,2.4200E-04,1.0900E-03,8.7300E-04,2.7300E-04,2.3500E-04 +4,3,0.065,0.00585,2.3600E-03,2.1000E-03,5.1700E-04,4.6500E-04,2.5200E-03,2.0100E-03,6.2900E-04,5.4100E-04 +4,4,0.135,0.01215,8.1500E-04,7.2600E-04,1.9100E-04,1.7200E-04,8.7400E-04,7.0000E-04,2.1900E-04,1.8800E-04 +5,1,0.016,0.00144,2.8100E-04,2.5000E-04,8.8400E-05,7.9600E-05,1.2500E-04,9.9900E-05,3.1200E-05,2.6800E-05 +5,2,0.032,0.00288,3.8100E-04,3.4000E-04,1.0800E-04,9.7300E-05,2.0800E-04,1.6600E-04,5.1900E-05,4.4600E-05 +5,3,0.065,0.00585,5.8000E-04,5.1600E-04,1.3800E-04,1.2400E-04,5.7100E-04,4.5700E-04,1.4300E-04,1.2300E-04 +5,4,0.135,0.01215,5.4100E-04,4.8100E-04,1.2100E-04,1.0800E-04,5.6900E-04,4.5500E-04,1.4200E-04,1.2200E-04 +5,5,0.279,0.02511,8.4100E-04,7.4900E-04,2.0500E-04,1.8500E-04,8.6900E-04,6.9500E-04,2.1700E-04,1.8700E-04 +6,1,0.016,0.00144,2.2100E-04,1.9700E-04,7.1000E-05,6.3900E-05,4.7600E-05,3.8100E-05,1.1900E-05,1.0200E-05 +6,2,0.032,0.00288,3.1900E-04,2.8400E-04,9.7800E-05,8.8000E-05,1.3800E-04,1.1100E-04,3.4600E-05,2.9800E-05 +6,3,0.065,0.00585,4.4900E-04,4.0000E-04,1.2400E-04,1.1100E-04,1.7000E-04,1.3600E-04,4.2500E-05,3.6500E-05 +6,4,0.135,0.01215,6.7700E-04,6.0300E-04,1.5400E-04,1.3800E-04,5.1000E-04,4.0800E-04,1.2700E-04,1.1000E-04 +6,5,0.279,0.02511,1.2800E-03,1.1400E-03,2.9100E-04,2.6200E-04,1.1700E-03,9.3300E-04,2.9100E-04,2.5100E-04 +6,6,0.601,0.05409,8.3600E-04,7.4400E-04,1.9800E-04,1.7800E-04,8.2700E-04,6.6100E-04,2.0700E-04,1.7800E-04 +7,1,0.016,0.00144,1.8500E-04,1.6500E-04,5.9600E-05,5.3700E-05,5.6700E-05,4.5400E-05,1.4200E-05,1.2200E-05 +7,2,0.032,0.00288,2.3400E-04,2.0800E-04,7.3700E-05,6.6300E-05,9.2100E-05,7.3700E-05,2.3000E-05,1.9800E-05 +7,3,0.065,0.00585,3.2000E-04,2.8500E-04,9.2000E-05,8.2800E-05,1.0600E-04,8.5000E-05,2.6600E-05,2.2800E-05 +7,4,0.135,0.01215,4.4900E-04,4.0000E-04,1.2000E-04,1.0800E-04,1.7800E-04,1.4200E-04,4.4400E-05,3.8200E-05 +7,5,0.279,0.02511,7.1800E-04,6.3900E-04,1.7600E-04,1.5800E-04,6.1600E-04,4.9300E-04,1.5400E-04,1.3200E-04 +7,6,0.601,0.05409,1.0300E-03,9.1800E-04,2.4500E-04,2.2000E-04,9.9900E-04,7.9900E-04,2.5000E-04,2.1500E-04 +7,7,1.206,0.10854,9.6000E-04,8.5400E-04,2.4400E-04,2.1900E-04,9.6100E-04,7.6900E-04,2.4000E-04,2.0700E-04 +8,1,0.016,0.00144,2.8900E-04,2.5800E-04,9.1800E-05,8.2700E-05,4.4800E-05,3.5800E-05,1.1200E-05,9.6300E-06 +8,2,0.032,0.00288,3.4200E-04,3.0500E-04,1.0500E-04,9.4300E-05,6.8300E-05,5.4600E-05,1.7100E-05,1.4700E-05 +8,3,0.065,0.00585,1.9300E-04,1.7200E-04,5.6900E-05,5.1200E-05,4.9700E-05,3.9800E-05,1.2400E-05,1.0700E-05 +8,4,0.135,0.01215,2.7000E-04,2.4000E-04,7.2300E-05,6.5000E-05,6.1300E-05,4.9000E-05,1.5300E-05,1.3200E-05 +8,5,0.279,0.02511,3.7600E-04,3.3500E-04,9.7400E-05,8.7700E-05,1.5500E-04,1.2400E-04,3.8800E-05,3.3300E-05 +8,6,0.601,0.05409,7.3600E-04,6.5500E-04,1.8400E-04,1.6600E-04,6.0000E-04,4.8000E-04,1.5000E-04,1.2900E-04 +8,7,1.206,0.10854,1.0600E-03,9.4100E-04,2.5600E-04,2.3100E-04,9.7300E-04,7.7900E-04,2.4300E-04,2.0900E-04 +8,8,2.361,0.21249,9.8400E-04,8.7500E-04,2.5500E-04,2.2900E-04,9.3600E-04,7.4900E-04,2.3400E-04,2.0100E-04 +Hi_Thr,,,,,,,,,,, +1,1,0.017,0.00153,6.4500E-04,5.7400E-04,1.4900E-04,1.3400E-04,7.1000E-04,5.6800E-04,1.7700E-04,1.5300E-04 +2,1,0.017,0.00153,4.7900E-04,4.2600E-04,1.1000E-04,9.9200E-05,4.6100E-04,3.6900E-04,1.1500E-04,9.9200E-05 +2,2,0.033,0.00297,7.4600E-04,6.6400E-04,1.6100E-04,1.4500E-04,7.9700E-04,6.3700E-04,1.9900E-04,1.7100E-04 +3,1,0.017,0.00153,8.8200E-04,7.8500E-04,2.2000E-04,1.9800E-04,6.9600E-04,5.5700E-04,1.7400E-04,1.5000E-04 +3,2,0.033,0.00297,9.8800E-04,8.7900E-04,2.3500E-04,2.1100E-04,1.0500E-03,8.4100E-04,2.6300E-04,2.2600E-04 +3,3,0.066,0.00594,1.1700E-03,1.0400E-03,2.7700E-04,2.4900E-04,1.2700E-03,1.0200E-03,3.1800E-04,2.7400E-04 +4,1,0.017,0.00153,1.1100E-03,9.8600E-04,2.9500E-04,2.6600E-04,6.9300E-04,5.5400E-04,1.7300E-04,1.4900E-04 +4,2,0.033,0.00297,1.9200E-03,1.7100E-03,4.4800E-04,4.0300E-04,1.8200E-03,1.4600E-03,4.5500E-04,3.9100E-04 +4,3,0.066,0.00594,3.9300E-03,3.4900E-03,8.6100E-04,7.7500E-04,4.1900E-03,3.3500E-03,1.0500E-03,9.0100E-04 +4,4,0.136,0.01224,1.3600E-03,1.2100E-03,3.1800E-04,2.8600E-04,1.4600E-03,1.1700E-03,3.6400E-04,3.1300E-04 +5,1,0.017,0.00153,4.6800E-04,4.1700E-04,1.4700E-04,1.3300E-04,2.0800E-04,1.6700E-04,5.2000E-05,4.4700E-05 +5,2,0.033,0.00297,6.3600E-04,5.6600E-04,1.8000E-04,1.6200E-04,3.4600E-04,2.7700E-04,8.6500E-05,7.4400E-05 +5,3,0.066,0.00594,9.6600E-04,8.6000E-04,2.3000E-04,2.0700E-04,9.5100E-04,7.6100E-04,2.3800E-04,2.0400E-04 +5,4,0.136,0.01224,9.0100E-04,8.0200E-04,2.0100E-04,1.8100E-04,9.4800E-04,7.5800E-04,2.3700E-04,2.0400E-04 +5,5,0.28,0.0252,1.4000E-03,1.2500E-03,3.4200E-04,3.0800E-04,1.4500E-03,1.1600E-03,3.6200E-04,3.1100E-04 +6,1,0.017,0.00153,3.6800E-04,3.2800E-04,1.1800E-04,1.0700E-04,7.9400E-05,6.3500E-05,1.9800E-05,1.7100E-05 +6,2,0.033,0.00297,5.3200E-04,4.7300E-04,1.6300E-04,1.4700E-04,2.3100E-04,1.8500E-04,5.7700E-05,4.9600E-05 +6,3,0.066,0.00594,7.4800E-04,6.6600E-04,2.0600E-04,1.8500E-04,2.8300E-04,2.2600E-04,7.0800E-05,6.0900E-05 +6,4,0.136,0.01224,1.1300E-03,1.0000E-03,2.5600E-04,2.3000E-04,8.4900E-04,6.8000E-04,2.1200E-04,1.8300E-04 +6,5,0.28,0.0252,2.1400E-03,1.9100E-03,4.8500E-04,4.3700E-04,1.9400E-03,1.5500E-03,4.8600E-04,4.1800E-04 +6,6,0.602,0.05418,1.3900E-03,1.2400E-03,3.3000E-04,2.9700E-04,1.3800E-03,1.1000E-03,3.4400E-04,2.9600E-04 +7,1,0.017,0.00153,3.0900E-04,2.7500E-04,9.9400E-05,8.9500E-05,9.4500E-05,7.5600E-05,2.3600E-05,2.0300E-05 +7,2,0.033,0.00297,3.9000E-04,3.4700E-04,1.2300E-04,1.1100E-04,1.5400E-04,1.2300E-04,3.8400E-05,3.3000E-05 +7,3,0.066,0.00594,5.3400E-04,4.7500E-04,1.5300E-04,1.3800E-04,1.7700E-04,1.4200E-04,4.4300E-05,3.8100E-05 +7,4,0.136,0.01224,7.4900E-04,6.6700E-04,2.0000E-04,1.8000E-04,2.9600E-04,2.3700E-04,7.4000E-05,6.3700E-05 +7,5,0.28,0.0252,1.2000E-03,1.0700E-03,2.9300E-04,2.6400E-04,1.0300E-03,8.2100E-04,2.5700E-04,2.2100E-04 +7,6,0.602,0.05418,1.7200E-03,1.5300E-03,4.0800E-04,3.6700E-04,1.6700E-03,1.3300E-03,4.1600E-04,3.5800E-04 +7,7,1.207,0.10863,1.6000E-03,1.4200E-03,4.0600E-04,3.6500E-04,1.6000E-03,1.2800E-03,4.0000E-04,3.4400E-04 +8,1,0.017,0.00153,4.8200E-04,4.2900E-04,1.5300E-04,1.3800E-04,7.4700E-05,5.9700E-05,1.8700E-05,1.6100E-05 +8,2,0.033,0.00297,5.7000E-04,5.0800E-04,1.7500E-04,1.5700E-04,1.1400E-04,9.1100E-05,2.8500E-05,2.4500E-05 +8,3,0.066,0.00594,3.2100E-04,2.8600E-04,9.4800E-05,8.5300E-05,8.2900E-05,6.6300E-05,2.0700E-05,1.7800E-05 +8,4,0.136,0.01224,4.5000E-04,4.0100E-04,1.2000E-04,1.0800E-04,1.0200E-04,8.1700E-05,2.5500E-05,2.2000E-05 +8,5,0.28,0.0252,6.2700E-04,5.5800E-04,1.6200E-04,1.4600E-04,2.5800E-04,2.0700E-04,6.4600E-05,5.5600E-05 +8,6,0.602,0.05418,1.2300E-03,1.0900E-03,3.0700E-04,2.7600E-04,1.0000E-03,8.0000E-04,2.5000E-04,2.1500E-04 +8,7,1.207,0.10863,1.7600E-03,1.5700E-03,4.2700E-04,3.8400E-04,1.6200E-03,1.3000E-03,4.0600E-04,3.4900E-04 +8,8,2.362,0.21258,1.6400E-03,1.4600E-03,4.2500E-04,3.8200E-04,1.5600E-03,1.2500E-03,3.9000E-04,3.3500E-04 \ No newline at end of file diff --git a/imap_processing/tests/lo/test_lo_l1b.py b/imap_processing/tests/lo/test_lo_l1b.py index 2a8f23039..4291dbdd8 100644 --- a/imap_processing/tests/lo/test_lo_l1b.py +++ b/imap_processing/tests/lo/test_lo_l1b.py @@ -1882,10 +1882,11 @@ def test_missing_field_raises(self): with pytest.raises(KeyError, match="ifb_ctrl_star_sync"): get_star_bin_offset(nhk, int(nhk["epoch"].values[0])) - def test_unexpected_state_defaults(self): - """An unrecognized star-sync state falls back to the default offset (0.5).""" + def test_unexpected_state(self): + """An unrecognized star-sync state raises a KeyError.""" nhk = self._nhk(["??"]) - assert get_star_bin_offset(nhk, int(nhk["epoch"].values[0])) == 0.5 + with pytest.raises(KeyError): + assert get_star_bin_offset(nhk, int(nhk["epoch"].values[0])) == 0.5 class TestL1bStar: From e76bad3f6bbdeb5b3ba685f7b4344c91bd3ed37c Mon Sep 17 00:00:00 2001 From: Vineet Bansal Date: Wed, 17 Jun 2026 14:04:31 -0400 Subject: [PATCH 6/6] Building docs on a recent python where we have spiceypy --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 902eeefad..72fd96a68 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -3,7 +3,7 @@ version: 2 build: os: "ubuntu-22.04" tools: - python: "3.10" + python: "3.12" sphinx: configuration: docs/source/conf.py