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
@@ -1,8 +1,32 @@
1
+ """Tests to support I-ALiRT SWE packet parsing."""
2
+
3
+ from unittest.mock import patch
4
+
1
5
  import numpy as np
2
6
  import pandas as pd
3
7
  import pytest
8
+ import xarray as xr
4
9
 
5
10
  from imap_processing import imap_module_directory
11
+ from imap_processing.ialirt.l0.process_swe import (
12
+ average_counts,
13
+ azimuthal_check_counterstreaming,
14
+ compute_bidirectional,
15
+ decompress_counts,
16
+ determine_streaming,
17
+ find_bin_offsets,
18
+ find_min_counts,
19
+ get_ialirt_energies,
20
+ normalize_counts,
21
+ phi_to_bin,
22
+ polar_check_counterstreaming,
23
+ prepare_raw_counts,
24
+ process_swe,
25
+ )
26
+ from imap_processing.swe.utils.swe_constants import (
27
+ ESA_VOLTAGE_ROW_INDEX_DICT,
28
+ GEOMETRIC_FACTORS,
29
+ )
6
30
  from imap_processing.utils import packet_file_to_datasets
7
31
 
8
32
 
@@ -19,7 +43,7 @@ def binary_packet_path():
19
43
  imap_module_directory
20
44
  / "tests"
21
45
  / "ialirt"
22
- / "test_data"
46
+ / "data"
23
47
  / "l0"
24
48
  / "20240827095047_SWE_IALIRT_packet.bin"
25
49
  )
@@ -32,7 +56,7 @@ def swe_test_data():
32
56
  imap_module_directory
33
57
  / "tests"
34
58
  / "ialirt"
35
- / "test_data"
59
+ / "data"
36
60
  / "l0"
37
61
  / "idle_export_eu.SWE_IALIRT_20240827_093852.csv"
38
62
  )
@@ -41,7 +65,7 @@ def swe_test_data():
41
65
  return data
42
66
 
43
67
 
44
- @pytest.fixture()
68
+ @pytest.fixture
45
69
  def xarray_data(binary_packet_path, xtce_swe_path):
46
70
  """Create xarray data"""
47
71
  apid = 1360
@@ -52,9 +76,9 @@ def xarray_data(binary_packet_path, xtce_swe_path):
52
76
  return xarray_data
53
77
 
54
78
 
55
- def test_decom_packets(xarray_data, swe_test_data):
56
- """This function checks that all instrument parameters are accounted for."""
57
-
79
+ @pytest.fixture
80
+ def fields_to_test():
81
+ """Create a dictionary to convert names"""
58
82
  fields_to_test = {
59
83
  "swe_shcoarse": "SHCOARSE",
60
84
  "swe_acq_sec": "ACQUISITION_TIME",
@@ -91,6 +115,38 @@ def test_decom_packets(xarray_data, swe_test_data):
91
115
  "swe_cem7_e3": "ELEC_COUNTS_SPIN_I_POL_6_E_2J",
92
116
  "swe_cem7_e4": "ELEC_COUNTS_SPIN_I_POL_6_E_3J",
93
117
  }
118
+ return fields_to_test
119
+
120
+
121
+ @pytest.fixture
122
+ def summed_half_cycle():
123
+ """Create test set with known peaks"""
124
+
125
+ summed_half_cycle = np.zeros((8, 30))
126
+
127
+ for i in range(8):
128
+ peak = i + 5
129
+ summed_half_cycle[i, peak] = 100
130
+ summed_half_cycle[i, (peak + 6) % 30] = 60 # +90 offset
131
+ summed_half_cycle[i, (peak + 8) % 30] = 80 # +90 offset
132
+ summed_half_cycle[i, (peak + 14) % 30] = 20 # +180 offset
133
+ summed_half_cycle[i, (peak + 16) % 30] = 40 # +180 offset
134
+ summed_half_cycle[i, (peak - 6) % 30] = 5 # -90 offset
135
+ summed_half_cycle[i, (peak - 8) % 30] = 15 # -90 offset
136
+
137
+ return summed_half_cycle
138
+
139
+
140
+ def test_get_energy():
141
+ """Tests get_alirt_energies function."""
142
+ energies = get_ialirt_energies()
143
+
144
+ for i in range(len(energies)):
145
+ assert i + 11 == ESA_VOLTAGE_ROW_INDEX_DICT[energies[i]]
146
+
147
+
148
+ def test_decom_packets(xarray_data, swe_test_data, fields_to_test):
149
+ """This function checks that all instrument parameters are accounted for."""
94
150
  _, index, test_index = np.intersect1d(
95
151
  xarray_data["swe_shcoarse"], swe_test_data["SHCOARSE"], return_indices=True
96
152
  )
@@ -104,3 +160,260 @@ def test_decom_packets(xarray_data, swe_test_data):
104
160
  f"Mismatch found in {xarray_field}: "
105
161
  f"actual {actual_values}, expected {expected_values}"
106
162
  )
163
+
164
+
165
+ def test_decompress_counts():
166
+ """Test that we get correct decompressed counts from the algorithm."""
167
+ expected_value = 24063
168
+ input_count = 230
169
+ returned_value = decompress_counts(np.array([input_count]))
170
+ assert np.all(expected_value == returned_value)
171
+
172
+
173
+ def test_phi_to_bin():
174
+ """Test phi_to_bin function."""
175
+
176
+ # Define expected phi-to-bin mapping for one full spin
177
+ phis = np.arange(12, 361, 12).tolist()
178
+
179
+ expected_bins = np.arange(30)
180
+
181
+ for phi, expected_bin in zip(phis, expected_bins):
182
+ assert phi_to_bin(phi) == expected_bin
183
+
184
+
185
+ def test_prepare_raw_counts():
186
+ """Test that prepare_raw_counts correctly bins counts into (30, 7, 4) array."""
187
+
188
+ # 2 rows = 4 phis (12, 24, 36, 48)
189
+ epochs = [0, 1]
190
+
191
+ data = {
192
+ "group": ("epoch", [1, 1]), # Both rows belong to group 1
193
+ # CEM 1 (Phi 12, 24, 36, 48)
194
+ "swe_cem1_e1": ("epoch", [1, 9]),
195
+ "swe_cem1_e2": ("epoch", [2, 10]),
196
+ "swe_cem1_e3": ("epoch", [3, 11]),
197
+ "swe_cem1_e4": ("epoch", [4, 12]),
198
+ # CEM 2
199
+ "swe_cem2_e1": ("epoch", [5, 13]),
200
+ "swe_cem2_e2": ("epoch", [6, 14]),
201
+ "swe_cem2_e3": ("epoch", [7, 15]),
202
+ "swe_cem2_e4": ("epoch", [8, 16]),
203
+ "swe_seq": ("epoch", [0, 1]),
204
+ }
205
+
206
+ grouped_data = xr.Dataset(data, coords={"epoch": epochs})
207
+ group_mask = grouped_data["group"] == 1
208
+ grouped = grouped_data.sel(epoch=group_mask)
209
+
210
+ raw_counts = prepare_raw_counts(grouped, cem_number=2)
211
+
212
+ # Expected shape (8, 7, 30) but only some CEMs are used.
213
+ expected = np.zeros((8, 2, 30), dtype=np.uint8)
214
+
215
+ # Phi bins for 12, 24, 36, 48)
216
+ phi_bin_12 = 0 # Phi 12
217
+ phi_bin_24 = 1 # Phi 24
218
+ phi_bin_36 = 2 # Phi 36
219
+ phi_bin_48 = 3 # Phi 48
220
+
221
+ # CEM 1, Phi 12 (E1, E2)
222
+ expected[1, 0, phi_bin_12] = 1
223
+ expected[5, 0, phi_bin_12] = 2
224
+
225
+ # CEM 1, Phi 24 (E3, E4)
226
+ expected[7, 0, phi_bin_24] = 3
227
+ expected[3, 0, phi_bin_24] = 4
228
+
229
+ # CEM 1, Phi 36 (E1, E2)
230
+ expected[1, 0, phi_bin_36] = 9
231
+ expected[5, 0, phi_bin_36] = 10
232
+
233
+ # CEM 1, Phi 48 (E3, E4)
234
+ expected[7, 0, phi_bin_48] = 11
235
+ expected[3, 0, phi_bin_48] = 12
236
+
237
+ # CEM 2, Phi 12 (E1, E2)
238
+ expected[1, 1, phi_bin_12] = 5
239
+ expected[5, 1, phi_bin_12] = 6
240
+
241
+ # CEM 2, Phi 24 (E3, E4)
242
+ expected[7, 1, phi_bin_24] = 7
243
+ expected[3, 1, phi_bin_24] = 8
244
+
245
+ # CEM 2, Phi 36 (E1, E2)
246
+ expected[1, 1, phi_bin_36] = 13
247
+ expected[5, 1, phi_bin_36] = 14
248
+
249
+ # CEM 2, Phi 48 (E3, E4)
250
+ expected[7, 1, phi_bin_48] = 15
251
+ expected[3, 1, phi_bin_48] = 16
252
+
253
+ assert np.array_equal(raw_counts, expected)
254
+
255
+
256
+ def test_normalize_counts():
257
+ """Tests normalize_counts function"""
258
+
259
+ # Shape (2, 7, 3) for a small test case
260
+ corrected_counts = np.array(
261
+ [
262
+ [
263
+ [1, 2, 3],
264
+ [4, 5, 6],
265
+ [7, 8, 9],
266
+ [10, 11, 12],
267
+ [13, 14, 15],
268
+ [16, 17, 18],
269
+ [19, 20, 21],
270
+ ],
271
+ [
272
+ [2, 4, 6],
273
+ [8, 10, 12],
274
+ [14, 16, 18],
275
+ [20, 22, 24],
276
+ [26, 28, 30],
277
+ [32, 34, 36],
278
+ [38, 40, 42],
279
+ ],
280
+ ],
281
+ dtype=np.uint8,
282
+ )
283
+
284
+ latest_cal = pd.Series(
285
+ [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0],
286
+ index=[
287
+ "cem1",
288
+ "cem2",
289
+ "cem3",
290
+ "cem4",
291
+ "cem5",
292
+ "cem6",
293
+ "cem7",
294
+ ], # Simulating real data structure
295
+ dtype=np.float64,
296
+ )
297
+ expected = np.zeros((2, 7, 3), dtype=np.float64)
298
+
299
+ for i in range(2):
300
+ for j in range(7):
301
+ for k in range(3):
302
+ if corrected_counts[i][j][k] < 0:
303
+ expected[i][j][k] = 0.0
304
+ else:
305
+ expected[i][j][k] = (
306
+ corrected_counts[i][j][k] * latest_cal[j] / GEOMETRIC_FACTORS[j]
307
+ )
308
+
309
+ norm_counts = normalize_counts(corrected_counts, latest_cal)
310
+
311
+ assert np.allclose(norm_counts, expected, atol=1e-9)
312
+
313
+
314
+ def test_find_bin_offsets():
315
+ """Tests find_bin_offsets function"""
316
+
317
+ peak_bins = np.array([5, 6, 29])
318
+ bins = find_bin_offsets(peak_bins, (2, 3))
319
+ np.testing.assert_array_equal(bins, np.array([[7, 8, 1], [8, 9, 2]]))
320
+
321
+
322
+ def test_average_counts(summed_half_cycle):
323
+ """Tests average_values_and_azimuth function"""
324
+
325
+ # Find the azimuth angle that corresponds to the maximum counts at each energy
326
+ peak_az_bin = np.argmax(summed_half_cycle, axis=1)
327
+
328
+ # Bins +6 and +8 correspond to +90 degrees.
329
+ counts_90 = average_counts(peak_az_bin, summed_half_cycle, (6, 8))
330
+
331
+ assert np.allclose(counts_90, np.full(8, 70), atol=1e-9)
332
+
333
+
334
+ def test_find_min_counts(summed_half_cycle):
335
+ """Tests find_min_counts function"""
336
+
337
+ cpeak, cmin, counts = find_min_counts(summed_half_cycle)
338
+ np.testing.assert_array_equal(cpeak, np.full(8, 100))
339
+ np.testing.assert_array_equal(cmin, counts[0])
340
+
341
+
342
+ def test_determine_streaming_summed_cems():
343
+ """Tests determine_streaming_summed_cems function."""
344
+
345
+ # Case where streaming should be True
346
+ cpeak = np.array([100, 80, 50, 60])
347
+ cmin = np.array([20, 70, 40, 60])
348
+ counts_180 = np.array([40, 60, 90, 110])
349
+ assert np.array_equal(
350
+ determine_streaming(cpeak, counts_180, cmin), np.array([1, 0, 0, 0])
351
+ )
352
+
353
+
354
+ def test_compute_bidirectional():
355
+ """Tests compute_bidirectional function."""
356
+
357
+ first_half = np.array([1, 0, 0, 0, 1, 0, 0, 0])
358
+ second_half = np.array([1, 0, 0, 0, 1, 0, 0, 0])
359
+ assert compute_bidirectional(first_half, second_half) == (0, 0)
360
+
361
+ first_half = np.array([1, 1, 1, 0, 0, 0, 0, 0])
362
+ second_half = np.array([0, 0, 0, 0, 0, 0, 0, 0])
363
+ assert compute_bidirectional(first_half, second_half) == (1, 0)
364
+
365
+
366
+ def test_azimuthal_check_counterstreaming(summed_half_cycle):
367
+ """Tests azimuthal_check_counterstreaming function."""
368
+
369
+ bde = azimuthal_check_counterstreaming(summed_half_cycle, summed_half_cycle)
370
+
371
+ assert bde == (1, 1)
372
+
373
+
374
+ def test_polar_check_counterstreaming():
375
+ """Tests polar_check_counterstreaming function."""
376
+
377
+ # cem0 (cem1) and cem6 (cem7) have high values
378
+ # cem2, cem3, cem4 (cem3 to cem5) are low and used for cmin
379
+ row = np.array([100, 20, 5, 5, 5, 20, 100])
380
+ summed_half = np.tile(row, (8, 1))
381
+
382
+ bde = polar_check_counterstreaming(summed_half, summed_half)
383
+
384
+ assert bde == (1, 1)
385
+
386
+
387
+ @patch(
388
+ "imap_processing.ialirt.l0.process_swe.read_in_flight_cal_data",
389
+ return_value=pd.DataFrame(
390
+ {
391
+ "met_time": [453051300, 453051900],
392
+ "cem1": [1, 2],
393
+ "cem2": [1, 2],
394
+ "cem3": [1, 2],
395
+ "cem4": [1, 2],
396
+ "cem5": [1, 2],
397
+ "cem6": [1, 2],
398
+ "cem7": [1, 2],
399
+ }
400
+ ),
401
+ )
402
+ def test_process_swe(mock_read_cal, swe_test_data, fields_to_test):
403
+ """Test processing for swe."""
404
+ swe_test_data = swe_test_data.rename(
405
+ columns={v: k for k, v in fields_to_test.items()}
406
+ )
407
+ swe_test_data.index.name = "epoch"
408
+ ds = swe_test_data.to_xarray()
409
+ ds["src_seq_ctr"] = ("epoch", np.arange(len(ds["swe_shcoarse"])))
410
+ in_flight_cal_file = (
411
+ imap_module_directory
412
+ / "tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv"
413
+ )
414
+ swe_data = process_swe(ds, [in_flight_cal_file])
415
+
416
+ # TODO: add tests with test data here.
417
+
418
+ # Check that all groups in the data are accounted for.
419
+ assert len(swe_data) == 912 // 60
@@ -0,0 +1,16 @@
1
+ """Tests grouping functions for I-ALiRT instruments."""
2
+
3
+ import numpy as np
4
+
5
+ from imap_processing.ialirt.utils.time import calculate_time
6
+
7
+
8
+ def test_calculate_time():
9
+ """Tests calculate_time function."""
10
+
11
+ coarse = np.array([1, 2, 3, 4, 5])
12
+ fine = np.array([0, 1, 2, 3, 4])
13
+
14
+ time = calculate_time(coarse, fine, 6553)
15
+
16
+ np.testing.assert_allclose(time, coarse + fine / 65535.0, atol=1e-03, rtol=0)
@@ -1,4 +1,4 @@
1
- from pathlib import Path
1
+ from unittest import mock
2
2
 
3
3
  import numpy as np
4
4
  import pytest
@@ -6,6 +6,19 @@ import xarray as xr
6
6
 
7
7
  from imap_processing import imap_module_directory
8
8
  from imap_processing.idex.idex_l1a import PacketParser
9
+ from imap_processing.idex.idex_l1b import idex_l1b
10
+ from imap_processing.idex.idex_l2a import idex_l2a
11
+
12
+ TEST_DATA_PATH = imap_module_directory / "tests" / "idex" / "test_data"
13
+
14
+ TEST_L0_FILE_SCI = TEST_DATA_PATH / "imap_idex_l0_raw_20231218_v001.pkts"
15
+ TEST_L0_FILE_EVT = TEST_DATA_PATH / "imap_idex_l0_raw_20250108_v001.pkts" # 1418
16
+ TEST_L0_FILE_CATLST = TEST_DATA_PATH / "imap_idex_l0_raw_20241206_v001.pkts" # 1419
17
+
18
+ L1A_EXAMPLE_FILE = TEST_DATA_PATH / "idex_l1a_validation_file.h5"
19
+ L1B_EXAMPLE_FILE = TEST_DATA_PATH / "idex_l1b_validation_file.h5"
20
+
21
+ pytestmark = pytest.mark.external_test_data
9
22
 
10
23
  SPICE_ARRAYS = [
11
24
  "ephemeris_position_x",
@@ -21,19 +34,86 @@ SPICE_ARRAYS = [
21
34
  ]
22
35
 
23
36
 
24
- @pytest.fixture(scope="module")
25
- def decom_test_data() -> xr.Dataset:
37
+ @pytest.fixture
38
+ def decom_test_data_sci() -> xr.Dataset:
26
39
  """Return a ``xarray`` dataset containing test data.
27
40
 
28
41
  Returns
29
42
  -------
30
43
  dataset : xarray.Dataset
44
+ A ``xarray`` dataset containing the science test data
45
+ """
46
+ return PacketParser(TEST_L0_FILE_SCI).data[0]
47
+
48
+
49
+ @pytest.fixture
50
+ def decom_test_data_catlst() -> xr.Dataset:
51
+ """Return a ``xarray`` dataset containing the catalog list summary data.
52
+
53
+ Returns
54
+ -------
55
+ dataset : xarray.Dataset
56
+ A ``xarray`` dataset containing the catalog list summary data.
57
+ """
58
+ return PacketParser(TEST_L0_FILE_CATLST).data[0]
59
+
60
+
61
+ @pytest.fixture
62
+ def decom_test_data_evt() -> xr.Dataset:
63
+ """Return a ``xarray`` dataset containing the event log data.
64
+
65
+ Returns
66
+ -------
67
+ dataset : xarray.Dataset
68
+ A ``xarray`` dataset containing the event log data.
69
+ """
70
+ return PacketParser(TEST_L0_FILE_EVT).data[0]
71
+
72
+
73
+ @pytest.fixture
74
+ def l1a_example_data(_download_test_data):
75
+ """
76
+ Pytest fixture to load example L1A data (produced by the IDEX team) for testing.
77
+
78
+ Returns
79
+ -------
80
+ dict
81
+ A dictionary containing the 6 waveform and telemetry arrays
82
+ """
83
+ return load_hdf_file(L1A_EXAMPLE_FILE)
84
+
85
+
86
+ @pytest.fixture
87
+ def l2a_dataset(decom_test_data_sci: xr.Dataset) -> xr.Dataset:
88
+ """Return a ``xarray`` dataset containing test data.
89
+
90
+ Returns
91
+ -------
92
+ dataset : xr.Dataset
31
93
  A ``xarray`` dataset containing the test data
32
94
  """
33
- test_file = Path(
34
- f"{imap_module_directory}/tests/idex/test_data/imap_idex_l0_raw_20231214_v001.pkts"
95
+ spin_phase_angles = xr.DataArray(
96
+ np.random.randint(0, 360, len(decom_test_data_sci.epoch))
35
97
  )
36
- return PacketParser(test_file, "001").data
98
+ with mock.patch(
99
+ "imap_processing.idex.idex_l1b.get_spice_data",
100
+ return_value={"spin_phase": spin_phase_angles},
101
+ ):
102
+ dataset = idex_l2a(idex_l1b(decom_test_data_sci))
103
+ return dataset
104
+
105
+
106
+ @pytest.fixture
107
+ def l1b_example_data(_download_test_data):
108
+ """
109
+ Pytest fixture to load example L1B data (produced by the IDEX team) for testing.
110
+
111
+ Returns
112
+ -------
113
+ dict
114
+ A dictionary containing the 6 waveform and telemetry arrays
115
+ """
116
+ return load_hdf_file(L1B_EXAMPLE_FILE)
37
117
 
38
118
 
39
119
  def get_spice_data_side_effect_func(l1a_ds, idex_attrs):
@@ -48,3 +128,44 @@ def get_spice_data_side_effect_func(l1a_ds, idex_attrs):
48
128
  )
49
129
  for name in SPICE_ARRAYS
50
130
  }
131
+
132
+
133
+ def load_hdf_file(path: str) -> xr.Dataset:
134
+ """
135
+ Loads an HDF5 file produced by the IDEX team into a dataset.
136
+
137
+ Parameters
138
+ ----------
139
+ path : str
140
+ The file path to the HDF5 file.
141
+
142
+ Returns
143
+ -------
144
+ dataset
145
+ A dataset containing the extracted data.
146
+ """
147
+ # Load hdf5 data into a datatree
148
+ datatree = xr.open_datatree(path, engine="netcdf4")
149
+ datasets = []
150
+ # Sort datatree by the event number
151
+ datatree = sorted(datatree.items(), key=lambda x: int(x[0]))
152
+ # Iterate through every nested tree in the datatree (Each nested tree represents
153
+ # data from one event).
154
+ # Rename the dimensions across every tree to be the same
155
+ # Add an "event" dimension which will allow them all to be concatenated together.
156
+ for event, tree in datatree:
157
+ event_num = int(event)
158
+ # Extract the metadata
159
+ metadata = tree.Metadata.to_dataset().expand_dims({"event": [event_num]})
160
+ ds = tree.to_dataset()
161
+ # Sort dimensions by shape. The high sampling time dimension is always less
162
+ # than the low sampling time.
163
+ dims = [k for k, v in sorted(ds.sizes.items(), key=lambda item: item[1])]
164
+ ds = ds.rename({dims[0]: "time_low", dims[1]: "time_high"}).expand_dims(
165
+ {"event": [event_num]}
166
+ )
167
+ datasets.append(xr.merge([ds, metadata]))
168
+
169
+ example_dataset = xr.concat(datasets, dim="event")
170
+
171
+ return example_dataset