imap-processing 0.11.0__py3-none-any.whl → 0.12.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 (288) hide show
  1. imap_processing/__init__.py +10 -11
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/excel_to_xtce.py +65 -16
  4. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +6 -28
  5. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +365 -42
  6. imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +0 -5
  7. imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +10 -11
  8. imap_processing/cdf/config/imap_hi_variable_attrs.yaml +17 -19
  9. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +26 -13
  10. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +106 -116
  11. imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +120 -145
  12. imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +14 -0
  13. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +6 -9
  14. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +1 -1
  15. imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +0 -12
  16. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +1 -1
  17. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +9 -21
  18. imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml +361 -0
  19. imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml +160 -0
  20. imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +160 -0
  21. imap_processing/cdf/config/imap_spacecraft_global_cdf_attrs.yaml +18 -0
  22. imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml +40 -0
  23. imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +1 -5
  24. imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +12 -4
  25. imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +16 -2
  26. imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +48 -52
  27. imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +71 -47
  28. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +2 -14
  29. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +51 -2
  30. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +29 -14
  31. imap_processing/cdf/utils.py +13 -7
  32. imap_processing/cli.py +23 -8
  33. imap_processing/codice/codice_l1a.py +207 -85
  34. imap_processing/codice/constants.py +1322 -568
  35. imap_processing/codice/decompress.py +2 -6
  36. imap_processing/ena_maps/ena_maps.py +480 -116
  37. imap_processing/ena_maps/utils/coordinates.py +19 -0
  38. imap_processing/ena_maps/utils/map_utils.py +14 -17
  39. imap_processing/ena_maps/utils/spatial_utils.py +45 -47
  40. imap_processing/hi/l1a/hi_l1a.py +24 -18
  41. imap_processing/hi/l1a/histogram.py +0 -1
  42. imap_processing/hi/l1a/science_direct_event.py +6 -8
  43. imap_processing/hi/l1b/hi_l1b.py +31 -39
  44. imap_processing/hi/l1c/hi_l1c.py +405 -17
  45. imap_processing/hi/utils.py +58 -12
  46. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt0-factors_20250219_v002.csv +205 -0
  47. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt1-factors_20250219_v002.csv +205 -0
  48. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt2-factors_20250219_v002.csv +205 -0
  49. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt3-factors_20250219_v002.csv +205 -0
  50. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-summed-dt0-factors_20250219_v002.csv +68 -0
  51. imap_processing/hit/hit_utils.py +173 -1
  52. imap_processing/hit/l0/constants.py +20 -11
  53. imap_processing/hit/l0/decom_hit.py +18 -4
  54. imap_processing/hit/l1a/hit_l1a.py +45 -54
  55. imap_processing/hit/l1b/constants.py +317 -0
  56. imap_processing/hit/l1b/hit_l1b.py +367 -18
  57. imap_processing/hit/l2/constants.py +281 -0
  58. imap_processing/hit/l2/hit_l2.py +614 -0
  59. imap_processing/hit/packet_definitions/hit_packet_definitions.xml +1323 -71
  60. imap_processing/ialirt/l0/mag_l0_ialirt_data.py +155 -0
  61. imap_processing/ialirt/l0/parse_mag.py +246 -0
  62. imap_processing/ialirt/l0/process_swe.py +252 -0
  63. imap_processing/ialirt/packet_definitions/ialirt.xml +7 -3
  64. imap_processing/ialirt/packet_definitions/ialirt_mag.xml +115 -0
  65. imap_processing/ialirt/utils/grouping.py +114 -0
  66. imap_processing/ialirt/utils/time.py +29 -0
  67. imap_processing/idex/atomic_masses.csv +22 -0
  68. imap_processing/idex/decode.py +2 -2
  69. imap_processing/idex/idex_constants.py +25 -0
  70. imap_processing/idex/idex_l1a.py +6 -7
  71. imap_processing/idex/idex_l1b.py +4 -31
  72. imap_processing/idex/idex_l2a.py +789 -0
  73. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +39 -33
  74. imap_processing/lo/l0/lo_science.py +6 -0
  75. imap_processing/lo/l1a/lo_l1a.py +0 -1
  76. imap_processing/lo/l1b/lo_l1b.py +177 -25
  77. imap_processing/mag/constants.py +8 -0
  78. imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +6 -0
  79. imap_processing/mag/l0/decom_mag.py +10 -3
  80. imap_processing/mag/l1a/mag_l1a.py +22 -11
  81. imap_processing/mag/l1a/mag_l1a_data.py +28 -3
  82. imap_processing/mag/l1b/mag_l1b.py +190 -48
  83. imap_processing/mag/l1c/interpolation_methods.py +211 -0
  84. imap_processing/mag/l1c/mag_l1c.py +447 -9
  85. imap_processing/quality_flags.py +1 -0
  86. imap_processing/spacecraft/packet_definitions/scid_x252.xml +538 -0
  87. imap_processing/spacecraft/quaternions.py +123 -0
  88. imap_processing/spice/geometry.py +16 -19
  89. imap_processing/spice/repoint.py +120 -0
  90. imap_processing/swapi/l1/swapi_l1.py +4 -0
  91. imap_processing/swapi/l2/swapi_l2.py +0 -1
  92. imap_processing/swe/l1a/swe_l1a.py +47 -8
  93. imap_processing/swe/l1a/swe_science.py +5 -2
  94. imap_processing/swe/l1b/swe_l1b_science.py +103 -56
  95. imap_processing/swe/l2/swe_l2.py +60 -65
  96. imap_processing/swe/packet_definitions/swe_packet_definition.xml +1121 -1
  97. imap_processing/swe/utils/swe_constants.py +63 -0
  98. imap_processing/swe/utils/swe_utils.py +85 -28
  99. imap_processing/tests/ccsds/test_data/expected_output.xml +40 -1
  100. imap_processing/tests/ccsds/test_excel_to_xtce.py +23 -20
  101. imap_processing/tests/cdf/test_data/imap_instrument2_global_cdf_attrs.yaml +0 -2
  102. imap_processing/tests/codice/conftest.py +1 -1
  103. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  104. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  105. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-ialirt_20241110193700_v0.0.0.cdf +0 -0
  106. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-omni_20241110193700_v0.0.0.cdf +0 -0
  107. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
  108. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-priorities_20241110193700_v0.0.0.cdf +0 -0
  109. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-sectored_20241110193700_v0.0.0.cdf +0 -0
  110. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  111. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  112. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  113. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-angular_20241110193700_v0.0.0.cdf +0 -0
  114. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-priority_20241110193700_v0.0.0.cdf +0 -0
  115. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-species_20241110193700_v0.0.0.cdf +0 -0
  116. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
  117. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-angular_20241110193700_v0.0.0.cdf +0 -0
  118. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-priority_20241110193700_v0.0.0.cdf +0 -0
  119. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-species_20241110193700_v0.0.0.cdf +0 -0
  120. imap_processing/tests/codice/test_codice_l1a.py +110 -46
  121. imap_processing/tests/codice/test_decompress.py +4 -4
  122. imap_processing/tests/conftest.py +166 -10
  123. imap_processing/tests/ena_maps/conftest.py +51 -0
  124. imap_processing/tests/ena_maps/test_ena_maps.py +638 -109
  125. imap_processing/tests/ena_maps/test_map_utils.py +66 -43
  126. imap_processing/tests/ena_maps/test_spatial_utils.py +16 -20
  127. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208.bin +0 -0
  128. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208_verify.csv +205 -0
  129. imap_processing/tests/hi/test_hi_l1b.py +12 -15
  130. imap_processing/tests/hi/test_hi_l1c.py +234 -6
  131. imap_processing/tests/hi/test_l1a.py +30 -0
  132. imap_processing/tests/hi/test_science_direct_event.py +1 -1
  133. imap_processing/tests/hi/test_utils.py +24 -2
  134. imap_processing/tests/hit/helpers/l1_validation.py +39 -39
  135. imap_processing/tests/hit/test_data/hskp_sample.ccsds +0 -0
  136. imap_processing/tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts +0 -0
  137. imap_processing/tests/hit/test_decom_hit.py +4 -0
  138. imap_processing/tests/hit/test_hit_l1a.py +24 -28
  139. imap_processing/tests/hit/test_hit_l1b.py +304 -40
  140. imap_processing/tests/hit/test_hit_l2.py +454 -0
  141. imap_processing/tests/hit/test_hit_utils.py +112 -2
  142. imap_processing/tests/hit/validation_data/hskp_sample_eu_3_6_2025.csv +89 -0
  143. imap_processing/tests/hit/validation_data/hskp_sample_raw.csv +89 -88
  144. imap_processing/tests/ialirt/test_data/l0/461971383-404.bin +0 -0
  145. imap_processing/tests/ialirt/test_data/l0/461971384-405.bin +0 -0
  146. imap_processing/tests/ialirt/test_data/l0/461971385-406.bin +0 -0
  147. imap_processing/tests/ialirt/test_data/l0/461971386-407.bin +0 -0
  148. imap_processing/tests/ialirt/test_data/l0/461971387-408.bin +0 -0
  149. imap_processing/tests/ialirt/test_data/l0/461971388-409.bin +0 -0
  150. imap_processing/tests/ialirt/test_data/l0/461971389-410.bin +0 -0
  151. imap_processing/tests/ialirt/test_data/l0/461971390-411.bin +0 -0
  152. imap_processing/tests/ialirt/test_data/l0/461971391-412.bin +0 -0
  153. imap_processing/tests/ialirt/test_data/l0/sample_decoded_i-alirt_data.csv +383 -0
  154. imap_processing/tests/ialirt/unit/test_grouping.py +81 -0
  155. imap_processing/tests/ialirt/unit/test_parse_mag.py +168 -0
  156. imap_processing/tests/ialirt/unit/test_process_swe.py +208 -3
  157. imap_processing/tests/ialirt/unit/test_time.py +16 -0
  158. imap_processing/tests/idex/conftest.py +62 -6
  159. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231218_v001.pkts +0 -0
  160. imap_processing/tests/idex/test_data/impact_14_tof_high_data.txt +4508 -4508
  161. imap_processing/tests/idex/test_idex_l1a.py +48 -4
  162. imap_processing/tests/idex/test_idex_l1b.py +3 -3
  163. imap_processing/tests/idex/test_idex_l2a.py +383 -0
  164. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20241022_v002.cdf +0 -0
  165. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20241022_v002.cdf +0 -0
  166. imap_processing/tests/lo/test_lo_l1b.py +148 -4
  167. imap_processing/tests/lo/test_lo_science.py +1 -0
  168. imap_processing/tests/mag/conftest.py +69 -0
  169. imap_processing/tests/mag/test_mag_decom.py +1 -1
  170. imap_processing/tests/mag/test_mag_l1a.py +38 -0
  171. imap_processing/tests/mag/test_mag_l1b.py +34 -53
  172. imap_processing/tests/mag/test_mag_l1c.py +251 -20
  173. imap_processing/tests/mag/test_mag_validation.py +109 -25
  174. imap_processing/tests/mag/validation/L1b/T009/MAGScience-normal-(2,2)-8s-20250204-16h39.csv +17 -0
  175. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-magi-out.csv +16 -16
  176. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-mago-out.csv +16 -16
  177. imap_processing/tests/mag/validation/L1b/T010/MAGScience-normal-(2,2)-8s-20250206-12h05.csv +17 -0
  178. imap_processing/tests/mag/validation/L1b/T011/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  179. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-magi-out.csv +16 -16
  180. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-mago-out.csv +16 -16
  181. imap_processing/tests/mag/validation/L1b/T012/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  182. imap_processing/tests/mag/validation/L1b/T012/data.bin +0 -0
  183. imap_processing/tests/mag/validation/L1b/T012/field_like_all_ranges.txt +19200 -0
  184. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-cal.cdf +0 -0
  185. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-in.csv +17 -0
  186. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-magi-out.csv +17 -0
  187. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-mago-out.csv +17 -0
  188. imap_processing/tests/mag/validation/imap_calibration_mag_20240229_v01.cdf +0 -0
  189. imap_processing/tests/spacecraft/__init__.py +0 -0
  190. imap_processing/tests/spacecraft/data/SSR_2024_190_20_08_12_0483851794_2_DA_apid0594_1packet.pkts +0 -0
  191. imap_processing/tests/spacecraft/test_quaternions.py +71 -0
  192. imap_processing/tests/spice/test_data/fake_repoint_data.csv +5 -0
  193. imap_processing/tests/spice/test_geometry.py +6 -9
  194. imap_processing/tests/spice/test_repoint.py +111 -0
  195. imap_processing/tests/swapi/test_swapi_l1.py +7 -3
  196. imap_processing/tests/swe/l0_data/2024051010_SWE_HK_packet.bin +0 -0
  197. imap_processing/tests/swe/l0_data/2024051011_SWE_CEM_RAW_packet.bin +0 -0
  198. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_APP_HK_20240510_092742.csv +49 -0
  199. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_CEM_RAW_20240510_092742.csv +593 -0
  200. imap_processing/tests/swe/test_swe_l1a.py +18 -0
  201. imap_processing/tests/swe/test_swe_l1a_cem_raw.py +52 -0
  202. imap_processing/tests/swe/test_swe_l1a_hk.py +68 -0
  203. imap_processing/tests/swe/test_swe_l1b_science.py +23 -4
  204. imap_processing/tests/swe/test_swe_l2.py +112 -30
  205. imap_processing/tests/test_cli.py +2 -2
  206. imap_processing/tests/test_utils.py +138 -16
  207. imap_processing/tests/ultra/data/l0/FM45_UltraFM45_Functional_2024-01-22T0105_20240122T010548.CCSDS +0 -0
  208. imap_processing/tests/ultra/data/l0/ultra45_raw_sc_ultraimgrates_20220530_00.csv +164 -0
  209. imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3243 -3243
  210. imap_processing/tests/ultra/data/mock_data.py +341 -0
  211. imap_processing/tests/ultra/unit/conftest.py +69 -26
  212. imap_processing/tests/ultra/unit/test_badtimes.py +2 -0
  213. imap_processing/tests/ultra/unit/test_cullingmask.py +4 -0
  214. imap_processing/tests/ultra/unit/test_de.py +12 -4
  215. imap_processing/tests/ultra/unit/test_decom_apid_881.py +44 -0
  216. imap_processing/tests/ultra/unit/test_spacecraft_pset.py +78 -0
  217. imap_processing/tests/ultra/unit/test_ultra_l1a.py +28 -12
  218. imap_processing/tests/ultra/unit/test_ultra_l1b.py +34 -6
  219. imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +22 -26
  220. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +86 -51
  221. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +94 -52
  222. imap_processing/ultra/l0/decom_tools.py +6 -5
  223. imap_processing/ultra/l1a/ultra_l1a.py +28 -56
  224. imap_processing/ultra/l1b/de.py +72 -28
  225. imap_processing/ultra/l1b/extendedspin.py +12 -14
  226. imap_processing/ultra/l1b/ultra_l1b.py +34 -9
  227. imap_processing/ultra/l1b/ultra_l1b_culling.py +65 -29
  228. imap_processing/ultra/l1b/ultra_l1b_extended.py +64 -19
  229. imap_processing/ultra/l1c/spacecraft_pset.py +86 -0
  230. imap_processing/ultra/l1c/ultra_l1c.py +7 -4
  231. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +112 -61
  232. imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
  233. imap_processing/ultra/utils/ultra_l1_utils.py +20 -2
  234. imap_processing/utils.py +68 -28
  235. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/METADATA +8 -5
  236. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/RECORD +250 -199
  237. imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +0 -237
  238. imap_processing/hi/l1a/housekeeping.py +0 -27
  239. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-aggregated_20240429_v001.cdf +0 -0
  240. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-singles_20240429_v001.cdf +0 -0
  241. imap_processing/tests/codice/data/imap_codice_l1a_hi-omni_20240429_v001.cdf +0 -0
  242. imap_processing/tests/codice/data/imap_codice_l1a_hi-sectored_20240429_v001.cdf +0 -0
  243. imap_processing/tests/codice/data/imap_codice_l1a_hskp_20100101_v001.cdf +0 -0
  244. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-aggregated_20240429_v001.cdf +0 -0
  245. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-singles_20240429_v001.cdf +0 -0
  246. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-angular_20240429_v001.cdf +0 -0
  247. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-priority_20240429_v001.cdf +0 -0
  248. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-species_20240429_v001.cdf +0 -0
  249. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-angular_20240429_v001.cdf +0 -0
  250. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-priority_20240429_v001.cdf +0 -0
  251. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-species_20240429_v001.cdf +0 -0
  252. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-aggregated_20240429_v001.cdf +0 -0
  253. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-singles_20240429_v001.cdf +0 -0
  254. imap_processing/tests/codice/data/imap_codice_l1b_hi-omni_20240429_v001.cdf +0 -0
  255. imap_processing/tests/codice/data/imap_codice_l1b_hi-sectored_20240429_v001.cdf +0 -0
  256. imap_processing/tests/codice/data/imap_codice_l1b_hskp_20100101_v001.cdf +0 -0
  257. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-aggregated_20240429_v001.cdf +0 -0
  258. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-singles_20240429_v001.cdf +0 -0
  259. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-angular_20240429_v001.cdf +0 -0
  260. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-priority_20240429_v001.cdf +0 -0
  261. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-species_20240429_v001.cdf +0 -0
  262. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-angular_20240429_v001.cdf +0 -0
  263. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-priority_20240429_v001.cdf +0 -0
  264. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-species_20240429_v001.cdf +0 -0
  265. imap_processing/tests/hi/data/l1/imap_hi_l1b_45sensor-de_20250415_v999.cdf +0 -0
  266. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1251.pkts +0 -0
  267. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1252.pkts +0 -0
  268. imap_processing/tests/hit/validation_data/hskp_sample_eu.csv +0 -89
  269. imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +0 -29
  270. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231214_v001.pkts +0 -0
  271. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20100101_v001.cdf +0 -0
  272. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20100101_v001.cdf +0 -0
  273. imap_processing/tests/ultra/test_data/mock_data.py +0 -161
  274. imap_processing/ultra/l1c/pset.py +0 -40
  275. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00_20240207T102740.CCSDS +0 -0
  276. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_7P_Phi0.0_BeamCal_LinearScan_phi0.04_theta-0.01_20230821T121304.CCSDS +0 -0
  277. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.CCSDS +0 -0
  278. /imap_processing/tests/ultra/{test_data → data}/l0/Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.CCSDS +0 -0
  279. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_auxdata_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  280. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_enaphxtofhangimg_FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.csv +0 -0
  281. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultraimgrates_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  282. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimgevent_FM45_7P_Phi00_BeamCal_LinearScan_phi004_theta-001_20230821T121304.csv +0 -0
  283. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E1.cdf +0 -0
  284. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E12.cdf +0 -0
  285. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E24.cdf +0 -0
  286. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/LICENSE +0 -0
  287. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/WHEEL +0 -0
  288. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/entry_points.txt +0 -0
@@ -27,9 +27,7 @@ from imap_processing.tests.hit.helpers.l1_validation import (
27
27
  @pytest.fixture(scope="module")
28
28
  def hk_packet_filepath():
29
29
  """Set path to test data file"""
30
- return (
31
- imap_module_directory / "tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts"
32
- )
30
+ return imap_module_directory / "tests/hit/test_data/hskp_sample.ccsds"
33
31
 
34
32
 
35
33
  @pytest.fixture(scope="module")
@@ -54,7 +52,7 @@ def validation_data():
54
52
  def test_subcom_sectorates(sci_packet_filepath):
55
53
  """Test the subcom_sectorates function.
56
54
 
57
- This function organizes the sector rates data
55
+ This function organizes the sectored rates data
58
56
  by species and adds the data as new variables
59
57
  to the dataset.
60
58
  """
@@ -69,26 +67,26 @@ def test_subcom_sectorates(sci_packet_filepath):
69
67
  # Number of science frames in the dataset
70
68
  frames = sci_dataset["epoch"].shape[0]
71
69
 
72
- # Check if the dataset has the expected new variables
73
- for species in ["h", "he4", "cno", "nemgsi", "fe"]:
74
- assert f"{species}_counts_sectored" in sci_dataset
75
- assert f"{species}_energy_min" in sci_dataset
76
- assert f"{species}_energy_max" in sci_dataset
70
+ # Shape of the new data variables
71
+ expected_shapes = {
72
+ "h": (3, 15, 8),
73
+ "he4": (2, 15, 8),
74
+ "cno": (2, 15, 8),
75
+ "nemgsi": (2, 15, 8),
76
+ "fe": (1, 15, 8),
77
+ }
77
78
 
79
+ for species, shape in expected_shapes.items():
80
+ # Check if the dataset has the new data variables
81
+ assert f"{species}_sectored_counts" in sci_dataset
82
+ assert f"{species}_energy_mean" in sci_dataset
83
+ assert f"{species}_energy_delta_minus" in sci_dataset
84
+ assert f"{species}_energy_delta_plus" in sci_dataset
78
85
  # Check the shape of the new data variables
79
- if species == "h":
80
- assert sci_dataset[f"{species}_counts_sectored"].shape == (frames, 3, 8, 15)
81
- assert sci_dataset[f"{species}_energy_min"].shape == (3,)
82
- elif species in ("4he", "cno", "nemgsi"):
83
- assert sci_dataset[f"{species}_counts_sectored"].shape == (frames, 2, 8, 15)
84
- assert sci_dataset[f"{species}_energy_min"].shape == (2,)
85
- elif species == "fe":
86
- assert sci_dataset[f"{species}_counts_sectored"].shape == (frames, 1, 8, 15)
87
- assert sci_dataset[f"{species}_energy_min"].shape == (1,)
88
- assert (
89
- sci_dataset[f"{species}_energy_max"].shape
90
- == sci_dataset[f"{species}_energy_min"].shape
91
- )
86
+ assert sci_dataset[f"{species}_sectored_counts"].shape == (frames, *shape)
87
+ assert sci_dataset[f"{species}_energy_mean"].shape == (shape[0],)
88
+ assert sci_dataset[f"{species}_energy_delta_minus"].shape == (shape[0],)
89
+ assert sci_dataset[f"{species}_energy_delta_plus"].shape == (shape[0],)
92
90
 
93
91
 
94
92
  def test_calculate_uncertainties():
@@ -151,6 +149,7 @@ def test_validate_l1a_housekeeping_data(hk_packet_filepath):
151
149
  )
152
150
  validation_data = pd.read_csv(validation_file)
153
151
  validation_data.columns = validation_data.columns.str.lower()
152
+ validation_data.columns = validation_data.columns.str.strip()
154
153
 
155
154
  # Get a list of leak columns in ascending order
156
155
  # (LEAK_I_00, LEAK_I_01, ..., LEAK_I_63)
@@ -166,7 +165,6 @@ def test_validate_l1a_housekeeping_data(hk_packet_filepath):
166
165
  # Define the keys that should have dropped from the housekeeping dataset
167
166
  dropped_fields = {
168
167
  "pkt_apid",
169
- "sc_tick",
170
168
  "version",
171
169
  "type",
172
170
  "sec_hdr_flg",
@@ -190,7 +188,6 @@ def test_validate_l1a_housekeeping_data(hk_packet_filepath):
190
188
  "ccsds_grp_flag",
191
189
  "ccsds_seq_cnt",
192
190
  "ccsds_length",
193
- "shcoarse",
194
191
  }
195
192
 
196
193
  # Check that dropped variables are not in the dataset
@@ -243,7 +240,7 @@ def test_validate_l1a_counts_data(sci_packet_filepath, validation_data):
243
240
  "seq_flgs",
244
241
  "src_seq_ctr",
245
242
  "pkt_len",
246
- "energy_idx",
243
+ "energy_bin",
247
244
  ]
248
245
 
249
246
  # Compare processed data to validation data
@@ -272,10 +269,9 @@ def test_hit_l1a(hk_packet_filepath, sci_packet_filepath):
272
269
  else:
273
270
  assert len(processed_datasets) == 2
274
271
  assert (
275
- processed_datasets[0].attrs["Logical_source"]
276
- == "imap_hit_l1a_count-rates"
272
+ processed_datasets[0].attrs["Logical_source"] == "imap_hit_l1a_counts"
277
273
  )
278
274
  assert (
279
275
  processed_datasets[1].attrs["Logical_source"]
280
- == "imap_hit_l1a_pulse-height-events"
276
+ == "imap_hit_l1a_direct-events"
281
277
  )
@@ -5,7 +5,17 @@ import xarray as xr
5
5
 
6
6
  from imap_processing import imap_module_directory
7
7
  from imap_processing.hit.l1a import hit_l1a
8
- from imap_processing.hit.l1b import hit_l1b
8
+ from imap_processing.hit.l1b.hit_l1b import (
9
+ PARTICLE_ENERGY_RANGE_MAPPING,
10
+ SummedCounts,
11
+ add_energy_variables,
12
+ add_rates_to_dataset,
13
+ calculate_summed_counts,
14
+ create_particle_data_arrays,
15
+ hit_l1b,
16
+ process_standard_rates_data,
17
+ process_summed_rates_data,
18
+ )
9
19
  from imap_processing.tests.hit.helpers.l1_validation import (
10
20
  prepare_standard_rates_validation_data,
11
21
  )
@@ -48,7 +58,7 @@ def dependencies(packet_filepath, sci_packet_filepath):
48
58
  @pytest.fixture()
49
59
  def l1b_hk_dataset(dependencies):
50
60
  """Get the housekeeping dataset"""
51
- datasets = hit_l1b.hit_l1b(dependencies, "001")
61
+ datasets = hit_l1b(dependencies, "001")
52
62
  for dataset in datasets:
53
63
  if dataset.attrs["Logical_source"] == "imap_hit_l1b_hk":
54
64
  return dataset
@@ -58,7 +68,7 @@ def l1b_hk_dataset(dependencies):
58
68
  def l1b_standard_rates_dataset(dependencies):
59
69
  """Get the standard rates dataset"""
60
70
  # TODO: use this fixture in future unit test to validate the standard rates dataset
61
- datasets = hit_l1b.hit_l1b(dependencies, "001")
71
+ datasets = hit_l1b(dependencies, "001")
62
72
  for dataset in datasets:
63
73
  if dataset.attrs["Logical_source"] == "imap_hit_l1b_standard-rates":
64
74
  return dataset
@@ -69,15 +79,232 @@ def l1a_counts_dataset(sci_packet_filepath):
69
79
  """Get L1A counts dataset to test l1b processing functions"""
70
80
  l1a_datasets = hit_l1a.hit_l1a(sci_packet_filepath, "001")
71
81
  for dataset in l1a_datasets:
72
- if dataset.attrs["Logical_source"] == "imap_hit_l1a_count-rates":
82
+ if dataset.attrs["Logical_source"] == "imap_hit_l1a_counts":
73
83
  return dataset
74
84
 
75
85
 
76
- def test_process_standard_rates_data(l1a_counts_dataset):
77
- """Test function for processing standard rates data"""
78
- l1b_standard_rates_dataset = hit_l1b.process_standard_rates_data(l1a_counts_dataset)
86
+ @pytest.fixture()
87
+ def livetime(l1a_counts_dataset):
88
+ """Calculate livetime for L1A counts dataset"""
89
+ return l1a_counts_dataset["livetime_counter"] / 270
90
+
91
+
92
+ def test_calculate_summed_counts():
93
+ # Create a mock raw_counts_dataset
94
+ data = {
95
+ "l2fgrates": (
96
+ ("epoch", "index"),
97
+ np.array([[1, 2, 3, 4, 5]] * 5, dtype=np.int64),
98
+ ),
99
+ "l3fgrates": (
100
+ ("epoch", "index"),
101
+ np.array([[6, 7, 8, 9, 10]] * 5, dtype=np.int64),
102
+ ),
103
+ "penfgrates": (
104
+ ("epoch", "index"),
105
+ np.array([[11, 12, 13, 14, 15]] * 5, dtype=np.int64),
106
+ ),
107
+ "l2fgrates_delta_minus": (
108
+ ("epoch", "index"),
109
+ np.zeros((5, 5), dtype=np.float32),
110
+ ),
111
+ "l3fgrates_delta_minus": (
112
+ ("epoch", "index"),
113
+ np.full((5, 5), 0.01, dtype=np.float32),
114
+ ),
115
+ "penfgrates_delta_minus": (
116
+ ("epoch", "index"),
117
+ np.full((5, 5), 0.001, dtype=np.float32),
118
+ ),
119
+ "l2fgrates_delta_plus": (
120
+ ("epoch", "index"),
121
+ np.full((5, 5), 0.02, dtype=np.float32),
122
+ ),
123
+ "l3fgrates_delta_plus": (
124
+ ("epoch", "index"),
125
+ np.full((5, 5), 0.002, dtype=np.float32),
126
+ ),
127
+ "penfgrates_delta_plus": (
128
+ ("epoch", "index"),
129
+ np.full((5, 5), 0.003, dtype=np.float32),
130
+ ),
131
+ }
132
+ coords = {"epoch": np.arange(5), "index": np.arange(5)}
133
+ raw_counts_dataset = xr.Dataset(data, coords=coords)
134
+
135
+ # Define count_indices
136
+ count_indices = {
137
+ "R2": [0, 1],
138
+ "R3": [2, 3],
139
+ "R4": [4],
140
+ }
141
+
142
+ # Call the function
143
+ summed_counts, summed_counts_delta_minus, summed_counts_delta_plus = (
144
+ calculate_summed_counts(raw_counts_dataset, count_indices)
145
+ )
146
+
147
+ # Expected values based on `count_indices`
148
+ expected_summed_counts = np.array([35, 35, 35, 35, 35])
149
+ expected_summed_counts_delta_minus = np.array([0.021, 0.021, 0.021, 0.021, 0.021])
150
+ expected_summed_counts_delta_plus = np.array([0.047, 0.047, 0.047, 0.047, 0.047])
151
+
152
+ # Assertions
153
+ assert summed_counts.shape == (5,)
154
+ assert summed_counts_delta_minus.shape == (5,)
155
+ assert summed_counts_delta_plus.shape == (5,)
156
+
157
+ np.testing.assert_array_almost_equal(summed_counts.values, expected_summed_counts)
158
+ np.testing.assert_array_almost_equal(
159
+ summed_counts_delta_minus.values, expected_summed_counts_delta_minus
160
+ )
161
+ np.testing.assert_array_almost_equal(
162
+ summed_counts_delta_plus.values, expected_summed_counts_delta_plus
163
+ )
164
+
165
+ # Check dtype consistency
166
+ assert summed_counts.dtype == np.int64, f"Unexpected dtype: {summed_counts.dtype}"
167
+ assert (
168
+ summed_counts_delta_minus.dtype == np.float32
169
+ ), f"Unexpected dtype: {summed_counts_delta_minus.dtype}"
170
+ assert (
171
+ summed_counts_delta_plus.dtype == np.float32
172
+ ), f"Unexpected dtype: {summed_counts_delta_plus.dtype}"
173
+
174
+
175
+ def test_add_rates_to_dataset():
176
+ # Create a sample dataset
177
+ dataset = xr.Dataset(
178
+ {
179
+ "epoch": ("epoch", np.arange(10)),
180
+ "livetime": ("epoch", np.random.rand(10) + 1), # Avoid division by zero
181
+ }
182
+ )
183
+
184
+ # Add empty data arrays for a sample particle
185
+ particle = "test_particle"
186
+ dataset[particle] = xr.DataArray(
187
+ data=np.zeros((10, 5), dtype=np.float32),
188
+ dims=["epoch", f"{particle}_energy_index"],
189
+ )
190
+ dataset[f"{particle}_delta_minus"] = xr.DataArray(
191
+ data=np.zeros((10, 5), dtype=np.float32),
192
+ dims=["epoch", f"{particle}_energy_index"],
193
+ )
194
+ dataset[f"{particle}_delta_plus"] = xr.DataArray(
195
+ data=np.zeros((10, 5), dtype=np.float32),
196
+ dims=["epoch", f"{particle}_energy_index"],
197
+ )
198
+
199
+ # Set the random seed for reproducibility
200
+ np.random.seed(42)
201
+
202
+ # Define the summed counts with random values in a namedtuple
203
+ summed_counts = SummedCounts(
204
+ xr.DataArray(np.random.rand(10), dims=["epoch"]),
205
+ xr.DataArray(np.random.rand(10), dims=["epoch"]),
206
+ xr.DataArray(np.random.rand(10), dims=["epoch"]),
207
+ )
208
+
209
+ # Call the function
210
+ updated_dataset = add_rates_to_dataset(
211
+ dataset, particle, 0, summed_counts, dataset["livetime"]
212
+ )
213
+
214
+ # Check the results
215
+ np.testing.assert_array_almost_equal(
216
+ updated_dataset[particle][:, 0].values,
217
+ summed_counts.summed_counts / dataset["livetime"].values,
218
+ )
219
+ np.testing.assert_array_almost_equal(
220
+ updated_dataset[f"{particle}_delta_minus"][:, 0].values,
221
+ summed_counts.summed_counts_delta_minus / dataset["livetime"].values,
222
+ )
223
+ np.testing.assert_array_almost_equal(
224
+ updated_dataset[f"{particle}_delta_plus"][:, 0].values,
225
+ summed_counts.summed_counts_delta_plus / dataset["livetime"].values,
226
+ )
227
+
228
+
229
+ def test_add_energy_variables():
230
+ dataset = xr.Dataset()
231
+ particle = "test_particle"
232
+ energy_min = np.array([1.8, 4.0, 6.0], dtype=np.float32)
233
+ energy_max = np.array([2.2, 6.0, 10.0], dtype=np.float32)
234
+ result = add_energy_variables(dataset, particle, energy_min, energy_max)
235
+ assert f"{particle}_energy_min" in result.data_vars
236
+ assert f"{particle}_energy_max" in result.data_vars
237
+ assert np.all(result[f"{particle}_energy_min"].values == energy_min)
238
+ assert np.all(result[f"{particle}_energy_max"].values == energy_max)
239
+
240
+
241
+ def test_create_particle_data_arrays():
242
+ dataset = xr.Dataset()
243
+ particle = "test_particle"
244
+ result = create_particle_data_arrays(
245
+ dataset, particle, num_energy_ranges=3, epoch_size=10
246
+ )
247
+
248
+ assert f"{particle}" in result.data_vars
249
+ assert f"{particle}_delta_minus" in result.data_vars
250
+ assert f"{particle}_delta_plus" in result.data_vars
251
+ assert f"{particle}_energy_index" in result.coords
252
+
253
+ for var in result.data_vars:
254
+ assert result[var].shape == (10, 3)
255
+
256
+ assert result[f"{particle}_energy_index"].shape == (3,)
257
+
258
+
259
+ def test_process_summed_rates_data(l1a_counts_dataset, livetime):
260
+ """Test the variables in the summed rates dataset"""
261
+
262
+ l1b_summed_rates_dataset = process_summed_rates_data(l1a_counts_dataset, livetime)
263
+
264
+ # Check that a xarray dataset is returned
265
+ assert isinstance(l1b_summed_rates_dataset, xr.Dataset)
266
+
267
+ valid_coords = {
268
+ "epoch",
269
+ "h_energy_index",
270
+ "he3_energy_index",
271
+ "he4_energy_index",
272
+ "he_energy_index",
273
+ "c_energy_index",
274
+ "o_energy_index",
275
+ "fe_energy_index",
276
+ "n_energy_index",
277
+ "si_energy_index",
278
+ "mg_energy_index",
279
+ "s_energy_index",
280
+ "ar_energy_index",
281
+ "ca_energy_index",
282
+ "na_energy_index",
283
+ "al_energy_index",
284
+ "ne_energy_index",
285
+ "ni_energy_index",
286
+ }
287
+
288
+ # Check that the dataset has the correct coords and variables
289
+ assert valid_coords == set(l1b_summed_rates_dataset.coords), "Coordinates mismatch"
290
+
291
+ assert "dynamic_threshold_state" in l1b_summed_rates_dataset.data_vars
292
+
293
+ for particle in PARTICLE_ENERGY_RANGE_MAPPING.keys():
294
+ assert f"{particle}" in l1b_summed_rates_dataset.data_vars
295
+ assert f"{particle}_delta_minus" in l1b_summed_rates_dataset.data_vars
296
+ assert f"{particle}_delta_plus" in l1b_summed_rates_dataset.data_vars
297
+ assert f"{particle}_energy_min" in l1b_summed_rates_dataset.data_vars
298
+ assert f"{particle}_energy_max" in l1b_summed_rates_dataset.data_vars
299
+
300
+
301
+ def test_process_standard_rates_data(l1a_counts_dataset, livetime):
302
+ """Test the variables in the standard rates dataset"""
303
+ l1b_standard_rates_dataset = process_standard_rates_data(
304
+ l1a_counts_dataset, livetime
305
+ )
79
306
 
80
- # Check that a xarray dataset with the correct logical source is returned
307
+ # Check that a xarray dataset is returned
81
308
  assert isinstance(l1b_standard_rates_dataset, xr.Dataset)
82
309
 
83
310
  # Define the data variables that should be present in the dataset
@@ -152,7 +379,6 @@ def test_hit_l1b_hk_dataset_variables(l1b_hk_dataset):
152
379
  # Define the keys that should have dropped from the housekeeping dataset
153
380
  dropped_keys = {
154
381
  "pkt_apid",
155
- "sc_tick",
156
382
  "version",
157
383
  "type",
158
384
  "sec_hdr_flg",
@@ -167,6 +393,7 @@ def test_hit_l1b_hk_dataset_variables(l1b_hk_dataset):
167
393
  }
168
394
  # Define the keys that should be present in the housekeeping dataset
169
395
  valid_keys = {
396
+ "sc_tick",
170
397
  "heater_on",
171
398
  "fsw_version_b",
172
399
  "ebox_m12va",
@@ -239,16 +466,13 @@ def test_validate_l1b_hk_data(l1b_hk_dataset):
239
466
 
240
467
  Parameters
241
468
  ----------
242
- hk_dataset : xr.Dataset
243
- Housekeeping dataset created by the L1B processing.
469
+ l1b_hk_dataset : xr.Dataset
470
+ Housekeeping dataset created by L1B processing.
244
471
  """
245
- # TODO: finish test. HIT will provide an updated validation file to fix issues:
246
- # - some fields have strings as values but in the processed data they're integers
247
- # - Some columns have blank cells where there should be data
248
472
 
249
473
  # Load the validation data
250
474
  validation_file = (
251
- imap_module_directory / "tests/hit/validation_data/hskp_sample_eu.csv"
475
+ imap_module_directory / "tests/hit/validation_data/hskp_sample_eu_3_6_2025.csv"
252
476
  )
253
477
  validation_data = pd.read_csv(validation_file)
254
478
  validation_data.columns = validation_data.columns.str.lower().str.strip()
@@ -260,14 +484,13 @@ def test_validate_l1b_hk_data(l1b_hk_dataset):
260
484
  col for col in validation_data.columns if col.startswith("leak_i_")
261
485
  ][::-1]
262
486
  validation_data["leak_i"] = validation_data[leak_columns].apply(
263
- lambda row: row.values, axis=1
487
+ lambda row: row.values.astype(np.float64), axis=1
264
488
  )
265
489
  validation_data.drop(columns=leak_columns, inplace=True)
266
490
 
267
491
  # Define the keys that should have dropped from the housekeeping dataset
268
492
  dropped_fields = {
269
493
  "pkt_apid",
270
- "sc_tick",
271
494
  "version",
272
495
  "type",
273
496
  "sec_hdr_flg",
@@ -284,29 +507,47 @@ def test_validate_l1b_hk_data(l1b_hk_dataset):
284
507
  # Check that dropped variables are not in the dataset
285
508
  assert set(dropped_fields).isdisjoint(set(l1b_hk_dataset.data_vars.keys()))
286
509
 
287
- # TODO: uncomment block after new validation data is provided
288
510
  # Define the keys that should be ignored in the validation
289
511
  # like ccsds headers
290
- # ignore_validation_fields = {
291
- # "ccsds_version",
292
- # "ccsds_type",
293
- # "ccsds_sec_hdr_flag",
294
- # "ccsds_appid",
295
- # "ccsds_grp_flag",
296
- # "ccsds_seq_cnt",
297
- # "ccsds_length",
298
- # "sc_tick",
299
- # }
300
-
301
- # # Compare the housekeeping dataset with the expected validation data
302
- # for field in validation_data.columns:
303
- # if field not in ignore_validation_fields:
304
- # print(field)
305
- # assert field in hk_dataset.data_vars.keys()
306
- # for pkt in range(validation_data.shape[0]):
307
- # assert np.array_equal(
308
- # hk_dataset[field][pkt].data, validation_data[field][pkt]
309
- # )
512
+ ignore_validation_fields = {
513
+ "ccsds_version",
514
+ "ccsds_type",
515
+ "ccsds_sec_hdr_flag",
516
+ "ccsds_appid",
517
+ "ccsds_grp_flag",
518
+ "ccsds_seq_cnt",
519
+ "ccsds_length",
520
+ "sc_tick",
521
+ }
522
+
523
+ for field in validation_data.columns:
524
+ if field not in ignore_validation_fields:
525
+ assert field in l1b_hk_dataset.data_vars.keys()
526
+ if field == "leak_i":
527
+ # Compare leak_i arrays
528
+ # Reshape validation_data to match the shape of l1b_hk_dataset
529
+ reshaped_validation_data = np.vstack(validation_data[field].values)
530
+ # Compare leak_i arrays
531
+ np.testing.assert_allclose(
532
+ l1b_hk_dataset[field].values.astype(np.float64),
533
+ reshaped_validation_data,
534
+ atol=1e-2,
535
+ err_msg=f"Mismatch in {field}",
536
+ )
537
+ elif l1b_hk_dataset[field].dtype.kind == "U":
538
+ np.testing.assert_array_equal(
539
+ l1b_hk_dataset[field].values,
540
+ validation_data[field].str.strip().values,
541
+ err_msg=f"Mismatch in {field}",
542
+ )
543
+ else:
544
+ # Compare float values
545
+ np.testing.assert_allclose(
546
+ l1b_hk_dataset[field].values.astype(np.float64),
547
+ validation_data[field].values,
548
+ atol=1e-2,
549
+ err_msg=f"Mismatch in {field}",
550
+ )
310
551
 
311
552
 
312
553
  def test_validate_l1b_standard_rates_data(l1b_standard_rates_dataset):
@@ -333,6 +574,28 @@ def test_validate_l1b_standard_rates_data(l1b_standard_rates_dataset):
333
574
  )
334
575
 
335
576
 
577
+ def test_hit_l1b_missing_apid(sci_packet_filepath):
578
+ """Test missing housekeeping apid from packet file
579
+
580
+ Check that no L1B datasets are created when the housekeeping
581
+ apid is missing from the L0 file path dependency since APIDs
582
+ are currently in separate packet files.
583
+
584
+ In the future, all HIT APIDs will be included in the same packet file.
585
+
586
+ Parameters
587
+ ----------
588
+ sci_packet_filepath : str
589
+ Science CCSDS packet file path. Only contains science APID and is
590
+ missing the housekeeping APID.
591
+ """
592
+ # Create a dependency dictionary with a science CCSDS packet file
593
+ # excluding the housekeeping apid
594
+ dependency = {"imap_hit_l0_raw": sci_packet_filepath}
595
+ datasets = hit_l1b(dependency, "001")
596
+ assert len(datasets) == 0
597
+
598
+
336
599
  def test_hit_l1b(dependencies):
337
600
  """Test creating L1B CDF files
338
601
 
@@ -344,10 +607,11 @@ def test_hit_l1b(dependencies):
344
607
  Dictionary of L1A datasets and CCSDS packet file path
345
608
  """
346
609
  # TODO: update assertions after science data processing is completed
347
- datasets = hit_l1b.hit_l1b(dependencies, "001")
610
+ datasets = hit_l1b(dependencies, "001")
348
611
 
349
- assert len(datasets) == 2
612
+ assert len(datasets) == 3
350
613
  for dataset in datasets:
351
614
  assert isinstance(dataset, xr.Dataset)
352
615
  assert datasets[0].attrs["Logical_source"] == "imap_hit_l1b_hk"
353
616
  assert datasets[1].attrs["Logical_source"] == "imap_hit_l1b_standard-rates"
617
+ assert datasets[2].attrs["Logical_source"] == "imap_hit_l1b_summed-rates"