Skip to content

Commit 9b032a3

Browse files
tmplummerCopilot
andauthored
2510 hi goodtimes set up cli call to processing 1 (#2779)
* Add hi goodtimes to Hi ProcessInstrument do_processing method Add test coverage for Hi goodtimes * Add high level Hi goodtimes functions and test coverage * Fix mocks after moving imports to global * Move loading of cdfs into cli.py for hi goodtimes * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Add Hi L1B Goodtimes product Add goodtimes.finalize_dataset accessor function Add yaml metadata for Hi Goodtimes * Correct hi goodtimes in cli module * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Address PR feedback for raising error if job fails and removal of try/except blocks * More PR feedback * Bug fixes from testing locally on flight data --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 3661b65 commit 9b032a3

6 files changed

Lines changed: 1178 additions & 49 deletions

File tree

imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ imap_hi_l1b_hk_attrs:
4949
Logical_source: imap_hi_l1b_{sensor}-hk
5050
Logical_source_description: IMAP-Hi Instrument Level-1B Housekeeping Data.
5151

52+
imap_hi_l1b_goodtimes_attrs:
53+
Data_type: L1B_GOODTIMES>Level-1B Good Times
54+
Logical_source: imap_hi_l1b_{sensor}-goodtimes
55+
Logical_source_description: IMAP-Hi Instrument Level-1B Good Times Data.
56+
5257
imap_hi_l1c_pset_attrs:
5358
Data_type: L1C_PSET>Level-1C Pointing Set
5459
Logical_source: imap_hi_l1c_{sensor}-pset

imap_processing/cdf/config/imap_hi_variable_attrs.yaml

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,4 +633,64 @@ hi_pset_label_vector_HAE:
633633
CATDESC: Label cartesian despun_z
634634
FIELDNAM: Label cartesian despun_z
635635
FORMAT: A5
636-
VAR_TYPE: metadata
636+
VAR_TYPE: metadata
637+
638+
# <=== L1B Goodtimes Attributes ===>
639+
hi_goodtimes_met:
640+
<<: *default_float64
641+
CATDESC: Mission Elapsed Time for each 8-spin histogram packet
642+
FIELDNAM: MET
643+
DEPEND_0: epoch
644+
LABLAXIS: MET
645+
UNITS: s
646+
VAR_TYPE: support_data
647+
VALIDMIN: 0
648+
VALIDMAX: 1.7976931348623157e+308
649+
650+
hi_goodtimes_cull_flags:
651+
<<: *default_uint8
652+
CATDESC: Cull flags indicating good (0) or bad (non-zero) times per spin bin
653+
FIELDNAM: Cull Flags
654+
DEPEND_0: epoch
655+
DEPEND_1: spin_bin
656+
LABL_PTR_1: spin_bin_label
657+
LABLAXIS: Cull Code
658+
UNITS: " "
659+
DISPLAY_TYPE: spectrogram
660+
VAR_NOTES: >
661+
Cull flags array with dimensions (epoch, spin_bin). Value of 0 indicates good time,
662+
non-zero values indicate bad times with specific cull reason codes.
663+
Cull code 1 (LOOSE) indicates times removed by quality filters.
664+
665+
hi_goodtimes_esa_step:
666+
<<: *default_uint8
667+
CATDESC: ESA energy step for each 8-spin histogram packet
668+
FIELDNAM: ESA Step
669+
DEPEND_0: epoch
670+
LABLAXIS: ESA Step
671+
UNITS: " "
672+
VAR_TYPE: support_data
673+
VALIDMIN: 1
674+
VALIDMAX: 10
675+
676+
hi_goodtimes_spin_bin:
677+
<<: *default_uint8
678+
CATDESC: Spin angle bin index
679+
FIELDNAM: Spin Bin
680+
FORMAT: I2
681+
LABLAXIS: Spin Bin
682+
UNITS: " "
683+
VAR_TYPE: support_data
684+
VALIDMIN: 0
685+
VALIDMAX: 89
686+
VAR_NOTES: >
687+
Spin angle bins numbered 0-89, covering 0-360 degrees of spacecraft spin.
688+
Each bin is 4 degrees wide.
689+
690+
hi_goodtimes_spin_bin_label:
691+
CATDESC: Label for spin bin
692+
FIELDNAM: Spin Bin Label
693+
DEPEND_1: spin_bin
694+
FORMAT: A3
695+
VAR_TYPE: metadata
696+

imap_processing/cli.py

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
from imap_processing.glows.l1a.glows_l1a import glows_l1a
5757
from imap_processing.glows.l1b.glows_l1b import glows_l1b, glows_l1b_de
5858
from imap_processing.glows.l2.glows_l2 import glows_l2
59-
from imap_processing.hi import hi_l1a, hi_l1b, hi_l1c, hi_l2
59+
from imap_processing.hi import hi_goodtimes, hi_l1a, hi_l1b, hi_l1c, hi_l2
6060
from imap_processing.hit.l1a.hit_l1a import hit_l1a
6161
from imap_processing.hit.l1b.hit_l1b import hit_l1b
6262
from imap_processing.hit.l2.hit_l2 import hit_l2
@@ -770,9 +770,9 @@ def do_processing(
770770
class Hi(ProcessInstrument):
771771
"""Process IMAP-Hi."""
772772

773-
def do_processing(
773+
def do_processing( # noqa: PLR0912
774774
self, dependencies: ProcessingInputCollection
775-
) -> list[xr.Dataset]:
775+
) -> list[xr.Dataset | Path]:
776776
"""
777777
Perform IMAP-Hi specific processing.
778778
@@ -789,6 +789,10 @@ def do_processing(
789789
print(f"Processing IMAP-Hi {self.data_level}")
790790
datasets: list[xr.Dataset] = []
791791

792+
# Check self.repointing is not None (for mypy type checking)
793+
if self.repointing is None:
794+
raise ValueError("Repointing must be provided for Hi processing.")
795+
792796
if self.data_level == "l1a":
793797
science_files = dependencies.get_file_paths(source="hi")
794798
if len(science_files) != 1:
@@ -801,6 +805,41 @@ def do_processing(
801805
l0_files = dependencies.get_file_paths(source="hi", descriptor="raw")
802806
if l0_files:
803807
datasets = hi_l1b.housekeeping(l0_files[0])
808+
elif "goodtimes" in self.descriptor:
809+
# Goodtimes processing
810+
l1b_de_paths = dependencies.get_file_paths(
811+
source="hi", data_type="l1b", descriptor="de"
812+
)
813+
if not l1b_de_paths:
814+
raise ValueError("No L1B DE files found for goodtimes processing")
815+
816+
l1b_hk_paths = dependencies.get_file_paths(
817+
source="hi", data_type="l1b", descriptor="hk"
818+
)
819+
if len(l1b_hk_paths) != 1:
820+
raise ValueError(
821+
f"Expected one L1B HK file, got {len(l1b_hk_paths)}"
822+
)
823+
824+
cal_prod_paths = dependencies.get_file_paths(
825+
data_type="ancillary", descriptor="cal-prod"
826+
)
827+
if len(cal_prod_paths) != 1:
828+
raise ValueError(
829+
f"Expected one cal-prod ancillary file, "
830+
f"got {len(cal_prod_paths)}"
831+
)
832+
833+
# Load CDFs before passing to hi_goodtimes
834+
l1b_de_datasets = [load_cdf(path) for path in l1b_de_paths]
835+
l1b_hk = load_cdf(l1b_hk_paths[0])
836+
837+
datasets = hi_goodtimes.hi_goodtimes(
838+
l1b_de_datasets,
839+
self.repointing,
840+
l1b_hk,
841+
cal_prod_paths[0],
842+
)
804843
else:
805844
l1a_de_file = dependencies.get_file_paths(
806845
source="hi", data_type="l1a", descriptor="de"
@@ -813,17 +852,21 @@ def do_processing(
813852
load_cdf(l1a_de_file), load_cdf(l1b_hk_file), esa_energies_csv
814853
)
815854
elif self.data_level == "l1c":
816-
science_paths = dependencies.get_file_paths(source="hi", data_type="l1b")
817-
if len(science_paths) != 1:
818-
raise ValueError(
819-
f"Expected only one science dependency. Got {science_paths}"
855+
if "pset" in self.descriptor:
856+
# L1C PSET processing
857+
science_paths = dependencies.get_file_paths(
858+
source="hi", data_type="l1b"
820859
)
821-
anc_paths = dependencies.get_file_paths(data_type="ancillary")
822-
if len(anc_paths) != 1:
823-
raise ValueError(
824-
f"Expected only one ancillary dependency. Got {anc_paths}"
825-
)
826-
datasets = hi_l1c.hi_l1c(load_cdf(science_paths[0]), anc_paths[0])
860+
if len(science_paths) != 1:
861+
raise ValueError(
862+
f"Expected only one science dependency. Got {science_paths}"
863+
)
864+
anc_paths = dependencies.get_file_paths(data_type="ancillary")
865+
if len(anc_paths) != 1:
866+
raise ValueError(
867+
f"Expected only one ancillary dependency. Got {anc_paths}"
868+
)
869+
datasets = hi_l1c.hi_l1c(load_cdf(science_paths[0]), anc_paths[0])
827870
elif self.data_level == "l2":
828871
science_paths = dependencies.get_file_paths(source="hi", data_type="l1c")
829872
anc_dependencies = dependencies.get_processing_inputs(data_type="ancillary")

0 commit comments

Comments
 (0)