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

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

Potentially problematic release.


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

Files changed (288) hide show
  1. imap_processing/__init__.py +10 -11
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/excel_to_xtce.py +65 -16
  4. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +6 -28
  5. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +365 -42
  6. imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +0 -5
  7. imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +10 -11
  8. imap_processing/cdf/config/imap_hi_variable_attrs.yaml +17 -19
  9. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +26 -13
  10. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +106 -116
  11. imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +120 -145
  12. imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +14 -0
  13. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +6 -9
  14. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +1 -1
  15. imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +0 -12
  16. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +1 -1
  17. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +9 -21
  18. imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml +361 -0
  19. imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml +160 -0
  20. imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +160 -0
  21. imap_processing/cdf/config/imap_spacecraft_global_cdf_attrs.yaml +18 -0
  22. imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml +40 -0
  23. imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +1 -5
  24. imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +12 -4
  25. imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +16 -2
  26. imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +48 -52
  27. imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +71 -47
  28. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +2 -14
  29. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +51 -2
  30. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +29 -14
  31. imap_processing/cdf/utils.py +13 -7
  32. imap_processing/cli.py +23 -8
  33. imap_processing/codice/codice_l1a.py +207 -85
  34. imap_processing/codice/constants.py +1322 -568
  35. imap_processing/codice/decompress.py +2 -6
  36. imap_processing/ena_maps/ena_maps.py +480 -116
  37. imap_processing/ena_maps/utils/coordinates.py +19 -0
  38. imap_processing/ena_maps/utils/map_utils.py +14 -17
  39. imap_processing/ena_maps/utils/spatial_utils.py +45 -47
  40. imap_processing/hi/l1a/hi_l1a.py +24 -18
  41. imap_processing/hi/l1a/histogram.py +0 -1
  42. imap_processing/hi/l1a/science_direct_event.py +6 -8
  43. imap_processing/hi/l1b/hi_l1b.py +31 -39
  44. imap_processing/hi/l1c/hi_l1c.py +405 -17
  45. imap_processing/hi/utils.py +58 -12
  46. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt0-factors_20250219_v002.csv +205 -0
  47. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt1-factors_20250219_v002.csv +205 -0
  48. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt2-factors_20250219_v002.csv +205 -0
  49. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt3-factors_20250219_v002.csv +205 -0
  50. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-summed-dt0-factors_20250219_v002.csv +68 -0
  51. imap_processing/hit/hit_utils.py +173 -1
  52. imap_processing/hit/l0/constants.py +20 -11
  53. imap_processing/hit/l0/decom_hit.py +18 -4
  54. imap_processing/hit/l1a/hit_l1a.py +45 -54
  55. imap_processing/hit/l1b/constants.py +317 -0
  56. imap_processing/hit/l1b/hit_l1b.py +367 -18
  57. imap_processing/hit/l2/constants.py +281 -0
  58. imap_processing/hit/l2/hit_l2.py +614 -0
  59. imap_processing/hit/packet_definitions/hit_packet_definitions.xml +1323 -71
  60. imap_processing/ialirt/l0/mag_l0_ialirt_data.py +155 -0
  61. imap_processing/ialirt/l0/parse_mag.py +246 -0
  62. imap_processing/ialirt/l0/process_swe.py +252 -0
  63. imap_processing/ialirt/packet_definitions/ialirt.xml +7 -3
  64. imap_processing/ialirt/packet_definitions/ialirt_mag.xml +115 -0
  65. imap_processing/ialirt/utils/grouping.py +114 -0
  66. imap_processing/ialirt/utils/time.py +29 -0
  67. imap_processing/idex/atomic_masses.csv +22 -0
  68. imap_processing/idex/decode.py +2 -2
  69. imap_processing/idex/idex_constants.py +25 -0
  70. imap_processing/idex/idex_l1a.py +6 -7
  71. imap_processing/idex/idex_l1b.py +4 -31
  72. imap_processing/idex/idex_l2a.py +789 -0
  73. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +39 -33
  74. imap_processing/lo/l0/lo_science.py +6 -0
  75. imap_processing/lo/l1a/lo_l1a.py +0 -1
  76. imap_processing/lo/l1b/lo_l1b.py +177 -25
  77. imap_processing/mag/constants.py +8 -0
  78. imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +6 -0
  79. imap_processing/mag/l0/decom_mag.py +10 -3
  80. imap_processing/mag/l1a/mag_l1a.py +22 -11
  81. imap_processing/mag/l1a/mag_l1a_data.py +28 -3
  82. imap_processing/mag/l1b/mag_l1b.py +190 -48
  83. imap_processing/mag/l1c/interpolation_methods.py +211 -0
  84. imap_processing/mag/l1c/mag_l1c.py +447 -9
  85. imap_processing/quality_flags.py +1 -0
  86. imap_processing/spacecraft/packet_definitions/scid_x252.xml +538 -0
  87. imap_processing/spacecraft/quaternions.py +123 -0
  88. imap_processing/spice/geometry.py +16 -19
  89. imap_processing/spice/repoint.py +120 -0
  90. imap_processing/swapi/l1/swapi_l1.py +4 -0
  91. imap_processing/swapi/l2/swapi_l2.py +0 -1
  92. imap_processing/swe/l1a/swe_l1a.py +47 -8
  93. imap_processing/swe/l1a/swe_science.py +5 -2
  94. imap_processing/swe/l1b/swe_l1b_science.py +103 -56
  95. imap_processing/swe/l2/swe_l2.py +60 -65
  96. imap_processing/swe/packet_definitions/swe_packet_definition.xml +1121 -1
  97. imap_processing/swe/utils/swe_constants.py +63 -0
  98. imap_processing/swe/utils/swe_utils.py +85 -28
  99. imap_processing/tests/ccsds/test_data/expected_output.xml +40 -1
  100. imap_processing/tests/ccsds/test_excel_to_xtce.py +23 -20
  101. imap_processing/tests/cdf/test_data/imap_instrument2_global_cdf_attrs.yaml +0 -2
  102. imap_processing/tests/codice/conftest.py +1 -1
  103. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  104. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  105. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-ialirt_20241110193700_v0.0.0.cdf +0 -0
  106. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-omni_20241110193700_v0.0.0.cdf +0 -0
  107. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
  108. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-priorities_20241110193700_v0.0.0.cdf +0 -0
  109. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-sectored_20241110193700_v0.0.0.cdf +0 -0
  110. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  111. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  112. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  113. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-angular_20241110193700_v0.0.0.cdf +0 -0
  114. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-priority_20241110193700_v0.0.0.cdf +0 -0
  115. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-species_20241110193700_v0.0.0.cdf +0 -0
  116. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
  117. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-angular_20241110193700_v0.0.0.cdf +0 -0
  118. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-priority_20241110193700_v0.0.0.cdf +0 -0
  119. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-species_20241110193700_v0.0.0.cdf +0 -0
  120. imap_processing/tests/codice/test_codice_l1a.py +110 -46
  121. imap_processing/tests/codice/test_decompress.py +4 -4
  122. imap_processing/tests/conftest.py +166 -10
  123. imap_processing/tests/ena_maps/conftest.py +51 -0
  124. imap_processing/tests/ena_maps/test_ena_maps.py +638 -109
  125. imap_processing/tests/ena_maps/test_map_utils.py +66 -43
  126. imap_processing/tests/ena_maps/test_spatial_utils.py +16 -20
  127. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208.bin +0 -0
  128. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208_verify.csv +205 -0
  129. imap_processing/tests/hi/test_hi_l1b.py +12 -15
  130. imap_processing/tests/hi/test_hi_l1c.py +234 -6
  131. imap_processing/tests/hi/test_l1a.py +30 -0
  132. imap_processing/tests/hi/test_science_direct_event.py +1 -1
  133. imap_processing/tests/hi/test_utils.py +24 -2
  134. imap_processing/tests/hit/helpers/l1_validation.py +39 -39
  135. imap_processing/tests/hit/test_data/hskp_sample.ccsds +0 -0
  136. imap_processing/tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts +0 -0
  137. imap_processing/tests/hit/test_decom_hit.py +4 -0
  138. imap_processing/tests/hit/test_hit_l1a.py +24 -28
  139. imap_processing/tests/hit/test_hit_l1b.py +304 -40
  140. imap_processing/tests/hit/test_hit_l2.py +454 -0
  141. imap_processing/tests/hit/test_hit_utils.py +112 -2
  142. imap_processing/tests/hit/validation_data/hskp_sample_eu_3_6_2025.csv +89 -0
  143. imap_processing/tests/hit/validation_data/hskp_sample_raw.csv +89 -88
  144. imap_processing/tests/ialirt/test_data/l0/461971383-404.bin +0 -0
  145. imap_processing/tests/ialirt/test_data/l0/461971384-405.bin +0 -0
  146. imap_processing/tests/ialirt/test_data/l0/461971385-406.bin +0 -0
  147. imap_processing/tests/ialirt/test_data/l0/461971386-407.bin +0 -0
  148. imap_processing/tests/ialirt/test_data/l0/461971387-408.bin +0 -0
  149. imap_processing/tests/ialirt/test_data/l0/461971388-409.bin +0 -0
  150. imap_processing/tests/ialirt/test_data/l0/461971389-410.bin +0 -0
  151. imap_processing/tests/ialirt/test_data/l0/461971390-411.bin +0 -0
  152. imap_processing/tests/ialirt/test_data/l0/461971391-412.bin +0 -0
  153. imap_processing/tests/ialirt/test_data/l0/sample_decoded_i-alirt_data.csv +383 -0
  154. imap_processing/tests/ialirt/unit/test_grouping.py +81 -0
  155. imap_processing/tests/ialirt/unit/test_parse_mag.py +168 -0
  156. imap_processing/tests/ialirt/unit/test_process_swe.py +208 -3
  157. imap_processing/tests/ialirt/unit/test_time.py +16 -0
  158. imap_processing/tests/idex/conftest.py +62 -6
  159. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231218_v001.pkts +0 -0
  160. imap_processing/tests/idex/test_data/impact_14_tof_high_data.txt +4508 -4508
  161. imap_processing/tests/idex/test_idex_l1a.py +48 -4
  162. imap_processing/tests/idex/test_idex_l1b.py +3 -3
  163. imap_processing/tests/idex/test_idex_l2a.py +383 -0
  164. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20241022_v002.cdf +0 -0
  165. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20241022_v002.cdf +0 -0
  166. imap_processing/tests/lo/test_lo_l1b.py +148 -4
  167. imap_processing/tests/lo/test_lo_science.py +1 -0
  168. imap_processing/tests/mag/conftest.py +69 -0
  169. imap_processing/tests/mag/test_mag_decom.py +1 -1
  170. imap_processing/tests/mag/test_mag_l1a.py +38 -0
  171. imap_processing/tests/mag/test_mag_l1b.py +34 -53
  172. imap_processing/tests/mag/test_mag_l1c.py +251 -20
  173. imap_processing/tests/mag/test_mag_validation.py +109 -25
  174. imap_processing/tests/mag/validation/L1b/T009/MAGScience-normal-(2,2)-8s-20250204-16h39.csv +17 -0
  175. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-magi-out.csv +16 -16
  176. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-mago-out.csv +16 -16
  177. imap_processing/tests/mag/validation/L1b/T010/MAGScience-normal-(2,2)-8s-20250206-12h05.csv +17 -0
  178. imap_processing/tests/mag/validation/L1b/T011/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  179. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-magi-out.csv +16 -16
  180. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-mago-out.csv +16 -16
  181. imap_processing/tests/mag/validation/L1b/T012/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  182. imap_processing/tests/mag/validation/L1b/T012/data.bin +0 -0
  183. imap_processing/tests/mag/validation/L1b/T012/field_like_all_ranges.txt +19200 -0
  184. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-cal.cdf +0 -0
  185. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-in.csv +17 -0
  186. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-magi-out.csv +17 -0
  187. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-mago-out.csv +17 -0
  188. imap_processing/tests/mag/validation/imap_calibration_mag_20240229_v01.cdf +0 -0
  189. imap_processing/tests/spacecraft/__init__.py +0 -0
  190. imap_processing/tests/spacecraft/data/SSR_2024_190_20_08_12_0483851794_2_DA_apid0594_1packet.pkts +0 -0
  191. imap_processing/tests/spacecraft/test_quaternions.py +71 -0
  192. imap_processing/tests/spice/test_data/fake_repoint_data.csv +5 -0
  193. imap_processing/tests/spice/test_geometry.py +6 -9
  194. imap_processing/tests/spice/test_repoint.py +111 -0
  195. imap_processing/tests/swapi/test_swapi_l1.py +7 -3
  196. imap_processing/tests/swe/l0_data/2024051010_SWE_HK_packet.bin +0 -0
  197. imap_processing/tests/swe/l0_data/2024051011_SWE_CEM_RAW_packet.bin +0 -0
  198. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_APP_HK_20240510_092742.csv +49 -0
  199. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_CEM_RAW_20240510_092742.csv +593 -0
  200. imap_processing/tests/swe/test_swe_l1a.py +18 -0
  201. imap_processing/tests/swe/test_swe_l1a_cem_raw.py +52 -0
  202. imap_processing/tests/swe/test_swe_l1a_hk.py +68 -0
  203. imap_processing/tests/swe/test_swe_l1b_science.py +23 -4
  204. imap_processing/tests/swe/test_swe_l2.py +112 -30
  205. imap_processing/tests/test_cli.py +2 -2
  206. imap_processing/tests/test_utils.py +138 -16
  207. imap_processing/tests/ultra/data/l0/FM45_UltraFM45_Functional_2024-01-22T0105_20240122T010548.CCSDS +0 -0
  208. imap_processing/tests/ultra/data/l0/ultra45_raw_sc_ultraimgrates_20220530_00.csv +164 -0
  209. imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3243 -3243
  210. imap_processing/tests/ultra/data/mock_data.py +341 -0
  211. imap_processing/tests/ultra/unit/conftest.py +69 -26
  212. imap_processing/tests/ultra/unit/test_badtimes.py +2 -0
  213. imap_processing/tests/ultra/unit/test_cullingmask.py +4 -0
  214. imap_processing/tests/ultra/unit/test_de.py +12 -4
  215. imap_processing/tests/ultra/unit/test_decom_apid_881.py +44 -0
  216. imap_processing/tests/ultra/unit/test_spacecraft_pset.py +78 -0
  217. imap_processing/tests/ultra/unit/test_ultra_l1a.py +28 -12
  218. imap_processing/tests/ultra/unit/test_ultra_l1b.py +34 -6
  219. imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +22 -26
  220. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +86 -51
  221. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +94 -52
  222. imap_processing/ultra/l0/decom_tools.py +6 -5
  223. imap_processing/ultra/l1a/ultra_l1a.py +28 -56
  224. imap_processing/ultra/l1b/de.py +72 -28
  225. imap_processing/ultra/l1b/extendedspin.py +12 -14
  226. imap_processing/ultra/l1b/ultra_l1b.py +34 -9
  227. imap_processing/ultra/l1b/ultra_l1b_culling.py +65 -29
  228. imap_processing/ultra/l1b/ultra_l1b_extended.py +64 -19
  229. imap_processing/ultra/l1c/spacecraft_pset.py +86 -0
  230. imap_processing/ultra/l1c/ultra_l1c.py +7 -4
  231. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +112 -61
  232. imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
  233. imap_processing/ultra/utils/ultra_l1_utils.py +20 -2
  234. imap_processing/utils.py +68 -28
  235. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/METADATA +8 -5
  236. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/RECORD +250 -199
  237. imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +0 -237
  238. imap_processing/hi/l1a/housekeeping.py +0 -27
  239. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-aggregated_20240429_v001.cdf +0 -0
  240. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-singles_20240429_v001.cdf +0 -0
  241. imap_processing/tests/codice/data/imap_codice_l1a_hi-omni_20240429_v001.cdf +0 -0
  242. imap_processing/tests/codice/data/imap_codice_l1a_hi-sectored_20240429_v001.cdf +0 -0
  243. imap_processing/tests/codice/data/imap_codice_l1a_hskp_20100101_v001.cdf +0 -0
  244. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-aggregated_20240429_v001.cdf +0 -0
  245. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-singles_20240429_v001.cdf +0 -0
  246. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-angular_20240429_v001.cdf +0 -0
  247. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-priority_20240429_v001.cdf +0 -0
  248. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-species_20240429_v001.cdf +0 -0
  249. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-angular_20240429_v001.cdf +0 -0
  250. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-priority_20240429_v001.cdf +0 -0
  251. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-species_20240429_v001.cdf +0 -0
  252. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-aggregated_20240429_v001.cdf +0 -0
  253. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-singles_20240429_v001.cdf +0 -0
  254. imap_processing/tests/codice/data/imap_codice_l1b_hi-omni_20240429_v001.cdf +0 -0
  255. imap_processing/tests/codice/data/imap_codice_l1b_hi-sectored_20240429_v001.cdf +0 -0
  256. imap_processing/tests/codice/data/imap_codice_l1b_hskp_20100101_v001.cdf +0 -0
  257. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-aggregated_20240429_v001.cdf +0 -0
  258. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-singles_20240429_v001.cdf +0 -0
  259. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-angular_20240429_v001.cdf +0 -0
  260. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-priority_20240429_v001.cdf +0 -0
  261. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-species_20240429_v001.cdf +0 -0
  262. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-angular_20240429_v001.cdf +0 -0
  263. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-priority_20240429_v001.cdf +0 -0
  264. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-species_20240429_v001.cdf +0 -0
  265. imap_processing/tests/hi/data/l1/imap_hi_l1b_45sensor-de_20250415_v999.cdf +0 -0
  266. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1251.pkts +0 -0
  267. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1252.pkts +0 -0
  268. imap_processing/tests/hit/validation_data/hskp_sample_eu.csv +0 -89
  269. imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +0 -29
  270. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231214_v001.pkts +0 -0
  271. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20100101_v001.cdf +0 -0
  272. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20100101_v001.cdf +0 -0
  273. imap_processing/tests/ultra/test_data/mock_data.py +0 -161
  274. imap_processing/ultra/l1c/pset.py +0 -40
  275. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00_20240207T102740.CCSDS +0 -0
  276. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_7P_Phi0.0_BeamCal_LinearScan_phi0.04_theta-0.01_20230821T121304.CCSDS +0 -0
  277. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.CCSDS +0 -0
  278. /imap_processing/tests/ultra/{test_data → data}/l0/Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.CCSDS +0 -0
  279. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_auxdata_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  280. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_enaphxtofhangimg_FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.csv +0 -0
  281. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultraimgrates_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  282. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimgevent_FM45_7P_Phi00_BeamCal_LinearScan_phi004_theta-001_20230821T121304.csv +0 -0
  283. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E1.cdf +0 -0
  284. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E12.cdf +0 -0
  285. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E24.cdf +0 -0
  286. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/LICENSE +0 -0
  287. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/WHEEL +0 -0
  288. {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/entry_points.txt +0 -0
@@ -7,6 +7,29 @@ default_attrs: &default
7
7
  VALIDMIN: -9223372036854775808
8
8
  VALIDMAX: 9223372036854775807
9
9
  VAR_TYPE: data
10
+ UNITS: " "
11
+
12
+ default_float32_attrs: &default_float32
13
+ <<: *default
14
+ FILLVAL: .NAN
15
+ FORMAT: F12.6
16
+ VALIDMIN: -3.4028235e+38
17
+ VALIDMAX: 3.4028235e+38
18
+ dtype: float32
19
+
20
+ latitude:
21
+ <<: *default_float32
22
+ CATDESC: Latitude bin center corresponding to healpix index with range [-90, 90].
23
+ FIELDNAM: latitude
24
+ LABLAXIS: latitude
25
+ UNITS: degrees
26
+
27
+ longitude:
28
+ <<: *default_float32
29
+ CATDESC: Longitude bin center corresponding to healpix index with range [0, 360].
30
+ FIELDNAM: longitude
31
+ LABLAXIS: longitude
32
+ UNITS: degrees
10
33
 
11
34
  spin_angle:
12
35
  <<: *default
@@ -16,14 +39,6 @@ spin_angle:
16
39
  # TODO: come back to format
17
40
  UNITS: degrees
18
41
 
19
- esa_step:
20
- <<: *default
21
- CATDESC: ESA step (0-10), nominally 9, but possibly 8 or 10, 0 is likely a background test. Energy bin.
22
- FIELDNAM: esa_step
23
- LABLAXIS: esa step
24
- # TODO: come back to format
25
- UNITS: " "
26
-
27
42
  time_bin:
28
43
  <<: *default
29
44
  CATDESC: Time bin defined by central location of the bin.
@@ -40,11 +55,11 @@ species_bin:
40
55
  # TODO: come back to format
41
56
  UNITS: " "
42
57
 
43
- exposure_times:
44
- <<: *default
45
- CATDESC: Exposure time for a spin.
46
- FIELDNAM: exposure_times
47
- LABLAXIS: exposure times
58
+ exposure_factor:
59
+ <<: *default_float32
60
+ CATDESC: Exposure time for a pointing.
61
+ FIELDNAM: exposure_factor
62
+ LABLAXIS: exposure factor
48
63
  # TODO: come back to format
49
64
  UNITS: seconds
50
65
 
@@ -65,7 +80,7 @@ counts:
65
80
  UNITS: counts
66
81
 
67
82
  background_rates:
68
- <<: *default
83
+ <<: *default_float32
69
84
  CATDESC: Background rates. Background dominated by accidentals caused by a combination of UV light and misregistered low energy ENA events.
70
85
  FIELDNAM: background_rates
71
86
  LABLAXIS: background rates
@@ -60,7 +60,9 @@ def load_cdf(
60
60
 
61
61
 
62
62
  def write_cdf(
63
- dataset: xr.Dataset, parent_files: Optional[list] = None, **extra_cdf_kwargs: dict
63
+ dataset: xr.Dataset,
64
+ parent_files: Optional[list] = None,
65
+ **extra_cdf_kwargs: dict,
64
66
  ) -> Path:
65
67
  """
66
68
  Write the contents of "data" to a CDF file using cdflib.xarray_to_cdf.
@@ -135,12 +137,16 @@ def write_cdf(
135
137
  ]
136
138
 
137
139
  # Convert the xarray object to a CDF
138
- xarray_to_cdf(
139
- dataset,
140
- str(file_path),
141
- terminate_on_warning=True,
142
- **extra_cdf_kwargs,
143
- ) # Terminate if not ISTP compliant
140
+ if "l1" in data_level:
141
+ if "terminate_on_warning" not in extra_cdf_kwargs:
142
+ extra_cdf_kwargs["terminate_on_warning"] = False # type: ignore
143
+ else:
144
+ if "terminate_on_warning" not in extra_cdf_kwargs:
145
+ extra_cdf_kwargs["terminate_on_warning"] = True # type: ignore
146
+ if "istp" not in extra_cdf_kwargs:
147
+ extra_cdf_kwargs["istp"] = True # type: ignore
148
+
149
+ xarray_to_cdf(dataset, str(file_path), **extra_cdf_kwargs)
144
150
 
145
151
  return file_path
146
152
 
imap_processing/cli.py CHANGED
@@ -44,6 +44,7 @@ from imap_processing.hi.l1b import hi_l1b
44
44
  from imap_processing.hi.l1c import hi_l1c
45
45
  from imap_processing.hit.l1a.hit_l1a import hit_l1a
46
46
  from imap_processing.hit.l1b.hit_l1b import hit_l1b
47
+ from imap_processing.hit.l2.hit_l2 import hit_l2
47
48
  from imap_processing.idex.idex_l1a import PacketParser
48
49
  from imap_processing.idex.idex_l1b import idex_l1b
49
50
  from imap_processing.lo.l1a import lo_l1a
@@ -583,17 +584,31 @@ class Hit(ProcessInstrument):
583
584
  datasets = hit_l1a(dependencies[0], self.version)
584
585
 
585
586
  elif self.data_level == "l1b":
587
+ if len(dependencies) > 1:
588
+ raise ValueError(
589
+ f"Unexpected dependencies found for HIT L1B:"
590
+ f"{dependencies}. Expected only one dependency."
591
+ )
586
592
  data_dict = {}
587
- for i, dependency in enumerate(dependencies):
588
- if self.dependencies[i]["data_level"] == "l0":
589
- # Add path to CCSDS file to process housekeeping
590
- data_dict["imap_hit_l0_raw"] = dependency
591
- else:
592
- # Add L1A datasets to process science data
593
- dataset = load_cdf(dependency)
594
- data_dict[dataset.attrs["Logical_source"]] = dataset
593
+ if self.dependencies[0]["data_level"] == "l0":
594
+ # Add path to CCSDS file to process housekeeping
595
+ data_dict["imap_hit_l0_raw"] = dependencies[0]
596
+ else:
597
+ # Add L1A dataset to process science data
598
+ l1a_dataset = load_cdf(dependencies[0])
599
+ data_dict[l1a_dataset.attrs["Logical_source"]] = l1a_dataset
595
600
  # process data to L1B products
596
601
  datasets = hit_l1b(data_dict, self.version)
602
+ elif self.data_level == "l2":
603
+ if len(dependencies) > 1:
604
+ raise ValueError(
605
+ f"Unexpected dependencies found for HIT L2:"
606
+ f"{dependencies}. Expected only one dependency."
607
+ )
608
+ # Add L1B dataset to process science data
609
+ l1b_dataset = load_cdf(dependencies[0])
610
+ # process data to L2 products
611
+ datasets = hit_l2(l1b_dataset, self.version)
597
612
 
598
613
  return datasets
599
614
 
@@ -74,6 +74,8 @@ class CoDICEL1aPipeline:
74
74
  Retrieve the acquisition times via the Lo stepping table.
75
75
  get_energy_table()
76
76
  Retrieve the ESA sweep values.
77
+ get_hi_energy_table_data(species)
78
+ Retrieve energy table data for CoDICE-Hi products
77
79
  reshape_data()
78
80
  Reshape the data arrays based on the data product being made.
79
81
  set_data_product_config()
@@ -149,7 +151,7 @@ class CoDICEL1aPipeline:
149
151
  """
150
152
  self.coords = {}
151
153
 
152
- coord_names = ["epoch", *list(self.config["dims"].keys())]
154
+ coord_names = ["epoch", *list(self.config["output_dims"].keys())]
153
155
 
154
156
  # These are labels unique to lo-counters products coordinates
155
157
  if self.config["dataset_name"] in [
@@ -158,11 +160,19 @@ class CoDICEL1aPipeline:
158
160
  ]:
159
161
  coord_names.append("spin_sector_pairs_label")
160
162
 
163
+ # Define the values for the coordinates
161
164
  for name in coord_names:
162
165
  if name == "epoch":
163
166
  values = self.calculate_epoch_values()
164
- elif name in ["esa_step", "inst_az", "spin_sector", "spin_sector_pairs"]:
165
- values = np.arange(self.config["dims"][name])
167
+ elif name in [
168
+ "esa_step",
169
+ "inst_az",
170
+ "spin_sector",
171
+ "spin_sector_pairs",
172
+ "spin_sector_index",
173
+ "ssd_index",
174
+ ]:
175
+ values = np.arange(self.config["output_dims"][name])
166
176
  elif name == "spin_sector_pairs_label":
167
177
  values = np.array(
168
178
  [
@@ -174,10 +184,6 @@ class CoDICEL1aPipeline:
174
184
  "150-180 deg",
175
185
  ]
176
186
  )
177
- else:
178
- # TODO: May need to implement other types of coords for Hi
179
- # and/or event data products
180
- continue
181
187
 
182
188
  coord = xr.DataArray(
183
189
  values,
@@ -226,9 +232,20 @@ class CoDICEL1aPipeline:
226
232
  cdf_attrs_key = f"{descriptor}-{variable_name}"
227
233
  attrs = self.cdf_attrs.get_variable_attributes(cdf_attrs_key)
228
234
 
229
- # The final CDF dimensions always has "epoch" as the first dimension,
230
- # followed by the dimensions for the specific data product
231
- dims = ["epoch", *list(self.config["dims"].keys())]
235
+ # For most products, the final CDF dimensions always has "epoch" as
236
+ # the first dimension followed by the dimensions for the specific
237
+ # data product
238
+ dims = ["epoch", *list(self.config["output_dims"].keys())]
239
+
240
+ # However, CoDICE-Hi products use specific energy bins for the
241
+ # energy dimension
242
+ # TODO: This will be expanded to all CoDICE-Hi products once I
243
+ # can validate them. For now, just operate on hi-sectored
244
+ if self.config["dataset_name"] == "imap_codice_l1a_hi-sectored":
245
+ dims = [
246
+ f"energy_{variable_name}" if item == "esa_step" else item
247
+ for item in dims
248
+ ]
232
249
 
233
250
  # Create the CDF data variable
234
251
  dataset[variable_name] = xr.DataArray(
@@ -241,6 +258,13 @@ class CoDICEL1aPipeline:
241
258
  # Add support data variables based on data product
242
259
  dataset = self.define_support_variables(dataset)
243
260
 
261
+ # For CoDICE-Hi products, since energy dimension was replaced, we no
262
+ # longer need the "esa_step" coordinate
263
+ # TODO: This will be expanded to all CoDICE-Hi products once I
264
+ # can validate them. For now, just operate on hi-sectored
265
+ if self.config["dataset_name"] == "imap_codice_l1a_hi-sectored":
266
+ dataset = dataset.drop_vars("esa_step")
267
+
244
268
  return dataset
245
269
 
246
270
  def define_support_variables(self, dataset: xr.Dataset) -> xr.Dataset:
@@ -269,45 +293,88 @@ class CoDICEL1aPipeline:
269
293
  "st_bias_gain_mode",
270
294
  ]
271
295
 
296
+ hi_energy_table_variables = [
297
+ "energy_h",
298
+ "energy_he3",
299
+ "energy_he4",
300
+ "energy_c",
301
+ "energy_o",
302
+ "energy_ne_mg_si",
303
+ "energy_fe",
304
+ "energy_uh",
305
+ "energy_junk",
306
+ "energy_he3he4",
307
+ "energy_cno",
308
+ ]
309
+
272
310
  for variable_name in self.config["support_variables"]:
273
- # These variables require reading in external tables
274
- if variable_name == "energy_table":
275
- variable_data = self.get_energy_table()
276
- dims = ["esa_step"]
277
- attrs = self.cdf_attrs.get_variable_attributes("energy_table")
278
-
279
- elif variable_name == "acquisition_time_per_step":
280
- variable_data = self.get_acquisition_times()
281
- dims = ["esa_step"]
282
- attrs = self.cdf_attrs.get_variable_attributes(
283
- "acquisition_time_per_step"
311
+ # CoDICE-Hi energy tables are treated differently because values
312
+ # are binned and we need to record the energies _and_ their deltas
313
+ if variable_name in hi_energy_table_variables:
314
+ centers, deltas = self.get_hi_energy_table_data(
315
+ variable_name.split("energy_")[-1]
284
316
  )
285
317
 
286
- elif variable_name in packet_data_variables:
287
- variable_data = self.dataset[variable_name].data
288
- dims = ["epoch"]
289
- attrs = self.cdf_attrs.get_variable_attributes(variable_name)
290
-
291
- # Data quality is named differently in packet data and needs to be
292
- # treated slightly differently
293
- elif variable_name == "data_quality":
294
- variable_data = self.dataset.suspect.data
295
- dims = ["epoch"]
296
- attrs = self.cdf_attrs.get_variable_attributes("data_quality")
297
-
298
- # Spin period requires the application of a conversion factor
299
- # See Table B.5 in the algorithm document
300
- elif variable_name == "spin_period":
301
- variable_data = self.dataset.spin_period.data * 0.00032
302
- dims = ["epoch"]
303
- attrs = self.cdf_attrs.get_variable_attributes("spin_period")
304
-
305
- # Add variable to the dataset
306
- dataset[variable_name] = xr.DataArray(
307
- variable_data,
308
- dims=dims,
309
- attrs=attrs,
310
- )
318
+ # Add bin centers and deltas to the dataset
319
+ dataset[variable_name] = xr.DataArray(
320
+ centers,
321
+ dims=[variable_name],
322
+ attrs=self.cdf_attrs.get_variable_attributes(
323
+ f"{self.config['dataset_name'].split('_')[-1]}-{variable_name}"
324
+ ),
325
+ )
326
+ dataset[f"{variable_name}_delta"] = xr.DataArray(
327
+ deltas,
328
+ dims=[f"{variable_name}_delta"],
329
+ attrs=self.cdf_attrs.get_variable_attributes(
330
+ f"{self.config['dataset_name'].split('_')[-1]}-{variable_name}_delta"
331
+ ),
332
+ )
333
+
334
+ # Otherwise, support variable data can be gathered from nominal
335
+ # lookup tables or packet data
336
+ else:
337
+ # These variables require reading in external tables
338
+ if variable_name == "energy_table":
339
+ variable_data = self.get_energy_table()
340
+ dims = ["esa_step"]
341
+ attrs = self.cdf_attrs.get_variable_attributes("energy_table")
342
+
343
+ elif variable_name == "acquisition_time_per_step":
344
+ variable_data = self.get_acquisition_times()
345
+ dims = ["esa_step"]
346
+ attrs = self.cdf_attrs.get_variable_attributes(
347
+ "acquisition_time_per_step"
348
+ )
349
+
350
+ # These variables can be gathered straight from the packet data
351
+ elif variable_name in packet_data_variables:
352
+ variable_data = self.dataset[variable_name].data
353
+ dims = ["epoch"]
354
+ attrs = self.cdf_attrs.get_variable_attributes(variable_name)
355
+
356
+ # Data quality is named differently in packet data and needs to be
357
+ # treated slightly differently
358
+ elif variable_name == "data_quality":
359
+ variable_data = self.dataset.suspect.data
360
+ dims = ["epoch"]
361
+ attrs = self.cdf_attrs.get_variable_attributes("data_quality")
362
+
363
+ # Spin period requires the application of a conversion factor
364
+ # See Table B.5 in the algorithm document
365
+ elif variable_name == "spin_period":
366
+ variable_data = (
367
+ self.dataset.spin_period.data * constants.SPIN_PERIOD_CONVERSION
368
+ ).astype(np.float32)
369
+ dims = ["epoch"]
370
+ attrs = self.cdf_attrs.get_variable_attributes("spin_period")
371
+
372
+ # Add variable to the dataset
373
+ dataset[variable_name] = xr.DataArray(
374
+ variable_data,
375
+ dims=dims,
376
+ attrs=attrs,
377
+ )
311
378
 
312
379
  return dataset
313
380
 
@@ -315,12 +382,11 @@ class CoDICEL1aPipeline:
315
382
  """
316
383
  Retrieve the acquisition times via the Lo stepping table.
317
384
 
318
- Get the acquisition times from the data file based on the values of
385
+ Get the acquisition times from the lookup table based on the values of
319
386
  ``plan_id`` and ``plan_step``
320
387
 
321
388
  The Lo stepping table defines how many voltage steps and which steps are
322
389
  used during each spacecraft spin. A full cycle takes 16 spins. The table
323
- provides the timing for a given energy step, and most importantly
324
390
  provides the "acquisition time", which is the acquisition time, in
325
391
  milliseconds, for the energy step.
326
392
 
@@ -329,37 +395,15 @@ class CoDICEL1aPipeline:
329
395
  acquisition_times : list[float]
330
396
  The list of acquisition times from the Lo stepping table.
331
397
  """
332
- # Read in the Lo stepping data table
333
- lo_stepping_data_file = Path(
334
- f"{imap_module_directory}/codice/data/lo_stepping_values.csv"
335
- )
336
- lo_stepping_data = pd.read_csv(lo_stepping_data_file)
337
-
338
398
  # Determine which Lo stepping table is needed
339
399
  lo_stepping_table_id = constants.LO_STEPPING_TABLE_ID_LOOKUP[
340
400
  (self.plan_id, self.plan_step)
341
401
  ]
342
402
 
343
- # Get the appropriate values
344
- lo_stepping_values = lo_stepping_data[
345
- lo_stepping_data["table_num"] == lo_stepping_table_id
403
+ acquisition_times: list[float] = constants.ACQUISITION_TIMES[
404
+ lo_stepping_table_id
346
405
  ]
347
406
 
348
- # Create a list for the acquisition times
349
- acquisition_times = []
350
-
351
- # Only need the energy columns from the table
352
- energy_steps = lo_stepping_values[
353
- ["e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8"]
354
- ].astype(str) # convert to string to avoid confusion with table index value
355
-
356
- # For each energy step (0-127), scan the energy columns and find the row
357
- # number, which corresponds to a specific acquisition time, then append
358
- # it to the list
359
- for step_number in range(128):
360
- row_number = np.argmax(energy_steps == str(step_number), axis=1).argmax()
361
- acquisition_times.append(lo_stepping_values.acq_time[row_number])
362
-
363
407
  return acquisition_times
364
408
 
365
409
  def get_energy_table(self) -> NDArray[float]:
@@ -400,32 +444,95 @@ class CoDICEL1aPipeline:
400
444
 
401
445
  return energy_table
402
446
 
447
+ def get_hi_energy_table_data(
448
+ self, species: str
449
+ ) -> tuple[NDArray[float], NDArray[float]]:
450
+ """
451
+ Retrieve energy table data for CoDICE-Hi products.
452
+
453
+ This includes the centers and deltas of the energy bins for a given
454
+ species. These data eventually get included in the CoDICE-Hi CDF data
455
+ products.
456
+
457
+ Parameters
458
+ ----------
459
+ species : str
460
+ The species of interest, which determines which lookup table to
461
+ use (e.g. ``h``).
462
+
463
+ Returns
464
+ -------
465
+ centers : NDArray[float]
466
+ An array whose values represent the centers of the energy bins.
467
+ deltas : NDArray[float]
468
+ An array whose values represent the deltas of the energy bins.
469
+ """
470
+ data_product = self.config["dataset_name"].split("-")[-1].upper()
471
+ energy_table = getattr(constants, f"{data_product}_ENERGY_TABLE")[species]
472
+
473
+ # Find the centers and deltas of the energy bins
474
+ centers = np.array(
475
+ [
476
+ (energy_table[i] + energy_table[i + 1]) / 2
477
+ for i in range(len(energy_table) - 1)
478
+ ]
479
+ )
480
+ deltas = energy_table[1:] - centers
481
+
482
+ return centers, deltas
483
+
403
484
  def reshape_data(self) -> None:
404
485
  """
405
486
  Reshape the data arrays based on the data product being made.
406
487
 
407
488
  These data need to be divided up by species or priorities (or
408
489
  what I am calling "counters" as a general term), and re-arranged into
409
- 3D arrays representing dimensions such as spin sectors, positions, and
410
- energies (depending on the data product).
490
+ 4D arrays representing dimensions such as time, spin sectors, positions,
491
+ and energies (depending on the data product).
492
+
493
+ However, the existence and order of these dimensions can vary depending
494
+ on the specific data product, so we define this in the "input_dims"
495
+ and "output_dims" values configuration dictionary; the "input_dims"
496
+ defines how the dimensions are written into the packet data, while
497
+ "output_dims" defines how the dimensions should be written to the final
498
+ CDF product.
411
499
  """
412
500
  # This will contain the reshaped data for all counters
413
501
  self.data = []
414
502
 
415
- # Typically, data are a 4D arrays with a shape representing some
416
- # combination of <num_counters>, <num_positions>, <num_spin_sectors>,
417
- # and <num_energy_steps>. However, the existence and order of these
418
- # dimensions can vary depending on the specific data product, so we
419
- # define this in the "dims" value configuration dictionary. The number
420
- # of counters is the first dimension/axis.
421
- reshape_dims = (self.config["num_counters"], *self.config["dims"].values())
503
+ # First reshape the data based on how it is written to the data array of
504
+ # the packet data. The number of counters is the first dimension / axis,
505
+ # with the exception of lo-counters-aggregated which is treated slightly
506
+ # differently
507
+ if self.config["dataset_name"] != "imap_codice_l1a_lo-counters-aggregated":
508
+ reshape_dims = (
509
+ self.config["num_counters"],
510
+ *self.config["input_dims"].values(),
511
+ )
512
+ else:
513
+ reshape_dims = (
514
+ *self.config["input_dims"].values(),
515
+ self.config["num_counters"],
516
+ )
517
+
518
+ # Then, transpose the data based on how the dimensions should be written
519
+ # to the CDF file. Since this is specific to each data product, we need
520
+ # to determine this dynamically based on the "output_dims" config.
521
+ # Again, lo-counters-aggregated is treated slightly differently
522
+ input_keys = ["num_counters", *self.config["input_dims"].keys()]
523
+ output_keys = ["num_counters", *self.config["output_dims"].keys()]
524
+ if self.config["dataset_name"] != "imap_codice_l1a_lo-counters-aggregated":
525
+ transpose_axes = [input_keys.index(dim) for dim in output_keys]
526
+ else:
527
+ transpose_axes = [1, 2, 0] # [esa_step, spin_sector_pairs, num_counters]
422
528
 
423
- # For each packet/epoch, reshape the data along these dimensions
424
529
  for packet_data in self.raw_data:
425
530
  reshaped_packet_data = np.array(packet_data, dtype=np.uint32).reshape(
426
531
  reshape_dims
427
532
  )
428
- self.data.append(reshaped_packet_data)
533
+ reshaped_cdf_data = np.transpose(reshaped_packet_data, axes=transpose_axes)
534
+
535
+ self.data.append(reshaped_cdf_data)
429
536
 
430
537
  # No longer need to keep the raw data around
431
538
  del self.raw_data
@@ -547,7 +654,23 @@ def create_hskp_dataset(
547
654
  attrs=cdf_attrs.get_global_attributes("imap_codice_l1a_hskp"),
548
655
  )
549
656
 
657
+ # These variables don't need to carry over from L0 to L1a
658
+ exclude_variables = [
659
+ "spare_1",
660
+ "spare_2",
661
+ "spare_3",
662
+ "spare_4",
663
+ "spare_5",
664
+ "spare_6",
665
+ "spare_62",
666
+ "spare_68",
667
+ "chksum",
668
+ ]
669
+
550
670
  for variable in packet:
671
+ if variable in exclude_variables:
672
+ continue
673
+
551
674
  attrs = cdf_attrs.get_variable_attributes(variable)
552
675
 
553
676
  dataset[variable] = xr.DataArray(
@@ -677,9 +800,8 @@ def process_codice_l1a(file_path: Path, data_version: str) -> list[xr.Dataset]:
677
800
 
678
801
  logger.info(f"\nFinal data product:\n{processed_dataset}\n")
679
802
 
680
- # TODO: Still need to implement I-ALiRT and hi-priorities data products
803
+ # TODO: Still need to implement I-ALiRT data products
681
804
  elif apid in [
682
- CODICEAPID.COD_HI_INST_COUNTS_PRIORITIES,
683
805
  CODICEAPID.COD_HI_IAL,
684
806
  CODICEAPID.COD_LO_IAL,
685
807
  ]: