imap-processing 0.11.0__py3-none-any.whl → 0.12.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (288) hide show
  1. imap_processing/__init__.py +10 -11
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/excel_to_xtce.py +65 -16
  4. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +6 -28
  5. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +365 -42
  6. imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +0 -5
  7. imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +10 -11
  8. imap_processing/cdf/config/imap_hi_variable_attrs.yaml +17 -19
  9. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +26 -13
  10. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +106 -116
  11. imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +120 -145
  12. imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +14 -0
  13. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +6 -9
  14. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +1 -1
  15. imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +0 -12
  16. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +1 -1
  17. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +9 -21
  18. imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml +361 -0
  19. imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml +160 -0
  20. imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +160 -0
  21. imap_processing/cdf/config/imap_spacecraft_global_cdf_attrs.yaml +18 -0
  22. imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml +40 -0
  23. imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +1 -5
  24. imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +12 -4
  25. imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +16 -2
  26. imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +48 -52
  27. imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +71 -47
  28. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +2 -14
  29. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +51 -2
  30. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +29 -14
  31. imap_processing/cdf/utils.py +13 -7
  32. imap_processing/cli.py +23 -8
  33. imap_processing/codice/codice_l1a.py +207 -85
  34. imap_processing/codice/constants.py +1322 -568
  35. imap_processing/codice/decompress.py +2 -6
  36. imap_processing/ena_maps/ena_maps.py +480 -116
  37. imap_processing/ena_maps/utils/coordinates.py +19 -0
  38. imap_processing/ena_maps/utils/map_utils.py +14 -17
  39. imap_processing/ena_maps/utils/spatial_utils.py +45 -47
  40. imap_processing/hi/l1a/hi_l1a.py +24 -18
  41. imap_processing/hi/l1a/histogram.py +0 -1
  42. imap_processing/hi/l1a/science_direct_event.py +6 -8
  43. imap_processing/hi/l1b/hi_l1b.py +31 -39
  44. imap_processing/hi/l1c/hi_l1c.py +405 -17
  45. imap_processing/hi/utils.py +58 -12
  46. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt0-factors_20250219_v002.csv +205 -0
  47. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt1-factors_20250219_v002.csv +205 -0
  48. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt2-factors_20250219_v002.csv +205 -0
  49. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt3-factors_20250219_v002.csv +205 -0
  50. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-summed-dt0-factors_20250219_v002.csv +68 -0
  51. imap_processing/hit/hit_utils.py +173 -1
  52. imap_processing/hit/l0/constants.py +20 -11
  53. imap_processing/hit/l0/decom_hit.py +18 -4
  54. imap_processing/hit/l1a/hit_l1a.py +45 -54
  55. imap_processing/hit/l1b/constants.py +317 -0
  56. imap_processing/hit/l1b/hit_l1b.py +367 -18
  57. imap_processing/hit/l2/constants.py +281 -0
  58. imap_processing/hit/l2/hit_l2.py +614 -0
  59. imap_processing/hit/packet_definitions/hit_packet_definitions.xml +1323 -71
  60. imap_processing/ialirt/l0/mag_l0_ialirt_data.py +155 -0
  61. imap_processing/ialirt/l0/parse_mag.py +246 -0
  62. imap_processing/ialirt/l0/process_swe.py +252 -0
  63. imap_processing/ialirt/packet_definitions/ialirt.xml +7 -3
  64. imap_processing/ialirt/packet_definitions/ialirt_mag.xml +115 -0
  65. imap_processing/ialirt/utils/grouping.py +114 -0
  66. imap_processing/ialirt/utils/time.py +29 -0
  67. imap_processing/idex/atomic_masses.csv +22 -0
  68. imap_processing/idex/decode.py +2 -2
  69. imap_processing/idex/idex_constants.py +25 -0
  70. imap_processing/idex/idex_l1a.py +6 -7
  71. imap_processing/idex/idex_l1b.py +4 -31
  72. imap_processing/idex/idex_l2a.py +789 -0
  73. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +39 -33
  74. imap_processing/lo/l0/lo_science.py +6 -0
  75. imap_processing/lo/l1a/lo_l1a.py +0 -1
  76. imap_processing/lo/l1b/lo_l1b.py +177 -25
  77. imap_processing/mag/constants.py +8 -0
  78. imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +6 -0
  79. imap_processing/mag/l0/decom_mag.py +10 -3
  80. imap_processing/mag/l1a/mag_l1a.py +22 -11
  81. imap_processing/mag/l1a/mag_l1a_data.py +28 -3
  82. imap_processing/mag/l1b/mag_l1b.py +190 -48
  83. imap_processing/mag/l1c/interpolation_methods.py +211 -0
  84. imap_processing/mag/l1c/mag_l1c.py +447 -9
  85. imap_processing/quality_flags.py +1 -0
  86. imap_processing/spacecraft/packet_definitions/scid_x252.xml +538 -0
  87. imap_processing/spacecraft/quaternions.py +123 -0
  88. imap_processing/spice/geometry.py +16 -19
  89. imap_processing/spice/repoint.py +120 -0
  90. imap_processing/swapi/l1/swapi_l1.py +4 -0
  91. imap_processing/swapi/l2/swapi_l2.py +0 -1
  92. imap_processing/swe/l1a/swe_l1a.py +47 -8
  93. imap_processing/swe/l1a/swe_science.py +5 -2
  94. imap_processing/swe/l1b/swe_l1b_science.py +103 -56
  95. imap_processing/swe/l2/swe_l2.py +60 -65
  96. imap_processing/swe/packet_definitions/swe_packet_definition.xml +1121 -1
  97. imap_processing/swe/utils/swe_constants.py +63 -0
  98. imap_processing/swe/utils/swe_utils.py +85 -28
  99. imap_processing/tests/ccsds/test_data/expected_output.xml +40 -1
  100. imap_processing/tests/ccsds/test_excel_to_xtce.py +23 -20
  101. imap_processing/tests/cdf/test_data/imap_instrument2_global_cdf_attrs.yaml +0 -2
  102. imap_processing/tests/codice/conftest.py +1 -1
  103. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  104. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  105. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-ialirt_20241110193700_v0.0.0.cdf +0 -0
  106. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-omni_20241110193700_v0.0.0.cdf +0 -0
  107. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
  108. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-priorities_20241110193700_v0.0.0.cdf +0 -0
  109. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-sectored_20241110193700_v0.0.0.cdf +0 -0
  110. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  111. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  112. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  113. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-angular_20241110193700_v0.0.0.cdf +0 -0
  114. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-priority_20241110193700_v0.0.0.cdf +0 -0
  115. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-species_20241110193700_v0.0.0.cdf +0 -0
  116. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
  117. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-angular_20241110193700_v0.0.0.cdf +0 -0
  118. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-priority_20241110193700_v0.0.0.cdf +0 -0
  119. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-species_20241110193700_v0.0.0.cdf +0 -0
  120. imap_processing/tests/codice/test_codice_l1a.py +110 -46
  121. imap_processing/tests/codice/test_decompress.py +4 -4
  122. imap_processing/tests/conftest.py +166 -10
  123. imap_processing/tests/ena_maps/conftest.py +51 -0
  124. imap_processing/tests/ena_maps/test_ena_maps.py +638 -109
  125. imap_processing/tests/ena_maps/test_map_utils.py +66 -43
  126. imap_processing/tests/ena_maps/test_spatial_utils.py +16 -20
  127. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208.bin +0 -0
  128. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208_verify.csv +205 -0
  129. imap_processing/tests/hi/test_hi_l1b.py +12 -15
  130. imap_processing/tests/hi/test_hi_l1c.py +234 -6
  131. imap_processing/tests/hi/test_l1a.py +30 -0
  132. imap_processing/tests/hi/test_science_direct_event.py +1 -1
  133. imap_processing/tests/hi/test_utils.py +24 -2
  134. imap_processing/tests/hit/helpers/l1_validation.py +39 -39
  135. imap_processing/tests/hit/test_data/hskp_sample.ccsds +0 -0
  136. imap_processing/tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts +0 -0
  137. imap_processing/tests/hit/test_decom_hit.py +4 -0
  138. imap_processing/tests/hit/test_hit_l1a.py +24 -28
  139. imap_processing/tests/hit/test_hit_l1b.py +304 -40
  140. imap_processing/tests/hit/test_hit_l2.py +454 -0
  141. imap_processing/tests/hit/test_hit_utils.py +112 -2
  142. imap_processing/tests/hit/validation_data/hskp_sample_eu_3_6_2025.csv +89 -0
  143. imap_processing/tests/hit/validation_data/hskp_sample_raw.csv +89 -88
  144. imap_processing/tests/ialirt/test_data/l0/461971383-404.bin +0 -0
  145. imap_processing/tests/ialirt/test_data/l0/461971384-405.bin +0 -0
  146. imap_processing/tests/ialirt/test_data/l0/461971385-406.bin +0 -0
  147. imap_processing/tests/ialirt/test_data/l0/461971386-407.bin +0 -0
  148. imap_processing/tests/ialirt/test_data/l0/461971387-408.bin +0 -0
  149. imap_processing/tests/ialirt/test_data/l0/461971388-409.bin +0 -0
  150. imap_processing/tests/ialirt/test_data/l0/461971389-410.bin +0 -0
  151. imap_processing/tests/ialirt/test_data/l0/461971390-411.bin +0 -0
  152. imap_processing/tests/ialirt/test_data/l0/461971391-412.bin +0 -0
  153. imap_processing/tests/ialirt/test_data/l0/sample_decoded_i-alirt_data.csv +383 -0
  154. imap_processing/tests/ialirt/unit/test_grouping.py +81 -0
  155. imap_processing/tests/ialirt/unit/test_parse_mag.py +168 -0
  156. imap_processing/tests/ialirt/unit/test_process_swe.py +208 -3
  157. imap_processing/tests/ialirt/unit/test_time.py +16 -0
  158. imap_processing/tests/idex/conftest.py +62 -6
  159. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231218_v001.pkts +0 -0
  160. imap_processing/tests/idex/test_data/impact_14_tof_high_data.txt +4508 -4508
  161. imap_processing/tests/idex/test_idex_l1a.py +48 -4
  162. imap_processing/tests/idex/test_idex_l1b.py +3 -3
  163. imap_processing/tests/idex/test_idex_l2a.py +383 -0
  164. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20241022_v002.cdf +0 -0
  165. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20241022_v002.cdf +0 -0
  166. imap_processing/tests/lo/test_lo_l1b.py +148 -4
  167. imap_processing/tests/lo/test_lo_science.py +1 -0
  168. imap_processing/tests/mag/conftest.py +69 -0
  169. imap_processing/tests/mag/test_mag_decom.py +1 -1
  170. imap_processing/tests/mag/test_mag_l1a.py +38 -0
  171. imap_processing/tests/mag/test_mag_l1b.py +34 -53
  172. imap_processing/tests/mag/test_mag_l1c.py +251 -20
  173. imap_processing/tests/mag/test_mag_validation.py +109 -25
  174. imap_processing/tests/mag/validation/L1b/T009/MAGScience-normal-(2,2)-8s-20250204-16h39.csv +17 -0
  175. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-magi-out.csv +16 -16
  176. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-mago-out.csv +16 -16
  177. imap_processing/tests/mag/validation/L1b/T010/MAGScience-normal-(2,2)-8s-20250206-12h05.csv +17 -0
  178. imap_processing/tests/mag/validation/L1b/T011/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  179. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-magi-out.csv +16 -16
  180. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-mago-out.csv +16 -16
  181. imap_processing/tests/mag/validation/L1b/T012/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  182. imap_processing/tests/mag/validation/L1b/T012/data.bin +0 -0
  183. imap_processing/tests/mag/validation/L1b/T012/field_like_all_ranges.txt +19200 -0
  184. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-cal.cdf +0 -0
  185. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-in.csv +17 -0
  186. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-magi-out.csv +17 -0
  187. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-mago-out.csv +17 -0
  188. imap_processing/tests/mag/validation/imap_calibration_mag_20240229_v01.cdf +0 -0
  189. imap_processing/tests/spacecraft/__init__.py +0 -0
  190. imap_processing/tests/spacecraft/data/SSR_2024_190_20_08_12_0483851794_2_DA_apid0594_1packet.pkts +0 -0
  191. imap_processing/tests/spacecraft/test_quaternions.py +71 -0
  192. imap_processing/tests/spice/test_data/fake_repoint_data.csv +5 -0
  193. imap_processing/tests/spice/test_geometry.py +6 -9
  194. imap_processing/tests/spice/test_repoint.py +111 -0
  195. imap_processing/tests/swapi/test_swapi_l1.py +7 -3
  196. imap_processing/tests/swe/l0_data/2024051010_SWE_HK_packet.bin +0 -0
  197. imap_processing/tests/swe/l0_data/2024051011_SWE_CEM_RAW_packet.bin +0 -0
  198. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_APP_HK_20240510_092742.csv +49 -0
  199. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_CEM_RAW_20240510_092742.csv +593 -0
  200. imap_processing/tests/swe/test_swe_l1a.py +18 -0
  201. imap_processing/tests/swe/test_swe_l1a_cem_raw.py +52 -0
  202. imap_processing/tests/swe/test_swe_l1a_hk.py +68 -0
  203. imap_processing/tests/swe/test_swe_l1b_science.py +23 -4
  204. imap_processing/tests/swe/test_swe_l2.py +112 -30
  205. imap_processing/tests/test_cli.py +2 -2
  206. imap_processing/tests/test_utils.py +138 -16
  207. imap_processing/tests/ultra/data/l0/FM45_UltraFM45_Functional_2024-01-22T0105_20240122T010548.CCSDS +0 -0
  208. imap_processing/tests/ultra/data/l0/ultra45_raw_sc_ultraimgrates_20220530_00.csv +164 -0
  209. imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3243 -3243
  210. imap_processing/tests/ultra/data/mock_data.py +341 -0
  211. imap_processing/tests/ultra/unit/conftest.py +69 -26
  212. imap_processing/tests/ultra/unit/test_badtimes.py +2 -0
  213. imap_processing/tests/ultra/unit/test_cullingmask.py +4 -0
  214. imap_processing/tests/ultra/unit/test_de.py +12 -4
  215. imap_processing/tests/ultra/unit/test_decom_apid_881.py +44 -0
  216. imap_processing/tests/ultra/unit/test_spacecraft_pset.py +78 -0
  217. imap_processing/tests/ultra/unit/test_ultra_l1a.py +28 -12
  218. imap_processing/tests/ultra/unit/test_ultra_l1b.py +34 -6
  219. imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +22 -26
  220. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +86 -51
  221. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +94 -52
  222. imap_processing/ultra/l0/decom_tools.py +6 -5
  223. imap_processing/ultra/l1a/ultra_l1a.py +28 -56
  224. imap_processing/ultra/l1b/de.py +72 -28
  225. imap_processing/ultra/l1b/extendedspin.py +12 -14
  226. imap_processing/ultra/l1b/ultra_l1b.py +34 -9
  227. imap_processing/ultra/l1b/ultra_l1b_culling.py +65 -29
  228. imap_processing/ultra/l1b/ultra_l1b_extended.py +64 -19
  229. imap_processing/ultra/l1c/spacecraft_pset.py +86 -0
  230. imap_processing/ultra/l1c/ultra_l1c.py +7 -4
  231. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +112 -61
  232. imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
  233. imap_processing/ultra/utils/ultra_l1_utils.py +20 -2
  234. imap_processing/utils.py +68 -28
  235. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/METADATA +8 -5
  236. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/RECORD +250 -199
  237. imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +0 -237
  238. imap_processing/hi/l1a/housekeeping.py +0 -27
  239. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-aggregated_20240429_v001.cdf +0 -0
  240. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-singles_20240429_v001.cdf +0 -0
  241. imap_processing/tests/codice/data/imap_codice_l1a_hi-omni_20240429_v001.cdf +0 -0
  242. imap_processing/tests/codice/data/imap_codice_l1a_hi-sectored_20240429_v001.cdf +0 -0
  243. imap_processing/tests/codice/data/imap_codice_l1a_hskp_20100101_v001.cdf +0 -0
  244. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-aggregated_20240429_v001.cdf +0 -0
  245. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-singles_20240429_v001.cdf +0 -0
  246. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-angular_20240429_v001.cdf +0 -0
  247. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-priority_20240429_v001.cdf +0 -0
  248. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-species_20240429_v001.cdf +0 -0
  249. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-angular_20240429_v001.cdf +0 -0
  250. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-priority_20240429_v001.cdf +0 -0
  251. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-species_20240429_v001.cdf +0 -0
  252. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-aggregated_20240429_v001.cdf +0 -0
  253. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-singles_20240429_v001.cdf +0 -0
  254. imap_processing/tests/codice/data/imap_codice_l1b_hi-omni_20240429_v001.cdf +0 -0
  255. imap_processing/tests/codice/data/imap_codice_l1b_hi-sectored_20240429_v001.cdf +0 -0
  256. imap_processing/tests/codice/data/imap_codice_l1b_hskp_20100101_v001.cdf +0 -0
  257. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-aggregated_20240429_v001.cdf +0 -0
  258. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-singles_20240429_v001.cdf +0 -0
  259. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-angular_20240429_v001.cdf +0 -0
  260. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-priority_20240429_v001.cdf +0 -0
  261. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-species_20240429_v001.cdf +0 -0
  262. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-angular_20240429_v001.cdf +0 -0
  263. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-priority_20240429_v001.cdf +0 -0
  264. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-species_20240429_v001.cdf +0 -0
  265. imap_processing/tests/hi/data/l1/imap_hi_l1b_45sensor-de_20250415_v999.cdf +0 -0
  266. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1251.pkts +0 -0
  267. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1252.pkts +0 -0
  268. imap_processing/tests/hit/validation_data/hskp_sample_eu.csv +0 -89
  269. imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +0 -29
  270. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231214_v001.pkts +0 -0
  271. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20100101_v001.cdf +0 -0
  272. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20100101_v001.cdf +0 -0
  273. imap_processing/tests/ultra/test_data/mock_data.py +0 -161
  274. imap_processing/ultra/l1c/pset.py +0 -40
  275. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00_20240207T102740.CCSDS +0 -0
  276. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_7P_Phi0.0_BeamCal_LinearScan_phi0.04_theta-0.01_20230821T121304.CCSDS +0 -0
  277. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.CCSDS +0 -0
  278. /imap_processing/tests/ultra/{test_data → data}/l0/Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.CCSDS +0 -0
  279. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_auxdata_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  280. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_enaphxtofhangimg_FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.csv +0 -0
  281. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultraimgrates_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  282. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimgevent_FM45_7P_Phi00_BeamCal_LinearScan_phi004_theta-001_20230821T121304.csv +0 -0
  283. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E1.cdf +0 -0
  284. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E12.cdf +0 -0
  285. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E24.cdf +0 -0
  286. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/LICENSE +0 -0
  287. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/WHEEL +0 -0
  288. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,454 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ import pytest
4
+ import xarray as xr
5
+
6
+ from imap_processing import imap_module_directory
7
+ from imap_processing.hit.l1a import hit_l1a
8
+ from imap_processing.hit.l1b.hit_l1b import (
9
+ PARTICLE_ENERGY_RANGE_MAPPING,
10
+ hit_l1b,
11
+ )
12
+ from imap_processing.hit.l2.hit_l2 import (
13
+ STANDARD_PARTICLE_ENERGY_RANGE_MAPPING,
14
+ IntensityFactors,
15
+ add_systematic_uncertainties,
16
+ calculate_intensities,
17
+ calculate_intensities_for_a_species,
18
+ calculate_intensities_for_all_species,
19
+ get_intensity_factors,
20
+ get_species_ancillary_data,
21
+ hit_l2,
22
+ process_standard_intensity_data,
23
+ process_summed_intensity_data,
24
+ )
25
+
26
+ # TODO: add unit test for add_standard_particle_rates_to_dataset
27
+
28
+
29
+ @pytest.fixture(scope="module")
30
+ def sci_packet_filepath():
31
+ """Set path to test data file"""
32
+ return imap_module_directory / "tests/hit/test_data/sci_sample.ccsds"
33
+
34
+
35
+ @pytest.fixture()
36
+ def dependencies(sci_packet_filepath):
37
+ """Get dependencies for L2 processing"""
38
+ # Create dictionary of dependencies
39
+ data_dict = {}
40
+ l1a_datasets = hit_l1a.hit_l1a(sci_packet_filepath, "001")
41
+ for l1a_dataset in l1a_datasets:
42
+ l1a_data_dict = {}
43
+ if l1a_dataset.attrs["Logical_source"] == "imap_hit_l1a_counts":
44
+ l1a_data_dict["imap_hit_l1a_counts"] = l1a_dataset
45
+ l1b_datasets = hit_l1b(l1a_data_dict, "001")
46
+ for l1b_dataset in l1b_datasets:
47
+ data_dict[l1b_dataset.attrs["Logical_source"]] = l1b_dataset
48
+ return data_dict
49
+
50
+
51
+ @pytest.fixture()
52
+ def l1b_summed_rates_dataset(dependencies):
53
+ """Get L1B summed rates dataset to test l2 processing function"""
54
+ return dependencies["imap_hit_l1b_summed-rates"]
55
+
56
+
57
+ @pytest.fixture()
58
+ def l1b_standard_rates_dataset(dependencies):
59
+ """Get L1B standard rates dataset to test l2 processing function"""
60
+ return dependencies["imap_hit_l1b_standard-rates"]
61
+
62
+
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
+ }
75
+ )
76
+
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]),
83
+ )
84
+
85
+ # Call the function
86
+ factors = get_intensity_factors(energy_min, species_ancillary_data)
87
+
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"
99
+
100
+
101
+ def test_get_species_ancillary_data():
102
+ """Test the get_species_ancillary_data function."""
103
+ # Sample input data
104
+ dynamic_threshold_state = 1
105
+ ancillary_data_frames = {
106
+ 0: pd.DataFrame(
107
+ {
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],
114
+ }
115
+ ),
116
+ 1: pd.DataFrame(
117
+ {
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],
124
+ }
125
+ ),
126
+ }
127
+ species = "h"
128
+
129
+ # Expected output
130
+ expected_output = ancillary_data_frames[dynamic_threshold_state][
131
+ ancillary_data_frames[dynamic_threshold_state]["species"] == species
132
+ ]
133
+
134
+ # Call the function
135
+ output = get_species_ancillary_data(
136
+ dynamic_threshold_state, ancillary_data_frames, species
137
+ )
138
+
139
+ # Assertions
140
+ pd.testing.assert_frame_equal(output, expected_output)
141
+
142
+
143
+ def test_calculate_intensities_for_all_species():
144
+ """Test the calculate_intensities_for_all_species function."""
145
+ # Sample input data
146
+ l2_dataset = xr.Dataset(
147
+ {
148
+ "dynamic_threshold_state": ("epoch", np.array([0, 1])),
149
+ "h": (
150
+ ("epoch", "h_energy_mean"),
151
+ np.array([[100, 200, 300], [400, 500, 600]]).astype("float32"),
152
+ ),
153
+ "h_energy_mean": (
154
+ "h_energy_mean",
155
+ np.array([1.0, 2.0, 3.0]).astype("float32"),
156
+ ),
157
+ "h_energy_delta_minus": (
158
+ "h_energy_mean",
159
+ np.array([0.1, 0.1, 0.1]).astype("float32"),
160
+ ),
161
+ "h_energy_delta_plus": (
162
+ "h_energy_mean",
163
+ np.array([0.1, 0.1, 0.1]).astype("float32"),
164
+ ),
165
+ "ni": (
166
+ ("epoch", "ni_energy_mean"),
167
+ np.array([[150, 250, 350], [450, 550, 650]]).astype("float32"),
168
+ ),
169
+ "ni_energy_mean": (
170
+ "ni_energy_mean",
171
+ np.array([1.5, 2.5, 3.5]).astype("float32"),
172
+ ),
173
+ "ni_energy_delta_minus": (
174
+ "ni_energy_mean",
175
+ np.array([0.1, 0.1, 0.1]).astype("float32"),
176
+ ),
177
+ "ni_energy_delta_plus": (
178
+ "ni_energy_mean",
179
+ np.array([0.1, 0.1, 0.1]).astype("float32"),
180
+ ),
181
+ }
182
+ )
183
+ ancillary_data_frames = {
184
+ 0: pd.DataFrame(
185
+ {
186
+ "species": ["h", "h", "h", "ni", "ni", "ni"],
187
+ "lower energy (mev)": [0.9, 1.9, 2.9, 1.4, 2.4, 3.4],
188
+ "delta e (mev)": [0.2, 0.2, 0.2, 0.2, 0.2, 0.2],
189
+ "geometry factor (cm2 sr)": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
190
+ "efficiency": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
191
+ "b": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
192
+ }
193
+ ),
194
+ 1: pd.DataFrame(
195
+ {
196
+ "species": ["h", "h", "h", "ni", "ni", "ni"],
197
+ "lower energy (mev)": [0.9, 1.9, 2.9, 1.4, 2.4, 3.4],
198
+ "delta e (mev)": [0.2, 0.2, 0.2, 0.2, 0.2, 0.2],
199
+ "geometry factor (cm2 sr)": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
200
+ "efficiency": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
201
+ "b": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
202
+ }
203
+ ),
204
+ }
205
+
206
+ # Expected output
207
+ expected_intensities_h = xr.DataArray(
208
+ [[8.333333, 16.666667, 25.0], [33.333333, 41.666667, 50.0]],
209
+ dims=["epoch", "h_energy_mean"],
210
+ )
211
+ expected_intensities_ni = xr.DataArray(
212
+ [[12.5, 20.833333, 29.166667], [37.5, 45.833333, 54.166667]],
213
+ dims=["epoch", "ni_energy_mean"],
214
+ )
215
+
216
+ # Call the function
217
+ calculate_intensities_for_all_species(l2_dataset, ancillary_data_frames)
218
+
219
+ # 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"
226
+
227
+
228
+ def test_calculate_intensities_for_a_species():
229
+ """Test the calculate_intensities_for_a_species function."""
230
+ # Sample input data
231
+ species_variable = "h"
232
+ l2_dataset = xr.Dataset(
233
+ {
234
+ "h": (
235
+ ("epoch", "h_energy_mean"),
236
+ np.array([[100.0, 200.0, 300.0], [400.0, 500.0, 600.0]]).astype(
237
+ "float32"
238
+ ),
239
+ ),
240
+ "dynamic_threshold_state": ("epoch", np.array([0, 1])),
241
+ "h_energy_mean": (
242
+ "h_energy_mean",
243
+ np.array([1.0, 2.0, 3.0]).astype("float32"),
244
+ ),
245
+ "h_energy_delta_minus": (
246
+ "h_energy_mean",
247
+ np.array([0.1, 0.1, 0.1]).astype("float32"),
248
+ ),
249
+ }
250
+ )
251
+ ancillary_data_frames = {
252
+ 0: pd.DataFrame(
253
+ {
254
+ "species": ["h", "h", "h"],
255
+ "lower energy (mev)": [0.9, 1.9, 2.9],
256
+ "delta e (mev)": [0.2, 0.5, 0.5],
257
+ "geometry factor (cm2 sr)": [1.0, 1.0, 1.5],
258
+ "efficiency": [1, 1, 1],
259
+ "b": [0, 0, 0],
260
+ }
261
+ ),
262
+ 1: pd.DataFrame(
263
+ {
264
+ "species": ["h", "h", "h"],
265
+ "lower energy (mev)": [0.9, 1.9, 2.9],
266
+ "delta e (mev)": [0.4, 0.5, 0.5],
267
+ "geometry factor (cm2 sr)": [1.5, 1.51, 1.51],
268
+ "efficiency": [1, 1, 1],
269
+ "b": [0, 0, 0],
270
+ }
271
+ ),
272
+ }
273
+
274
+ # Expected output
275
+ expected_intensities = xr.DataArray(
276
+ [[8.333333, 6.666667, 6.666667], [11.111111, 11.037528, 13.245033]],
277
+ dims=["epoch", "h_energy_mean"],
278
+ )
279
+
280
+ # Call the function
281
+ calculate_intensities_for_a_species(
282
+ species_variable, l2_dataset, ancillary_data_frames
283
+ )
284
+
285
+ # Assertions
286
+ assert np.allclose(
287
+ l2_dataset["h"].values, expected_intensities.values
288
+ ), "Intensities mismatch"
289
+
290
+
291
+ def test_calculate_intensities():
292
+ """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])
299
+
300
+ # Expected output
301
+ expected_intensities = xr.DataArray(
302
+ [1.66666667, 3.33333333, 5.0], dims=["energy_bin"]
303
+ )
304
+
305
+ # Call the function
306
+ intensities = calculate_intensities(
307
+ rate, delta_e_factor, geometry_factor, efficiency, b
308
+ )
309
+
310
+ # Assertions
311
+ assert np.allclose(
312
+ intensities.values, expected_intensities.values
313
+ ), "Intensities mismatch"
314
+
315
+
316
+ def test_add_systematic_uncertainties():
317
+ """Test the add_systematic_uncertainties function."""
318
+ # Create sample function inputs
319
+ 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": []},
324
+ ]
325
+ dataset = xr.Dataset()
326
+
327
+ # Call the function
328
+ add_systematic_uncertainties(dataset, particle, len(energy_ranges))
329
+
330
+ # 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),)
337
+
338
+
339
+ def test_process_summed_intensity_data(l1b_summed_rates_dataset):
340
+ """Test the variables in the summed intensity dataset"""
341
+
342
+ l2_summed_intensity_dataset = process_summed_intensity_data(
343
+ l1b_summed_rates_dataset
344
+ )
345
+
346
+ # Check that a xarray dataset is returned
347
+ assert isinstance(l2_summed_intensity_dataset, xr.Dataset)
348
+
349
+ valid_coords = {
350
+ "epoch",
351
+ "h_energy_mean",
352
+ "he3_energy_mean",
353
+ "he4_energy_mean",
354
+ "he_energy_mean",
355
+ "c_energy_mean",
356
+ "o_energy_mean",
357
+ "fe_energy_mean",
358
+ "n_energy_mean",
359
+ "si_energy_mean",
360
+ "mg_energy_mean",
361
+ "s_energy_mean",
362
+ "ar_energy_mean",
363
+ "ca_energy_mean",
364
+ "na_energy_mean",
365
+ "al_energy_mean",
366
+ "ne_energy_mean",
367
+ "ni_energy_mean",
368
+ }
369
+
370
+ # Check that the dataset has the correct coords and variables
371
+ assert valid_coords == set(
372
+ l2_summed_intensity_dataset.coords
373
+ ), "Coordinates mismatch"
374
+
375
+ assert "dynamic_threshold_state" in l1b_summed_rates_dataset.data_vars
376
+
377
+ for particle in PARTICLE_ENERGY_RANGE_MAPPING.keys():
378
+ 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
383
+
384
+
385
+ def test_process_standard_intensity_data(l1b_standard_rates_dataset):
386
+ """Test the variables in the standard intensity dataset"""
387
+
388
+ l2_standard_intensity_dataset = process_standard_intensity_data(
389
+ l1b_standard_rates_dataset
390
+ )
391
+
392
+ # Check that a xarray dataset is returned
393
+ assert isinstance(l2_standard_intensity_dataset, xr.Dataset)
394
+
395
+ valid_coords = {
396
+ "epoch",
397
+ "h_energy_mean",
398
+ "he3_energy_mean",
399
+ "he4_energy_mean",
400
+ "he_energy_mean",
401
+ "c_energy_mean",
402
+ "n_energy_mean",
403
+ "o_energy_mean",
404
+ "ne_energy_mean",
405
+ "na_energy_mean",
406
+ "mg_energy_mean",
407
+ "al_energy_mean",
408
+ "si_energy_mean",
409
+ "s_energy_mean",
410
+ "ar_energy_mean",
411
+ "ca_energy_mean",
412
+ "fe_energy_mean",
413
+ "ni_energy_mean",
414
+ }
415
+
416
+ # Check that the dataset has the correct coords and variables
417
+ assert valid_coords == set(
418
+ l2_standard_intensity_dataset.coords
419
+ ), "Coordinates mismatch"
420
+
421
+ assert "dynamic_threshold_state" in l1b_standard_rates_dataset.data_vars
422
+
423
+ for particle in STANDARD_PARTICLE_ENERGY_RANGE_MAPPING.keys():
424
+ 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
429
+ assert (
430
+ f"{particle}_energy_delta_minus" in l2_standard_intensity_dataset.data_vars
431
+ )
432
+ assert (
433
+ f"{particle}_energy_delta_plus" in l2_standard_intensity_dataset.data_vars
434
+ )
435
+
436
+
437
+ def test_hit_l2(dependencies):
438
+ """Test creating L2 datasets ready for CDF output
439
+
440
+ Creates a list of xarray datasets for L2 products.
441
+
442
+ Parameters
443
+ ----------
444
+ dependencies : dict
445
+ Dictionary of L1B datasets
446
+ """
447
+ # TODO: update assertions after science data processing is completed
448
+ l2_datasets = hit_l2(dependencies["imap_hit_l1b_summed-rates"], "001")
449
+ assert len(l2_datasets) == 1
450
+ assert l2_datasets[0].attrs["Logical_source"] == "imap_hit_l2_summed-intensity"
451
+
452
+ l2_datasets = hit_l2(dependencies["imap_hit_l1b_standard-rates"], "001")
453
+ assert len(l2_datasets) == 1
454
+ assert l2_datasets[0].attrs["Logical_source"] == "imap_hit_l2_standard-intensity"
@@ -6,12 +6,17 @@ from imap_processing import imap_module_directory
6
6
  from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
7
7
  from imap_processing.hit.hit_utils import (
8
8
  HitAPID,
9
+ add_energy_variables,
9
10
  concatenate_leak_variables,
10
11
  get_attribute_manager,
11
12
  get_datasets_by_apid,
13
+ initialize_particle_data_arrays,
12
14
  process_housekeeping_data,
15
+ sum_particle_data,
13
16
  )
14
17
 
18
+ np.random.seed(42)
19
+
15
20
 
16
21
  @pytest.fixture(scope="module")
17
22
  def packet_filepath():
@@ -96,7 +101,6 @@ def test_process_housekeeping(housekeeping_dataset, attribute_manager):
96
101
  # Define the keys that should have dropped from the dataset
97
102
  dropped_keys = {
98
103
  "pkt_apid",
99
- "sc_tick",
100
104
  "version",
101
105
  "type",
102
106
  "sec_hdr_flg",
@@ -111,6 +115,7 @@ def test_process_housekeeping(housekeeping_dataset, attribute_manager):
111
115
  }
112
116
  # Define the keys that should be present
113
117
  valid_keys = {
118
+ "sc_tick",
114
119
  "heater_on",
115
120
  "fsw_version_b",
116
121
  "ebox_m12va",
@@ -173,7 +178,6 @@ def test_process_housekeeping(housekeeping_dataset, attribute_manager):
173
178
  "Acknowledgement": "Please acknowledge the IMAP Mission Principal "
174
179
  "Investigator, Prof. David J. McComas of Princeton "
175
180
  "University.\n",
176
- "Data_level": "1A",
177
181
  "Data_type": "L1A_HK>Level-1A Housekeeping",
178
182
  "Data_version": "001",
179
183
  "Descriptor": "HIT>IMAP High-energy Ion Telescope",
@@ -216,3 +220,109 @@ def test_process_housekeeping(housekeeping_dataset, attribute_manager):
216
220
  # Check that the dataset has the correct attributes, coordinates, and dimensions
217
221
  assert processed_hskp_dataset.attrs == dataset_attrs
218
222
  assert processed_hskp_dataset.coords.keys() == dataset_coords_dims
223
+
224
+
225
+ def test_add_energy_variables():
226
+ dataset = xr.Dataset()
227
+ particle = "test_particle"
228
+ energy_min = np.array([1.8, 4.0, 6.0], dtype=np.float32)
229
+ energy_max = np.array([2.2, 6.0, 10.0], dtype=np.float32)
230
+ energy_mean = np.mean([energy_min, energy_max], axis=0)
231
+ result = add_energy_variables(dataset, particle, energy_min, energy_max)
232
+ assert f"{particle}_energy_delta_minus" in result.data_vars
233
+ assert f"{particle}_energy_delta_plus" in result.data_vars
234
+ assert f"{particle}_energy_mean" in result.coords
235
+ assert np.all(
236
+ result[f"{particle}_energy_delta_minus"].values
237
+ == np.array(energy_mean - np.array(energy_min), dtype=np.float32)
238
+ )
239
+ assert np.all(
240
+ result[f"{particle}_energy_delta_plus"].values
241
+ == np.array(energy_max - energy_mean, dtype=np.float32)
242
+ )
243
+ assert np.all(
244
+ result[f"{particle}_energy_mean"].values
245
+ == np.mean([energy_min, energy_max], axis=0)
246
+ )
247
+
248
+
249
+ def test_sum_particle_data():
250
+ # Create a sample dataset
251
+ data = {
252
+ "l2fgrates": (("epoch", "energy"), np.random.rand(10, 5)),
253
+ "l3fgrates": (("epoch", "energy"), np.random.rand(10, 5)),
254
+ "penfgrates": (("epoch", "energy"), np.random.rand(10, 5)),
255
+ "l2fgrates_delta_minus": (("epoch", "energy"), np.random.rand(10, 5)),
256
+ "l3fgrates_delta_minus": (("epoch", "energy"), np.random.rand(10, 5)),
257
+ "penfgrates_delta_minus": (("epoch", "energy"), np.random.rand(10, 5)),
258
+ "l2fgrates_delta_plus": (("epoch", "energy"), np.random.rand(10, 5)),
259
+ "l3fgrates_delta_plus": (("epoch", "energy"), np.random.rand(10, 5)),
260
+ "penfgrates_delta_plus": (("epoch", "energy"), np.random.rand(10, 5)),
261
+ }
262
+ dataset = xr.Dataset(data)
263
+
264
+ # Define indices for summing
265
+ indices = {
266
+ "R2": [0, 1],
267
+ "R3": [2, 3],
268
+ "R4": [4],
269
+ }
270
+
271
+ # Call the function
272
+ summed_data, summed_uncertainty_delta_minus, summed_uncertainty_delta_plus = (
273
+ sum_particle_data(dataset, indices)
274
+ )
275
+
276
+ # Assertions
277
+ assert summed_data.shape == (10,)
278
+ assert summed_uncertainty_delta_minus.shape == (10,)
279
+ assert summed_uncertainty_delta_plus.shape == (10,)
280
+ assert np.all(
281
+ summed_data
282
+ == dataset["l2fgrates"][:, indices["R2"]].sum(axis=1)
283
+ + dataset["l3fgrates"][:, indices["R3"]].sum(axis=1)
284
+ + dataset["penfgrates"][:, indices["R4"]].sum(axis=1)
285
+ )
286
+ assert np.all(
287
+ summed_uncertainty_delta_minus
288
+ == dataset["l2fgrates_delta_minus"][:, indices["R2"]].sum(axis=1)
289
+ + dataset["l3fgrates_delta_minus"][:, indices["R3"]].sum(axis=1)
290
+ + dataset["penfgrates_delta_minus"][:, indices["R4"]].sum(axis=1)
291
+ )
292
+ assert np.all(
293
+ summed_uncertainty_delta_plus
294
+ == dataset["l2fgrates_delta_plus"][:, indices["R2"]].sum(axis=1)
295
+ + dataset["l3fgrates_delta_plus"][:, indices["R3"]].sum(axis=1)
296
+ + dataset["penfgrates_delta_plus"][:, indices["R4"]].sum(axis=1)
297
+ )
298
+
299
+
300
+ def test_initialize_particle_data_arrays():
301
+ # Create an empty dataset
302
+ dataset = xr.Dataset()
303
+
304
+ # Define parameters
305
+ particle = "test_particle"
306
+ num_energy_ranges = 5
307
+ epoch_size = 10
308
+
309
+ # Call the function
310
+ result = initialize_particle_data_arrays(
311
+ dataset, particle, num_energy_ranges, epoch_size
312
+ )
313
+
314
+ # Assertions
315
+ assert f"{particle}" in result.data_vars
316
+ assert f"{particle}_delta_minus" in result.data_vars
317
+ assert f"{particle}_delta_plus" in result.data_vars
318
+ assert f"{particle}_energy_mean" in result.coords
319
+
320
+ assert result[f"{particle}"].shape == (epoch_size, num_energy_ranges)
321
+ assert result[f"{particle}_delta_minus"].shape == (epoch_size, num_energy_ranges)
322
+ assert result[f"{particle}_delta_plus"].shape == (epoch_size, num_energy_ranges)
323
+ assert result[f"{particle}_energy_mean"].shape == (num_energy_ranges,)
324
+
325
+ assert np.all(result[f"{particle}"].values == 0)
326
+ assert np.all(result[f"{particle}_delta_minus"].values == 0)
327
+ assert np.all(result[f"{particle}_delta_plus"].values == 0)
328
+ assert np.all(result[f"{particle}_energy_mean"].values == 0)