imap-processing 0.11.0__py3-none-any.whl → 0.13.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 (415) hide show
  1. imap_processing/__init__.py +11 -11
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/ccsds_data.py +1 -2
  4. imap_processing/ccsds/excel_to_xtce.py +66 -18
  5. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +24 -40
  6. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +934 -42
  7. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
  8. imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +0 -5
  9. imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +10 -11
  10. imap_processing/cdf/config/imap_hi_variable_attrs.yaml +17 -19
  11. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +27 -14
  12. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +106 -116
  13. imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +120 -145
  14. imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +14 -0
  15. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +25 -9
  16. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +6 -4
  17. imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +3 -3
  18. imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +0 -12
  19. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +1 -1
  20. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +23 -20
  21. imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml +361 -0
  22. imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml +160 -0
  23. imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +160 -0
  24. imap_processing/cdf/config/imap_spacecraft_global_cdf_attrs.yaml +18 -0
  25. imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml +40 -0
  26. imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +1 -5
  27. imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
  28. imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +12 -4
  29. imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +16 -2
  30. imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +64 -52
  31. imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +71 -47
  32. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +180 -19
  33. imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
  34. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +80 -17
  35. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +32 -57
  36. imap_processing/cdf/utils.py +52 -38
  37. imap_processing/cli.py +477 -233
  38. imap_processing/codice/codice_l1a.py +466 -131
  39. imap_processing/codice/codice_l1b.py +51 -152
  40. imap_processing/codice/constants.py +1360 -569
  41. imap_processing/codice/decompress.py +2 -6
  42. imap_processing/ena_maps/ena_maps.py +1103 -146
  43. imap_processing/ena_maps/utils/coordinates.py +19 -0
  44. imap_processing/ena_maps/utils/map_utils.py +14 -17
  45. imap_processing/ena_maps/utils/spatial_utils.py +55 -52
  46. imap_processing/glows/l1a/glows_l1a.py +28 -99
  47. imap_processing/glows/l1a/glows_l1a_data.py +2 -2
  48. imap_processing/glows/l1b/glows_l1b.py +1 -4
  49. imap_processing/glows/l1b/glows_l1b_data.py +1 -3
  50. imap_processing/glows/l2/glows_l2.py +2 -5
  51. imap_processing/hi/l1a/hi_l1a.py +54 -29
  52. imap_processing/hi/l1a/histogram.py +0 -1
  53. imap_processing/hi/l1a/science_direct_event.py +6 -8
  54. imap_processing/hi/l1b/hi_l1b.py +111 -82
  55. imap_processing/hi/l1c/hi_l1c.py +416 -32
  56. imap_processing/hi/utils.py +58 -12
  57. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
  58. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt0-factors_20250219_v002.csv +205 -0
  59. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt1-factors_20250219_v002.csv +205 -0
  60. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt2-factors_20250219_v002.csv +205 -0
  61. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt3-factors_20250219_v002.csv +205 -0
  62. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-summed-dt0-factors_20250219_v002.csv +68 -0
  63. imap_processing/hit/hit_utils.py +235 -5
  64. imap_processing/hit/l0/constants.py +20 -11
  65. imap_processing/hit/l0/decom_hit.py +21 -5
  66. imap_processing/hit/l1a/hit_l1a.py +71 -75
  67. imap_processing/hit/l1b/constants.py +321 -0
  68. imap_processing/hit/l1b/hit_l1b.py +377 -67
  69. imap_processing/hit/l2/constants.py +318 -0
  70. imap_processing/hit/l2/hit_l2.py +723 -0
  71. imap_processing/hit/packet_definitions/hit_packet_definitions.xml +1323 -71
  72. imap_processing/ialirt/l0/mag_l0_ialirt_data.py +155 -0
  73. imap_processing/ialirt/l0/parse_mag.py +374 -0
  74. imap_processing/ialirt/l0/process_swapi.py +69 -0
  75. imap_processing/ialirt/l0/process_swe.py +548 -0
  76. imap_processing/ialirt/packet_definitions/ialirt.xml +216 -208
  77. imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +1 -1
  78. imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +1 -1
  79. imap_processing/ialirt/packet_definitions/ialirt_mag.xml +115 -0
  80. imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
  81. imap_processing/ialirt/utils/grouping.py +114 -0
  82. imap_processing/ialirt/utils/time.py +29 -0
  83. imap_processing/idex/atomic_masses.csv +22 -0
  84. imap_processing/idex/decode.py +2 -2
  85. imap_processing/idex/idex_constants.py +33 -0
  86. imap_processing/idex/idex_l0.py +22 -8
  87. imap_processing/idex/idex_l1a.py +81 -51
  88. imap_processing/idex/idex_l1b.py +13 -39
  89. imap_processing/idex/idex_l2a.py +823 -0
  90. imap_processing/idex/idex_l2b.py +120 -0
  91. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +11 -11
  92. imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
  93. imap_processing/lo/l0/lo_science.py +7 -2
  94. imap_processing/lo/l1a/lo_l1a.py +1 -5
  95. imap_processing/lo/l1b/lo_l1b.py +702 -29
  96. imap_processing/lo/l1b/tof_conversions.py +11 -0
  97. imap_processing/lo/l1c/lo_l1c.py +1 -4
  98. imap_processing/mag/constants.py +51 -0
  99. imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
  100. imap_processing/mag/l0/decom_mag.py +10 -3
  101. imap_processing/mag/l1a/mag_l1a.py +23 -19
  102. imap_processing/mag/l1a/mag_l1a_data.py +35 -10
  103. imap_processing/mag/l1b/mag_l1b.py +259 -50
  104. imap_processing/mag/l1c/interpolation_methods.py +388 -0
  105. imap_processing/mag/l1c/mag_l1c.py +621 -17
  106. imap_processing/mag/l2/mag_l2.py +140 -0
  107. imap_processing/mag/l2/mag_l2_data.py +288 -0
  108. imap_processing/quality_flags.py +1 -0
  109. imap_processing/spacecraft/packet_definitions/scid_x252.xml +538 -0
  110. imap_processing/spacecraft/quaternions.py +121 -0
  111. imap_processing/spice/geometry.py +19 -22
  112. imap_processing/spice/kernels.py +0 -276
  113. imap_processing/spice/pointing_frame.py +257 -0
  114. imap_processing/spice/repoint.py +149 -0
  115. imap_processing/spice/spin.py +38 -33
  116. imap_processing/spice/time.py +24 -0
  117. imap_processing/swapi/l1/swapi_l1.py +20 -12
  118. imap_processing/swapi/l2/swapi_l2.py +116 -5
  119. imap_processing/swapi/swapi_utils.py +32 -0
  120. imap_processing/swe/l1a/swe_l1a.py +44 -12
  121. imap_processing/swe/l1a/swe_science.py +13 -13
  122. imap_processing/swe/l1b/swe_l1b.py +898 -23
  123. imap_processing/swe/l2/swe_l2.py +75 -136
  124. imap_processing/swe/packet_definitions/swe_packet_definition.xml +1121 -1
  125. imap_processing/swe/utils/swe_constants.py +64 -0
  126. imap_processing/swe/utils/swe_utils.py +85 -28
  127. imap_processing/tests/ccsds/test_data/expected_output.xml +40 -1
  128. imap_processing/tests/ccsds/test_excel_to_xtce.py +24 -21
  129. imap_processing/tests/cdf/test_data/imap_instrument2_global_cdf_attrs.yaml +0 -2
  130. imap_processing/tests/cdf/test_utils.py +14 -16
  131. imap_processing/tests/codice/conftest.py +44 -33
  132. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  133. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  134. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-ialirt_20241110193700_v0.0.0.cdf +0 -0
  135. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-omni_20241110193700_v0.0.0.cdf +0 -0
  136. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
  137. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-priorities_20241110193700_v0.0.0.cdf +0 -0
  138. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-sectored_20241110193700_v0.0.0.cdf +0 -0
  139. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  140. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  141. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  142. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-angular_20241110193700_v0.0.0.cdf +0 -0
  143. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-priority_20241110193700_v0.0.0.cdf +0 -0
  144. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-species_20241110193700_v0.0.0.cdf +0 -0
  145. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
  146. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-angular_20241110193700_v0.0.0.cdf +0 -0
  147. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-priority_20241110193700_v0.0.0.cdf +0 -0
  148. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-species_20241110193700_v0.0.0.cdf +0 -0
  149. imap_processing/tests/codice/test_codice_l1a.py +126 -53
  150. imap_processing/tests/codice/test_codice_l1b.py +6 -7
  151. imap_processing/tests/codice/test_decompress.py +4 -4
  152. imap_processing/tests/conftest.py +239 -27
  153. imap_processing/tests/ena_maps/conftest.py +51 -0
  154. imap_processing/tests/ena_maps/test_ena_maps.py +1068 -110
  155. imap_processing/tests/ena_maps/test_map_utils.py +66 -43
  156. imap_processing/tests/ena_maps/test_spatial_utils.py +17 -21
  157. imap_processing/tests/glows/conftest.py +10 -14
  158. imap_processing/tests/glows/test_glows_decom.py +4 -4
  159. imap_processing/tests/glows/test_glows_l1a_cdf.py +6 -27
  160. imap_processing/tests/glows/test_glows_l1a_data.py +6 -8
  161. imap_processing/tests/glows/test_glows_l1b.py +11 -11
  162. imap_processing/tests/glows/test_glows_l1b_data.py +5 -5
  163. imap_processing/tests/glows/test_glows_l2.py +2 -8
  164. imap_processing/tests/hi/conftest.py +1 -1
  165. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208.bin +0 -0
  166. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208_verify.csv +205 -0
  167. imap_processing/tests/hi/test_hi_l1b.py +22 -27
  168. imap_processing/tests/hi/test_hi_l1c.py +249 -18
  169. imap_processing/tests/hi/test_l1a.py +35 -7
  170. imap_processing/tests/hi/test_science_direct_event.py +3 -3
  171. imap_processing/tests/hi/test_utils.py +24 -2
  172. imap_processing/tests/hit/helpers/l1_validation.py +74 -73
  173. imap_processing/tests/hit/test_data/hskp_sample.ccsds +0 -0
  174. imap_processing/tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts +0 -0
  175. imap_processing/tests/hit/test_decom_hit.py +5 -1
  176. imap_processing/tests/hit/test_hit_l1a.py +32 -36
  177. imap_processing/tests/hit/test_hit_l1b.py +300 -81
  178. imap_processing/tests/hit/test_hit_l2.py +716 -0
  179. imap_processing/tests/hit/test_hit_utils.py +184 -7
  180. imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
  181. imap_processing/tests/hit/validation_data/hskp_sample_eu_3_6_2025.csv +89 -0
  182. imap_processing/tests/hit/validation_data/hskp_sample_raw.csv +89 -88
  183. imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
  184. imap_processing/tests/ialirt/data/l0/461971383-404.bin +0 -0
  185. imap_processing/tests/ialirt/data/l0/461971384-405.bin +0 -0
  186. imap_processing/tests/ialirt/data/l0/461971385-406.bin +0 -0
  187. imap_processing/tests/ialirt/data/l0/461971386-407.bin +0 -0
  188. imap_processing/tests/ialirt/data/l0/461971387-408.bin +0 -0
  189. imap_processing/tests/ialirt/data/l0/461971388-409.bin +0 -0
  190. imap_processing/tests/ialirt/data/l0/461971389-410.bin +0 -0
  191. imap_processing/tests/ialirt/data/l0/461971390-411.bin +0 -0
  192. imap_processing/tests/ialirt/data/l0/461971391-412.bin +0 -0
  193. imap_processing/tests/ialirt/data/l0/sample_decoded_i-alirt_data.csv +383 -0
  194. imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
  195. imap_processing/tests/ialirt/unit/test_grouping.py +81 -0
  196. imap_processing/tests/ialirt/unit/test_parse_mag.py +223 -0
  197. imap_processing/tests/ialirt/unit/test_process_codicehi.py +3 -3
  198. imap_processing/tests/ialirt/unit/test_process_codicelo.py +3 -10
  199. imap_processing/tests/ialirt/unit/test_process_ephemeris.py +4 -4
  200. imap_processing/tests/ialirt/unit/test_process_hit.py +3 -3
  201. imap_processing/tests/ialirt/unit/test_process_swapi.py +24 -16
  202. imap_processing/tests/ialirt/unit/test_process_swe.py +319 -6
  203. imap_processing/tests/ialirt/unit/test_time.py +16 -0
  204. imap_processing/tests/idex/conftest.py +127 -6
  205. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231218_v001.pkts +0 -0
  206. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20241206_v001.pkts +0 -0
  207. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20250108_v001.pkts +0 -0
  208. imap_processing/tests/idex/test_data/impact_14_tof_high_data.txt +4508 -4508
  209. imap_processing/tests/idex/test_idex_l0.py +33 -11
  210. imap_processing/tests/idex/test_idex_l1a.py +92 -21
  211. imap_processing/tests/idex/test_idex_l1b.py +106 -27
  212. imap_processing/tests/idex/test_idex_l2a.py +399 -0
  213. imap_processing/tests/idex/test_idex_l2b.py +93 -0
  214. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20241022_v002.cdf +0 -0
  215. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20241022_v002.cdf +0 -0
  216. imap_processing/tests/lo/test_lo_l1a.py +3 -3
  217. imap_processing/tests/lo/test_lo_l1b.py +515 -6
  218. imap_processing/tests/lo/test_lo_l1c.py +1 -1
  219. imap_processing/tests/lo/test_lo_science.py +7 -7
  220. imap_processing/tests/lo/test_star_sensor.py +1 -1
  221. imap_processing/tests/mag/conftest.py +120 -2
  222. imap_processing/tests/mag/test_mag_decom.py +5 -4
  223. imap_processing/tests/mag/test_mag_l1a.py +51 -7
  224. imap_processing/tests/mag/test_mag_l1b.py +40 -59
  225. imap_processing/tests/mag/test_mag_l1c.py +354 -19
  226. imap_processing/tests/mag/test_mag_l2.py +130 -0
  227. imap_processing/tests/mag/test_mag_validation.py +247 -26
  228. imap_processing/tests/mag/validation/L1b/T009/MAGScience-normal-(2,2)-8s-20250204-16h39.csv +17 -0
  229. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-magi-out.csv +16 -16
  230. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-mago-out.csv +16 -16
  231. imap_processing/tests/mag/validation/L1b/T010/MAGScience-normal-(2,2)-8s-20250206-12h05.csv +17 -0
  232. imap_processing/tests/mag/validation/L1b/T011/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  233. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-magi-out.csv +16 -16
  234. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-mago-out.csv +16 -16
  235. imap_processing/tests/mag/validation/L1b/T012/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  236. imap_processing/tests/mag/validation/L1b/T012/data.bin +0 -0
  237. imap_processing/tests/mag/validation/L1b/T012/field_like_all_ranges.txt +19200 -0
  238. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-cal.cdf +0 -0
  239. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-in.csv +17 -0
  240. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-magi-out.csv +17 -0
  241. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-mago-out.csv +17 -0
  242. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-in.csv +1217 -0
  243. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-out.csv +1857 -0
  244. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-in.csv +1217 -0
  245. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-out.csv +1857 -0
  246. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-in.csv +1217 -0
  247. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-out.csv +1793 -0
  248. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-in.csv +1217 -0
  249. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-out.csv +1793 -0
  250. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-burst-in.csv +2561 -0
  251. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-in.csv +961 -0
  252. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-out.csv +1539 -0
  253. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-in.csv +1921 -0
  254. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-out.csv +2499 -0
  255. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-in.csv +865 -0
  256. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv +1196 -0
  257. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-in.csv +1729 -0
  258. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv +3053 -0
  259. imap_processing/tests/mag/validation/L2/imap_mag_l1b_norm-mago_20251017_v002.cdf +0 -0
  260. imap_processing/tests/mag/validation/calibration/imap_mag_l1b-calibration_20240229_v001.cdf +0 -0
  261. imap_processing/tests/mag/validation/calibration/imap_mag_l2-calibration-matrices_20251017_v004.cdf +0 -0
  262. imap_processing/tests/mag/validation/calibration/imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf +0 -0
  263. imap_processing/tests/spacecraft/data/SSR_2024_190_20_08_12_0483851794_2_DA_apid0594_1packet.pkts +0 -0
  264. imap_processing/tests/spacecraft/test_quaternions.py +71 -0
  265. imap_processing/tests/spice/test_data/fake_repoint_data.csv +5 -0
  266. imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
  267. imap_processing/tests/spice/test_geometry.py +9 -12
  268. imap_processing/tests/spice/test_kernels.py +1 -200
  269. imap_processing/tests/spice/test_pointing_frame.py +185 -0
  270. imap_processing/tests/spice/test_repoint.py +121 -0
  271. imap_processing/tests/spice/test_spin.py +50 -9
  272. imap_processing/tests/spice/test_time.py +14 -0
  273. imap_processing/tests/swapi/lut/imap_swapi_esa-unit-conversion_20250211_v000.csv +73 -0
  274. imap_processing/tests/swapi/lut/imap_swapi_lut-notes_20250211_v000.csv +1025 -0
  275. imap_processing/tests/swapi/test_swapi_l1.py +13 -11
  276. imap_processing/tests/swapi/test_swapi_l2.py +180 -8
  277. imap_processing/tests/swe/l0_data/2024051010_SWE_HK_packet.bin +0 -0
  278. imap_processing/tests/swe/l0_data/2024051011_SWE_CEM_RAW_packet.bin +0 -0
  279. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_APP_HK_20240510_092742.csv +49 -0
  280. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_CEM_RAW_20240510_092742.csv +593 -0
  281. imap_processing/tests/swe/lut/checker-board-indices.csv +24 -0
  282. imap_processing/tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv +385 -0
  283. imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv +3 -0
  284. imap_processing/tests/swe/test_swe_l1a.py +20 -2
  285. imap_processing/tests/swe/test_swe_l1a_cem_raw.py +52 -0
  286. imap_processing/tests/swe/test_swe_l1a_hk.py +68 -0
  287. imap_processing/tests/swe/test_swe_l1a_science.py +3 -3
  288. imap_processing/tests/swe/test_swe_l1b.py +162 -24
  289. imap_processing/tests/swe/test_swe_l2.py +153 -91
  290. imap_processing/tests/test_cli.py +171 -88
  291. imap_processing/tests/test_utils.py +140 -17
  292. imap_processing/tests/ultra/data/l0/FM45_UltraFM45_Functional_2024-01-22T0105_20240122T010548.CCSDS +0 -0
  293. imap_processing/tests/ultra/data/l0/ultra45_raw_sc_ultraimgrates_20220530_00.csv +164 -0
  294. 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
  295. imap_processing/tests/ultra/data/mock_data.py +369 -0
  296. imap_processing/tests/ultra/unit/conftest.py +115 -89
  297. imap_processing/tests/ultra/unit/test_badtimes.py +4 -4
  298. imap_processing/tests/ultra/unit/test_cullingmask.py +8 -6
  299. imap_processing/tests/ultra/unit/test_de.py +14 -13
  300. imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
  301. imap_processing/tests/ultra/unit/test_decom_apid_881.py +54 -11
  302. imap_processing/tests/ultra/unit/test_decom_apid_883.py +12 -10
  303. imap_processing/tests/ultra/unit/test_decom_apid_896.py +202 -55
  304. imap_processing/tests/ultra/unit/test_lookup_utils.py +23 -1
  305. imap_processing/tests/ultra/unit/test_spacecraft_pset.py +77 -0
  306. imap_processing/tests/ultra/unit/test_ultra_l1a.py +98 -305
  307. imap_processing/tests/ultra/unit/test_ultra_l1b.py +60 -14
  308. imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
  309. imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +26 -27
  310. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +239 -70
  311. imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
  312. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +114 -83
  313. imap_processing/tests/ultra/unit/test_ultra_l2.py +230 -0
  314. imap_processing/ultra/constants.py +1 -1
  315. imap_processing/ultra/l0/decom_tools.py +27 -39
  316. imap_processing/ultra/l0/decom_ultra.py +168 -204
  317. imap_processing/ultra/l0/ultra_utils.py +152 -136
  318. imap_processing/ultra/l1a/ultra_l1a.py +55 -271
  319. imap_processing/ultra/l1b/badtimes.py +1 -4
  320. imap_processing/ultra/l1b/cullingmask.py +2 -6
  321. imap_processing/ultra/l1b/de.py +116 -57
  322. imap_processing/ultra/l1b/extendedspin.py +20 -18
  323. imap_processing/ultra/l1b/lookup_utils.py +72 -9
  324. imap_processing/ultra/l1b/ultra_l1b.py +36 -16
  325. imap_processing/ultra/l1b/ultra_l1b_culling.py +66 -30
  326. imap_processing/ultra/l1b/ultra_l1b_extended.py +297 -94
  327. imap_processing/ultra/l1c/histogram.py +2 -6
  328. imap_processing/ultra/l1c/spacecraft_pset.py +84 -0
  329. imap_processing/ultra/l1c/ultra_l1c.py +8 -9
  330. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +206 -108
  331. imap_processing/ultra/l2/ultra_l2.py +299 -0
  332. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +526 -0
  333. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +526 -0
  334. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +526 -0
  335. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +526 -0
  336. imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -2
  337. imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
  338. imap_processing/ultra/packet_definitions/README.md +38 -0
  339. imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +15302 -482
  340. imap_processing/ultra/utils/ultra_l1_utils.py +31 -12
  341. imap_processing/utils.py +69 -29
  342. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +10 -6
  343. imap_processing-0.13.0.dist-info/RECORD +578 -0
  344. imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +0 -237
  345. imap_processing/hi/l1a/housekeeping.py +0 -27
  346. imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
  347. imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
  348. imap_processing/swe/l1b/swe_l1b_science.py +0 -652
  349. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-aggregated_20240429_v001.cdf +0 -0
  350. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-singles_20240429_v001.cdf +0 -0
  351. imap_processing/tests/codice/data/imap_codice_l1a_hi-omni_20240429_v001.cdf +0 -0
  352. imap_processing/tests/codice/data/imap_codice_l1a_hi-sectored_20240429_v001.cdf +0 -0
  353. imap_processing/tests/codice/data/imap_codice_l1a_hskp_20100101_v001.cdf +0 -0
  354. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-aggregated_20240429_v001.cdf +0 -0
  355. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-singles_20240429_v001.cdf +0 -0
  356. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-angular_20240429_v001.cdf +0 -0
  357. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-priority_20240429_v001.cdf +0 -0
  358. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-species_20240429_v001.cdf +0 -0
  359. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-angular_20240429_v001.cdf +0 -0
  360. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-priority_20240429_v001.cdf +0 -0
  361. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-species_20240429_v001.cdf +0 -0
  362. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-aggregated_20240429_v001.cdf +0 -0
  363. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-singles_20240429_v001.cdf +0 -0
  364. imap_processing/tests/codice/data/imap_codice_l1b_hi-omni_20240429_v001.cdf +0 -0
  365. imap_processing/tests/codice/data/imap_codice_l1b_hi-sectored_20240429_v001.cdf +0 -0
  366. imap_processing/tests/codice/data/imap_codice_l1b_hskp_20100101_v001.cdf +0 -0
  367. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-aggregated_20240429_v001.cdf +0 -0
  368. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-singles_20240429_v001.cdf +0 -0
  369. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-angular_20240429_v001.cdf +0 -0
  370. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-priority_20240429_v001.cdf +0 -0
  371. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-species_20240429_v001.cdf +0 -0
  372. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-angular_20240429_v001.cdf +0 -0
  373. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-priority_20240429_v001.cdf +0 -0
  374. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-species_20240429_v001.cdf +0 -0
  375. imap_processing/tests/hi/data/l1/imap_hi_l1b_45sensor-de_20250415_v999.cdf +0 -0
  376. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1251.pkts +0 -0
  377. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1252.pkts +0 -0
  378. imap_processing/tests/hit/validation_data/hskp_sample_eu.csv +0 -89
  379. imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +0 -29
  380. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231214_v001.pkts +0 -0
  381. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20100101_v001.cdf +0 -0
  382. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20100101_v001.cdf +0 -0
  383. imap_processing/tests/swe/test_swe_l1b_science.py +0 -84
  384. imap_processing/tests/ultra/test_data/mock_data.py +0 -161
  385. imap_processing/ultra/l1c/pset.py +0 -40
  386. imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
  387. imap_processing-0.11.0.dist-info/RECORD +0 -488
  388. /imap_processing/idex/packet_definitions/{idex_packet_definition.xml → idex_science_packet_definition.xml} +0 -0
  389. /imap_processing/tests/ialirt/{test_data → data}/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
  390. /imap_processing/tests/ialirt/{test_data → data}/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
  391. /imap_processing/tests/ialirt/{test_data → data}/l0/IALiRT Raw Packet Telemetry.txt +0 -0
  392. /imap_processing/tests/ialirt/{test_data → data}/l0/apid01152.tlm +0 -0
  393. /imap_processing/tests/ialirt/{test_data → data}/l0/eu_SWP_IAL_20240826_152033.csv +0 -0
  394. /imap_processing/tests/ialirt/{test_data → data}/l0/hi_fsw_view_1_ccsds.bin +0 -0
  395. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.ccsds +0 -0
  396. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.csv +0 -0
  397. /imap_processing/tests/ialirt/{test_data → data}/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +0 -0
  398. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
  399. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  400. /imap_processing/{mag/l1b → tests/spacecraft}/__init__.py +0 -0
  401. /imap_processing/{swe/l1b/engineering_unit_convert_table.csv → tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv} +0 -0
  402. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00_20240207T102740.CCSDS +0 -0
  403. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_7P_Phi0.0_BeamCal_LinearScan_phi0.04_theta-0.01_20230821T121304.CCSDS +0 -0
  404. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.CCSDS +0 -0
  405. /imap_processing/tests/ultra/{test_data → data}/l0/Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.CCSDS +0 -0
  406. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_auxdata_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  407. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_enaphxtofhangimg_FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.csv +0 -0
  408. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultraimgrates_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  409. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimgevent_FM45_7P_Phi00_BeamCal_LinearScan_phi004_theta-001_20230821T121304.csv +0 -0
  410. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E1.cdf +0 -0
  411. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E12.cdf +0 -0
  412. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E24.cdf +0 -0
  413. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
  414. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
  415. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
@@ -5,7 +5,16 @@ 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
+ SUMMED_PARTICLE_ENERGY_RANGE_MAPPING,
10
+ calculate_rates,
11
+ hit_l1b,
12
+ process_sectored_rates_data,
13
+ process_standard_rates_data,
14
+ process_summed_rates_data,
15
+ subset_data_for_sectored_counts,
16
+ sum_livetime_10min,
17
+ )
9
18
  from imap_processing.tests.hit.helpers.l1_validation import (
10
19
  prepare_standard_rates_validation_data,
11
20
  )
@@ -31,53 +40,188 @@ def sci_packet_filepath():
31
40
  return imap_module_directory / "tests/hit/test_data/sci_sample.ccsds"
32
41
 
33
42
 
34
- @pytest.fixture()
43
+ @pytest.fixture
35
44
  def dependencies(packet_filepath, sci_packet_filepath):
36
45
  """Get dependencies for L1B processing"""
37
46
  # Create dictionary of dependencies and add CCSDS packet file
38
47
  data_dict = {"imap_hit_l0_raw": packet_filepath}
39
48
  # Add L1A datasets
40
- l1a_datasets = hit_l1a.hit_l1a(packet_filepath, "001")
49
+ l1a_datasets = hit_l1a.hit_l1a(packet_filepath)
41
50
  # TODO: Remove this when HIT provides a packet file with all apids.
42
- l1a_datasets.extend(hit_l1a.hit_l1a(sci_packet_filepath, "001"))
51
+ l1a_datasets.extend(hit_l1a.hit_l1a(sci_packet_filepath))
43
52
  for dataset in l1a_datasets:
44
53
  data_dict[dataset.attrs["Logical_source"]] = dataset
45
54
  return data_dict
46
55
 
47
56
 
48
- @pytest.fixture()
57
+ @pytest.fixture
49
58
  def l1b_hk_dataset(dependencies):
50
59
  """Get the housekeeping dataset"""
51
- datasets = hit_l1b.hit_l1b(dependencies, "001")
60
+ datasets = hit_l1b(dependencies)
52
61
  for dataset in datasets:
53
62
  if dataset.attrs["Logical_source"] == "imap_hit_l1b_hk":
54
63
  return dataset
55
64
 
56
65
 
57
- @pytest.fixture()
66
+ @pytest.fixture
58
67
  def l1b_standard_rates_dataset(dependencies):
59
68
  """Get the standard rates dataset"""
60
- # TODO: use this fixture in future unit test to validate the standard rates dataset
61
- datasets = hit_l1b.hit_l1b(dependencies, "001")
69
+ datasets = hit_l1b(dependencies)
62
70
  for dataset in datasets:
63
71
  if dataset.attrs["Logical_source"] == "imap_hit_l1b_standard-rates":
64
72
  return dataset
65
73
 
66
74
 
67
- @pytest.fixture()
75
+ @pytest.fixture
68
76
  def l1a_counts_dataset(sci_packet_filepath):
69
77
  """Get L1A counts dataset to test l1b processing functions"""
70
- l1a_datasets = hit_l1a.hit_l1a(sci_packet_filepath, "001")
78
+ l1a_datasets = hit_l1a.hit_l1a(sci_packet_filepath)
71
79
  for dataset in l1a_datasets:
72
- if dataset.attrs["Logical_source"] == "imap_hit_l1a_count-rates":
80
+ if dataset.attrs["Logical_source"] == "imap_hit_l1a_counts":
73
81
  return dataset
74
82
 
75
83
 
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)
84
+ @pytest.fixture
85
+ def livetime(l1a_counts_dataset: xr.Dataset) -> xr.DataArray:
86
+ """Calculate livetime for L1A counts dataset"""
87
+ return xr.DataArray(l1a_counts_dataset["livetime_counter"] / 270)
88
+
89
+
90
+ def test_calculate_rates():
91
+ """Test the calculate_rates function"""
92
+
93
+ # Create a sample dataset
94
+ data = {
95
+ "counts": (("epoch",), np.array([100, 200, 300], dtype=np.float32)),
96
+ "counts_stat_uncert_minus": (
97
+ ("epoch",),
98
+ np.array([10, 20, 30], dtype=np.float32),
99
+ ),
100
+ "counts_stat_uncert_plus": (
101
+ ("epoch",),
102
+ np.array([15, 25, 35], dtype=np.float32),
103
+ ),
104
+ }
105
+ coords = {"epoch": np.array([0, 1, 2], dtype=np.float32)}
106
+ dataset = xr.Dataset(data, coords=coords)
107
+
108
+ # Create a sample livetime array
109
+ livetime = xr.DataArray(np.array([10, 20, 30], dtype=np.float32), dims="epoch")
110
+
111
+ # Call the function
112
+ result = calculate_rates(dataset, "counts", livetime)
113
+
114
+ # Check the results
115
+ expected_counts = np.array([10, 10, 10], dtype=np.float32)
116
+ expected_counts_uncert_minus = np.array([1, 1, 1], dtype=np.float32)
117
+ expected_counts_uncert_plus = np.array([1.5, 1.25, 1.1666666], dtype=np.float32)
118
+
119
+ np.testing.assert_allclose(result["counts"].values, expected_counts)
120
+ np.testing.assert_allclose(
121
+ result["counts_stat_uncert_minus"].values, expected_counts_uncert_minus
122
+ )
123
+ np.testing.assert_allclose(
124
+ result["counts_stat_uncert_plus"].values, expected_counts_uncert_plus
125
+ )
126
+
127
+
128
+ def test_sum_livetime_10min():
129
+ """Test the sum_livetime_10min function."""
130
+ # Create a sample livetime DataArray
131
+ livetime_values = np.arange(1, 31) # 30 epochs with values 1 to 30
132
+ livetime = xr.DataArray(
133
+ livetime_values, dims=["epoch"], coords={"epoch": np.arange(30)}
134
+ )
135
+
136
+ # Expected result: sum of every 10 values repeated 10 times
137
+ expected_values = np.repeat(
138
+ [sum(livetime_values[i : i + 10]) for i in range(0, 30, 10)], 10
139
+ )
140
+ expected_livetime = xr.DataArray(
141
+ expected_values, dims=["epoch"], coords={"epoch": np.arange(30)}
142
+ )
143
+
144
+ # Call the function
145
+ result = sum_livetime_10min(livetime)
146
+
147
+ # Assert the result is as expected
148
+ xr.testing.assert_equal(result, expected_livetime)
149
+
150
+
151
+ def test_subset_data_for_sectored_counts():
152
+ """Test the subset_data_for_sectored_counts function."""
153
+ # Create a sample L1A counts dataset
154
+ l1a_counts_dataset = xr.Dataset(
155
+ {
156
+ "hdr_minute_cnt": ("epoch", np.arange(105, 135)),
157
+ "h_sectored_counts": ("epoch", np.arange(0, 30)),
158
+ "he4_sectored_counts": ("epoch", np.arange(0, 30)),
159
+ },
160
+ )
161
+
162
+ # Create a sample livetime data array
163
+ livetime = xr.DataArray(np.arange(1.0, 31.0, dtype=np.float32), dims=["epoch"])
164
+
165
+ # Call the function
166
+ subset_dataset, subset_livetime = subset_data_for_sectored_counts(
167
+ l1a_counts_dataset, livetime
168
+ )
169
+
170
+ # Check the results
171
+ assert subset_dataset.dims["epoch"] == 10
172
+ assert len(subset_livetime["epoch"]) == 10
173
+ assert np.all(subset_dataset["hdr_minute_cnt"].values % 10 == np.arange(10))
174
+
175
+
176
+ def test_process_summed_rates_data(l1a_counts_dataset, livetime):
177
+ """Test the variables in the summed rates dataset"""
178
+
179
+ l1b_summed_rates_dataset = process_summed_rates_data(l1a_counts_dataset, livetime)
180
+
181
+ # Check that a xarray dataset is returned
182
+ assert isinstance(l1b_summed_rates_dataset, xr.Dataset)
183
+
184
+ valid_coords = {
185
+ "epoch",
186
+ "h_energy_mean",
187
+ "he3_energy_mean",
188
+ "he4_energy_mean",
189
+ "he_energy_mean",
190
+ "c_energy_mean",
191
+ "o_energy_mean",
192
+ "fe_energy_mean",
193
+ "n_energy_mean",
194
+ "si_energy_mean",
195
+ "mg_energy_mean",
196
+ "s_energy_mean",
197
+ "ar_energy_mean",
198
+ "ca_energy_mean",
199
+ "na_energy_mean",
200
+ "al_energy_mean",
201
+ "ne_energy_mean",
202
+ "ni_energy_mean",
203
+ }
204
+
205
+ # Check that the dataset has the correct coords and variables
206
+ assert valid_coords == set(l1b_summed_rates_dataset.coords), "Coordinates mismatch"
207
+
208
+ assert "dynamic_threshold_state" in l1b_summed_rates_dataset.data_vars
209
+
210
+ for particle in SUMMED_PARTICLE_ENERGY_RANGE_MAPPING.keys():
211
+ assert f"{particle}" in l1b_summed_rates_dataset.data_vars
212
+ assert f"{particle}_stat_uncert_minus" in l1b_summed_rates_dataset.data_vars
213
+ assert f"{particle}_stat_uncert_plus" in l1b_summed_rates_dataset.data_vars
214
+ assert f"{particle}_energy_delta_minus" in l1b_summed_rates_dataset.data_vars
215
+ assert f"{particle}_energy_delta_plus" in l1b_summed_rates_dataset.data_vars
216
+
217
+
218
+ def test_process_standard_rates_data(l1a_counts_dataset, livetime):
219
+ """Test the variables in the standard rates dataset"""
220
+ l1b_standard_rates_dataset = process_standard_rates_data(
221
+ l1a_counts_dataset, livetime
222
+ )
79
223
 
80
- # Check that a xarray dataset with the correct logical source is returned
224
+ # Check that a xarray dataset is returned
81
225
  assert isinstance(l1b_standard_rates_dataset, xr.Dataset)
82
226
 
83
227
  # Define the data variables that should be present in the dataset
@@ -94,30 +238,30 @@ def test_process_standard_rates_data(l1a_counts_dataset):
94
238
  "ialirtrates",
95
239
  "l4fgrates",
96
240
  "l4bgrates",
97
- "sngrates_delta_plus",
98
- "coinrates_delta_plus",
99
- "pbufrates_delta_plus",
100
- "l2fgrates_delta_plus",
101
- "l2bgrates_delta_plus",
102
- "l3fgrates_delta_plus",
103
- "l3bgrates_delta_plus",
104
- "penfgrates_delta_plus",
105
- "penbgrates_delta_plus",
106
- "ialirtrates_delta_plus",
107
- "l4fgrates_delta_plus",
108
- "l4bgrates_delta_plus",
109
- "sngrates_delta_minus",
110
- "coinrates_delta_minus",
111
- "pbufrates_delta_minus",
112
- "l2fgrates_delta_minus",
113
- "l2bgrates_delta_minus",
114
- "l3fgrates_delta_minus",
115
- "l3bgrates_delta_minus",
116
- "penfgrates_delta_minus",
117
- "penbgrates_delta_minus",
118
- "ialirtrates_delta_minus",
119
- "l4fgrates_delta_minus",
120
- "l4bgrates_delta_minus",
241
+ "sngrates_stat_uncert_plus",
242
+ "coinrates_stat_uncert_plus",
243
+ "pbufrates_stat_uncert_plus",
244
+ "l2fgrates_stat_uncert_plus",
245
+ "l2bgrates_stat_uncert_plus",
246
+ "l3fgrates_stat_uncert_plus",
247
+ "l3bgrates_stat_uncert_plus",
248
+ "penfgrates_stat_uncert_plus",
249
+ "penbgrates_stat_uncert_plus",
250
+ "ialirtrates_stat_uncert_plus",
251
+ "l4fgrates_stat_uncert_plus",
252
+ "l4bgrates_stat_uncert_plus",
253
+ "sngrates_stat_uncert_minus",
254
+ "coinrates_stat_uncert_minus",
255
+ "pbufrates_stat_uncert_minus",
256
+ "l2fgrates_stat_uncert_minus",
257
+ "l2bgrates_stat_uncert_minus",
258
+ "l3fgrates_stat_uncert_minus",
259
+ "l3bgrates_stat_uncert_minus",
260
+ "penfgrates_stat_uncert_minus",
261
+ "penbgrates_stat_uncert_minus",
262
+ "ialirtrates_stat_uncert_minus",
263
+ "l4fgrates_stat_uncert_minus",
264
+ "l4bgrates_stat_uncert_minus",
121
265
  "dynamic_threshold_state",
122
266
  }
123
267
 
@@ -139,12 +283,49 @@ def test_process_standard_rates_data(l1a_counts_dataset):
139
283
  ]
140
284
 
141
285
  # Check that the dataset has the correct variables
142
- assert valid_data_vars == set(
143
- l1b_standard_rates_dataset.data_vars.keys()
144
- ), "Data variables mismatch"
145
- assert valid_coords == list(
146
- l1b_standard_rates_dataset.coords
147
- ), "Coordinates mismatch"
286
+ assert valid_data_vars == set(l1b_standard_rates_dataset.data_vars.keys()), (
287
+ "Data variables mismatch"
288
+ )
289
+ assert valid_coords == list(l1b_standard_rates_dataset.coords), (
290
+ "Coordinates mismatch"
291
+ )
292
+
293
+
294
+ def test_process_sectored_rates_data(l1a_counts_dataset, livetime):
295
+ """Test the variables in the sectored rates dataset"""
296
+
297
+ l1b_sectored_rates_dataset = process_sectored_rates_data(
298
+ l1a_counts_dataset, livetime
299
+ )
300
+
301
+ # Check that a xarray dataset is returned
302
+ assert isinstance(l1b_sectored_rates_dataset, xr.Dataset)
303
+
304
+ valid_coords = {
305
+ "epoch",
306
+ "declination",
307
+ "azimuth",
308
+ "h_energy_mean",
309
+ "he4_energy_mean",
310
+ "cno_energy_mean",
311
+ "nemgsi_energy_mean",
312
+ "fe_energy_mean",
313
+ }
314
+
315
+ # Check that the dataset has the correct coords and variables
316
+ assert valid_coords == set(l1b_sectored_rates_dataset.coords), (
317
+ "Coordinates mismatch"
318
+ )
319
+
320
+ assert "dynamic_threshold_state" in l1b_sectored_rates_dataset.data_vars
321
+
322
+ particles = ["h", "he4", "cno", "nemgsi", "fe"]
323
+ for particle in particles:
324
+ assert f"{particle}" in l1b_sectored_rates_dataset.data_vars
325
+ assert f"{particle}_stat_uncert_minus" in l1b_sectored_rates_dataset.data_vars
326
+ assert f"{particle}_stat_uncert_plus" in l1b_sectored_rates_dataset.data_vars
327
+ assert f"{particle}_energy_delta_minus" in l1b_sectored_rates_dataset.data_vars
328
+ assert f"{particle}_energy_delta_plus" in l1b_sectored_rates_dataset.data_vars
148
329
 
149
330
 
150
331
  def test_hit_l1b_hk_dataset_variables(l1b_hk_dataset):
@@ -152,7 +333,6 @@ def test_hit_l1b_hk_dataset_variables(l1b_hk_dataset):
152
333
  # Define the keys that should have dropped from the housekeeping dataset
153
334
  dropped_keys = {
154
335
  "pkt_apid",
155
- "sc_tick",
156
336
  "version",
157
337
  "type",
158
338
  "sec_hdr_flg",
@@ -167,6 +347,7 @@ def test_hit_l1b_hk_dataset_variables(l1b_hk_dataset):
167
347
  }
168
348
  # Define the keys that should be present in the housekeeping dataset
169
349
  valid_keys = {
350
+ "sc_tick",
170
351
  "heater_on",
171
352
  "fsw_version_b",
172
353
  "ebox_m12va",
@@ -239,16 +420,13 @@ def test_validate_l1b_hk_data(l1b_hk_dataset):
239
420
 
240
421
  Parameters
241
422
  ----------
242
- hk_dataset : xr.Dataset
243
- Housekeeping dataset created by the L1B processing.
423
+ l1b_hk_dataset : xr.Dataset
424
+ Housekeeping dataset created by L1B processing.
244
425
  """
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
426
 
249
427
  # Load the validation data
250
428
  validation_file = (
251
- imap_module_directory / "tests/hit/validation_data/hskp_sample_eu.csv"
429
+ imap_module_directory / "tests/hit/validation_data/hskp_sample_eu_3_6_2025.csv"
252
430
  )
253
431
  validation_data = pd.read_csv(validation_file)
254
432
  validation_data.columns = validation_data.columns.str.lower().str.strip()
@@ -260,14 +438,13 @@ def test_validate_l1b_hk_data(l1b_hk_dataset):
260
438
  col for col in validation_data.columns if col.startswith("leak_i_")
261
439
  ][::-1]
262
440
  validation_data["leak_i"] = validation_data[leak_columns].apply(
263
- lambda row: row.values, axis=1
441
+ lambda row: row.values.astype(np.float64), axis=1
264
442
  )
265
443
  validation_data.drop(columns=leak_columns, inplace=True)
266
444
 
267
445
  # Define the keys that should have dropped from the housekeeping dataset
268
446
  dropped_fields = {
269
447
  "pkt_apid",
270
- "sc_tick",
271
448
  "version",
272
449
  "type",
273
450
  "sec_hdr_flg",
@@ -284,29 +461,47 @@ def test_validate_l1b_hk_data(l1b_hk_dataset):
284
461
  # Check that dropped variables are not in the dataset
285
462
  assert set(dropped_fields).isdisjoint(set(l1b_hk_dataset.data_vars.keys()))
286
463
 
287
- # TODO: uncomment block after new validation data is provided
288
464
  # Define the keys that should be ignored in the validation
289
465
  # 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
- # )
466
+ ignore_validation_fields = {
467
+ "ccsds_version",
468
+ "ccsds_type",
469
+ "ccsds_sec_hdr_flag",
470
+ "ccsds_appid",
471
+ "ccsds_grp_flag",
472
+ "ccsds_seq_cnt",
473
+ "ccsds_length",
474
+ "sc_tick",
475
+ }
476
+
477
+ for field in validation_data.columns:
478
+ if field not in ignore_validation_fields:
479
+ assert field in l1b_hk_dataset.data_vars.keys()
480
+ if field == "leak_i":
481
+ # Compare leak_i arrays
482
+ # Reshape validation_data to match the shape of l1b_hk_dataset
483
+ reshaped_validation_data = np.vstack(validation_data[field].values)
484
+ # Compare leak_i arrays
485
+ np.testing.assert_allclose(
486
+ l1b_hk_dataset[field].values.astype(np.float64),
487
+ reshaped_validation_data,
488
+ atol=1e-2,
489
+ err_msg=f"Mismatch in {field}",
490
+ )
491
+ elif l1b_hk_dataset[field].dtype.kind == "U":
492
+ np.testing.assert_array_equal(
493
+ l1b_hk_dataset[field].values,
494
+ validation_data[field].str.strip().values,
495
+ err_msg=f"Mismatch in {field}",
496
+ )
497
+ else:
498
+ # Compare float values
499
+ np.testing.assert_allclose(
500
+ l1b_hk_dataset[field].values.astype(np.float64),
501
+ validation_data[field].values,
502
+ atol=1e-2,
503
+ err_msg=f"Mismatch in {field}",
504
+ )
310
505
 
311
506
 
312
507
  def test_validate_l1b_standard_rates_data(l1b_standard_rates_dataset):
@@ -320,9 +515,9 @@ def test_validate_l1b_standard_rates_data(l1b_standard_rates_dataset):
320
515
  validation_data = prepare_standard_rates_validation_data(validation_data)
321
516
 
322
517
  for field in validation_data.columns:
323
- assert (
324
- field in l1b_standard_rates_dataset.data_vars.keys()
325
- ), f"Field {field} not found in actual data variables"
518
+ assert field in l1b_standard_rates_dataset.data_vars.keys(), (
519
+ f"Field {field} not found in actual data variables"
520
+ )
326
521
  for frame in range(validation_data.shape[0]):
327
522
  np.testing.assert_allclose(
328
523
  l1b_standard_rates_dataset[field][frame].data,
@@ -333,6 +528,28 @@ def test_validate_l1b_standard_rates_data(l1b_standard_rates_dataset):
333
528
  )
334
529
 
335
530
 
531
+ def test_hit_l1b_missing_apid(sci_packet_filepath):
532
+ """Test missing housekeeping apid from packet file
533
+
534
+ Check that no L1B datasets are created when the housekeeping
535
+ apid is missing from the L0 file path dependency since APIDs
536
+ are currently in separate packet files.
537
+
538
+ In the future, all HIT APIDs will be included in the same packet file.
539
+
540
+ Parameters
541
+ ----------
542
+ sci_packet_filepath : str
543
+ Science CCSDS packet file path. Only contains science APID and is
544
+ missing the housekeeping APID.
545
+ """
546
+ # Create a dependency dictionary with a science CCSDS packet file
547
+ # excluding the housekeeping apid
548
+ dependency = {"imap_hit_l0_raw": sci_packet_filepath}
549
+ datasets = hit_l1b(dependency)
550
+ assert len(datasets) == 0
551
+
552
+
336
553
  def test_hit_l1b(dependencies):
337
554
  """Test creating L1B CDF files
338
555
 
@@ -344,10 +561,12 @@ def test_hit_l1b(dependencies):
344
561
  Dictionary of L1A datasets and CCSDS packet file path
345
562
  """
346
563
  # TODO: update assertions after science data processing is completed
347
- datasets = hit_l1b.hit_l1b(dependencies, "001")
564
+ datasets = hit_l1b(dependencies)
348
565
 
349
- assert len(datasets) == 2
566
+ assert len(datasets) == 4
350
567
  for dataset in datasets:
351
568
  assert isinstance(dataset, xr.Dataset)
352
569
  assert datasets[0].attrs["Logical_source"] == "imap_hit_l1b_hk"
353
570
  assert datasets[1].attrs["Logical_source"] == "imap_hit_l1b_standard-rates"
571
+ assert datasets[2].attrs["Logical_source"] == "imap_hit_l1b_summed-rates"
572
+ assert datasets[3].attrs["Logical_source"] == "imap_hit_l1b_sectored-rates"