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

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

Potentially problematic release.


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

Files changed (272) hide show
  1. imap_processing/__init__.py +1 -0
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/ccsds_data.py +1 -2
  4. imap_processing/ccsds/excel_to_xtce.py +1 -2
  5. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +18 -12
  6. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +569 -0
  7. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
  8. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +5 -5
  9. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +20 -1
  10. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +6 -4
  11. imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +3 -3
  12. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +15 -0
  13. imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
  14. imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +16 -0
  15. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +178 -5
  16. imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
  17. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +33 -19
  18. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +8 -48
  19. imap_processing/cdf/utils.py +41 -33
  20. imap_processing/cli.py +463 -234
  21. imap_processing/codice/codice_l1a.py +260 -47
  22. imap_processing/codice/codice_l1b.py +51 -152
  23. imap_processing/codice/constants.py +38 -1
  24. imap_processing/ena_maps/ena_maps.py +658 -65
  25. imap_processing/ena_maps/utils/coordinates.py +1 -1
  26. imap_processing/ena_maps/utils/spatial_utils.py +10 -5
  27. imap_processing/glows/l1a/glows_l1a.py +28 -99
  28. imap_processing/glows/l1a/glows_l1a_data.py +2 -2
  29. imap_processing/glows/l1b/glows_l1b.py +1 -4
  30. imap_processing/glows/l1b/glows_l1b_data.py +1 -3
  31. imap_processing/glows/l2/glows_l2.py +2 -5
  32. imap_processing/hi/l1a/hi_l1a.py +31 -12
  33. imap_processing/hi/l1b/hi_l1b.py +80 -43
  34. imap_processing/hi/l1c/hi_l1c.py +12 -16
  35. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
  36. imap_processing/hit/hit_utils.py +93 -35
  37. imap_processing/hit/l0/decom_hit.py +3 -1
  38. imap_processing/hit/l1a/hit_l1a.py +30 -25
  39. imap_processing/hit/l1b/constants.py +6 -2
  40. imap_processing/hit/l1b/hit_l1b.py +279 -318
  41. imap_processing/hit/l2/constants.py +37 -0
  42. imap_processing/hit/l2/hit_l2.py +373 -264
  43. imap_processing/ialirt/l0/parse_mag.py +138 -10
  44. imap_processing/ialirt/l0/process_swapi.py +69 -0
  45. imap_processing/ialirt/l0/process_swe.py +318 -22
  46. imap_processing/ialirt/packet_definitions/ialirt.xml +216 -212
  47. imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +1 -1
  48. imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +1 -1
  49. imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
  50. imap_processing/ialirt/utils/grouping.py +1 -1
  51. imap_processing/idex/idex_constants.py +9 -1
  52. imap_processing/idex/idex_l0.py +22 -8
  53. imap_processing/idex/idex_l1a.py +75 -44
  54. imap_processing/idex/idex_l1b.py +9 -8
  55. imap_processing/idex/idex_l2a.py +79 -45
  56. imap_processing/idex/idex_l2b.py +120 -0
  57. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -39
  58. imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
  59. imap_processing/lo/l0/lo_science.py +1 -2
  60. imap_processing/lo/l1a/lo_l1a.py +1 -4
  61. imap_processing/lo/l1b/lo_l1b.py +527 -6
  62. imap_processing/lo/l1b/tof_conversions.py +11 -0
  63. imap_processing/lo/l1c/lo_l1c.py +1 -4
  64. imap_processing/mag/constants.py +43 -0
  65. imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
  66. imap_processing/mag/l1a/mag_l1a.py +2 -9
  67. imap_processing/mag/l1a/mag_l1a_data.py +10 -10
  68. imap_processing/mag/l1b/mag_l1b.py +84 -17
  69. imap_processing/mag/l1c/interpolation_methods.py +180 -3
  70. imap_processing/mag/l1c/mag_l1c.py +236 -70
  71. imap_processing/mag/l2/mag_l2.py +140 -0
  72. imap_processing/mag/l2/mag_l2_data.py +288 -0
  73. imap_processing/spacecraft/quaternions.py +1 -3
  74. imap_processing/spice/geometry.py +3 -3
  75. imap_processing/spice/kernels.py +0 -276
  76. imap_processing/spice/pointing_frame.py +257 -0
  77. imap_processing/spice/repoint.py +48 -19
  78. imap_processing/spice/spin.py +38 -33
  79. imap_processing/spice/time.py +24 -0
  80. imap_processing/swapi/l1/swapi_l1.py +16 -12
  81. imap_processing/swapi/l2/swapi_l2.py +116 -4
  82. imap_processing/swapi/swapi_utils.py +32 -0
  83. imap_processing/swe/l1a/swe_l1a.py +2 -9
  84. imap_processing/swe/l1a/swe_science.py +8 -11
  85. imap_processing/swe/l1b/swe_l1b.py +898 -23
  86. imap_processing/swe/l2/swe_l2.py +21 -77
  87. imap_processing/swe/utils/swe_constants.py +1 -0
  88. imap_processing/tests/ccsds/test_excel_to_xtce.py +1 -1
  89. imap_processing/tests/cdf/test_utils.py +14 -16
  90. imap_processing/tests/codice/conftest.py +44 -33
  91. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
  92. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
  93. imap_processing/tests/codice/test_codice_l1a.py +20 -11
  94. imap_processing/tests/codice/test_codice_l1b.py +6 -7
  95. imap_processing/tests/conftest.py +78 -22
  96. imap_processing/tests/ena_maps/test_ena_maps.py +462 -33
  97. imap_processing/tests/ena_maps/test_spatial_utils.py +1 -1
  98. imap_processing/tests/glows/conftest.py +10 -14
  99. imap_processing/tests/glows/test_glows_decom.py +4 -4
  100. imap_processing/tests/glows/test_glows_l1a_cdf.py +6 -27
  101. imap_processing/tests/glows/test_glows_l1a_data.py +6 -8
  102. imap_processing/tests/glows/test_glows_l1b.py +11 -11
  103. imap_processing/tests/glows/test_glows_l1b_data.py +5 -5
  104. imap_processing/tests/glows/test_glows_l2.py +2 -8
  105. imap_processing/tests/hi/conftest.py +1 -1
  106. imap_processing/tests/hi/test_hi_l1b.py +10 -12
  107. imap_processing/tests/hi/test_hi_l1c.py +27 -24
  108. imap_processing/tests/hi/test_l1a.py +7 -9
  109. imap_processing/tests/hi/test_science_direct_event.py +2 -2
  110. imap_processing/tests/hit/helpers/l1_validation.py +44 -43
  111. imap_processing/tests/hit/test_decom_hit.py +1 -1
  112. imap_processing/tests/hit/test_hit_l1a.py +9 -9
  113. imap_processing/tests/hit/test_hit_l1b.py +172 -217
  114. imap_processing/tests/hit/test_hit_l2.py +380 -118
  115. imap_processing/tests/hit/test_hit_utils.py +122 -55
  116. imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
  117. imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
  118. imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
  119. imap_processing/tests/ialirt/unit/test_grouping.py +2 -2
  120. imap_processing/tests/ialirt/unit/test_parse_mag.py +71 -16
  121. imap_processing/tests/ialirt/unit/test_process_codicehi.py +3 -3
  122. imap_processing/tests/ialirt/unit/test_process_codicelo.py +3 -10
  123. imap_processing/tests/ialirt/unit/test_process_ephemeris.py +4 -4
  124. imap_processing/tests/ialirt/unit/test_process_hit.py +3 -3
  125. imap_processing/tests/ialirt/unit/test_process_swapi.py +24 -16
  126. imap_processing/tests/ialirt/unit/test_process_swe.py +115 -7
  127. imap_processing/tests/idex/conftest.py +72 -7
  128. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20241206_v001.pkts +0 -0
  129. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20250108_v001.pkts +0 -0
  130. imap_processing/tests/idex/test_idex_l0.py +33 -11
  131. imap_processing/tests/idex/test_idex_l1a.py +50 -23
  132. imap_processing/tests/idex/test_idex_l1b.py +104 -25
  133. imap_processing/tests/idex/test_idex_l2a.py +48 -32
  134. imap_processing/tests/idex/test_idex_l2b.py +93 -0
  135. imap_processing/tests/lo/test_lo_l1a.py +3 -3
  136. imap_processing/tests/lo/test_lo_l1b.py +371 -6
  137. imap_processing/tests/lo/test_lo_l1c.py +1 -1
  138. imap_processing/tests/lo/test_lo_science.py +6 -7
  139. imap_processing/tests/lo/test_star_sensor.py +1 -1
  140. imap_processing/tests/mag/conftest.py +58 -9
  141. imap_processing/tests/mag/test_mag_decom.py +4 -3
  142. imap_processing/tests/mag/test_mag_l1a.py +13 -7
  143. imap_processing/tests/mag/test_mag_l1b.py +9 -9
  144. imap_processing/tests/mag/test_mag_l1c.py +151 -47
  145. imap_processing/tests/mag/test_mag_l2.py +130 -0
  146. imap_processing/tests/mag/test_mag_validation.py +144 -7
  147. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-in.csv +1217 -0
  148. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-out.csv +1857 -0
  149. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-in.csv +1217 -0
  150. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-out.csv +1857 -0
  151. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-in.csv +1217 -0
  152. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-out.csv +1793 -0
  153. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-in.csv +1217 -0
  154. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-out.csv +1793 -0
  155. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-burst-in.csv +2561 -0
  156. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-in.csv +961 -0
  157. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-out.csv +1539 -0
  158. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-in.csv +1921 -0
  159. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-out.csv +2499 -0
  160. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-in.csv +865 -0
  161. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv +1196 -0
  162. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-in.csv +1729 -0
  163. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv +3053 -0
  164. imap_processing/tests/mag/validation/L2/imap_mag_l1b_norm-mago_20251017_v002.cdf +0 -0
  165. imap_processing/tests/mag/validation/calibration/imap_mag_l2-calibration-matrices_20251017_v004.cdf +0 -0
  166. imap_processing/tests/mag/validation/calibration/imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf +0 -0
  167. imap_processing/tests/spacecraft/test_quaternions.py +1 -1
  168. imap_processing/tests/spice/test_data/fake_repoint_data.csv +4 -4
  169. imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
  170. imap_processing/tests/spice/test_geometry.py +3 -3
  171. imap_processing/tests/spice/test_kernels.py +1 -200
  172. imap_processing/tests/spice/test_pointing_frame.py +185 -0
  173. imap_processing/tests/spice/test_repoint.py +20 -10
  174. imap_processing/tests/spice/test_spin.py +50 -9
  175. imap_processing/tests/spice/test_time.py +14 -0
  176. imap_processing/tests/swapi/lut/imap_swapi_esa-unit-conversion_20250211_v000.csv +73 -0
  177. imap_processing/tests/swapi/lut/imap_swapi_lut-notes_20250211_v000.csv +1025 -0
  178. imap_processing/tests/swapi/test_swapi_l1.py +7 -9
  179. imap_processing/tests/swapi/test_swapi_l2.py +180 -8
  180. imap_processing/tests/swe/lut/checker-board-indices.csv +24 -0
  181. imap_processing/tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv +385 -0
  182. imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv +3 -0
  183. imap_processing/tests/swe/test_swe_l1a.py +6 -6
  184. imap_processing/tests/swe/test_swe_l1a_science.py +3 -3
  185. imap_processing/tests/swe/test_swe_l1b.py +162 -24
  186. imap_processing/tests/swe/test_swe_l2.py +82 -102
  187. imap_processing/tests/test_cli.py +171 -88
  188. imap_processing/tests/test_utils.py +2 -1
  189. imap_processing/tests/ultra/data/mock_data.py +49 -21
  190. imap_processing/tests/ultra/unit/conftest.py +53 -70
  191. imap_processing/tests/ultra/unit/test_badtimes.py +2 -4
  192. imap_processing/tests/ultra/unit/test_cullingmask.py +4 -6
  193. imap_processing/tests/ultra/unit/test_de.py +3 -10
  194. imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
  195. imap_processing/tests/ultra/unit/test_decom_apid_881.py +15 -16
  196. imap_processing/tests/ultra/unit/test_decom_apid_883.py +12 -10
  197. imap_processing/tests/ultra/unit/test_decom_apid_896.py +202 -55
  198. imap_processing/tests/ultra/unit/test_lookup_utils.py +23 -1
  199. imap_processing/tests/ultra/unit/test_spacecraft_pset.py +3 -4
  200. imap_processing/tests/ultra/unit/test_ultra_l1a.py +84 -307
  201. imap_processing/tests/ultra/unit/test_ultra_l1b.py +30 -12
  202. imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
  203. imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +4 -1
  204. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +163 -29
  205. imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
  206. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +32 -43
  207. imap_processing/tests/ultra/unit/test_ultra_l2.py +230 -0
  208. imap_processing/ultra/constants.py +1 -1
  209. imap_processing/ultra/l0/decom_tools.py +21 -34
  210. imap_processing/ultra/l0/decom_ultra.py +168 -204
  211. imap_processing/ultra/l0/ultra_utils.py +152 -136
  212. imap_processing/ultra/l1a/ultra_l1a.py +55 -243
  213. imap_processing/ultra/l1b/badtimes.py +1 -4
  214. imap_processing/ultra/l1b/cullingmask.py +2 -6
  215. imap_processing/ultra/l1b/de.py +62 -47
  216. imap_processing/ultra/l1b/extendedspin.py +8 -4
  217. imap_processing/ultra/l1b/lookup_utils.py +72 -9
  218. imap_processing/ultra/l1b/ultra_l1b.py +3 -8
  219. imap_processing/ultra/l1b/ultra_l1b_culling.py +4 -4
  220. imap_processing/ultra/l1b/ultra_l1b_extended.py +236 -78
  221. imap_processing/ultra/l1c/histogram.py +2 -6
  222. imap_processing/ultra/l1c/spacecraft_pset.py +2 -4
  223. imap_processing/ultra/l1c/ultra_l1c.py +1 -5
  224. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +107 -60
  225. imap_processing/ultra/l2/ultra_l2.py +299 -0
  226. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +526 -0
  227. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +526 -0
  228. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +526 -0
  229. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +526 -0
  230. imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -2
  231. imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
  232. imap_processing/ultra/packet_definitions/README.md +38 -0
  233. imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +15302 -482
  234. imap_processing/ultra/utils/ultra_l1_utils.py +13 -12
  235. imap_processing/utils.py +1 -1
  236. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +3 -2
  237. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/RECORD +264 -225
  238. imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
  239. imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +0 -6
  240. imap_processing/mag/l1b/__init__.py +0 -0
  241. imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
  242. imap_processing/swe/l1b/swe_l1b_science.py +0 -699
  243. imap_processing/tests/swe/test_swe_l1b_science.py +0 -103
  244. imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
  245. imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
  246. /imap_processing/idex/packet_definitions/{idex_packet_definition.xml → idex_science_packet_definition.xml} +0 -0
  247. /imap_processing/tests/ialirt/{test_data → data}/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
  248. /imap_processing/tests/ialirt/{test_data → data}/l0/461971383-404.bin +0 -0
  249. /imap_processing/tests/ialirt/{test_data → data}/l0/461971384-405.bin +0 -0
  250. /imap_processing/tests/ialirt/{test_data → data}/l0/461971385-406.bin +0 -0
  251. /imap_processing/tests/ialirt/{test_data → data}/l0/461971386-407.bin +0 -0
  252. /imap_processing/tests/ialirt/{test_data → data}/l0/461971387-408.bin +0 -0
  253. /imap_processing/tests/ialirt/{test_data → data}/l0/461971388-409.bin +0 -0
  254. /imap_processing/tests/ialirt/{test_data → data}/l0/461971389-410.bin +0 -0
  255. /imap_processing/tests/ialirt/{test_data → data}/l0/461971390-411.bin +0 -0
  256. /imap_processing/tests/ialirt/{test_data → data}/l0/461971391-412.bin +0 -0
  257. /imap_processing/tests/ialirt/{test_data → data}/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
  258. /imap_processing/tests/ialirt/{test_data → data}/l0/IALiRT Raw Packet Telemetry.txt +0 -0
  259. /imap_processing/tests/ialirt/{test_data → data}/l0/apid01152.tlm +0 -0
  260. /imap_processing/tests/ialirt/{test_data → data}/l0/eu_SWP_IAL_20240826_152033.csv +0 -0
  261. /imap_processing/tests/ialirt/{test_data → data}/l0/hi_fsw_view_1_ccsds.bin +0 -0
  262. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.ccsds +0 -0
  263. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.csv +0 -0
  264. /imap_processing/tests/ialirt/{test_data → data}/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +0 -0
  265. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
  266. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  267. /imap_processing/tests/ialirt/{test_data → data}/l0/sample_decoded_i-alirt_data.csv +0 -0
  268. /imap_processing/tests/mag/validation/{imap_calibration_mag_20240229_v01.cdf → calibration/imap_mag_l1b-calibration_20240229_v001.cdf} +0 -0
  269. /imap_processing/{swe/l1b/engineering_unit_convert_table.csv → tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv} +0 -0
  270. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
  271. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
  272. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
@@ -75,7 +75,7 @@ def test_data_order(decom_test_data):
75
75
  )
76
76
 
77
77
  # Get unpacked science data
78
- processed_data = swe_science(decom_test_data, "001")
78
+ processed_data = swe_science(decom_test_data)
79
79
 
80
80
  quarter_cycle = processed_data["quarter_cycle"].isel(epoch=slice(0, 4))
81
81
  np.testing.assert_array_equal(quarter_cycle, [0, 1, 2, 3])
@@ -84,7 +84,7 @@ def test_data_order(decom_test_data):
84
84
  def test_swe_science_algorithm(decom_test_data):
85
85
  """Test general shape of return dataset from swe_science."""
86
86
  # Get unpacked science data
87
- processed_data = swe_science(decom_test_data, "001")
87
+ processed_data = swe_science(decom_test_data)
88
88
 
89
89
  # science data should have this shape, 15x12x7.
90
90
  science_data = processed_data["science_data"].data[0]
@@ -101,7 +101,7 @@ def test_decompress_counts(decom_test_data, l1a_validation_df):
101
101
  raw_counts = l1a_validation_df.iloc[:, 1:8]
102
102
  decompressed_counts = l1a_validation_df.iloc[:, 8:15]
103
103
 
104
- l1a_dataset = swe_science(decom_test_data, "001")
104
+ l1a_dataset = swe_science(decom_test_data)
105
105
 
106
106
  # compare raw counts
107
107
  assert np.all(
@@ -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,9 +1,13 @@
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
@@ -13,41 +17,17 @@ from imap_processing.swe.l2.swe_l2 import (
13
17
  calculate_flux,
14
18
  calculate_phase_space_density,
15
19
  find_angle_bin_indices,
16
- get_particle_energy,
17
20
  put_data_into_angle_bins,
18
21
  swe_l2,
19
22
  )
20
23
  from imap_processing.swe.utils import swe_constants
21
- from imap_processing.swe.utils.swe_utils import (
22
- read_lookup_table,
23
- )
24
-
25
-
26
- def test_get_particle_energy():
27
- """Test get_particle_energy function."""
28
- all_energy = get_particle_energy()
29
- expected_energy = (
30
- read_lookup_table()["esa_v"].values * swe_constants.ENERGY_CONVERSION_FACTOR
31
- )
32
- np.testing.assert_array_equal(all_energy["energy"], expected_energy)
33
24
 
34
25
 
35
26
  @patch(
36
27
  "imap_processing.swe.utils.swe_constants.GEOMETRIC_FACTORS",
37
28
  new=np.full(swe_constants.N_CEMS, 1),
38
29
  )
39
- @patch(
40
- "imap_processing.swe.l2.swe_l2.get_particle_energy",
41
- return_value=pd.DataFrame(
42
- {
43
- "table_index": np.repeat([0, 1], 720),
44
- "e_step": np.tile(np.arange(720), 2),
45
- "esa_v": np.repeat([1, 2], 720),
46
- "energy": np.repeat([1, 2], 720),
47
- }
48
- ),
49
- )
50
- def test_calculate_phase_space_density(patch_get_particle_energy):
30
+ def test_calculate_phase_space_density():
51
31
  """Test calculate_phase_space_density function."""
52
32
  # Create a dummy l1b dataset
53
33
  total_sweeps = 2
@@ -66,20 +46,21 @@ def test_calculate_phase_space_density(patch_get_particle_energy):
66
46
  1,
67
47
  ),
68
48
  ),
69
- "acq_duration": (
70
- ["epoch", "cycle"],
71
- np.full((total_sweeps, swe_constants.N_QUARTER_CYCLES), 80.0),
72
- ),
73
- "esa_table_num": (
74
- ["epoch", "cycle"],
75
- np.repeat([0, 1], swe_constants.N_QUARTER_CYCLES).reshape(
76
- total_sweeps, swe_constants.N_QUARTER_CYCLES
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,
77
58
  ),
78
59
  ),
79
60
  }
80
61
  )
81
- phase_space_density_ds = calculate_phase_space_density(l1b_dataset)
82
- 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 == (
83
64
  total_sweeps,
84
65
  swe_constants.N_ESA_STEPS,
85
66
  swe_constants.N_ANGLE_SECTORS,
@@ -102,68 +83,40 @@ def test_calculate_phase_space_density(patch_get_particle_energy):
102
83
  ),
103
84
  expected_calculated_density,
104
85
  )
105
- np.testing.assert_array_equal(
106
- phase_space_density_ds["phase_space_density"][0].data, expected_density
107
- )
86
+ np.testing.assert_array_equal(phase_space_density[0].data, expected_density)
108
87
 
109
- # Test that second sweep has correct values, similar to first sweep,
110
- # but with energy 2.
111
- expected_calculated_density = (2 * 1) / (
112
- 1 * swe_constants.VELOCITY_CONVERSION_FACTOR * 2**2
113
- )
114
- expected_density = np.full(
88
+
89
+ def test_calculate_flux():
90
+ """Test calculate_flux function."""
91
+ # Create a dummy l1b dataset
92
+ total_sweeps = 2
93
+ phase_space_density = np.full(
115
94
  (
95
+ total_sweeps,
116
96
  swe_constants.N_ESA_STEPS,
117
97
  swe_constants.N_ANGLE_SECTORS,
118
98
  swe_constants.N_CEMS,
119
99
  ),
120
- expected_calculated_density,
100
+ 1,
121
101
  )
122
- np.testing.assert_array_equal(
123
- phase_space_density_ds["phase_space_density"][1].data, expected_density
124
- )
125
- assert type(phase_space_density_ds) == xr.Dataset
126
102
 
127
-
128
- def test_calculate_flux():
129
- """Test calculate_flux function."""
130
- # Create a dummy l1b dataset
131
- total_sweeps = 2
132
- l1b_dataset = xr.Dataset(
133
- {
134
- "science_data": (
135
- ["epoch", "energy", "angle", "cem"],
136
- np.full(
137
- (
138
- total_sweeps,
139
- swe_constants.N_ESA_STEPS,
140
- swe_constants.N_ANGLE_SECTORS,
141
- swe_constants.N_CEMS,
142
- ),
143
- 1,
144
- ),
145
- ),
146
- "acq_duration": (
147
- ["epoch", "cycle"],
148
- np.full((total_sweeps, swe_constants.N_QUARTER_CYCLES), 80.0),
149
- ),
150
- "esa_table_num": (
151
- ["epoch", "cycle"],
152
- np.repeat([0, 1], swe_constants.N_QUARTER_CYCLES).reshape(
153
- total_sweeps, swe_constants.N_QUARTER_CYCLES
154
- ),
155
- ),
156
- }
103
+ esa_energy = np.full(
104
+ (
105
+ total_sweeps,
106
+ swe_constants.N_ESA_STEPS,
107
+ swe_constants.N_ANGLE_SECTORS,
108
+ ),
109
+ 1,
157
110
  )
158
111
 
159
- flux = calculate_flux(l1b_dataset)
112
+ flux = calculate_flux(phase_space_density, esa_energy)
160
113
  assert flux.shape == (
161
114
  total_sweeps,
162
115
  swe_constants.N_ESA_STEPS,
163
116
  swe_constants.N_ANGLE_SECTORS,
164
117
  swe_constants.N_CEMS,
165
118
  )
166
- assert type(flux) == np.ndarray
119
+ assert isinstance(flux, np.ndarray)
167
120
 
168
121
 
169
122
  def test_find_angle_bin_indices():
@@ -298,35 +251,54 @@ def test_put_data_into_angle_bins():
298
251
  np.testing.assert_array_equal(even_col_mean_data, expected_mean_data)
299
252
 
300
253
 
301
- @patch(
302
- "imap_processing.swe.l1b.swe_l1b_science.read_in_flight_cal_data",
303
- return_value=pd.DataFrame(
304
- {
305
- "met_time": [453050300, 453077900],
306
- "cem1": [1, 1],
307
- "cem2": [1, 1],
308
- "cem3": [1, 1],
309
- "cem4": [1, 1],
310
- "cem5": [1, 1],
311
- "cem6": [1, 1],
312
- "cem7": [1, 1],
313
- }
314
- ),
315
- )
254
+ @patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths")
316
255
  @pytest.mark.usefixtures("use_fake_spin_data_for_time")
317
- 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):
318
257
  """Test L2 processing."""
319
258
  data_start_time = 453051293.099714
320
259
  data_end_time = 453070000.0
321
260
  use_fake_spin_data_for_time(data_start_time, data_end_time)
322
261
 
323
262
  test_data_path = "tests/swe/l0_data/2024051010_SWE_SCIENCE_packet.bin"
324
- 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"
268
+
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}")
325
289
 
326
- l1b_dataset = swe_l1b(l1a_datasets[0], "002")
327
- l2_dataset = swe_l2(l1b_dataset[0], "002")
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)
328
300
 
329
- assert type(l2_dataset) == xr.Dataset
301
+ assert isinstance(l2_dataset, xr.Dataset)
330
302
  assert l2_dataset["phase_space_density_spin_sector"].shape == (
331
303
  6,
332
304
  swe_constants.N_ESA_STEPS,
@@ -345,6 +317,14 @@ def test_swe_l2(mock_read_in_flight_cal_data, use_fake_spin_data_for_time):
345
317
  swe_constants.N_ANGLE_SECTORS,
346
318
  )
347
319
 
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)
326
+
348
327
  # Write L2 to CDF
328
+ l2_dataset.attrs["Data_version"] = "v002"
349
329
  l2_cdf_filepath = write_cdf(l2_dataset)
350
330
  assert l2_cdf_filepath.name == "imap_swe_l2_sci_20240510_v002.cdf"