imap-processing 0.7.0__py3-none-any.whl → 0.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of imap-processing might be problematic. Click here for more details.

Files changed (172) hide show
  1. imap_processing/__init__.py +1 -1
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/excel_to_xtce.py +36 -2
  4. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +1 -1
  5. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +145 -30
  6. imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +36 -36
  7. imap_processing/cdf/config/imap_hi_variable_attrs.yaml +136 -9
  8. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +14 -0
  9. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +63 -1
  10. imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +9 -0
  11. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +14 -7
  12. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +577 -235
  13. imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +326 -0
  14. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +33 -23
  15. imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +24 -28
  16. imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +1 -0
  17. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +137 -79
  18. imap_processing/cdf/config/imap_variable_schema.yaml +13 -0
  19. imap_processing/cdf/imap_cdf_manager.py +31 -27
  20. imap_processing/cdf/utils.py +3 -5
  21. imap_processing/cli.py +25 -14
  22. imap_processing/codice/codice_l1a.py +153 -63
  23. imap_processing/codice/constants.py +10 -10
  24. imap_processing/codice/decompress.py +10 -11
  25. imap_processing/codice/utils.py +1 -0
  26. imap_processing/glows/l1a/glows_l1a.py +1 -2
  27. imap_processing/glows/l1b/glows_l1b.py +3 -3
  28. imap_processing/glows/l1b/glows_l1b_data.py +59 -37
  29. imap_processing/glows/l2/glows_l2_data.py +123 -0
  30. imap_processing/hi/l1a/hi_l1a.py +4 -4
  31. imap_processing/hi/l1a/histogram.py +107 -109
  32. imap_processing/hi/l1a/science_direct_event.py +92 -225
  33. imap_processing/hi/l1b/hi_l1b.py +85 -11
  34. imap_processing/hi/l1c/hi_l1c.py +23 -1
  35. imap_processing/hi/packet_definitions/TLM_HI_COMBINED_SCI.xml +3994 -0
  36. imap_processing/hi/utils.py +1 -1
  37. imap_processing/hit/hit_utils.py +221 -0
  38. imap_processing/hit/l0/constants.py +118 -0
  39. imap_processing/hit/l0/decom_hit.py +100 -156
  40. imap_processing/hit/l1a/hit_l1a.py +170 -184
  41. imap_processing/hit/l1b/hit_l1b.py +33 -153
  42. imap_processing/ialirt/l0/process_codicelo.py +153 -0
  43. imap_processing/ialirt/l0/process_hit.py +5 -5
  44. imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +281 -0
  45. imap_processing/ialirt/process_ephemeris.py +212 -0
  46. imap_processing/idex/idex_l1a.py +65 -84
  47. imap_processing/idex/idex_l1b.py +192 -0
  48. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -0
  49. imap_processing/idex/packet_definitions/idex_packet_definition.xml +97 -595
  50. imap_processing/lo/l0/decompression_tables/decompression_tables.py +17 -1
  51. imap_processing/lo/l0/lo_science.py +45 -13
  52. imap_processing/lo/l1a/lo_l1a.py +76 -8
  53. imap_processing/lo/packet_definitions/lo_xtce.xml +8344 -1849
  54. imap_processing/mag/l0/decom_mag.py +4 -3
  55. imap_processing/mag/l1a/mag_l1a.py +12 -13
  56. imap_processing/mag/l1a/mag_l1a_data.py +1 -2
  57. imap_processing/mag/l1b/mag_l1b.py +90 -7
  58. imap_processing/spice/geometry.py +156 -16
  59. imap_processing/spice/time.py +144 -2
  60. imap_processing/swapi/l1/swapi_l1.py +4 -4
  61. imap_processing/swapi/l2/swapi_l2.py +1 -1
  62. imap_processing/swapi/packet_definitions/swapi_packet_definition.xml +1535 -446
  63. imap_processing/swe/l1b/swe_l1b_science.py +8 -8
  64. imap_processing/swe/l2/swe_l2.py +134 -17
  65. imap_processing/tests/ccsds/test_data/expected_output.xml +2 -1
  66. imap_processing/tests/ccsds/test_excel_to_xtce.py +4 -4
  67. imap_processing/tests/cdf/test_imap_cdf_manager.py +0 -10
  68. imap_processing/tests/codice/conftest.py +1 -17
  69. imap_processing/tests/codice/data/imap_codice_l0_raw_20241110_v001.pkts +0 -0
  70. imap_processing/tests/codice/test_codice_l0.py +8 -2
  71. imap_processing/tests/codice/test_codice_l1a.py +127 -107
  72. imap_processing/tests/codice/test_codice_l1b.py +1 -0
  73. imap_processing/tests/codice/test_decompress.py +7 -7
  74. imap_processing/tests/conftest.py +100 -58
  75. imap_processing/tests/glows/conftest.py +6 -0
  76. imap_processing/tests/glows/test_glows_l1b.py +9 -9
  77. imap_processing/tests/glows/test_glows_l1b_data.py +9 -9
  78. imap_processing/tests/hi/test_data/l0/H90_NHK_20241104.bin +0 -0
  79. imap_processing/tests/hi/test_data/l0/H90_sci_cnt_20241104.bin +0 -0
  80. imap_processing/tests/hi/test_data/l0/H90_sci_de_20241104.bin +0 -0
  81. imap_processing/tests/hi/test_data/l1a/imap_hi_l1a_45sensor-de_20250415_v000.cdf +0 -0
  82. imap_processing/tests/hi/test_hi_l1b.py +73 -3
  83. imap_processing/tests/hi/test_hi_l1c.py +10 -2
  84. imap_processing/tests/hi/test_l1a.py +31 -58
  85. imap_processing/tests/hi/test_science_direct_event.py +58 -0
  86. imap_processing/tests/hi/test_utils.py +4 -3
  87. imap_processing/tests/hit/test_data/sci_sample1.ccsds +0 -0
  88. imap_processing/tests/hit/{test_hit_decom.py → test_decom_hit.py} +95 -36
  89. imap_processing/tests/hit/test_hit_l1a.py +299 -179
  90. imap_processing/tests/hit/test_hit_l1b.py +231 -24
  91. imap_processing/tests/hit/test_hit_utils.py +218 -0
  92. imap_processing/tests/hit/validation_data/hskp_sample_eu.csv +89 -0
  93. imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +29 -0
  94. imap_processing/tests/ialirt/test_data/l0/apid01152.tlm +0 -0
  95. imap_processing/tests/ialirt/test_data/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  96. imap_processing/tests/ialirt/unit/test_process_codicelo.py +106 -0
  97. imap_processing/tests/ialirt/unit/test_process_ephemeris.py +109 -0
  98. imap_processing/tests/ialirt/unit/test_process_hit.py +9 -6
  99. imap_processing/tests/idex/conftest.py +2 -2
  100. imap_processing/tests/idex/imap_idex_l0_raw_20231214_v001.pkts +0 -0
  101. imap_processing/tests/idex/impact_14_tof_high_data.txt +4444 -4444
  102. imap_processing/tests/idex/test_idex_l0.py +4 -4
  103. imap_processing/tests/idex/test_idex_l1a.py +8 -2
  104. imap_processing/tests/idex/test_idex_l1b.py +126 -0
  105. imap_processing/tests/lo/test_lo_l1a.py +7 -16
  106. imap_processing/tests/lo/test_lo_science.py +69 -5
  107. imap_processing/tests/lo/test_pkts/imap_lo_l0_raw_20240803_v002.pkts +0 -0
  108. imap_processing/tests/lo/validation_data/Instrument_FM1_T104_R129_20240803_ILO_SCI_DE_dec_DN_with_fills.csv +1999 -0
  109. imap_processing/tests/mag/imap_mag_l1a_norm-magi_20251017_v001.cdf +0 -0
  110. imap_processing/tests/mag/test_mag_l1b.py +97 -7
  111. imap_processing/tests/spice/test_data/imap_ena_sim_metakernel.template +3 -1
  112. imap_processing/tests/spice/test_geometry.py +115 -9
  113. imap_processing/tests/spice/test_time.py +135 -6
  114. imap_processing/tests/swapi/test_swapi_decom.py +75 -69
  115. imap_processing/tests/swapi/test_swapi_l1.py +4 -4
  116. imap_processing/tests/swe/conftest.py +33 -0
  117. imap_processing/tests/swe/l1_validation/swe_l0_unpacked-data_20240510_v001_VALIDATION_L1B_v3.dat +4332 -0
  118. imap_processing/tests/swe/test_swe_l1b.py +29 -8
  119. imap_processing/tests/swe/test_swe_l2.py +64 -8
  120. imap_processing/tests/test_utils.py +2 -2
  121. imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3314 -3314
  122. imap_processing/tests/ultra/test_data/l1/dps_exposure_helio_45_E12.cdf +0 -0
  123. imap_processing/tests/ultra/test_data/l1/dps_exposure_helio_45_E24.cdf +0 -0
  124. imap_processing/tests/ultra/unit/test_de.py +113 -0
  125. imap_processing/tests/ultra/unit/test_spatial_utils.py +125 -0
  126. imap_processing/tests/ultra/unit/test_ultra_l1b.py +27 -3
  127. imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +31 -10
  128. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +55 -35
  129. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +10 -68
  130. imap_processing/ultra/constants.py +12 -3
  131. imap_processing/ultra/l1b/de.py +168 -30
  132. imap_processing/ultra/l1b/ultra_l1b_annotated.py +24 -10
  133. imap_processing/ultra/l1b/ultra_l1b_extended.py +46 -80
  134. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +60 -144
  135. imap_processing/ultra/utils/spatial_utils.py +221 -0
  136. {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/METADATA +15 -14
  137. {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/RECORD +142 -139
  138. imap_processing/cdf/cdf_attribute_manager.py +0 -322
  139. imap_processing/cdf/config/shared/default_global_cdf_attrs_schema.yaml +0 -246
  140. imap_processing/cdf/config/shared/default_variable_cdf_attrs_schema.yaml +0 -466
  141. imap_processing/hi/l0/decom_hi.py +0 -24
  142. imap_processing/hi/packet_definitions/hi_packet_definition.xml +0 -482
  143. imap_processing/hit/l0/data_classes/housekeeping.py +0 -240
  144. imap_processing/hit/l0/data_classes/science_packet.py +0 -259
  145. imap_processing/hit/l0/utils/hit_base.py +0 -57
  146. imap_processing/tests/cdf/shared/default_global_cdf_attrs_schema.yaml +0 -246
  147. imap_processing/tests/cdf/shared/default_variable_cdf_attrs_schema.yaml +0 -466
  148. imap_processing/tests/cdf/test_cdf_attribute_manager.py +0 -353
  149. imap_processing/tests/codice/data/imap_codice_l0_hi-counters-aggregated_20240429_v001.pkts +0 -0
  150. imap_processing/tests/codice/data/imap_codice_l0_hi-counters-singles_20240429_v001.pkts +0 -0
  151. imap_processing/tests/codice/data/imap_codice_l0_hi-omni_20240429_v001.pkts +0 -0
  152. imap_processing/tests/codice/data/imap_codice_l0_hi-pha_20240429_v001.pkts +0 -0
  153. imap_processing/tests/codice/data/imap_codice_l0_hi-sectored_20240429_v001.pkts +0 -0
  154. imap_processing/tests/codice/data/imap_codice_l0_hskp_20100101_v001.pkts +0 -0
  155. imap_processing/tests/codice/data/imap_codice_l0_lo-counters-aggregated_20240429_v001.pkts +0 -0
  156. imap_processing/tests/codice/data/imap_codice_l0_lo-counters-singles_20240429_v001.pkts +0 -0
  157. imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-angular_20240429_v001.pkts +0 -0
  158. imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-priority_20240429_v001.pkts +0 -0
  159. imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-species_20240429_v001.pkts +0 -0
  160. imap_processing/tests/codice/data/imap_codice_l0_lo-pha_20240429_v001.pkts +0 -0
  161. imap_processing/tests/codice/data/imap_codice_l0_lo-sw-angular_20240429_v001.pkts +0 -0
  162. imap_processing/tests/codice/data/imap_codice_l0_lo-sw-priority_20240429_v001.pkts +0 -0
  163. imap_processing/tests/codice/data/imap_codice_l0_lo-sw-species_20240429_v001.pkts +0 -0
  164. imap_processing/tests/hi/test_decom.py +0 -55
  165. imap_processing/tests/hi/test_l1a_sci_de.py +0 -72
  166. imap_processing/tests/idex/imap_idex_l0_raw_20230725_v001.pkts +0 -0
  167. imap_processing/tests/mag/imap_mag_l1a_burst-magi_20231025_v001.cdf +0 -0
  168. /imap_processing/{hi/l0/__init__.py → tests/glows/test_glows_l2_data.py} +0 -0
  169. /imap_processing/tests/hit/test_data/{imap_hit_l0_hk_20100105_v001.pkts → imap_hit_l0_raw_20100105_v001.pkts} +0 -0
  170. {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/LICENSE +0 -0
  171. {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/WHEEL +0 -0
  172. {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/entry_points.txt +0 -0
@@ -1,52 +1,259 @@
1
+ import pandas as pd
1
2
  import pytest
2
3
  import xarray as xr
3
4
 
4
5
  from imap_processing import imap_module_directory
5
- from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
6
6
  from imap_processing.hit.l1a import hit_l1a
7
7
  from imap_processing.hit.l1b import hit_l1b
8
8
 
9
9
 
10
+ @pytest.fixture(scope="module")
11
+ def packet_filepath():
12
+ """Set path to test data file"""
13
+ return (
14
+ imap_module_directory / "tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts"
15
+ )
16
+
17
+
10
18
  @pytest.fixture()
11
- def dependency():
12
- """Get L1A data from test packet file"""
19
+ def dependencies(packet_filepath):
20
+ """Get dependencies for L1B processing"""
21
+ # Create dictionary of dependencies and add CCSDS packet file
22
+ data_dict = {"imap_hit_l0_raw": packet_filepath}
23
+ # Add L1A datasets
24
+ l1a_datasets = hit_l1a.hit_l1a(packet_filepath, "001")
25
+ for dataset in l1a_datasets:
26
+ data_dict[dataset.attrs["Logical_source"]] = dataset
27
+ return data_dict
13
28
 
14
- packet_filepath = (
15
- imap_module_directory / "tests/hit/test_data/imap_hit_l0_hk_20100105_v001.pkts"
16
- )
17
- l1a_data = hit_l1a.hit_l1a(packet_filepath, "001")[0]
18
29
 
19
- return l1a_data
30
+ @pytest.fixture()
31
+ def hk_dataset(dependencies):
32
+ """Get the housekeeping dataset"""
33
+ datasets = hit_l1b.hit_l1b(dependencies, "001")
34
+ for dataset in datasets:
35
+ if dataset.attrs["Logical_source"] == "imap_hit_l1b_hk":
36
+ return dataset
37
+
38
+
39
+ def test_hit_l1b_hk_dataset_variables(hk_dataset):
40
+ """Test the variables in the housekeeping dataset"""
41
+ # Define the keys that should have dropped from the housekeeping dataset
42
+ dropped_keys = {
43
+ "pkt_apid",
44
+ "sc_tick",
45
+ "version",
46
+ "type",
47
+ "sec_hdr_flg",
48
+ "seq_flgs",
49
+ "src_seq_ctr",
50
+ "pkt_len",
51
+ "hskp_spare1",
52
+ "hskp_spare2",
53
+ "hskp_spare3",
54
+ "hskp_spare4",
55
+ "hskp_spare5",
56
+ }
57
+ # Define the keys that should be present in the housekeeping dataset
58
+ valid_keys = {
59
+ "heater_on",
60
+ "fsw_version_b",
61
+ "ebox_m12va",
62
+ "phasic_stat",
63
+ "ebox_3d4vd",
64
+ "ebox_p2d0vd",
65
+ "temp1",
66
+ "last_bad_seq_num",
67
+ "ebox_m5d7va",
68
+ "ebox_p12va",
69
+ "table_status",
70
+ "enable_50khz",
71
+ "mram_disabled",
72
+ "temp3",
73
+ "preamp_l1a",
74
+ "l2ab_bias",
75
+ "l34b_bias",
76
+ "fsw_version_c",
77
+ "num_evnt_last_hk",
78
+ "dac1_enable",
79
+ "preamp_l234b",
80
+ "analog_temp",
81
+ "fee_running",
82
+ "fsw_version_a",
83
+ "num_errors",
84
+ "test_pulser_on",
85
+ "dac0_enable",
86
+ "preamp_l1b",
87
+ "l1ab_bias",
88
+ "l34a_bias",
89
+ "leak_i",
90
+ "last_good_cmd",
91
+ "lvps_temp",
92
+ "idpu_temp",
93
+ "temp2",
94
+ "preamp_l234a",
95
+ "last_good_seq_num",
96
+ "num_good_cmds",
97
+ "heater_control",
98
+ "hvps_temp",
99
+ "ebox_p5d7va",
100
+ "spin_period_long",
101
+ "enable_hvps",
102
+ "temp0",
103
+ "spin_period_short",
104
+ "dyn_thresh_lvl",
105
+ "num_bad_cmds",
106
+ "adc_mode",
107
+ "ebox_5d1vd",
108
+ "active_heater",
109
+ "last_error_num",
110
+ "last_bad_cmd",
111
+ "ref_p5v",
112
+ "code_checksum",
113
+ "mode",
114
+ }
115
+ # Check that the dataset has the correct variables
116
+ assert valid_keys == set(hk_dataset.data_vars.keys())
117
+ assert set(dropped_keys).isdisjoint(set(hk_dataset.data_vars.keys()))
118
+
119
+
120
+ def test_hit_l1b_hk_dataset_attributes(hk_dataset):
121
+ """Test the attributes, dims, and coords in the housekeeping dataset"""
122
+ # TODO consider removing this test since it may be hard to upkeep if
123
+ # attributes change
124
+ # Define the housekeeping dataset attributes
125
+ dataset_attrs = {
126
+ "Acknowledgement": "Please acknowledge the IMAP Mission Principal "
127
+ "Investigator, Prof. David J. McComas of Princeton "
128
+ "University.\n",
129
+ "Data_level": "1B",
130
+ "Data_type": "L1B_HK>Level-1B Housekeeping",
131
+ "Data_version": "001",
132
+ "Descriptor": "HIT>IMAP High-energy Ion Telescope",
133
+ "Discipline": "Solar Physics>Heliospheric Physics",
134
+ "File_naming_convention": "source_descriptor_datatype_yyyyMMdd_vNNN",
135
+ "HTTP_LINK": "https://imap.princeton.edu/",
136
+ "Instrument_type": "Particles (space)",
137
+ "LINK_TITLE": "IMAP The Interstellar Mapping and Acceleration Probe",
138
+ "Logical_file_id": None,
139
+ "Logical_source": "imap_hit_l1b_hk",
140
+ "Logical_source_description": "IMAP Mission HIT Instrument Level-1B "
141
+ "Housekeeping Data.",
142
+ "Mission_group": "IMAP",
143
+ "PI_affiliation": "Princeton University",
144
+ "PI_name": "Prof. David J. McComas",
145
+ "Project": "STP>Solar Terrestrial Probes",
146
+ "Rules_of_use": "All IMAP data products are publicly released and citable for "
147
+ "use in publications. Please consult the IMAP team "
148
+ "publications and personnel for further details on "
149
+ "production, processing, and usage of these data.\n",
150
+ "Source_name": "IMAP>Interstellar Mapping and Acceleration Probe",
151
+ "TEXT": "The High-energy Ion Telescope (HIT) measures the elemental "
152
+ "composition, energy spectra, angle distributions, and arrival "
153
+ "times of high-energy ions. HIT delivers full-sky coverage from "
154
+ "a wide instrument field-of-view (FOV) to enable a high resolution "
155
+ "of ion measurements, such as observing shock-accelerated ions, "
156
+ "determining the origin of the solar energetic particles (SEPs) "
157
+ "spectra, and resolving particle transport in the heliosphere. "
158
+ "See https://imap.princeton.edu/instruments/hit for more details.\n",
159
+ }
160
+
161
+ # Define the coordinates and dimensions. Both have equivalent values
162
+ dataset_coords_dims = {"epoch", "adc_channels", "adc_channels_label"}
20
163
 
164
+ # Check that the dataset has the correct attributes, coordinates, and dimensions
165
+ assert hk_dataset.attrs == dataset_attrs
166
+ assert hk_dataset.coords.keys() == dataset_coords_dims
21
167
 
22
- def test_create_hk_dataset():
23
- """Test creating housekeeping L1B dataset
24
168
 
25
- Creates a xarray dataset for housekeeping data
169
+ def test_validate_l1b_housekeeping_data(hk_dataset):
170
+ """Validate the housekeeping dataset created by the L1B processing.
171
+
172
+ Parameters
173
+ ----------
174
+ hk_dataset : xr.Dataset
175
+ Housekeeping dataset created by the L1B processing.
26
176
  """
177
+ # TODO: finish test. HIT will provide an updated validation file to fix issues:
178
+ # - some fields have strings as values but in the processed data they're integers
179
+ # - Some columns have blank cells where there should be data
180
+
181
+ # Load the validation data
182
+ validation_file = (
183
+ imap_module_directory / "tests/hit/validation_data/hskp_sample_eu.csv"
184
+ )
185
+ validation_data = pd.read_csv(validation_file)
186
+ validation_data.columns = validation_data.columns.str.lower().str.strip()
27
187
 
28
- # create the attribute manager for this data level
29
- attr_mgr = ImapCdfAttributes()
30
- attr_mgr.add_instrument_global_attrs(instrument="hit")
31
- attr_mgr.add_instrument_variable_attrs(instrument="hit", level="l1b")
32
- attr_mgr.add_global_attribute("Data_version", "001")
188
+ # Get a list of leak columns in ascending order
189
+ # (LEAK_I_00, LEAK_I_01, ..., LEAK_I_63)
190
+ # and group values into a single column
191
+ leak_columns = [
192
+ col for col in validation_data.columns if col.startswith("leak_i_")
193
+ ][::-1]
194
+ validation_data["leak_i"] = validation_data[leak_columns].apply(
195
+ lambda row: row.values, axis=1
196
+ )
197
+ validation_data.drop(columns=leak_columns, inplace=True)
198
+
199
+ # Define the keys that should have dropped from the housekeeping dataset
200
+ dropped_fields = {
201
+ "pkt_apid",
202
+ "sc_tick",
203
+ "version",
204
+ "type",
205
+ "sec_hdr_flg",
206
+ "seq_flgs",
207
+ "src_seq_ctr",
208
+ "pkt_len",
209
+ "hskp_spare1",
210
+ "hskp_spare2",
211
+ "hskp_spare3",
212
+ "hskp_spare4",
213
+ "hskp_spare5",
214
+ }
215
+
216
+ # Check that dropped variables are not in the dataset
217
+ assert set(dropped_fields).isdisjoint(set(hk_dataset.data_vars.keys()))
33
218
 
34
- l1b_hk_dataset = hit_l1b.create_hk_dataset(attr_mgr)
35
- assert isinstance(l1b_hk_dataset, xr.Dataset)
219
+ # TODO: uncomment block after new validation data is provided
220
+ # Define the keys that should be ignored in the validation
221
+ # like ccsds headers
222
+ # ignore_validation_fields = {
223
+ # "ccsds_version",
224
+ # "ccsds_type",
225
+ # "ccsds_sec_hdr_flag",
226
+ # "ccsds_appid",
227
+ # "ccsds_grp_flag",
228
+ # "ccsds_seq_cnt",
229
+ # "ccsds_length",
230
+ # "sc_tick",
231
+ # }
36
232
 
233
+ # # Compare the housekeeping dataset with the expected validation data
234
+ # for field in validation_data.columns:
235
+ # if field not in ignore_validation_fields:
236
+ # print(field)
237
+ # assert field in hk_dataset.data_vars.keys()
238
+ # for pkt in range(validation_data.shape[0]):
239
+ # assert np.array_equal(
240
+ # hk_dataset[field][pkt].data, validation_data[field][pkt]
241
+ # )
37
242
 
38
- def test_hit_l1b(dependency):
243
+
244
+ def test_hit_l1b(dependencies):
39
245
  """Test creating L1B CDF files
40
246
 
41
- Creates a CDF file for each L1B product and stores
42
- their filepaths in a list
247
+ Creates a list of xarray datasets for each L1B product
43
248
 
44
249
  Parameters
45
250
  ----------
46
- dependency : xr.dataset
47
- L1A data
251
+ dependencies : dict
252
+ Dictionary of L1A datasets and CCSDS packet file path
48
253
  """
49
- datasets = hit_l1b.hit_l1b(dependency, "001")
254
+ # TODO: update assertions after science data processing is completed
255
+ datasets = hit_l1b.hit_l1b(dependencies, "001")
256
+
50
257
  assert len(datasets) == 1
51
258
  assert isinstance(datasets[0], xr.Dataset)
52
259
  assert datasets[0].attrs["Logical_source"] == "imap_hit_l1b_hk"
@@ -0,0 +1,218 @@
1
+ import numpy as np
2
+ import pytest
3
+ import xarray as xr
4
+
5
+ from imap_processing import imap_module_directory
6
+ from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
7
+ from imap_processing.hit.hit_utils import (
8
+ HitAPID,
9
+ concatenate_leak_variables,
10
+ get_attribute_manager,
11
+ get_datasets_by_apid,
12
+ process_housekeeping_data,
13
+ )
14
+
15
+
16
+ @pytest.fixture(scope="module")
17
+ def packet_filepath():
18
+ """Set path to test data file"""
19
+ return (
20
+ imap_module_directory / "tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts"
21
+ )
22
+
23
+
24
+ @pytest.fixture(scope="module")
25
+ def attribute_manager():
26
+ """Create the attribute manager"""
27
+ data_version = "001"
28
+ level = "l1a"
29
+ attr_mgr = get_attribute_manager(data_version, level)
30
+ return attr_mgr
31
+
32
+
33
+ @pytest.fixture(scope="module")
34
+ def housekeeping_dataset(packet_filepath):
35
+ """Get the housekeeping dataset"""
36
+ # Unpack ccsds file to xarray datasets
37
+ datasets_by_apid = get_datasets_by_apid(packet_filepath)
38
+ return datasets_by_apid[HitAPID.HIT_HSKP]
39
+
40
+
41
+ def test_get_datasets_by_apid(packet_filepath):
42
+ result = get_datasets_by_apid(packet_filepath)
43
+
44
+ assert isinstance(result, dict)
45
+ assert HitAPID.HIT_HSKP in result
46
+ # assert HitAPID.HIT_SCIENCE in result
47
+
48
+
49
+ def test_get_attribute_manager():
50
+ data_version = "001"
51
+ level = "l1a"
52
+ attr_mgr = get_attribute_manager(data_version, level)
53
+
54
+ assert isinstance(attr_mgr, ImapCdfAttributes)
55
+
56
+
57
+ def test_concatenate_leak_variables(housekeeping_dataset):
58
+ """Test concatenation of leak_i variables"""
59
+
60
+ # Create data array for leak_i dependency
61
+ adc_channels = xr.DataArray(
62
+ np.arange(64, dtype=np.uint8),
63
+ name="adc_channels",
64
+ dims=["adc_channels"],
65
+ )
66
+
67
+ updated_dataset = concatenate_leak_variables(housekeeping_dataset, adc_channels)
68
+
69
+ # Assertions
70
+ # ----------------
71
+ assert "leak_i" in updated_dataset
72
+ assert updated_dataset["leak_i"].shape == (88, 64)
73
+ for i in range(64):
74
+ # Check if the values in the `leak_i` variable match the values in
75
+ # the original `leak_i_XX` variable.
76
+ # - First access the `leak_i` variable in the `updated_dataset`.
77
+ # The [:, i] selects all rows (`:`) and the `i`-th column of the `leak_i`
78
+ # variable.
79
+ # - Then access the `leak_i_XX` variable in the `housekeeping_dataset`.
80
+ # The `f"leak_i_{i:02d}"` selects the variable with the name `leak_i_XX`
81
+ # where `XX` is the `i`-th value.
82
+ # - Compare values
83
+ np.testing.assert_array_equal(
84
+ updated_dataset["leak_i"][:, i], housekeeping_dataset[f"leak_i_{i:02d}"]
85
+ )
86
+
87
+
88
+ def test_process_housekeeping(housekeeping_dataset, attribute_manager):
89
+ """Test processing of housekeeping dataset"""
90
+
91
+ # Call the function
92
+ processed_hskp_dataset = process_housekeeping_data(
93
+ housekeeping_dataset, attribute_manager, "imap_hit_l1a_hk"
94
+ )
95
+
96
+ # Define the keys that should have dropped from the dataset
97
+ dropped_keys = {
98
+ "pkt_apid",
99
+ "sc_tick",
100
+ "version",
101
+ "type",
102
+ "sec_hdr_flg",
103
+ "seq_flgs",
104
+ "src_seq_ctr",
105
+ "pkt_len",
106
+ "hskp_spare1",
107
+ "hskp_spare2",
108
+ "hskp_spare3",
109
+ "hskp_spare4",
110
+ "hskp_spare5",
111
+ }
112
+ # Define the keys that should be present
113
+ valid_keys = {
114
+ "heater_on",
115
+ "fsw_version_b",
116
+ "ebox_m12va",
117
+ "phasic_stat",
118
+ "ebox_3d4vd",
119
+ "ebox_p2d0vd",
120
+ "temp1",
121
+ "last_bad_seq_num",
122
+ "ebox_m5d7va",
123
+ "ebox_p12va",
124
+ "table_status",
125
+ "enable_50khz",
126
+ "mram_disabled",
127
+ "temp3",
128
+ "preamp_l1a",
129
+ "l2ab_bias",
130
+ "l34b_bias",
131
+ "fsw_version_c",
132
+ "num_evnt_last_hk",
133
+ "dac1_enable",
134
+ "preamp_l234b",
135
+ "analog_temp",
136
+ "fee_running",
137
+ "fsw_version_a",
138
+ "num_errors",
139
+ "test_pulser_on",
140
+ "dac0_enable",
141
+ "preamp_l1b",
142
+ "l1ab_bias",
143
+ "l34a_bias",
144
+ "leak_i",
145
+ "last_good_cmd",
146
+ "lvps_temp",
147
+ "idpu_temp",
148
+ "temp2",
149
+ "preamp_l234a",
150
+ "last_good_seq_num",
151
+ "num_good_cmds",
152
+ "heater_control",
153
+ "hvps_temp",
154
+ "ebox_p5d7va",
155
+ "spin_period_long",
156
+ "enable_hvps",
157
+ "temp0",
158
+ "spin_period_short",
159
+ "dyn_thresh_lvl",
160
+ "num_bad_cmds",
161
+ "adc_mode",
162
+ "ebox_5d1vd",
163
+ "active_heater",
164
+ "last_error_num",
165
+ "last_bad_cmd",
166
+ "ref_p5v",
167
+ "code_checksum",
168
+ "mode",
169
+ }
170
+
171
+ # Define the dataset attributes
172
+ dataset_attrs = {
173
+ "Acknowledgement": "Please acknowledge the IMAP Mission Principal "
174
+ "Investigator, Prof. David J. McComas of Princeton "
175
+ "University.\n",
176
+ "Data_level": "1A",
177
+ "Data_type": "L1A_HK>Level-1A Housekeeping",
178
+ "Data_version": "001",
179
+ "Descriptor": "HIT>IMAP High-energy Ion Telescope",
180
+ "Discipline": "Solar Physics>Heliospheric Physics",
181
+ "File_naming_convention": "source_descriptor_datatype_yyyyMMdd_vNNN",
182
+ "HTTP_LINK": "https://imap.princeton.edu/",
183
+ "Instrument_type": "Particles (space)",
184
+ "LINK_TITLE": "IMAP The Interstellar Mapping and Acceleration Probe",
185
+ "Logical_file_id": None,
186
+ "Logical_source": "imap_hit_l1a_hk",
187
+ "Logical_source_description": "IMAP Mission HIT Instrument Level-1A "
188
+ "Housekeeping Data.",
189
+ "Mission_group": "IMAP",
190
+ "PI_affiliation": "Princeton University",
191
+ "PI_name": "Prof. David J. McComas",
192
+ "Project": "STP>Solar Terrestrial Probes",
193
+ "Rules_of_use": "All IMAP data products are publicly released and citable for "
194
+ "use in publications. Please consult the IMAP team "
195
+ "publications and personnel for further details on "
196
+ "production, processing, and usage of these data.\n",
197
+ "Source_name": "IMAP>Interstellar Mapping and Acceleration Probe",
198
+ "TEXT": "The High-energy Ion Telescope (HIT) measures the elemental "
199
+ "composition, energy spectra, angle distributions, and arrival "
200
+ "times of high-energy ions. HIT delivers full-sky coverage from "
201
+ "a wide instrument field-of-view (FOV) to enable a high resolution "
202
+ "of ion measurements, such as observing shock-accelerated ions, "
203
+ "determining the origin of the solar energetic particles (SEPs) "
204
+ "spectra, and resolving particle transport in the heliosphere. "
205
+ "See https://imap.princeton.edu/instruments/hit for more details.\n",
206
+ }
207
+
208
+ # Define the coordinates and dimensions. Both have equivalent values
209
+ dataset_coords_dims = {"epoch", "adc_channels", "adc_channels_label"}
210
+
211
+ # Assertions
212
+ # ----------------
213
+ # Check that the dataset has the correct variables
214
+ assert valid_keys == set(processed_hskp_dataset.data_vars.keys())
215
+ assert set(dropped_keys).isdisjoint(set(processed_hskp_dataset.data_vars.keys()))
216
+ # Check that the dataset has the correct attributes, coordinates, and dimensions
217
+ assert processed_hskp_dataset.attrs == dataset_attrs
218
+ assert processed_hskp_dataset.coords.keys() == dataset_coords_dims