imap-processing 0.12.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 (272) hide show
  1. imap_processing/__init__.py +1 -0
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/ccsds_data.py +1 -2
  4. imap_processing/ccsds/excel_to_xtce.py +1 -2
  5. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +18 -12
  6. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +569 -0
  7. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
  8. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +5 -5
  9. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +20 -1
  10. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +6 -4
  11. imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +3 -3
  12. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +15 -0
  13. imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
  14. imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +16 -0
  15. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +178 -5
  16. imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
  17. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +33 -19
  18. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +8 -48
  19. imap_processing/cdf/utils.py +41 -33
  20. imap_processing/cli.py +463 -234
  21. imap_processing/codice/codice_l1a.py +260 -47
  22. imap_processing/codice/codice_l1b.py +51 -152
  23. imap_processing/codice/constants.py +38 -1
  24. imap_processing/ena_maps/ena_maps.py +658 -65
  25. imap_processing/ena_maps/utils/coordinates.py +1 -1
  26. imap_processing/ena_maps/utils/spatial_utils.py +10 -5
  27. imap_processing/glows/l1a/glows_l1a.py +28 -99
  28. imap_processing/glows/l1a/glows_l1a_data.py +2 -2
  29. imap_processing/glows/l1b/glows_l1b.py +1 -4
  30. imap_processing/glows/l1b/glows_l1b_data.py +1 -3
  31. imap_processing/glows/l2/glows_l2.py +2 -5
  32. imap_processing/hi/l1a/hi_l1a.py +31 -12
  33. imap_processing/hi/l1b/hi_l1b.py +80 -43
  34. imap_processing/hi/l1c/hi_l1c.py +12 -16
  35. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
  36. imap_processing/hit/hit_utils.py +93 -35
  37. imap_processing/hit/l0/decom_hit.py +3 -1
  38. imap_processing/hit/l1a/hit_l1a.py +30 -25
  39. imap_processing/hit/l1b/constants.py +6 -2
  40. imap_processing/hit/l1b/hit_l1b.py +279 -318
  41. imap_processing/hit/l2/constants.py +37 -0
  42. imap_processing/hit/l2/hit_l2.py +373 -264
  43. imap_processing/ialirt/l0/parse_mag.py +138 -10
  44. imap_processing/ialirt/l0/process_swapi.py +69 -0
  45. imap_processing/ialirt/l0/process_swe.py +318 -22
  46. imap_processing/ialirt/packet_definitions/ialirt.xml +216 -212
  47. imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +1 -1
  48. imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +1 -1
  49. imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
  50. imap_processing/ialirt/utils/grouping.py +1 -1
  51. imap_processing/idex/idex_constants.py +9 -1
  52. imap_processing/idex/idex_l0.py +22 -8
  53. imap_processing/idex/idex_l1a.py +75 -44
  54. imap_processing/idex/idex_l1b.py +9 -8
  55. imap_processing/idex/idex_l2a.py +79 -45
  56. imap_processing/idex/idex_l2b.py +120 -0
  57. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -39
  58. imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
  59. imap_processing/lo/l0/lo_science.py +1 -2
  60. imap_processing/lo/l1a/lo_l1a.py +1 -4
  61. imap_processing/lo/l1b/lo_l1b.py +527 -6
  62. imap_processing/lo/l1b/tof_conversions.py +11 -0
  63. imap_processing/lo/l1c/lo_l1c.py +1 -4
  64. imap_processing/mag/constants.py +43 -0
  65. imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
  66. imap_processing/mag/l1a/mag_l1a.py +2 -9
  67. imap_processing/mag/l1a/mag_l1a_data.py +10 -10
  68. imap_processing/mag/l1b/mag_l1b.py +84 -17
  69. imap_processing/mag/l1c/interpolation_methods.py +180 -3
  70. imap_processing/mag/l1c/mag_l1c.py +236 -70
  71. imap_processing/mag/l2/mag_l2.py +140 -0
  72. imap_processing/mag/l2/mag_l2_data.py +288 -0
  73. imap_processing/spacecraft/quaternions.py +1 -3
  74. imap_processing/spice/geometry.py +3 -3
  75. imap_processing/spice/kernels.py +0 -276
  76. imap_processing/spice/pointing_frame.py +257 -0
  77. imap_processing/spice/repoint.py +48 -19
  78. imap_processing/spice/spin.py +38 -33
  79. imap_processing/spice/time.py +24 -0
  80. imap_processing/swapi/l1/swapi_l1.py +16 -12
  81. imap_processing/swapi/l2/swapi_l2.py +116 -4
  82. imap_processing/swapi/swapi_utils.py +32 -0
  83. imap_processing/swe/l1a/swe_l1a.py +2 -9
  84. imap_processing/swe/l1a/swe_science.py +8 -11
  85. imap_processing/swe/l1b/swe_l1b.py +898 -23
  86. imap_processing/swe/l2/swe_l2.py +21 -77
  87. imap_processing/swe/utils/swe_constants.py +1 -0
  88. imap_processing/tests/ccsds/test_excel_to_xtce.py +1 -1
  89. imap_processing/tests/cdf/test_utils.py +14 -16
  90. imap_processing/tests/codice/conftest.py +44 -33
  91. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
  92. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
  93. imap_processing/tests/codice/test_codice_l1a.py +20 -11
  94. imap_processing/tests/codice/test_codice_l1b.py +6 -7
  95. imap_processing/tests/conftest.py +78 -22
  96. imap_processing/tests/ena_maps/test_ena_maps.py +462 -33
  97. imap_processing/tests/ena_maps/test_spatial_utils.py +1 -1
  98. imap_processing/tests/glows/conftest.py +10 -14
  99. imap_processing/tests/glows/test_glows_decom.py +4 -4
  100. imap_processing/tests/glows/test_glows_l1a_cdf.py +6 -27
  101. imap_processing/tests/glows/test_glows_l1a_data.py +6 -8
  102. imap_processing/tests/glows/test_glows_l1b.py +11 -11
  103. imap_processing/tests/glows/test_glows_l1b_data.py +5 -5
  104. imap_processing/tests/glows/test_glows_l2.py +2 -8
  105. imap_processing/tests/hi/conftest.py +1 -1
  106. imap_processing/tests/hi/test_hi_l1b.py +10 -12
  107. imap_processing/tests/hi/test_hi_l1c.py +27 -24
  108. imap_processing/tests/hi/test_l1a.py +7 -9
  109. imap_processing/tests/hi/test_science_direct_event.py +2 -2
  110. imap_processing/tests/hit/helpers/l1_validation.py +44 -43
  111. imap_processing/tests/hit/test_decom_hit.py +1 -1
  112. imap_processing/tests/hit/test_hit_l1a.py +9 -9
  113. imap_processing/tests/hit/test_hit_l1b.py +172 -217
  114. imap_processing/tests/hit/test_hit_l2.py +380 -118
  115. imap_processing/tests/hit/test_hit_utils.py +122 -55
  116. imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
  117. imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
  118. imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
  119. imap_processing/tests/ialirt/unit/test_grouping.py +2 -2
  120. imap_processing/tests/ialirt/unit/test_parse_mag.py +71 -16
  121. imap_processing/tests/ialirt/unit/test_process_codicehi.py +3 -3
  122. imap_processing/tests/ialirt/unit/test_process_codicelo.py +3 -10
  123. imap_processing/tests/ialirt/unit/test_process_ephemeris.py +4 -4
  124. imap_processing/tests/ialirt/unit/test_process_hit.py +3 -3
  125. imap_processing/tests/ialirt/unit/test_process_swapi.py +24 -16
  126. imap_processing/tests/ialirt/unit/test_process_swe.py +115 -7
  127. imap_processing/tests/idex/conftest.py +72 -7
  128. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20241206_v001.pkts +0 -0
  129. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20250108_v001.pkts +0 -0
  130. imap_processing/tests/idex/test_idex_l0.py +33 -11
  131. imap_processing/tests/idex/test_idex_l1a.py +50 -23
  132. imap_processing/tests/idex/test_idex_l1b.py +104 -25
  133. imap_processing/tests/idex/test_idex_l2a.py +48 -32
  134. imap_processing/tests/idex/test_idex_l2b.py +93 -0
  135. imap_processing/tests/lo/test_lo_l1a.py +3 -3
  136. imap_processing/tests/lo/test_lo_l1b.py +371 -6
  137. imap_processing/tests/lo/test_lo_l1c.py +1 -1
  138. imap_processing/tests/lo/test_lo_science.py +6 -7
  139. imap_processing/tests/lo/test_star_sensor.py +1 -1
  140. imap_processing/tests/mag/conftest.py +58 -9
  141. imap_processing/tests/mag/test_mag_decom.py +4 -3
  142. imap_processing/tests/mag/test_mag_l1a.py +13 -7
  143. imap_processing/tests/mag/test_mag_l1b.py +9 -9
  144. imap_processing/tests/mag/test_mag_l1c.py +151 -47
  145. imap_processing/tests/mag/test_mag_l2.py +130 -0
  146. imap_processing/tests/mag/test_mag_validation.py +144 -7
  147. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-in.csv +1217 -0
  148. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-out.csv +1857 -0
  149. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-in.csv +1217 -0
  150. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-out.csv +1857 -0
  151. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-in.csv +1217 -0
  152. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-out.csv +1793 -0
  153. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-in.csv +1217 -0
  154. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-out.csv +1793 -0
  155. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-burst-in.csv +2561 -0
  156. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-in.csv +961 -0
  157. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-out.csv +1539 -0
  158. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-in.csv +1921 -0
  159. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-out.csv +2499 -0
  160. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-in.csv +865 -0
  161. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv +1196 -0
  162. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-in.csv +1729 -0
  163. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv +3053 -0
  164. imap_processing/tests/mag/validation/L2/imap_mag_l1b_norm-mago_20251017_v002.cdf +0 -0
  165. imap_processing/tests/mag/validation/calibration/imap_mag_l2-calibration-matrices_20251017_v004.cdf +0 -0
  166. imap_processing/tests/mag/validation/calibration/imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf +0 -0
  167. imap_processing/tests/spacecraft/test_quaternions.py +1 -1
  168. imap_processing/tests/spice/test_data/fake_repoint_data.csv +4 -4
  169. imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
  170. imap_processing/tests/spice/test_geometry.py +3 -3
  171. imap_processing/tests/spice/test_kernels.py +1 -200
  172. imap_processing/tests/spice/test_pointing_frame.py +185 -0
  173. imap_processing/tests/spice/test_repoint.py +20 -10
  174. imap_processing/tests/spice/test_spin.py +50 -9
  175. imap_processing/tests/spice/test_time.py +14 -0
  176. imap_processing/tests/swapi/lut/imap_swapi_esa-unit-conversion_20250211_v000.csv +73 -0
  177. imap_processing/tests/swapi/lut/imap_swapi_lut-notes_20250211_v000.csv +1025 -0
  178. imap_processing/tests/swapi/test_swapi_l1.py +7 -9
  179. imap_processing/tests/swapi/test_swapi_l2.py +180 -8
  180. imap_processing/tests/swe/lut/checker-board-indices.csv +24 -0
  181. imap_processing/tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv +385 -0
  182. imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv +3 -0
  183. imap_processing/tests/swe/test_swe_l1a.py +6 -6
  184. imap_processing/tests/swe/test_swe_l1a_science.py +3 -3
  185. imap_processing/tests/swe/test_swe_l1b.py +162 -24
  186. imap_processing/tests/swe/test_swe_l2.py +82 -102
  187. imap_processing/tests/test_cli.py +171 -88
  188. imap_processing/tests/test_utils.py +2 -1
  189. imap_processing/tests/ultra/data/mock_data.py +49 -21
  190. imap_processing/tests/ultra/unit/conftest.py +53 -70
  191. imap_processing/tests/ultra/unit/test_badtimes.py +2 -4
  192. imap_processing/tests/ultra/unit/test_cullingmask.py +4 -6
  193. imap_processing/tests/ultra/unit/test_de.py +3 -10
  194. imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
  195. imap_processing/tests/ultra/unit/test_decom_apid_881.py +15 -16
  196. imap_processing/tests/ultra/unit/test_decom_apid_883.py +12 -10
  197. imap_processing/tests/ultra/unit/test_decom_apid_896.py +202 -55
  198. imap_processing/tests/ultra/unit/test_lookup_utils.py +23 -1
  199. imap_processing/tests/ultra/unit/test_spacecraft_pset.py +3 -4
  200. imap_processing/tests/ultra/unit/test_ultra_l1a.py +84 -307
  201. imap_processing/tests/ultra/unit/test_ultra_l1b.py +30 -12
  202. imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
  203. imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +4 -1
  204. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +163 -29
  205. imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
  206. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +32 -43
  207. imap_processing/tests/ultra/unit/test_ultra_l2.py +230 -0
  208. imap_processing/ultra/constants.py +1 -1
  209. imap_processing/ultra/l0/decom_tools.py +21 -34
  210. imap_processing/ultra/l0/decom_ultra.py +168 -204
  211. imap_processing/ultra/l0/ultra_utils.py +152 -136
  212. imap_processing/ultra/l1a/ultra_l1a.py +55 -243
  213. imap_processing/ultra/l1b/badtimes.py +1 -4
  214. imap_processing/ultra/l1b/cullingmask.py +2 -6
  215. imap_processing/ultra/l1b/de.py +62 -47
  216. imap_processing/ultra/l1b/extendedspin.py +8 -4
  217. imap_processing/ultra/l1b/lookup_utils.py +72 -9
  218. imap_processing/ultra/l1b/ultra_l1b.py +3 -8
  219. imap_processing/ultra/l1b/ultra_l1b_culling.py +4 -4
  220. imap_processing/ultra/l1b/ultra_l1b_extended.py +236 -78
  221. imap_processing/ultra/l1c/histogram.py +2 -6
  222. imap_processing/ultra/l1c/spacecraft_pset.py +2 -4
  223. imap_processing/ultra/l1c/ultra_l1c.py +1 -5
  224. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +107 -60
  225. imap_processing/ultra/l2/ultra_l2.py +299 -0
  226. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +526 -0
  227. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +526 -0
  228. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +526 -0
  229. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +526 -0
  230. imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -2
  231. imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
  232. imap_processing/ultra/packet_definitions/README.md +38 -0
  233. imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +15302 -482
  234. imap_processing/ultra/utils/ultra_l1_utils.py +13 -12
  235. imap_processing/utils.py +1 -1
  236. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +3 -2
  237. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/RECORD +264 -225
  238. imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
  239. imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +0 -6
  240. imap_processing/mag/l1b/__init__.py +0 -0
  241. imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
  242. imap_processing/swe/l1b/swe_l1b_science.py +0 -699
  243. imap_processing/tests/swe/test_swe_l1b_science.py +0 -103
  244. imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
  245. imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
  246. /imap_processing/idex/packet_definitions/{idex_packet_definition.xml → idex_science_packet_definition.xml} +0 -0
  247. /imap_processing/tests/ialirt/{test_data → data}/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
  248. /imap_processing/tests/ialirt/{test_data → data}/l0/461971383-404.bin +0 -0
  249. /imap_processing/tests/ialirt/{test_data → data}/l0/461971384-405.bin +0 -0
  250. /imap_processing/tests/ialirt/{test_data → data}/l0/461971385-406.bin +0 -0
  251. /imap_processing/tests/ialirt/{test_data → data}/l0/461971386-407.bin +0 -0
  252. /imap_processing/tests/ialirt/{test_data → data}/l0/461971387-408.bin +0 -0
  253. /imap_processing/tests/ialirt/{test_data → data}/l0/461971388-409.bin +0 -0
  254. /imap_processing/tests/ialirt/{test_data → data}/l0/461971389-410.bin +0 -0
  255. /imap_processing/tests/ialirt/{test_data → data}/l0/461971390-411.bin +0 -0
  256. /imap_processing/tests/ialirt/{test_data → data}/l0/461971391-412.bin +0 -0
  257. /imap_processing/tests/ialirt/{test_data → data}/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
  258. /imap_processing/tests/ialirt/{test_data → data}/l0/IALiRT Raw Packet Telemetry.txt +0 -0
  259. /imap_processing/tests/ialirt/{test_data → data}/l0/apid01152.tlm +0 -0
  260. /imap_processing/tests/ialirt/{test_data → data}/l0/eu_SWP_IAL_20240826_152033.csv +0 -0
  261. /imap_processing/tests/ialirt/{test_data → data}/l0/hi_fsw_view_1_ccsds.bin +0 -0
  262. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.ccsds +0 -0
  263. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.csv +0 -0
  264. /imap_processing/tests/ialirt/{test_data → data}/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +0 -0
  265. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
  266. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  267. /imap_processing/tests/ialirt/{test_data → data}/l0/sample_decoded_i-alirt_data.csv +0 -0
  268. /imap_processing/tests/mag/validation/{imap_calibration_mag_20240229_v01.cdf → calibration/imap_mag_l1b-calibration_20240229_v001.cdf} +0 -0
  269. /imap_processing/{swe/l1b/engineering_unit_convert_table.csv → tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv} +0 -0
  270. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
  271. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
  272. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
@@ -6,25 +6,30 @@ import xarray as xr
6
6
  from imap_processing import imap_module_directory
7
7
  from imap_processing.hit.l1a import hit_l1a
8
8
  from imap_processing.hit.l1b.hit_l1b import (
9
- PARTICLE_ENERGY_RANGE_MAPPING,
9
+ SUMMED_PARTICLE_ENERGY_RANGE_MAPPING,
10
10
  hit_l1b,
11
11
  )
12
12
  from imap_processing.hit.l2.hit_l2 import (
13
+ FILLVAL_FLOAT32,
14
+ N_AZIMUTH,
15
+ SECONDS_PER_10_MIN,
16
+ SECONDS_PER_MIN,
13
17
  STANDARD_PARTICLE_ENERGY_RANGE_MAPPING,
14
- IntensityFactors,
18
+ VALID_SECTORED_SPECIES,
15
19
  add_systematic_uncertainties,
20
+ add_total_uncertainties,
21
+ build_ancillary_dataset,
16
22
  calculate_intensities,
17
23
  calculate_intensities_for_a_species,
18
24
  calculate_intensities_for_all_species,
19
- get_intensity_factors,
20
25
  get_species_ancillary_data,
21
26
  hit_l2,
27
+ process_sectored_intensity_data,
22
28
  process_standard_intensity_data,
23
29
  process_summed_intensity_data,
30
+ reshape_for_sectored,
24
31
  )
25
32
 
26
- # TODO: add unit test for add_standard_particle_rates_to_dataset
27
-
28
33
 
29
34
  @pytest.fixture(scope="module")
30
35
  def sci_packet_filepath():
@@ -32,112 +37,239 @@ def sci_packet_filepath():
32
37
  return imap_module_directory / "tests/hit/test_data/sci_sample.ccsds"
33
38
 
34
39
 
35
- @pytest.fixture()
40
+ @pytest.fixture
36
41
  def dependencies(sci_packet_filepath):
37
42
  """Get dependencies for L2 processing"""
38
43
  # Create dictionary of dependencies
39
44
  data_dict = {}
40
- l1a_datasets = hit_l1a.hit_l1a(sci_packet_filepath, "001")
45
+ l1a_datasets = hit_l1a.hit_l1a(sci_packet_filepath)
41
46
  for l1a_dataset in l1a_datasets:
42
47
  l1a_data_dict = {}
43
48
  if l1a_dataset.attrs["Logical_source"] == "imap_hit_l1a_counts":
44
49
  l1a_data_dict["imap_hit_l1a_counts"] = l1a_dataset
45
- l1b_datasets = hit_l1b(l1a_data_dict, "001")
50
+ l1b_datasets = hit_l1b(l1a_data_dict)
46
51
  for l1b_dataset in l1b_datasets:
47
52
  data_dict[l1b_dataset.attrs["Logical_source"]] = l1b_dataset
48
53
  return data_dict
49
54
 
50
55
 
51
- @pytest.fixture()
56
+ @pytest.fixture
52
57
  def l1b_summed_rates_dataset(dependencies):
53
58
  """Get L1B summed rates dataset to test l2 processing function"""
54
59
  return dependencies["imap_hit_l1b_summed-rates"]
55
60
 
56
61
 
57
- @pytest.fixture()
62
+ @pytest.fixture
58
63
  def l1b_standard_rates_dataset(dependencies):
59
64
  """Get L1B standard rates dataset to test l2 processing function"""
60
65
  return dependencies["imap_hit_l1b_standard-rates"]
61
66
 
62
67
 
63
- def test_get_intensity_factors():
64
- """Test the get_intensity_factors function."""
65
- # Sample input data
66
- energy_min = np.array([1.8, 2.2, 2.7], dtype=np.float32)
67
- species_ancillary_data = pd.DataFrame(
68
- {
69
- "lower energy (mev)": [1.8, 2.2, 2.7],
70
- "delta e (mev)": [0.4, 0.5, 0.6],
71
- "geometry factor (cm2 sr)": [1.0, 1.1, 1.2],
72
- "efficiency": [0.9, 0.8, 0.7],
73
- "b": [0.1, 0.2, 0.3],
74
- }
68
+ @pytest.fixture
69
+ def l1b_sectored_rates_dataset(dependencies):
70
+ """Get L1B standard rates dataset to test l2 processing function"""
71
+ return dependencies["imap_hit_l1b_sectored-rates"]
72
+
73
+
74
+ def _check_ancillary_dataset(
75
+ ancillary_ds,
76
+ species_array,
77
+ delta_e,
78
+ geometry_factors,
79
+ efficiencies,
80
+ b,
81
+ expected_delta_time,
82
+ ):
83
+ # Helper function - not a test
84
+
85
+ shape = species_array.shape
86
+
87
+ # Assert that all expected variables are present
88
+ assert set(ancillary_ds.data_vars) == {
89
+ "delta_e",
90
+ "geometry_factor",
91
+ "efficiency",
92
+ "b",
93
+ "delta_time",
94
+ }
95
+
96
+ # Check that shapes match
97
+ assert ancillary_ds["delta_e"].shape == shape
98
+ assert ancillary_ds["delta_time"].shape == (len(species_array.coords["epoch"]),)
99
+
100
+ # Check values
101
+ np.testing.assert_array_equal(ancillary_ds["delta_e"].values, delta_e)
102
+ np.testing.assert_array_equal(
103
+ ancillary_ds["geometry_factor"].values, geometry_factors
104
+ )
105
+ np.testing.assert_array_equal(ancillary_ds["efficiency"].values, efficiencies)
106
+ np.testing.assert_array_equal(ancillary_ds["b"].values, b)
107
+ np.testing.assert_array_equal(
108
+ ancillary_ds["delta_time"].values,
109
+ np.full(len(species_array.epoch), expected_delta_time),
75
110
  )
76
111
 
77
- # Expected output
78
- expected_factors = IntensityFactors(
79
- delta_e_factor=np.array([0.4, 0.5, 0.6]),
80
- geometry_factor=np.array([1.0, 1.1, 1.2]),
81
- efficiency=np.array([0.9, 0.8, 0.7]),
82
- b=np.array([0.1, 0.2, 0.3]),
112
+ # Check coordinates match
113
+ for coord in species_array.coords:
114
+ assert coord in ancillary_ds.coords
115
+ np.testing.assert_array_equal(
116
+ species_array.coords[coord], ancillary_ds.coords[coord]
117
+ )
118
+
119
+
120
+ def test_build_ancillary_dataset_sectored():
121
+ """
122
+ Test the build_ancillary_dataset function for sectored data
123
+ """
124
+ np.random.seed(42) # Set a random seed for reproducibility
125
+ epoch = np.array(["2025-01-01T00:00", "2025-01-01T00:01"], dtype="datetime64[m]")
126
+ energy_mean = [1.8, 4, 6]
127
+ declination = np.arange(8)
128
+ azimuth = np.arange(15)
129
+
130
+ species_array = xr.DataArray(
131
+ data=np.random.rand(2, 3, 15, 8), # (epoch, energy_mean, azimuth, declination)
132
+ dims=("epoch", "energy_mean", "azimuth", "declination"),
133
+ coords={
134
+ "epoch": epoch,
135
+ "energy_mean": energy_mean,
136
+ "declination": declination,
137
+ "azimuth": azimuth,
138
+ },
139
+ name="h",
83
140
  )
84
141
 
85
- # Call the function
86
- factors = get_intensity_factors(energy_min, species_ancillary_data)
142
+ shape = species_array.shape
143
+ delta_e = np.full(shape, 1.0)
144
+ geometry_factors = np.full(shape, 2.0)
145
+ efficiencies = np.full(shape, 0.5)
146
+ b = np.full(shape, 0.1)
87
147
 
88
- # Assertions
89
- assert np.array_equal(
90
- factors.delta_e_factor, expected_factors.delta_e_factor
91
- ), "Delta E factors mismatch"
92
- assert np.array_equal(
93
- factors.geometry_factor, expected_factors.geometry_factor
94
- ), "Geometry factors mismatch"
95
- assert np.array_equal(
96
- factors.efficiency, expected_factors.efficiency
97
- ), "Efficiency factors mismatch"
98
- assert np.array_equal(factors.b, expected_factors.b), "B factors mismatch"
148
+ ancillary_ds = build_ancillary_dataset(
149
+ delta_e, geometry_factors, efficiencies, b, species_array
150
+ )
151
+ _check_ancillary_dataset(
152
+ ancillary_ds,
153
+ species_array,
154
+ delta_e,
155
+ geometry_factors,
156
+ efficiencies,
157
+ b,
158
+ SECONDS_PER_10_MIN,
159
+ )
160
+
161
+
162
+ def test_build_ancillary_dataset_nonsectored():
163
+ """
164
+ Test the build_ancillary_dataset function for non-sectored data.
165
+
166
+ Non-sectored datasets are either L2 standard or L2 summed datasets
167
+ They both have the same shape (epoch, energy_mean).
168
+ """
169
+ np.random.seed(42) # Set a random seed for reproducibility
170
+ epoch = np.array(["2025-01-01T00:00", "2025-01-01T00:01"], dtype="datetime64[m]")
171
+ energy_mean = [1.8, 4, 6]
172
+
173
+ species_array = xr.DataArray(
174
+ data=np.random.rand(2, 3), # (epoch, energy_mean)
175
+ dims=("epoch", "energy_mean"),
176
+ coords={"epoch": epoch, "energy_mean": energy_mean},
177
+ name="h",
178
+ )
179
+
180
+ shape = species_array.shape
181
+ delta_e = np.full(shape, 1.0)
182
+ geometry_factors = np.full(shape, 2.0)
183
+ efficiencies = np.full(shape, 0.5)
184
+ b = np.full(shape, 0.1)
185
+
186
+ ancillary_ds = build_ancillary_dataset(
187
+ delta_e, geometry_factors, efficiencies, b, species_array
188
+ )
189
+ _check_ancillary_dataset(
190
+ ancillary_ds,
191
+ species_array,
192
+ delta_e,
193
+ geometry_factors,
194
+ efficiencies,
195
+ b,
196
+ SECONDS_PER_MIN,
197
+ )
99
198
 
100
199
 
101
200
  def test_get_species_ancillary_data():
102
201
  """Test the get_species_ancillary_data function."""
103
- # Sample input data
104
- dynamic_threshold_state = 1
202
+
203
+ # Mock ancillary data for dynamic threshold states 0 and 1
105
204
  ancillary_data_frames = {
106
205
  0: pd.DataFrame(
107
206
  {
108
- "species": ["h", "he", "c"],
109
- "lower energy (mev)": [1.0, 2.0, 3.0],
110
- "delta e (mev)": [0.1, 0.2, 0.3],
111
- "geometry factor (cm2 sr)": [1.0, 1.1, 1.2],
112
- "efficiency": [0.9, 0.8, 0.7],
113
- "b": [0.01, 0.02, 0.03],
207
+ "species": ["h", "h", "he", "he"],
208
+ "lower energy (mev)": [1, 2, 1, 2],
209
+ "delta e (mev)": [0.1, 0.2, 0.3, 0.4],
210
+ "geometry factor (cm2 sr)": [10, 20, 30, 40],
211
+ "efficiency": [0.9, 0.8, 0.7, 0.6],
212
+ "b": [0.01, 0.02, 0.03, 0.04],
114
213
  }
115
214
  ),
116
215
  1: pd.DataFrame(
117
216
  {
118
- "species": ["h", "he", "c"],
119
- "lower energy (mev)": [1.0, 2.0, 3.0],
120
- "delta e (mev)": [0.15, 0.25, 0.35],
121
- "geometry factor (cm2 sr)": [1.05, 1.15, 1.25],
122
- "efficiency": [0.85, 0.75, 0.65],
123
- "b": [0.015, 0.025, 0.035],
217
+ "species": ["h", "h", "he", "he"],
218
+ "lower energy (mev)": [1, 2, 1, 2],
219
+ "delta e (mev)": [0.15, 0.25, 0.35, 0.45],
220
+ "geometry factor (cm2 sr)": [15, 25, 35, 45],
221
+ "efficiency": [0.85, 0.75, 0.65, 0.55],
222
+ "b": [0.015, 0.025, 0.035, 0.045],
124
223
  }
125
224
  ),
126
225
  }
127
- species = "h"
128
226
 
129
- # Expected output
130
- expected_output = ancillary_data_frames[dynamic_threshold_state][
131
- ancillary_data_frames[dynamic_threshold_state]["species"] == species
132
- ]
227
+ # Test for dynamic threshold state 0 and species "h"
228
+ result = get_species_ancillary_data(0, ancillary_data_frames, "h")
229
+ expected = {
230
+ "delta_e": np.array([[0.1], [0.2]]),
231
+ "geometry_factor": np.array([[10], [20]]),
232
+ "efficiency": np.array([[0.9], [0.8]]),
233
+ "b": np.array([[0.01], [0.02]]),
234
+ }
235
+ for key, value in expected.items():
236
+ np.testing.assert_array_equal(result[key], value)
237
+
238
+ # Test for dynamic threshold state 1 and species "he"
239
+ result = get_species_ancillary_data(1, ancillary_data_frames, "he")
240
+ expected = {
241
+ "delta_e": np.array([[0.35], [0.45]]),
242
+ "geometry_factor": np.array([[35], [45]]),
243
+ "efficiency": np.array([[0.65], [0.55]]),
244
+ "b": np.array([[0.035], [0.045]]),
245
+ }
246
+ for key in expected:
247
+ np.testing.assert_array_equal(result[key], expected[key])
248
+
249
+
250
+ def test_reshape_for_sectored():
251
+ """
252
+ Test the reshape_for_sectored function.
253
+ """
254
+ # Mock input data: 3D array (epoch, energy, declination)
255
+ np.random.seed(42) # Set a random seed for reproducibility
256
+ epoch, energy, declination = 2, 3, 8
257
+ input_array = np.random.rand(epoch, energy, declination)
258
+
259
+ # Expected output shape: 4D array (epoch, energy, azimuth, declination)
260
+ expected_shape = (epoch, energy, N_AZIMUTH, declination)
133
261
 
134
262
  # Call the function
135
- output = get_species_ancillary_data(
136
- dynamic_threshold_state, ancillary_data_frames, species
137
- )
263
+ reshaped_array = reshape_for_sectored(input_array)
138
264
 
139
265
  # Assertions
140
- pd.testing.assert_frame_equal(output, expected_output)
266
+ assert reshaped_array.shape == expected_shape, "Output shape mismatch"
267
+ for azimuth in range(N_AZIMUTH):
268
+ np.testing.assert_array_equal(
269
+ reshaped_array[:, :, azimuth, :],
270
+ input_array,
271
+ err_msg=f"Mismatch in azimuth dimension {azimuth}",
272
+ )
141
273
 
142
274
 
143
275
  def test_calculate_intensities_for_all_species():
@@ -214,15 +346,23 @@ def test_calculate_intensities_for_all_species():
214
346
  )
215
347
 
216
348
  # Call the function
217
- calculate_intensities_for_all_species(l2_dataset, ancillary_data_frames)
349
+ l2_dataset = calculate_intensities_for_all_species(
350
+ l2_dataset, ancillary_data_frames, valid_data_variables=["h", "ni"]
351
+ )
218
352
 
219
353
  # Assertions
220
- assert np.allclose(
221
- l2_dataset["h"].values, expected_intensities_h.values
222
- ), "Intensities mismatch for H"
223
- assert np.allclose(
224
- l2_dataset["ni"].values, expected_intensities_ni.values
225
- ), "Intensities mismatch for He"
354
+ (
355
+ np.testing.assert_allclose(
356
+ l2_dataset["h"].values, expected_intensities_h.values
357
+ ),
358
+ ("Intensities mismatch for H"),
359
+ )
360
+ (
361
+ np.testing.assert_allclose(
362
+ l2_dataset["ni"].values, expected_intensities_ni.values
363
+ ),
364
+ ("Intensities mismatch for He"),
365
+ )
226
366
 
227
367
 
228
368
  def test_calculate_intensities_for_a_species():
@@ -278,62 +418,176 @@ def test_calculate_intensities_for_a_species():
278
418
  )
279
419
 
280
420
  # Call the function
281
- calculate_intensities_for_a_species(
421
+ l2_dataset = calculate_intensities_for_a_species(
282
422
  species_variable, l2_dataset, ancillary_data_frames
283
423
  )
284
424
 
285
425
  # Assertions
286
- assert np.allclose(
287
- l2_dataset["h"].values, expected_intensities.values
288
- ), "Intensities mismatch"
426
+ (
427
+ np.testing.assert_allclose(l2_dataset["h"].values, expected_intensities.values),
428
+ ("Intensities mismatch"),
429
+ )
289
430
 
290
431
 
291
432
  def test_calculate_intensities():
292
433
  """Test the calculate_intensities function."""
293
- # Sample input data
294
- rate = xr.DataArray([100, 200, 300], dims=["energy_bin"])
295
- delta_e_factor = np.array([1.0, 1.0, 1.0])
296
- geometry_factor = np.array([1.0, 1.0, 1.0])
297
- efficiency = np.array([1.0, 1.0, 1.0])
298
- b = np.array([0.0, 0.0, 0.0])
434
+ # Create sample function inputs
435
+ rates = xr.DataArray(
436
+ data=[10.0, 20.0, FILLVAL_FLOAT32, 40.0],
437
+ dims=["epoch"],
438
+ coords={"epoch": [0, 1, 2, 3]},
439
+ )
440
+ factors = xr.Dataset(
441
+ {
442
+ "delta_time": ("epoch", [60.0, 60.0, 60.0, 60.0]),
443
+ "delta_e": ("epoch", [1.0, 1.0, 1.0, 1.0]),
444
+ "geometry_factor": ("epoch", [2.0, 2.0, 2.0, 2.0]),
445
+ "efficiency": ("epoch", [0.5, 0.5, 0.5, 0.5]),
446
+ "b": ("epoch", [0.0, 0, 0, 0]),
447
+ }
448
+ )
299
449
 
300
450
  # Expected output
301
- expected_intensities = xr.DataArray(
302
- [1.66666667, 3.33333333, 5.0], dims=["energy_bin"]
451
+ expected_intensity = xr.DataArray(
452
+ data=[0.1666667, 0.3333333, FILLVAL_FLOAT32, 0.6666667],
453
+ dims=["epoch"],
454
+ coords={"epoch": [0, 1, 2, 3]},
303
455
  )
304
456
 
305
457
  # Call the function
306
- intensities = calculate_intensities(
307
- rate, delta_e_factor, geometry_factor, efficiency, b
308
- )
458
+ result = calculate_intensities(rates, factors)
309
459
 
310
460
  # Assertions
311
- assert np.allclose(
312
- intensities.values, expected_intensities.values
313
- ), "Intensities mismatch"
461
+ xr.testing.assert_allclose(result, expected_intensity)
314
462
 
315
463
 
316
464
  def test_add_systematic_uncertainties():
317
465
  """Test the add_systematic_uncertainties function."""
318
466
  # Create sample function inputs
467
+ np.random.seed(42) # Set a random seed for reproducibility
319
468
  particle = "h"
320
- energy_ranges = [
321
- {"energy_min": 1.8, "energy_max": 2.2, "R2": [1], "R3": [], "R4": []},
322
- {"energy_min": 2.2, "energy_max": 2.7, "R2": [2], "R3": [], "R4": []},
323
- {"energy_min": 2.7, "energy_max": 3.2, "R2": [3], "R3": [], "R4": []},
469
+ datasets = [
470
+ xr.Dataset(
471
+ {"h": (("epoch", "h_energy_mean"), np.random.rand(2, 3).astype("float32"))}
472
+ ),
473
+ xr.Dataset(
474
+ {
475
+ "h": (
476
+ ("epoch", "h_energy_mean", "azimuth", "declination"),
477
+ np.random.rand(2, 3, 15, 8).astype("float32"),
478
+ )
479
+ }
480
+ ),
324
481
  ]
325
- dataset = xr.Dataset()
482
+
483
+ for dataset in datasets:
484
+ # Call the function
485
+ updated_dataset = add_systematic_uncertainties(dataset, particle)
486
+ # Assertions
487
+ assert f"{particle}_sys_err_minus" in updated_dataset.data_vars
488
+ assert f"{particle}_sys_err_plus" in updated_dataset.data_vars
489
+ assert (
490
+ updated_dataset[f"{particle}_sys_err_minus"].shape
491
+ == dataset[particle].shape
492
+ )
493
+ assert (
494
+ updated_dataset[f"{particle}_sys_err_plus"].shape == dataset[particle].shape
495
+ )
496
+ np.testing.assert_array_equal(
497
+ updated_dataset[f"{particle}_sys_err_minus"].values, 0
498
+ )
499
+ np.testing.assert_array_equal(
500
+ updated_dataset[f"{particle}_sys_err_plus"].values, 0
501
+ )
502
+
503
+
504
+ def test_add_total_uncertainties():
505
+ # Create a sample dataset
506
+ np.random.seed(42) # Set a random seed for reproducibility
507
+ data = np.random.rand(10, 5).astype(np.float32)
508
+ stat_uncert_minus = np.random.rand(10, 5).astype(np.float32)
509
+ stat_uncert_plus = np.random.rand(10, 5).astype(np.float32)
510
+ sys_err_minus = np.zeros(
511
+ (10, 5), dtype=np.float32
512
+ ) # zeros, unless changed during mission
513
+ sys_err_plus = np.zeros(
514
+ (10, 5), dtype=np.float32
515
+ ) # zeros, unless changed during mission
516
+
517
+ dataset = xr.Dataset(
518
+ {
519
+ "particle": (("dim_0", "dim_1"), data),
520
+ "particle_stat_uncert_minus": (("dim_0", "dim_1"), stat_uncert_minus),
521
+ "particle_stat_uncert_plus": (("dim_0", "dim_1"), stat_uncert_plus),
522
+ "particle_sys_err_minus": (("dim_0", "dim_1"), sys_err_minus),
523
+ "particle_sys_err_plus": (("dim_0", "dim_1"), sys_err_plus),
524
+ }
525
+ )
326
526
 
327
527
  # Call the function
328
- add_systematic_uncertainties(dataset, particle, len(energy_ranges))
528
+ updated_dataset = add_total_uncertainties(dataset, "particle")
329
529
 
330
530
  # Assertions
331
- assert f"{particle}_sys_delta_minus" in dataset.data_vars
332
- assert f"{particle}_sys_delta_plus" in dataset.data_vars
333
- assert np.all(dataset[f"{particle}_sys_delta_minus"].values == 0)
334
- assert np.all(dataset[f"{particle}_sys_delta_plus"].values == 0)
335
- assert dataset[f"{particle}_sys_delta_minus"].shape == (len(energy_ranges),)
336
- assert dataset[f"{particle}_sys_delta_plus"].shape == (len(energy_ranges),)
531
+ np.testing.assert_array_almost_equal(
532
+ updated_dataset["particle_total_uncert_minus"].values,
533
+ np.sqrt(np.square(stat_uncert_minus) + np.square(sys_err_minus)),
534
+ )
535
+ np.testing.assert_array_almost_equal(
536
+ updated_dataset["particle_total_uncert_plus"].values,
537
+ np.sqrt(np.square(stat_uncert_plus) + np.square(sys_err_plus)),
538
+ )
539
+
540
+ # Check that the dimensions and attributes are preserved
541
+ assert (
542
+ updated_dataset["particle_total_uncert_minus"].dims == dataset["particle"].dims
543
+ )
544
+ assert (
545
+ updated_dataset["particle_total_uncert_plus"].dims == dataset["particle"].dims
546
+ )
547
+
548
+
549
+ def test_process_sectored_intensity_data(l1b_sectored_rates_dataset):
550
+ """Test the variables in the sectored intensity dataset"""
551
+
552
+ l2_sectored_intensity_dataset = process_sectored_intensity_data(
553
+ l1b_sectored_rates_dataset
554
+ )
555
+
556
+ # Check that a xarray dataset is returned
557
+ assert isinstance(l2_sectored_intensity_dataset, xr.Dataset)
558
+
559
+ valid_coords = {
560
+ "epoch",
561
+ "azimuth",
562
+ "declination",
563
+ "h_energy_mean",
564
+ "he4_energy_mean",
565
+ "cno_energy_mean",
566
+ "nemgsi_energy_mean",
567
+ "fe_energy_mean",
568
+ }
569
+
570
+ # Check that the dataset has the correct coords and variables
571
+ assert valid_coords == set(l2_sectored_intensity_dataset.coords), (
572
+ "Coordinates mismatch"
573
+ )
574
+
575
+ assert "dynamic_threshold_state" in l2_sectored_intensity_dataset.data_vars
576
+
577
+ for particle in VALID_SECTORED_SPECIES:
578
+ assert f"{particle}" in l2_sectored_intensity_dataset.data_vars
579
+ assert (
580
+ f"{particle}_stat_uncert_minus" in l2_sectored_intensity_dataset.data_vars
581
+ )
582
+ assert f"{particle}_stat_uncert_plus" in l2_sectored_intensity_dataset.data_vars
583
+ assert f"{particle}_sys_err_minus" in l2_sectored_intensity_dataset.data_vars
584
+ assert f"{particle}_sys_err_plus" in l2_sectored_intensity_dataset.data_vars
585
+ assert (
586
+ f"{particle}_energy_delta_minus" in l2_sectored_intensity_dataset.data_vars
587
+ )
588
+ assert (
589
+ f"{particle}_energy_delta_plus" in l2_sectored_intensity_dataset.data_vars
590
+ )
337
591
 
338
592
 
339
593
  def test_process_summed_intensity_data(l1b_summed_rates_dataset):
@@ -368,18 +622,20 @@ def test_process_summed_intensity_data(l1b_summed_rates_dataset):
368
622
  }
369
623
 
370
624
  # Check that the dataset has the correct coords and variables
371
- assert valid_coords == set(
372
- l2_summed_intensity_dataset.coords
373
- ), "Coordinates mismatch"
625
+ assert valid_coords == set(l2_summed_intensity_dataset.coords), (
626
+ "Coordinates mismatch"
627
+ )
374
628
 
375
629
  assert "dynamic_threshold_state" in l1b_summed_rates_dataset.data_vars
376
630
 
377
- for particle in PARTICLE_ENERGY_RANGE_MAPPING.keys():
631
+ for particle in SUMMED_PARTICLE_ENERGY_RANGE_MAPPING.keys():
378
632
  assert f"{particle}" in l2_summed_intensity_dataset.data_vars
379
- assert f"{particle}_delta_minus" in l2_summed_intensity_dataset.data_vars
380
- assert f"{particle}_delta_plus" in l2_summed_intensity_dataset.data_vars
381
- assert f"{particle}_sys_delta_minus" in l2_summed_intensity_dataset.data_vars
382
- assert f"{particle}_sys_delta_plus" in l2_summed_intensity_dataset.data_vars
633
+ assert f"{particle}_stat_uncert_minus" in l2_summed_intensity_dataset.data_vars
634
+ assert f"{particle}_stat_uncert_plus" in l2_summed_intensity_dataset.data_vars
635
+ assert f"{particle}_sys_err_minus" in l2_summed_intensity_dataset.data_vars
636
+ assert f"{particle}_sys_err_plus" in l2_summed_intensity_dataset.data_vars
637
+ assert f"{particle}_energy_delta_minus" in l2_summed_intensity_dataset.data_vars
638
+ assert f"{particle}_energy_delta_plus" in l2_summed_intensity_dataset.data_vars
383
639
 
384
640
 
385
641
  def test_process_standard_intensity_data(l1b_standard_rates_dataset):
@@ -414,18 +670,20 @@ def test_process_standard_intensity_data(l1b_standard_rates_dataset):
414
670
  }
415
671
 
416
672
  # Check that the dataset has the correct coords and variables
417
- assert valid_coords == set(
418
- l2_standard_intensity_dataset.coords
419
- ), "Coordinates mismatch"
673
+ assert valid_coords == set(l2_standard_intensity_dataset.coords), (
674
+ "Coordinates mismatch"
675
+ )
420
676
 
421
677
  assert "dynamic_threshold_state" in l1b_standard_rates_dataset.data_vars
422
678
 
423
679
  for particle in STANDARD_PARTICLE_ENERGY_RANGE_MAPPING.keys():
424
680
  assert f"{particle}" in l2_standard_intensity_dataset.data_vars
425
- assert f"{particle}_delta_minus" in l2_standard_intensity_dataset.data_vars
426
- assert f"{particle}_delta_plus" in l2_standard_intensity_dataset.data_vars
427
- assert f"{particle}_sys_delta_minus" in l2_standard_intensity_dataset.data_vars
428
- assert f"{particle}_sys_delta_plus" in l2_standard_intensity_dataset.data_vars
681
+ assert (
682
+ f"{particle}_stat_uncert_minus" in l2_standard_intensity_dataset.data_vars
683
+ )
684
+ assert f"{particle}_stat_uncert_plus" in l2_standard_intensity_dataset.data_vars
685
+ assert f"{particle}_sys_err_minus" in l2_standard_intensity_dataset.data_vars
686
+ assert f"{particle}_sys_err_plus" in l2_standard_intensity_dataset.data_vars
429
687
  assert (
430
688
  f"{particle}_energy_delta_minus" in l2_standard_intensity_dataset.data_vars
431
689
  )
@@ -445,10 +703,14 @@ def test_hit_l2(dependencies):
445
703
  Dictionary of L1B datasets
446
704
  """
447
705
  # TODO: update assertions after science data processing is completed
448
- l2_datasets = hit_l2(dependencies["imap_hit_l1b_summed-rates"], "001")
706
+ l2_datasets = hit_l2(dependencies["imap_hit_l1b_summed-rates"])
449
707
  assert len(l2_datasets) == 1
450
708
  assert l2_datasets[0].attrs["Logical_source"] == "imap_hit_l2_summed-intensity"
451
709
 
452
- l2_datasets = hit_l2(dependencies["imap_hit_l1b_standard-rates"], "001")
710
+ l2_datasets = hit_l2(dependencies["imap_hit_l1b_standard-rates"])
453
711
  assert len(l2_datasets) == 1
454
712
  assert l2_datasets[0].attrs["Logical_source"] == "imap_hit_l2_standard-intensity"
713
+
714
+ l2_datasets = hit_l2(dependencies["imap_hit_l1b_sectored-rates"])
715
+ assert len(l2_datasets) == 1
716
+ assert l2_datasets[0].attrs["Logical_source"] == "imap_hit_l2_macropixel-intensity"