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
@@ -5,11 +5,25 @@ from unittest import mock
5
5
 
6
6
  import pytest
7
7
  import xarray as xr
8
+ from imap_data_access.processing_input import (
9
+ ProcessingInputCollection,
10
+ ScienceInput,
11
+ )
8
12
 
9
- from imap_processing.cli import Codice, Hi, Hit, Swe, Ultra, _validate_args, main
13
+ from imap_processing.cli import (
14
+ Codice,
15
+ Glows,
16
+ Hi,
17
+ Hit,
18
+ Spacecraft,
19
+ Swe,
20
+ Ultra,
21
+ _validate_args,
22
+ main,
23
+ )
10
24
 
11
25
 
12
- @pytest.fixture()
26
+ @pytest.fixture
13
27
  def mock_instrument_dependencies():
14
28
  with (
15
29
  mock.patch("imap_processing.cli.imap_data_access.query") as mock_query,
@@ -17,6 +31,9 @@ def mock_instrument_dependencies():
17
31
  mock.patch("imap_processing.cli.imap_data_access.upload") as mock_upload,
18
32
  mock.patch("imap_processing.cli.write_cdf") as mock_write_cdf,
19
33
  mock.patch("imap_processing.cli.load_cdf") as mock_load_cdf,
34
+ mock.patch(
35
+ "imap_processing.cli.ProcessInstrument.pre_processing"
36
+ ) as mock_pre_processing,
20
37
  ):
21
38
  mocks = {
22
39
  "mock_query": mock_query,
@@ -24,6 +41,7 @@ def mock_instrument_dependencies():
24
41
  "mock_upload": mock_upload,
25
42
  "mock_write_cdf": mock_write_cdf,
26
43
  "mock_load_cdf": mock_load_cdf,
44
+ "mock_pre_processing": mock_pre_processing,
27
45
  }
28
46
  yield mocks
29
47
 
@@ -37,18 +55,28 @@ def test_main(mock_instrument):
37
55
  "mag",
38
56
  "--dependency",
39
57
  (
40
- '[{"instrument": "mag", '
41
- '"data_level": "l0", '
42
- '"descriptor": "sci", '
43
- '"version": "v001", '
44
- '"start_date": "20240430"}]'
58
+ "["
59
+ "{"
60
+ '"type": "ancillary",'
61
+ '"files": ['
62
+ '"imap_mag_l1b-cal_20250101_v001.cdf",'
63
+ '"imap_mag_l1b-cal_20250103-20250104_v002.cdf"'
64
+ "]"
65
+ "},"
66
+ "{"
67
+ '"type": "science",'
68
+ '"files": ['
69
+ '"imap_mag_l0_raw_20240430_v001.cdf",'
70
+ "]"
71
+ "}"
72
+ "]"
45
73
  ),
46
74
  "--data-level",
47
75
  "l1a",
48
76
  "--start-date",
49
77
  "20240430",
50
- "--end-date",
51
- "20240501",
78
+ "--repointing",
79
+ "repoint12345",
52
80
  "--version",
53
81
  "v001",
54
82
  "--upload-to-sdc",
@@ -60,18 +88,25 @@ def test_main(mock_instrument):
60
88
 
61
89
 
62
90
  @pytest.mark.parametrize(
63
- "instrument, data_level, raises_value_error",
91
+ "instrument, data_level, start_date, repointing, raises_value_error",
64
92
  [
65
- ("mag", "l0", ""),
66
- ("foo", "l0", "foo is not in the supported .*"),
67
- ("codice", "l1z", "l1z is not a supported .*"),
93
+ ("mag", "l1a", "20250101", None, ""),
94
+ ("foo", "l1a", None, None, "foo is not in the supported .*"),
95
+ ("codice", "l1z", None, None, "l1z is not a supported .*"),
96
+ ("glows", "l1a", None, "repoint12345", ""),
97
+ ("glows", "l1a", None, "12345", ".* not a valid repointing.*"),
98
+ ("glows", "l1a", "2000001", None, ".* not a valid date.*"),
68
99
  ],
69
100
  )
70
- def test_validate_args(instrument, data_level, raises_value_error):
101
+ def test_validate_args(
102
+ instrument, data_level, start_date, repointing, raises_value_error
103
+ ):
71
104
  """Test coverage for imap_processing.cli._validate_args()"""
72
105
  args = mock.Mock
73
106
  args.instrument = instrument
74
107
  args.data_level = data_level
108
+ args.start_date = start_date
109
+ args.repointing = repointing
75
110
 
76
111
  if raises_value_error:
77
112
  with pytest.raises(ValueError, match=raises_value_error):
@@ -85,90 +120,139 @@ def test_codice(mock_codice_l1a, mock_instrument_dependencies):
85
120
  """Test coverage for cli.CoDICE class"""
86
121
 
87
122
  test_dataset = xr.Dataset({}, attrs={"cdf_filename": "file0"})
88
-
123
+ input_collection = ProcessingInputCollection(
124
+ ScienceInput("imap_codice_l0_raw_20230822_v001.pkts")
125
+ )
89
126
  mocks = mock_instrument_dependencies
90
127
  mocks["mock_query"].return_value = [{"file_path": "/path/to/file0"}]
91
128
  mocks["mock_download"].return_value = "file0"
92
- mock_codice_l1a.return_value = test_dataset
129
+ mock_codice_l1a.return_value = [test_dataset]
93
130
  mocks["mock_write_cdf"].side_effect = ["/path/to/file0"]
131
+ mocks["mock_pre_processing"].return_value = input_collection
94
132
 
95
133
  dependency_str = (
96
- "[{"
97
- "'instrument': 'codice',"
98
- "'data_level': 'l0',"
99
- "'descriptor': 'hskp',"
100
- "'version': 'v001',"
101
- "'start_date': '20230822'"
102
- "}]"
103
- )
104
- instrument = Codice(
105
- "l1a", "hskp", dependency_str, "20230822", "20230822", "v001", True
134
+ '[{"type": "science","files": ["imap_codice_l0_raw_20230822_v001.pkts"]}]'
106
135
  )
136
+
137
+ instrument = Codice("l1a", "hskp", dependency_str, "20230822", None, "v001", True)
138
+
107
139
  instrument.process()
108
- assert mocks["mock_query"].call_count == 1
109
- assert mocks["mock_download"].call_count == 1
110
140
  assert mock_codice_l1a.call_count == 1
111
141
  assert mocks["mock_upload"].call_count == 1
112
142
 
113
143
 
114
- @pytest.mark.parametrize("data_level, n_prods", [("l1a", 2), ("l1b", 1), ("l1c", 1)])
115
- def test_hi_l1(mock_instrument_dependencies, data_level, n_prods):
144
+ def test_repointing_file_creation(mock_instrument_dependencies):
145
+ test_datasets = [xr.Dataset({}, attrs={"cdf_filename": "file0"})]
146
+ input_collection = ProcessingInputCollection(
147
+ ScienceInput("imap_glows_l0_raw_20230822-repoint00001_v001.pkts")
148
+ )
149
+ dependency_str = (
150
+ '[{"type": "science","files": '
151
+ '["imap_glows_l0_raw_20230822-repoint00001_v001.pkts"]}]'
152
+ )
153
+ instrument = Glows(
154
+ "l1a", "hist", dependency_str, None, "repoint00002", "v001", False
155
+ )
156
+
157
+ mock_instrument_dependencies["mock_write_cdf"].side_effect = ["/path/to/file0"]
158
+
159
+ # Call the method that uses write_cdf
160
+ instrument.post_processing(test_datasets, input_collection)
161
+
162
+ # Assert that write_cdf was called with the expected arguments
163
+ assert mock_instrument_dependencies["mock_write_cdf"].call_count == 1
164
+ assert (
165
+ mock_instrument_dependencies["mock_write_cdf"]
166
+ .call_args[0][0]
167
+ .attrs.get("Repointing", None)
168
+ == "repoint00002"
169
+ )
170
+
171
+
172
+ @pytest.mark.parametrize(
173
+ "data_level, science_input, n_prods",
174
+ [
175
+ ("l1a", ["imap_hi_l0_raw_20231212_v001.pkts"], 2),
176
+ ("l1b", ["imap_hi_l1a_90sensor-de_20241105_v001.cdf"], 1),
177
+ ("l1b", ["imap_hi_l0_raw_20231212_v001.pkts"], 2),
178
+ ("l1c", ["imap_hi_l1b_45sensor-de_20250415_v001.cdf"], 1),
179
+ ],
180
+ )
181
+ def test_hi_l1(mock_instrument_dependencies, data_level, science_input, n_prods):
116
182
  """Test coverage for cli.Hi class"""
117
183
  mocks = mock_instrument_dependencies
118
- mocks["mock_query"].return_value = [{"file_path": "/path/to/file0"}]
119
- mocks["mock_download"].return_value = "file0"
120
- mocks["mock_write_cdf"].side_effect = ["/path/to/file0", "/path/to/file1"]
184
+ mocks["mock_write_cdf"].side_effect = ["/path/to/file0"] * n_prods
121
185
  mocks["mock_load_cdf"].return_value = xr.Dataset()
186
+ input_collection = ProcessingInputCollection(
187
+ *[ScienceInput(file) for file in science_input]
188
+ )
189
+ mocks["mock_pre_processing"].return_value = input_collection
122
190
 
123
191
  # patch autospec=True makes this test confirm that the function call in cli.py
124
192
  # matches the mocked function signature.
125
193
  with mock.patch(
126
194
  f"imap_processing.cli.hi_{data_level}.hi_{data_level}", autospec=True
127
195
  ) as mock_hi:
128
- mock_hi.return_value = [f"{data_level}_file{n}" for n in range(n_prods)]
196
+ mock_hi.return_value = [xr.Dataset()] * n_prods
129
197
  dependency_str = (
130
- "[{"
131
- "'instrument': 'lo',"
132
- "'data_level': 'l0',"
133
- "'descriptor': 'sci',"
134
- "'version': 'v00-01',"
135
- "'start_date': '20231212'"
136
- "}]"
198
+ '[{"type": "science","files": ["imap_hi_l0_raw_20231212_v001.pkts"]}]'
137
199
  )
138
200
  instrument = Hi(
139
201
  data_level, "sci", dependency_str, "20231212", "20231213", "v005", True
140
202
  )
203
+
141
204
  instrument.process()
142
- assert mocks["mock_query"].call_count == 1
143
- assert mocks["mock_download"].call_count == 1
144
205
  assert mock_hi.call_count == 1
145
206
  assert mocks["mock_upload"].call_count == n_prods
146
207
 
147
208
 
209
+ @mock.patch("imap_processing.cli.quaternions.process_quaternions", autospec=True)
210
+ def test_spacecraft(mock_spacecraft_l1a, mock_instrument_dependencies):
211
+ """Test coverage for cli.Spacecraft class"""
212
+
213
+ test_dataset = xr.Dataset({}, attrs={"cdf_filename": "file0"})
214
+ input_collection = ProcessingInputCollection(
215
+ ScienceInput("imap_spacecraft_l0_raw_20230822_v001.pkts")
216
+ )
217
+ mocks = mock_instrument_dependencies
218
+ mocks["mock_query"].return_value = [{"file_path": "/path/to/file0"}]
219
+ mocks["mock_download"].return_value = "file0"
220
+ mock_spacecraft_l1a.return_value = [test_dataset]
221
+ mocks["mock_write_cdf"].side_effect = ["/path/to/file0"]
222
+ mocks["mock_pre_processing"].return_value = input_collection
223
+
224
+ dependency_str = (
225
+ '[{"type": "science","files": ["imap_spacecraft_l0_raw_20230822_v001.pkts"]}]'
226
+ )
227
+
228
+ instrument = Spacecraft(
229
+ "l1a", "quaternions", dependency_str, "20230822", "20230822", "v001", True
230
+ )
231
+
232
+ instrument.process()
233
+ assert mock_spacecraft_l1a.call_count == 1
234
+ assert mocks["mock_upload"].call_count == 1
235
+
236
+
148
237
  @mock.patch("imap_processing.cli.ultra_l1a.ultra_l1a")
149
238
  def test_ultra_l1a(mock_ultra_l1a, mock_instrument_dependencies):
150
239
  """Test coverage for cli.Ultra class with l1a data level"""
151
240
  mocks = mock_instrument_dependencies
152
- mocks["mock_query"].return_value = [{"file_path": "/path/to/file0"}]
153
- mocks["mock_download"].return_value = "dependency0"
154
- mock_ultra_l1a.return_value = ["l1a_dataset0", "l1a_dataset1"]
241
+ mock_ultra_l1a.return_value = [xr.Dataset(), xr.Dataset()]
155
242
  mocks["mock_write_cdf"].side_effect = ["/path/to/product0", "/path/to/product1"]
243
+ input_collection = ProcessingInputCollection(
244
+ ScienceInput("imap_ultra_l0_raw_20240207_v001.pkts")
245
+ )
246
+ mocks["mock_pre_processing"].return_value = input_collection
156
247
 
157
248
  dependency_str = (
158
- "[{"
159
- "'instrument': 'ultra',"
160
- "'data_level': 'l0',"
161
- "'descriptor': 'raw',"
162
- "'version': 'v001',"
163
- "'start_date': '20240207'"
164
- "}]"
249
+ '[{"type": "science","files": ["imap_ultra_l0_raw_20240207_v001.pkts"]}]'
165
250
  )
166
251
  instrument = Ultra(
167
252
  "l1a", "raw", dependency_str, "20240207", "20240208", "v001", True
168
253
  )
254
+
169
255
  instrument.process()
170
- assert mocks["mock_query"].call_count == 1
171
- assert mocks["mock_download"].call_count == 1
172
256
  assert mock_ultra_l1a.call_count == 1
173
257
  assert mocks["mock_upload"].call_count == 2
174
258
 
@@ -177,14 +261,17 @@ def test_ultra_l1a(mock_ultra_l1a, mock_instrument_dependencies):
177
261
  def test_ultra_l1b(mock_ultra_l1b, mock_instrument_dependencies):
178
262
  """Test coverage for cli.Ultra class with l1b data level"""
179
263
  mocks = mock_instrument_dependencies
180
- mocks["mock_query"].return_value = [{"file_path": "/path/to/file0"}]
181
264
  mocks["mock_download"].return_value = "dependency0"
182
- mock_ultra_l1b.return_value = ["l1b_dataset0", "l1b_dataset1"]
265
+ mock_ultra_l1b.return_value = [xr.Dataset(), xr.Dataset()]
183
266
  mocks["mock_write_cdf"].side_effect = ["/path/to/product0", "/path/to/product1"]
267
+ input_collection = ProcessingInputCollection(
268
+ ScienceInput("imap_ultra_l1a_de_20240207_v001.cdf")
269
+ )
270
+ mocks["mock_pre_processing"].return_value = input_collection
184
271
 
185
272
  instrument = Ultra("l1b", "de", "[]", "20240207", "20240208", "v001", True)
273
+
186
274
  instrument.process()
187
- assert mocks["mock_query"].call_count == 0
188
275
  assert mocks["mock_download"].call_count == 0
189
276
  assert mock_ultra_l1b.call_count == 1
190
277
  assert mocks["mock_upload"].call_count == 2
@@ -194,15 +281,16 @@ def test_ultra_l1b(mock_ultra_l1b, mock_instrument_dependencies):
194
281
  def test_ultra_l1c(mock_ultra_l1c, mock_instrument_dependencies):
195
282
  """Test coverage for cli.Ultra class with l1c data level"""
196
283
  mocks = mock_instrument_dependencies
197
- mocks["mock_query"].return_value = [{"file_path": "/path/to/file0"}]
198
- mocks["mock_download"].return_value = "dependency0"
199
- mock_ultra_l1c.return_value = ["l1c_dataset0", "l1c_dataset1"]
284
+ mock_ultra_l1c.return_value = [xr.Dataset(), xr.Dataset()]
200
285
  mocks["mock_write_cdf"].side_effect = ["/path/to/product0", "/path/to/product1"]
286
+ input_collection = ProcessingInputCollection(
287
+ ScienceInput("imap_ultra_l1b_de_20240207_v001.cdf")
288
+ )
289
+ mocks["mock_pre_processing"].return_value = input_collection
201
290
 
202
291
  instrument = Ultra("l1c", "pset", "[]", "20240207", "20240208", "v001", True)
292
+
203
293
  instrument.process()
204
- assert mocks["mock_query"].call_count == 0
205
- assert mocks["mock_download"].call_count == 0
206
294
  assert mock_ultra_l1c.call_count == 1
207
295
  assert mocks["mock_upload"].call_count == 2
208
296
 
@@ -211,24 +299,19 @@ def test_ultra_l1c(mock_ultra_l1c, mock_instrument_dependencies):
211
299
  def test_hit_l1a(mock_hit_l1a, mock_instrument_dependencies):
212
300
  """Test coverage for cli.Hit class with l1a data level"""
213
301
  mocks = mock_instrument_dependencies
214
- mocks["mock_query"].return_value = [{"file_path": "/path/to/file0"}]
215
- mocks["mock_download"].return_value = "dependency0"
216
- mock_hit_l1a.return_value = ["l1a_dataset0", "l1a_dataset1"]
302
+ mock_hit_l1a.return_value = [xr.Dataset(), xr.Dataset()]
217
303
  mocks["mock_write_cdf"].side_effect = ["/path/to/product0", "/path/to/product1"]
304
+ input_collection = ProcessingInputCollection(
305
+ ScienceInput("imap_hit_l0_raw_20100105_v001.pkts")
306
+ )
307
+ mocks["mock_pre_processing"].return_value = input_collection
218
308
 
219
309
  dependency_str = (
220
- "[{"
221
- "'instrument': 'hit',"
222
- "'data_level': 'l0',"
223
- "'descriptor': 'raw',"
224
- "'version': 'v001',"
225
- "'start_date': '20100105'"
226
- "}]"
310
+ '[{"type": "science","files": ["imap_hit_l0_raw_20100105_v001.pkts"]}]'
227
311
  )
228
312
  instrument = Hit("l1a", "raw", dependency_str, "20100105", "20100101", "v001", True)
313
+
229
314
  instrument.process()
230
- assert mocks["mock_query"].call_count == 1
231
- assert mocks["mock_download"].call_count == 1
232
315
  assert mock_hit_l1a.call_count == 1
233
316
  assert mocks["mock_upload"].call_count == 2
234
317
 
@@ -237,25 +320,25 @@ def test_hit_l1a(mock_hit_l1a, mock_instrument_dependencies):
237
320
  def test_post_processing(mock_swe_l1a, mock_instrument_dependencies):
238
321
  """Test coverage for post processing"""
239
322
  mocks = mock_instrument_dependencies
240
- mocks["mock_query"].return_value = [{"file_path": "/path/to/file0"}]
241
323
  mocks["mock_download"].return_value = "dependency0"
242
- # Return empty list to simulate no data to write
243
- mock_swe_l1a.return_value = []
324
+ test_ds = xr.Dataset()
325
+ mock_swe_l1a.return_value = [test_ds]
326
+ input_collection = ProcessingInputCollection(
327
+ ScienceInput("imap_swe_l0_raw_20100105_v001.pkts")
328
+ )
329
+ mocks["mock_pre_processing"].return_value = input_collection
244
330
 
245
331
  dependency_str = (
246
- "[{"
247
- "'instrument': 'hit',"
248
- "'data_level': 'l0',"
249
- "'descriptor': 'raw',"
250
- "'version': 'v001',"
251
- "'start_date': '20100105'"
252
- "}]"
332
+ '[{"type": "science","files": ["imap_swe_l0_raw_20100105_v001.pkts"]}]'
253
333
  )
254
- instrument = Swe("l1a", "raw", dependency_str, "20100105", "20100101", "v001", True)
334
+ instrument = Swe("l1a", "raw", dependency_str, "20100105", None, "v001", True)
255
335
 
256
336
  # This function calls both the instrument.do_processing() and
257
337
  # instrument.post_processing()
258
338
  instrument.process()
259
339
  assert mock_swe_l1a.call_count == 1
260
- # This test is testing that no upload happened
261
- assert mocks["mock_upload"].call_count == 0
340
+ # This test is testing that one file was uploaded
341
+ assert mocks["mock_upload"].call_count == 1
342
+
343
+ # Test parent injection
344
+ assert test_ds.attrs["Parents"] == ["imap_swe_l0_raw_20100105_v001.pkts"]
@@ -11,20 +11,29 @@ from imap_processing import imap_module_directory, utils
11
11
  def test_convert_raw_to_eu(tmp_path):
12
12
  """Test coverage for utils.convert_raw_to_eu()"""
13
13
  # Generate a csv for testing
14
+ # Include segmented and unsegmented polyvals
15
+ dn_cutoff = 2
14
16
  test_df = pd.DataFrame(
15
17
  data={
16
- "packetName": ["PACKET_0", "PACKET_0", "PACKET_1"],
17
- "mnemonic": ["FIELD_0", "FIELD_1", "FIELD_0"],
18
- "convertAs": ["UNSEGMENTED_POLY", "UNSEGMENTED_POLY", "FOO_METHOD"],
19
- "c0": [0, 1, 2],
20
- "c1": [0, 1, 2],
21
- "c2": [0, 0, 2],
22
- "c3": [0, 0, 2],
23
- "c4": [0, 0, 2],
24
- "c5": [0, 1, 2],
25
- "c6": [0, 0, 2],
26
- "c7": [0, 0, 2],
27
- "unit": ["a", "b", "c"],
18
+ "packetName": ["PACKET_0", "PACKET_0", "PACKET_2", "PACKET_2", "PACKET_1"],
19
+ "mnemonic": ["FIELD_0", "FIELD_1", "FIELD_2", "FIELD_2", "FIELD_0"],
20
+ "convertAs": [
21
+ "UNSEGMENTED_POLY",
22
+ "UNSEGMENTED_POLY",
23
+ "SEGMENTED_POLY",
24
+ "SEGMENTED_POLY",
25
+ "FOO_METHOD",
26
+ ],
27
+ "dn_range_start": [0, 0, 1, dn_cutoff + 1, 0],
28
+ "dn_range_stop": [0, 0, dn_cutoff, 4, 0],
29
+ "c0": [0, 1, 3, 4, 2],
30
+ "c1": [0, 1, 3, 4, 2],
31
+ "c2": [0, 0, 3, 4, 2],
32
+ "c3": [0, 0, 3, 4, 2],
33
+ "c5": [0, 1, 3, 4, 2],
34
+ "c6": [0, 0, 3, 4, 2],
35
+ "c7": [0, 0, 3, 4, 2],
36
+ "unit": ["a", "b", "d", "d", "c"],
28
37
  }
29
38
  )
30
39
  test_csv = tmp_path / "test_convert_table.csv"
@@ -36,11 +45,13 @@ def test_convert_raw_to_eu(tmp_path):
36
45
  n_packets = 3
37
46
  field_0 = np.arange(n_packets)
38
47
  field_1 = np.arange(n_packets) + 10
48
+ field_2 = np.arange(n_packets) + 1
39
49
  time = np.arange(n_packets) + 1000
40
50
  dn_dataset = xr.Dataset(
41
51
  data_vars=dict(
42
52
  FIELD_0=(["time"], field_0),
43
53
  FIELD_1=(["time"], field_1),
54
+ FIELD_2=(["time"], field_2),
44
55
  ),
45
56
  coords=dict(
46
57
  time=time,
@@ -53,7 +64,7 @@ def test_convert_raw_to_eu(tmp_path):
53
64
 
54
65
  # Check the converted values by manually doing the polynomial math
55
66
  np.testing.assert_array_equal(eu_dataset["FIELD_0"].data, np.zeros(n_packets))
56
- assert eu_dataset["FIELD_0"].attrs["units"] == test_df["unit"].iloc[0]
67
+ assert eu_dataset["FIELD_0"].attrs["UNITS"] == test_df["unit"].iloc[0]
57
68
 
58
69
  field_1_coeffs = (
59
70
  test_df[test_df["mnemonic"] == "FIELD_1"].filter(regex=r"c\d").values[0]
@@ -63,14 +74,125 @@ def test_convert_raw_to_eu(tmp_path):
63
74
  field_1_compare += coeff * np.power(field_1, p)
64
75
  np.testing.assert_array_equal(eu_dataset["FIELD_1"].data, field_1_compare)
65
76
 
77
+ eu_dataset = utils.convert_raw_to_eu(
78
+ dn_dataset.copy(), test_csv.absolute(), "PACKET_2", comment="#"
79
+ )
80
+ # Test the segmented polynomials
81
+ field_2_coeffs = (
82
+ test_df[test_df["mnemonic"] == "FIELD_2"].filter(regex=r"c\d").values
83
+ )
84
+ field_2_compare_seg_1 = np.zeros(len(field_2[field_2 <= dn_cutoff]))
85
+ field_2_compare_seg_2 = np.zeros(len(field_2[field_2 > dn_cutoff]))
86
+ for p, coeff in enumerate(field_2_coeffs[0]):
87
+ field_2_compare_seg_1 += coeff * np.power(field_2[field_2 <= dn_cutoff], p)
88
+ for p, coeff in enumerate(field_2_coeffs[1]):
89
+ field_2_compare_seg_2 += coeff * np.power(field_2[field_2 > dn_cutoff], p)
90
+
91
+ field_2_compare = np.concatenate([field_2_compare_seg_1, field_2_compare_seg_2])
92
+ np.testing.assert_array_equal(eu_dataset["FIELD_2"].data, field_2_compare)
93
+
94
+ assert eu_dataset["FIELD_2"].attrs["UNITS"] == test_df["unit"].iloc[2]
66
95
  # Check that a ValueError is raised for unexpected conversion specified in
67
96
  # conversion table "convertAs" column
68
- with pytest.raises(ValueError, match=r"Unexpected conversion type: .*"):
69
- eu_dataset = utils.convert_raw_to_eu(
97
+ with pytest.raises(
98
+ ValueError,
99
+ match="Column 'convertAs' must all be UNSEGMENTED_POLY or "
100
+ "SEGMENTED_POLY for a packet name and mnemonic",
101
+ ):
102
+ utils.convert_raw_to_eu(
70
103
  dn_dataset.copy(), test_csv.absolute(), "PACKET_1", comment="#"
71
104
  )
72
105
 
73
106
 
107
+ def test_segmented_poly_out_of_range(tmp_path):
108
+ """Test that a value error is thrown if a raw DN value is out of range"""
109
+ # Generate a csv for testing
110
+ test_df = pd.DataFrame(
111
+ data={
112
+ "packetName": ["PACKET_0", "PACKET_0"],
113
+ "mnemonic": ["FIELD_0", "FIELD_0"],
114
+ "convertAs": ["SEGMENTED_POLY", "SEGMENTED_POLY"],
115
+ # Make ranges higher than DNs
116
+ "dn_range_start": [100, 201],
117
+ "dn_range_stop": [200, 400],
118
+ "c0": [0, 1],
119
+ "c1": [0, 1],
120
+ "c2": [0, 1],
121
+ "c3": [0, 1],
122
+ "c5": [0, 1],
123
+ "c6": [0, 1],
124
+ "c7": [0, 1],
125
+ "unit": ["a", "b"],
126
+ }
127
+ )
128
+ test_csv = tmp_path / "test_convert_table.csv"
129
+ with open(test_csv, "w") as f:
130
+ f.write("# Comment on first line of file\n")
131
+ test_df.to_csv(f, index=False)
132
+
133
+ # Generate a fake dataset for testing
134
+ n_packets = 3
135
+ field_0 = np.arange(n_packets)
136
+ time = np.arange(n_packets) + 1000
137
+ dn_dataset = xr.Dataset(
138
+ data_vars=dict(
139
+ FIELD_0=(["time"], field_0),
140
+ ),
141
+ coords=dict(
142
+ time=time,
143
+ ),
144
+ )
145
+ # Check that a ValueError is raised for DNs not in any ranges
146
+ with pytest.raises(
147
+ ValueError, match="Raw DN values found outside of the expected range"
148
+ ):
149
+ utils.convert_raw_to_eu(
150
+ dn_dataset.copy(), test_csv.absolute(), "PACKET_0", comment="#"
151
+ )
152
+
153
+
154
+ def test_unsegmented_poly_multiple_rows(tmp_path):
155
+ """Test that a value error is thrown if there are multiple rows with the same
156
+ mnemonic and packet name and convertAs is UNSEGMENTED_POLY"""
157
+ # Generate a csv for testing
158
+ test_df = pd.DataFrame(
159
+ data={
160
+ "packetName": ["PACKET_0", "PACKET_0"],
161
+ "mnemonic": ["FIELD_0", "FIELD_0"],
162
+ "convertAs": ["UNSEGMENTED_POLY", "UNSEGMENTED_POLY"],
163
+ "c0": [0, 1],
164
+ "c1": [0, 1],
165
+ "c2": [0, 1],
166
+ "c3": [0, 1],
167
+ "c5": [0, 1],
168
+ "c6": [0, 1],
169
+ "c7": [0, 1],
170
+ "unit": ["a", "a"],
171
+ }
172
+ )
173
+ test_csv = tmp_path / "test_convert_table.csv"
174
+ with open(test_csv, "w") as f:
175
+ f.write("# Comment on first line of file\n")
176
+ test_df.to_csv(f, index=False)
177
+
178
+ # Generate a fake dataset for testing
179
+ field_0 = np.arange(3)
180
+ dn_dataset = xr.Dataset(
181
+ data_vars=dict(
182
+ FIELD_0=(["time"], field_0),
183
+ )
184
+ )
185
+ # Check that a ValueError is raised for DNs not in any ranges
186
+ with pytest.raises(
187
+ ValueError,
188
+ match="For unsegmented polynomial conversions, there should "
189
+ "only be one row per mnemonic and packet name",
190
+ ):
191
+ utils.convert_raw_to_eu(
192
+ dn_dataset.copy(), test_csv.absolute(), "PACKET_0", comment="#"
193
+ )
194
+
195
+
74
196
  @pytest.mark.parametrize(
75
197
  "use_derived_value, expected_mode",
76
198
  [(True, np.array(["HVENG", "HVSCI"])), (False, np.array([2, 3]))],
@@ -100,10 +222,11 @@ def test_packet_file_to_datasets(use_derived_value, expected_mode):
100
222
 
101
223
 
102
224
  def test_packet_file_to_datasets_flat_definition():
103
- test_file = "tests/idex/test_data/imap_idex_l0_raw_20231214_v001.pkts"
225
+ test_file = "tests/idex/test_data/imap_idex_l0_raw_20231218_v001.pkts"
104
226
  packet_files = imap_module_directory / test_file
105
227
  packet_definition = (
106
- imap_module_directory / "idex/packet_definitions/idex_packet_definition.xml"
228
+ imap_module_directory
229
+ / "idex/packet_definitions/idex_science_packet_definition.xml"
107
230
  )
108
231
  with pytest.raises(ValueError, match="Packet fields do not match"):
109
232
  utils.packet_file_to_datasets(packet_files, packet_definition)