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
@@ -2,19 +2,112 @@ from unittest.mock import patch
2
2
 
3
3
  import numpy as np
4
4
  import pandas as pd
5
+ import pytest
6
+ from imap_data_access.processing_input import (
7
+ AncillaryInput,
8
+ ProcessingInputCollection,
9
+ ScienceInput,
10
+ )
5
11
 
6
12
  from imap_processing import imap_module_directory
7
13
  from imap_processing.cdf.utils import load_cdf, write_cdf
8
14
  from imap_processing.swe.l1a.swe_l1a import swe_l1a
9
15
  from imap_processing.swe.l1a.swe_science import swe_science
10
- from imap_processing.swe.l1b.swe_l1b import swe_l1b
11
- from imap_processing.swe.l1b.swe_l1b_science import (
16
+ from imap_processing.swe.l1b.swe_l1b import (
17
+ apply_in_flight_calibration,
12
18
  convert_counts_to_rate,
13
19
  deadtime_correction,
20
+ get_checker_board_pattern,
21
+ get_indices_of_full_cycles,
22
+ swe_l1b,
14
23
  )
24
+ from imap_processing.swe.utils import swe_constants
25
+
26
+
27
+ @pytest.fixture(scope="session")
28
+ def l1a_test_data(decom_test_data):
29
+ """Read test data from file and process to l1a"""
30
+ processed_data = swe_science(decom_test_data)
31
+ return processed_data
32
+
33
+
34
+ def test_get_full_cycle_data_indices():
35
+ q = np.array([0, 1, 2, 0, 1, 2, 3, 2, 3, 0, 2, 3, 0, 1, 2, 3, 2, 3, 1, 0])
36
+ filtered_q = get_indices_of_full_cycles(q)
37
+ np.testing.assert_array_equal(filtered_q, np.array([3, 4, 5, 6, 12, 13, 14, 15]))
38
+
39
+ q = np.array([0, 1, 0, 1, 2, 3, 0, 2])
40
+ filtered_q = get_indices_of_full_cycles(q)
41
+ np.testing.assert_array_equal(filtered_q, np.array([2, 3, 4, 5]))
42
+
43
+ q = np.array([0, 1, 2, 3])
44
+ filtered_q = get_indices_of_full_cycles(q)
45
+ np.testing.assert_array_equal(filtered_q, np.array([0, 1, 2, 3]))
46
+
47
+ q = np.array([1, 2])
48
+ filtered_q = get_indices_of_full_cycles(q)
49
+ np.testing.assert_array_equal(filtered_q, np.array([]))
15
50
 
16
51
 
17
- def test_swe_l1b(decom_test_data_derived):
52
+ def test_in_flight_calibration_factor(l1a_test_data):
53
+ """Test that the L1B processing is working as expected."""
54
+ # create sample data
55
+
56
+ input_time = 453051355.0
57
+ input_count = 19967
58
+ one_full_cycle_data = np.full(
59
+ (
60
+ swe_constants.N_ESA_STEPS,
61
+ swe_constants.N_ANGLE_SECTORS,
62
+ swe_constants.N_CEMS,
63
+ ),
64
+ input_count,
65
+ )
66
+ acquisition_time = np.full(
67
+ (swe_constants.N_ESA_STEPS, swe_constants.N_ANGLE_SECTORS), input_time
68
+ )
69
+
70
+ # Test that calibration factor is within correct range given test data
71
+ expected_cal_factor = 1 + ((1 - 1) / (453051900 - 453051300)) * (
72
+ input_time - 453051300
73
+ )
74
+
75
+ in_flight_cal_files = [
76
+ imap_module_directory
77
+ / "tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv"
78
+ ]
79
+ calibrated_count = apply_in_flight_calibration(
80
+ one_full_cycle_data,
81
+ acquisition_time,
82
+ in_flight_cal_files,
83
+ )
84
+
85
+ np.testing.assert_allclose(
86
+ calibrated_count,
87
+ np.full(
88
+ (
89
+ swe_constants.N_ESA_STEPS,
90
+ swe_constants.N_ANGLE_SECTORS,
91
+ swe_constants.N_CEMS,
92
+ ),
93
+ input_count * expected_cal_factor,
94
+ ),
95
+ rtol=1e-9,
96
+ )
97
+
98
+ # Check for value outside of calibration time range
99
+ input_time = 1.0
100
+ acquisition_time = np.full(
101
+ (swe_constants.N_ESA_STEPS, swe_constants.N_ANGLE_SECTORS), input_time
102
+ )
103
+
104
+ with pytest.raises(ValueError, match="Acquisition min/max times: "):
105
+ apply_in_flight_calibration(
106
+ one_full_cycle_data, acquisition_time, in_flight_cal_files
107
+ )
108
+
109
+
110
+ def test_swe_l1b_conversion(decom_test_data_derived):
18
111
  """Test that calculate engineering unit(EU) matches validation data.
19
112
 
20
113
  Parameters
@@ -22,7 +115,7 @@ def test_swe_l1b(decom_test_data_derived):
22
115
  decom_test_data_derived : xarray.dataset
23
116
  Dataset with derived values
24
117
  """
25
- science_l1a_ds = swe_science(decom_test_data_derived, "001")
118
+ science_l1a_ds = swe_science(decom_test_data_derived)
26
119
 
27
120
  # read science validation data
28
121
  test_data_path = imap_module_directory / "tests/swe/l0_validation_data"
@@ -47,29 +140,73 @@ def test_swe_l1b(decom_test_data_derived):
47
140
  )
48
141
 
49
142
 
50
- @patch(
51
- "imap_processing.swe.l1b.swe_l1b_science.read_in_flight_cal_data",
52
- return_value=pd.DataFrame(
53
- {
54
- "met_time": [452051300, 454051900],
55
- "cem1": [1, 1],
56
- "cem2": [1, 1],
57
- "cem3": [1, 1],
58
- "cem4": [1, 1],
59
- "cem5": [1, 1],
60
- "cem6": [1, 1],
61
- "cem7": [1, 1],
62
- }
63
- ),
64
- )
65
- def test_cdf_creation(mock_read_in_flight_cal_data, l1b_validation_df):
143
+ def test_get_checker_board_pattern():
144
+ """Test that the checkerboard pattern is generated correctly."""
145
+ # First read the checkerboard pattern from the file
146
+ expected_checkerboard = pd.read_csv(
147
+ imap_module_directory / "tests/swe/lut/checker-board-indices.csv", header=None
148
+ ).values
149
+ esa_lut_file = (
150
+ imap_module_directory / "tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv"
151
+ )
152
+ checkerboard_pattern = get_checker_board_pattern(esa_lut_file)
153
+
154
+ # Use assert_array_equal to compare the arrays
155
+ np.testing.assert_array_equal(
156
+ checkerboard_pattern,
157
+ expected_checkerboard,
158
+ err_msg="Checkerboard pattern is not the same as the one in the LUT file.",
159
+ )
160
+
161
+
162
+ @patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths")
163
+ def test_swe_l1b(mock_get_file_paths, l1b_validation_df):
66
164
  """Test that CDF file is created and has the correct name."""
67
165
  test_data_path = "tests/swe/l0_data/2024051010_SWE_SCIENCE_packet.bin"
68
- l1a_datasets = swe_l1a(imap_module_directory / test_data_path, "002")
166
+ l1a_datasets = swe_l1a(imap_module_directory / test_data_path)
167
+
168
+ l1b_input = l1a_datasets[0]
169
+
170
+ # Set these two as cli.py -> post_processing would have.
171
+ l1b_input.attrs["Data_version"] = "v002"
172
+ # write data to CDF
173
+ l1a_cdf_filepath = write_cdf(l1b_input)
174
+ assert l1a_cdf_filepath.name == "imap_swe_l1a_sci_20240510_v002.cdf"
175
+
176
+ def get_file_paths_side_effect(descriptor):
177
+ if descriptor == "sci":
178
+ return [l1a_cdf_filepath]
179
+ elif descriptor == "l1b-in-flight-cal":
180
+ return [
181
+ imap_module_directory
182
+ / "tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv"
183
+ ]
184
+ elif descriptor == "eu-conversion":
185
+ return [
186
+ imap_module_directory
187
+ / "tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv"
188
+ ]
189
+ elif descriptor == "esa-lut":
190
+ return [
191
+ imap_module_directory
192
+ / "tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv"
193
+ ]
194
+ else:
195
+ raise ValueError(f"Unknown descriptor: {descriptor}")
196
+
197
+ mock_get_file_paths.side_effect = get_file_paths_side_effect
198
+ science_input = ScienceInput(l1a_cdf_filepath.name)
199
+ inflight_anc = AncillaryInput(
200
+ "imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv"
201
+ )
202
+ eu_anc = AncillaryInput("imap_swe_eu-conversion_20240510_v000.csv")
203
+ dependencies = ProcessingInputCollection(science_input, inflight_anc, eu_anc)
204
+ l1b_datasets = swe_l1b(dependencies)
69
205
 
70
- l1b_dataset = swe_l1b(l1a_datasets[0], "002")
206
+ l1b_write_ds = l1b_datasets[0]
207
+ l1b_write_ds.attrs["Data_version"] = "v002"
71
208
 
72
- sci_l1b_filepath = write_cdf(l1b_dataset[0])
209
+ sci_l1b_filepath = write_cdf(l1b_write_ds)
73
210
 
74
211
  assert sci_l1b_filepath.name == "imap_swe_l1b_sci_20240510_v002.cdf"
75
212
  # load the CDF file and compare the values
@@ -81,9 +218,10 @@ def test_cdf_creation(mock_read_in_flight_cal_data, l1b_validation_df):
81
218
 
82
219
  def test_count_rate():
83
220
  x = np.array([1, 10, 100, 1000, 10000, 38911, 65535])
84
- acq_duration = 80000
221
+ acq_duration = np.array([80000])
85
222
  deatime_corrected = deadtime_correction(x, acq_duration)
86
223
  count_rate = convert_counts_to_rate(deatime_corrected, acq_duration)
224
+ count_rate = count_rate.flatten() # Ensure the shape matches expected_output
87
225
  # Ruth provided the expected output for this test
88
226
  expected_output = [
89
227
  12.50005653,
@@ -1,47 +1,33 @@
1
1
  from unittest.mock import patch
2
2
 
3
3
  import numpy as np
4
- import pandas as pd
5
4
  import pytest
6
5
  import xarray as xr
6
+ from imap_data_access.processing_input import (
7
+ AncillaryInput,
8
+ ProcessingInputCollection,
9
+ ScienceInput,
10
+ )
7
11
 
8
12
  from imap_processing import imap_module_directory
9
13
  from imap_processing.cdf.utils import write_cdf
10
14
  from imap_processing.swe.l1a.swe_l1a import swe_l1a
11
15
  from imap_processing.swe.l1b.swe_l1b import swe_l1b
12
16
  from imap_processing.swe.l2.swe_l2 import (
13
- ENERGY_CONVERSION_FACTOR,
14
- VELOCITY_CONVERSION_FACTOR,
15
17
  calculate_flux,
16
18
  calculate_phase_space_density,
17
19
  find_angle_bin_indices,
18
- get_particle_energy,
19
20
  put_data_into_angle_bins,
20
21
  swe_l2,
21
22
  )
22
- from imap_processing.swe.utils.swe_utils import read_lookup_table
23
-
24
-
25
- def test_get_particle_energy():
26
- """Test get_particle_energy function."""
27
- all_energy = get_particle_energy()
28
- expected_energy = read_lookup_table()["esa_v"].values * ENERGY_CONVERSION_FACTOR
29
- np.testing.assert_array_equal(all_energy["energy"], expected_energy)
23
+ from imap_processing.swe.utils import swe_constants
30
24
 
31
25
 
32
- @patch("imap_processing.swe.l2.swe_l2.GEOMETRIC_FACTORS", new=np.full(7, 1))
33
26
  @patch(
34
- "imap_processing.swe.l2.swe_l2.get_particle_energy",
35
- return_value=pd.DataFrame(
36
- {
37
- "table_index": np.repeat([0, 1], 720),
38
- "e_step": np.tile(np.arange(720), 2),
39
- "esa_v": np.repeat([1, 2], 720),
40
- "energy": np.repeat([1, 2], 720),
41
- }
42
- ),
27
+ "imap_processing.swe.utils.swe_constants.GEOMETRIC_FACTORS",
28
+ new=np.full(swe_constants.N_CEMS, 1),
43
29
  )
44
- def test_calculate_phase_space_density(patch_get_particle_energy):
30
+ def test_calculate_phase_space_density():
45
31
  """Test calculate_phase_space_density function."""
46
32
  # Create a dummy l1b dataset
47
33
  total_sweeps = 2
@@ -50,21 +36,35 @@ def test_calculate_phase_space_density(patch_get_particle_energy):
50
36
  {
51
37
  "science_data": (
52
38
  ["epoch", "energy", "angle", "cem"],
53
- np.full((total_sweeps, 24, 30, 7), 1),
39
+ np.full(
40
+ (
41
+ total_sweeps,
42
+ swe_constants.N_ESA_STEPS,
43
+ swe_constants.N_ANGLE_SECTORS,
44
+ swe_constants.N_CEMS,
45
+ ),
46
+ 1,
47
+ ),
54
48
  ),
55
- "acq_duration": (["epoch", "cycle"], np.full((total_sweeps, 4), 80.0)),
56
- "esa_table_num": (
57
- ["epoch", "cycle"],
58
- np.repeat([0, 1], 4).reshape(total_sweeps, 4),
49
+ "esa_energy": (
50
+ ["epoch", "energy", "angle"],
51
+ np.full(
52
+ (
53
+ total_sweeps,
54
+ swe_constants.N_ESA_STEPS,
55
+ swe_constants.N_ANGLE_SECTORS,
56
+ ),
57
+ 1,
58
+ ),
59
59
  ),
60
60
  }
61
61
  )
62
- phase_space_density_ds = calculate_phase_space_density(l1b_dataset)
63
- assert phase_space_density_ds["phase_space_density"].shape == (
62
+ phase_space_density = calculate_phase_space_density(l1b_dataset)
63
+ assert phase_space_density.shape == (
64
64
  total_sweeps,
65
- 24,
66
- 30,
67
- 7,
65
+ swe_constants.N_ESA_STEPS,
66
+ swe_constants.N_ANGLE_SECTORS,
67
+ swe_constants.N_CEMS,
68
68
  )
69
69
 
70
70
  # Test that first sweep has correct values. In patch,
@@ -72,43 +72,51 @@ def test_calculate_phase_space_density(patch_get_particle_energy):
72
72
  # 2. we have set energy to 1.
73
73
  # 3. we have set science_data to 1.
74
74
  # Using this in the formula, we calculate expected density value.
75
- expected_calculated_density = (2 * 1) / (1 * VELOCITY_CONVERSION_FACTOR * 1**2)
76
- expected_density = np.full((24, 30, 7), expected_calculated_density)
77
- np.testing.assert_array_equal(
78
- phase_space_density_ds["phase_space_density"][0].data, expected_density
75
+ expected_calculated_density = (2 * 1) / (
76
+ 1 * swe_constants.VELOCITY_CONVERSION_FACTOR * 1**2
79
77
  )
80
-
81
- # Test that second sweep has correct values, similar to first sweep,
82
- # but with energy 2.
83
- expected_calculated_density = (2 * 1) / (1 * VELOCITY_CONVERSION_FACTOR * 2**2)
84
- expected_density = np.full((24, 30, 7), expected_calculated_density)
85
- np.testing.assert_array_equal(
86
- phase_space_density_ds["phase_space_density"][1].data, expected_density
78
+ expected_density = np.full(
79
+ (
80
+ swe_constants.N_ESA_STEPS,
81
+ swe_constants.N_ANGLE_SECTORS,
82
+ swe_constants.N_CEMS,
83
+ ),
84
+ expected_calculated_density,
87
85
  )
88
- assert type(phase_space_density_ds) == xr.Dataset
86
+ np.testing.assert_array_equal(phase_space_density[0].data, expected_density)
89
87
 
90
88
 
91
89
  def test_calculate_flux():
92
90
  """Test calculate_flux function."""
93
91
  # Create a dummy l1b dataset
94
92
  total_sweeps = 2
95
- l1b_dataset = xr.Dataset(
96
- {
97
- "science_data": (
98
- ["epoch", "energy", "angle", "cem"],
99
- np.full((total_sweeps, 24, 30, 7), 1),
100
- ),
101
- "acq_duration": (["epoch", "cycle"], np.full((total_sweeps, 4), 80.0)),
102
- "esa_table_num": (
103
- ["epoch", "cycle"],
104
- np.repeat([0, 1], 4).reshape(total_sweeps, 4),
105
- ),
106
- }
93
+ phase_space_density = np.full(
94
+ (
95
+ total_sweeps,
96
+ swe_constants.N_ESA_STEPS,
97
+ swe_constants.N_ANGLE_SECTORS,
98
+ swe_constants.N_CEMS,
99
+ ),
100
+ 1,
101
+ )
102
+
103
+ esa_energy = np.full(
104
+ (
105
+ total_sweeps,
106
+ swe_constants.N_ESA_STEPS,
107
+ swe_constants.N_ANGLE_SECTORS,
108
+ ),
109
+ 1,
107
110
  )
108
111
 
109
- flux = calculate_flux(l1b_dataset)
110
- assert flux.shape == (total_sweeps, 24, 30, 7)
111
- assert type(flux) == np.ndarray
112
+ flux = calculate_flux(phase_space_density, esa_energy)
113
+ assert flux.shape == (
114
+ total_sweeps,
115
+ swe_constants.N_ESA_STEPS,
116
+ swe_constants.N_ANGLE_SECTORS,
117
+ swe_constants.N_CEMS,
118
+ )
119
+ assert isinstance(flux, np.ndarray)
112
120
 
113
121
 
114
122
  def test_find_angle_bin_indices():
@@ -142,18 +150,19 @@ def test_find_angle_bin_indices():
142
150
  def test_put_data_into_angle_bins():
143
151
  """Test put_data_into_angle_bins function."""
144
152
  num_cycles = 1
145
- num_esa_step = 24
146
- num_angle_bins = 30
147
- num_cems = 7
148
153
  # Create test counts data to test
149
154
  # Find all even numbers in the range 0 to 30
150
155
  even_numbers = np.arange(0, 30, 2)
151
156
  # repeat it twice now to get:
152
157
  # [0, 0, 2, 2, ...., 28, 28]
153
158
  example_data = np.repeat(even_numbers, 2)
154
- energy_angle_test_data = np.tile(example_data, (num_cycles, num_esa_step, 1))
159
+ energy_angle_test_data = np.tile(
160
+ example_data, (num_cycles, swe_constants.N_ESA_STEPS, 1)
161
+ )
155
162
  # Expand to include 7 CEMs by repeating across last dimension
156
- test_data = np.repeat(energy_angle_test_data[..., np.newaxis], num_cems, axis=-1)
163
+ test_data = np.repeat(
164
+ energy_angle_test_data[..., np.newaxis], swe_constants.N_CEMS, axis=-1
165
+ )
157
166
 
158
167
  # Took this example from intermediate output from actual data
159
168
  angle_bins_example = [
@@ -190,16 +199,28 @@ def test_put_data_into_angle_bins():
190
199
  ]
191
200
  # Now data with every row to be same as angle_bins_example
192
201
  test_angle_bin_indices_data = np.full(
193
- (num_cycles, num_esa_step, num_angle_bins), angle_bins_example
202
+ (num_cycles, swe_constants.N_ESA_STEPS, swe_constants.N_ANGLE_SECTORS),
203
+ angle_bins_example,
194
204
  )
195
205
 
196
206
  binned_data = put_data_into_angle_bins(test_data, test_angle_bin_indices_data)
197
- assert binned_data.shape == (num_cycles, num_esa_step, num_angle_bins, num_cems)
207
+ assert binned_data.shape == (
208
+ num_cycles,
209
+ swe_constants.N_ESA_STEPS,
210
+ swe_constants.N_ANGLE_BINS,
211
+ swe_constants.N_CEMS,
212
+ )
198
213
 
199
214
  # Test that the binned data has correct values in correct bins by
200
215
  # checking that odd number columns are filled with nan
201
216
  expected_binned_data = np.full(
202
- (num_cycles, num_esa_step, num_angle_bins, num_cems), np.nan
217
+ (
218
+ num_cycles,
219
+ swe_constants.N_ESA_STEPS,
220
+ swe_constants.N_ANGLE_BINS,
221
+ swe_constants.N_CEMS,
222
+ ),
223
+ np.nan,
203
224
  )
204
225
  np.testing.assert_array_equal(
205
226
  binned_data[0, 0, 1::2, 0], expected_binned_data[0, 0, 1::2, 0]
@@ -230,39 +251,80 @@ def test_put_data_into_angle_bins():
230
251
  np.testing.assert_array_equal(even_col_mean_data, expected_mean_data)
231
252
 
232
253
 
233
- @patch(
234
- "imap_processing.swe.l1b.swe_l1b_science.read_in_flight_cal_data",
235
- return_value=pd.DataFrame(
236
- {
237
- "met_time": [453050300, 453077900],
238
- "cem1": [1, 1],
239
- "cem2": [1, 1],
240
- "cem3": [1, 1],
241
- "cem4": [1, 1],
242
- "cem5": [1, 1],
243
- "cem6": [1, 1],
244
- "cem7": [1, 1],
245
- }
246
- ),
247
- )
254
+ @patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths")
248
255
  @pytest.mark.usefixtures("use_fake_spin_data_for_time")
249
- def test_swe_l2(mock_read_in_flight_cal_data, use_fake_spin_data_for_time):
256
+ def test_swe_l2(mock_get_file_paths, use_fake_spin_data_for_time):
250
257
  """Test L2 processing."""
251
258
  data_start_time = 453051293.099714
252
259
  data_end_time = 453070000.0
253
260
  use_fake_spin_data_for_time(data_start_time, data_end_time)
254
261
 
255
262
  test_data_path = "tests/swe/l0_data/2024051010_SWE_SCIENCE_packet.bin"
256
- l1a_datasets = swe_l1a(imap_module_directory / test_data_path, "002")
263
+ l1a_datasets = swe_l1a(imap_module_directory / test_data_path)
264
+ l1a_ds = l1a_datasets[0]
265
+ l1a_ds.attrs["Data_version"] = "v000"
266
+ l1a_cdf_filepath = write_cdf(l1a_ds)
267
+ assert l1a_cdf_filepath.name == "imap_swe_l1a_sci_20240510_v000.cdf"
257
268
 
258
- l1b_dataset = swe_l1b(l1a_datasets[0], "002")
259
- l2_dataset = swe_l2(l1b_dataset[0], "002")
269
+ def get_file_paths_side_effect(descriptor):
270
+ if descriptor == "sci":
271
+ return [l1a_cdf_filepath]
272
+ elif descriptor == "l1b-in-flight-cal":
273
+ return [
274
+ imap_module_directory
275
+ / "tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv"
276
+ ]
277
+ elif descriptor == "eu-conversion":
278
+ return [
279
+ imap_module_directory
280
+ / "tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv"
281
+ ]
282
+ elif descriptor == "esa-lut":
283
+ return [
284
+ imap_module_directory
285
+ / "tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv"
286
+ ]
287
+ else:
288
+ raise ValueError(f"Unknown descriptor: {descriptor}")
289
+
290
+ mock_get_file_paths.side_effect = get_file_paths_side_effect
291
+ science_input = ScienceInput(l1a_cdf_filepath.name)
292
+ inflight_anc = AncillaryInput(
293
+ "imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv"
294
+ )
295
+ eu_anc = AncillaryInput("imap_swe_eu-conversion_20240510_v000.csv")
296
+ dependencies = ProcessingInputCollection(science_input, inflight_anc, eu_anc)
297
+ l1b_dataset = swe_l1b(dependencies)[0]
298
+ l1b_dataset.attrs["Data_version"] = "v000"
299
+ l2_dataset = swe_l2(l1b_dataset)
300
+
301
+ assert isinstance(l2_dataset, xr.Dataset)
302
+ assert l2_dataset["phase_space_density_spin_sector"].shape == (
303
+ 6,
304
+ swe_constants.N_ESA_STEPS,
305
+ swe_constants.N_ANGLE_SECTORS,
306
+ swe_constants.N_CEMS,
307
+ )
308
+ assert l2_dataset["flux_spin_sector"].shape == (
309
+ 6,
310
+ swe_constants.N_ESA_STEPS,
311
+ swe_constants.N_ANGLE_SECTORS,
312
+ swe_constants.N_CEMS,
313
+ )
314
+ assert l2_dataset["acquisition_time"].shape == (
315
+ 6,
316
+ swe_constants.N_ESA_STEPS,
317
+ swe_constants.N_ANGLE_SECTORS,
318
+ )
260
319
 
261
- assert type(l2_dataset) == xr.Dataset
262
- assert l2_dataset["phase_space_density_spin_sector"].shape == (6, 24, 30, 7)
263
- assert l2_dataset["flux_spin_sector"].shape == (6, 24, 30, 7)
264
- assert l2_dataset["acquisition_time"].shape == (6, 24, 30)
320
+ rate = l1b_dataset.science_data.to_numpy()
321
+ psd = l2_dataset.phase_space_density_spin_sector.to_numpy()
322
+ rate = rate[2, :, :, 3] # nonzero counts at all energy & spin
323
+ psd = psd[2, :, :, 3]
324
+ cal_factor = psd / rate # same CEM, should be constant at a given energy
325
+ assert np.allclose(cal_factor, cal_factor[:, 0:1], rtol=1e-9, atol=0)
265
326
 
266
327
  # Write L2 to CDF
328
+ l2_dataset.attrs["Data_version"] = "v002"
267
329
  l2_cdf_filepath = write_cdf(l2_dataset)
268
330
  assert l2_cdf_filepath.name == "imap_swe_l2_sci_20240510_v002.cdf"