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
@@ -0,0 +1,155 @@
1
+ """Classes for Level 0 MAG I-ALiRT data."""
2
+
3
+ # Science samples are split across 4 sequential packets so
4
+ # several packets need to be processed before a single science
5
+ # sample can be processed. The packets are as follows:
6
+
7
+ from __future__ import annotations
8
+
9
+
10
+ class Packet0:
11
+ """
12
+ Class for packet 0.
13
+
14
+ Parameters
15
+ ----------
16
+ status : int
17
+ 24-bit integer value.
18
+
19
+ Notes
20
+ -----
21
+ Bits 23-22 → Packet Number (2-bit value)
22
+ Bits 21-17 → hk1v5_warn, hk1v5_danger, hk1v5c_warn, hk1v5c_danger,
23
+ hk1v8_warn (5-bit value)
24
+ Bits 16-13 → hk1v8_danger, hk1v8c_warn, hk1v8c_danger (4-bit value)
25
+ Bit 5 → fob_saturated (1-bit value)
26
+ Bit 4 → fib_saturated (1-bit value)
27
+ Bits 3-0 → mode (4-bit value)
28
+ Bits 12-6 → icu_temp (7-bit value)
29
+ """
30
+
31
+ def __init__(self, status: int) -> None:
32
+ # +1.5v voltage warning flag raised
33
+ self.hk1v5_warn = (status >> 20) & 0x01
34
+ # +1.5v voltage danger flag raised
35
+ self.hk1v5_danger = (status >> 19) & 0x01
36
+ # +1.5v current warning flag raised
37
+ self.hk1v5c_warn = (status >> 18) & 0x01
38
+ # +1.5v current danger flag raised
39
+ self.hk1v5c_danger = (status >> 17) & 0x01
40
+ # +1.8v voltage warning flag raised
41
+ self.hk1v8_warn = (status >> 16) & 0x01
42
+ # +1.8v voltage danger flag raised
43
+ self.hk1v8_danger = (status >> 15) & 0x01
44
+ # +1.8v current warning flag raised
45
+ self.hk1v8c_warn = (status >> 14) & 0x01
46
+ # +1.8v current danger flag raised
47
+ self.hk1v8c_danger = (status >> 13) & 0x01
48
+ # Outboard (MAGo) sensor is saturated (danger)
49
+ self.fob_saturated = (status >> 5) & 0x01
50
+ # Inboard (MAGi) sensor is saturated (danger)
51
+ self.fib_saturated = (status >> 4) & 0x01
52
+ # Instrument mode
53
+ self.mode = (status >> 0) & 0x0F
54
+ # instrument control unit temperature (top 7/16 bits, eng. units)
55
+ self.icu_temp = ((status >> 6) & 0x7F) << 5
56
+
57
+
58
+ class Packet1:
59
+ """
60
+ Class for packet 1.
61
+
62
+ Parameters
63
+ ----------
64
+ status : int
65
+ 24-bit integer value.
66
+
67
+ Notes
68
+ -----
69
+ Bit 5 → pri_isvalid (1-bit value)
70
+ Bits 4-1 → hk2v5_warn, hk2v5_danger, hk2v5c_warn, hk2v5c_danger (4-bit value)
71
+ Bits 16-9 → hk3v3 (8-bit value)
72
+ Bits 8-0 → hk3v3_current (9-bit value)
73
+ """
74
+
75
+ def __init__(self, status: int) -> None:
76
+ # +2.5v voltage warning flag raised
77
+ self.hk2v5_warn = (status >> 20) & 0x01
78
+ # +2.5v voltage danger flag raised
79
+ self.hk2v5_danger = (status >> 19) & 0x01
80
+ # +2.5v current warning flag raised
81
+ self.hk2v5c_warn = (status >> 18) & 0x01
82
+ # +2.5v current warning flag raised
83
+ self.hk2v5c_danger = (status >> 17) & 0x01
84
+ # +3.3v voltage (top 8/16 bits, in eng. units)
85
+ self.hk3v3 = ((status >> 9) & 0xFF) << 4
86
+ # +3.3v current (top 9/16 bits, in eng. units)
87
+ self.hk3v3_current = ((status >> 0) & 0x1FF) << 3
88
+ # Primary sensor (typically MAGo) science data is valid
89
+ self.pri_isvalid = (status >> 21) & 0x01
90
+
91
+
92
+ class Packet2:
93
+ """
94
+ Class for packet 2.
95
+
96
+ Parameters
97
+ ----------
98
+ status : int
99
+ 24-bit integer value.
100
+
101
+ Notes
102
+ -----
103
+ Bits 23-22 → Packet Number (2-bit value)
104
+ Bits 21-17 → Various warning/danger flags (5-bit value)
105
+ Bits 16-9 → hkn8v5 (8-bit value)
106
+ Bits 8-0 → hkn8v5_current (9-bit value)
107
+ """
108
+
109
+ def __init__(self, status: int) -> None:
110
+ # +8.5v voltage warning flag raised
111
+ self.hkp8v5_warn = (status >> 20) & 0x01
112
+ # +8.5v voltage danger flag raised
113
+ self.hkp8v5_danger = (status >> 19) & 0x01
114
+ # +8.5v current warning flag raised
115
+ self.hkp8v5c_warn = (status >> 18) & 0x01
116
+ # +8.5v current danger flag raised
117
+ self.hkp8v5c_danger = (status >> 17) & 0x01
118
+ # -8.5v voltage (top 8/16 bits, in eng. units)
119
+ self.hkn8v5 = ((status >> 9) & 0xFF) << 4
120
+ # -8.5v current (top 9/16 bits, in eng. units)
121
+ self.hkn8v5_current = ((status >> 0) & 0x1FF) << 3
122
+
123
+
124
+ class Packet3:
125
+ """
126
+ Class for packet 3.
127
+
128
+ Parameters
129
+ ----------
130
+ status : int
131
+ 24-bit integer value.
132
+
133
+ Notes
134
+ -----
135
+ Bits 20-13 → fob_temp (8-bit value, shifted left by 4)
136
+ Bits 12-5 → fib_temp (8-bit value, shifted left by 4)
137
+ Bits 4-3 → fob_range (2-bit value)
138
+ Bits 2-1 → fib_range (2-bit value)
139
+ Bit 0 → multbit_errs (1-bit value)
140
+ Bit 5 → sec_isvalid (1-bit value, overlapping with fib_temp extraction)
141
+ """
142
+
143
+ def __init__(self, status: int) -> None:
144
+ # Temp of outboard (MAGo) sensor (top 8/16 bits, in eng. units)
145
+ self.fob_temp = ((status >> 13) & 0xFF) << 4
146
+ # Temp of outboard (MAGo) sensor (top 8/16 bits, in eng. units)
147
+ self.fib_temp = ((status >> 5) & 0xFF) << 4
148
+ # Outboard (MAGo) sensor range [0-3]
149
+ self.fob_range = (status >> 3) & 0x03
150
+ # Inboard (MAGi) sensor range [0-3]
151
+ self.fib_range = (status >> 1) & 0x03
152
+ # Multiple (SEU) memory error bits danger flag raised
153
+ self.multbit_errs = (status >> 0) & 0x01
154
+ # Secondary sensor (typically MAGi) science data is valid
155
+ self.sec_isvalid = (status >> 21) & 0x01
@@ -0,0 +1,246 @@
1
+ """Functions to support I-ALiRT MAG packet parsing."""
2
+
3
+ import logging
4
+
5
+ import numpy as np
6
+ import xarray as xr
7
+
8
+ from imap_processing.ialirt.l0.mag_l0_ialirt_data import (
9
+ Packet0,
10
+ Packet1,
11
+ Packet2,
12
+ Packet3,
13
+ )
14
+ from imap_processing.ialirt.utils.grouping import find_groups
15
+ from imap_processing.ialirt.utils.time import calculate_time
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ def get_pkt_counter(status_values: xr.DataArray) -> xr.DataArray:
21
+ """
22
+ Get the packet counters.
23
+
24
+ Parameters
25
+ ----------
26
+ status_values : xr.DataArray
27
+ Status data.
28
+
29
+ Returns
30
+ -------
31
+ pkt_counters : xr.DataArray
32
+ Packet counters.
33
+ """
34
+ # mag_status is a 24 bit unsigned field
35
+ # The leading 2 bits of STATUS are a 2 bit 0-3 counter
36
+ pkt_counter = (status_values >> 22) & 0x03
37
+
38
+ return pkt_counter
39
+
40
+
41
+ def get_status_data(status_values: xr.DataArray, pkt_counters: xr.DataArray) -> dict:
42
+ """
43
+ Get the status data.
44
+
45
+ Parameters
46
+ ----------
47
+ status_values : xr.DataArray
48
+ Status data.
49
+ pkt_counters : xr.DataArray
50
+ Packet counters.
51
+
52
+ Returns
53
+ -------
54
+ combined_packets : dict
55
+ Decoded packets.
56
+ """
57
+ decoders = {
58
+ 0: Packet0,
59
+ 1: Packet1,
60
+ 2: Packet2,
61
+ 3: Packet3,
62
+ }
63
+
64
+ combined_packets = {}
65
+
66
+ for pkt_num, decoder in decoders.items():
67
+ status_subset = status_values[pkt_counters == pkt_num]
68
+ decoded_packet = decoder(int(status_subset))
69
+ combined_packets.update(vars(decoded_packet))
70
+
71
+ return combined_packets
72
+
73
+
74
+ def get_bytes(val: int) -> list[int]:
75
+ """
76
+ Extract three bytes from a 24-bit integer.
77
+
78
+ Parameters
79
+ ----------
80
+ val : int
81
+ 24-bit integer value.
82
+
83
+ Returns
84
+ -------
85
+ list[int]
86
+ List of three extracted bytes.
87
+ """
88
+ return [
89
+ (val >> 16) & 0xFF, # Most significant byte (Byte2)
90
+ (val >> 8) & 0xFF, # Middle byte (Byte1)
91
+ (val >> 0) & 0xFF, # Least significant byte (Byte0)
92
+ ]
93
+
94
+
95
+ def extract_magnetic_vectors(science_values: xr.DataArray) -> dict:
96
+ """
97
+ Extract the magnetic vectors.
98
+
99
+ Parameters
100
+ ----------
101
+ science_values : xr.DataArray
102
+ Science data.
103
+
104
+ Returns
105
+ -------
106
+ vectors : dict
107
+ Magnetic vectors.
108
+ """
109
+ # Primary sensor:
110
+ pri_x = (int(science_values[0]) >> 8) & 0xFFFF
111
+ pri_y = ((int(science_values[0]) << 8) & 0xFF00) | (
112
+ (int(science_values[1]) >> 16) & 0xFF
113
+ )
114
+ pri_z = int(science_values[1]) & 0xFFFF
115
+
116
+ # Secondary sensor:
117
+ sec_x = (int(science_values[2]) >> 8) & 0xFFFF
118
+ sec_y = ((int(science_values[2]) << 8) & 0xFF00) | (
119
+ (int(science_values[3]) >> 16) & 0xFF
120
+ )
121
+ sec_z = int(science_values[3]) & 0xFFFF
122
+
123
+ vectors = {
124
+ "pri_x": pri_x,
125
+ "pri_y": pri_y,
126
+ "pri_z": pri_z,
127
+ "sec_x": sec_x,
128
+ "sec_y": sec_y,
129
+ "sec_z": sec_z,
130
+ }
131
+
132
+ return vectors
133
+
134
+
135
+ def get_time(grouped_data: xr.Dataset, group: int, pkt_counter: xr.DataArray) -> dict:
136
+ """
137
+ Get the time for the grouped data.
138
+
139
+ Parameters
140
+ ----------
141
+ grouped_data : xr.Dataset
142
+ Grouped data.
143
+ group : int
144
+ Group number.
145
+ pkt_counter : xr.DataArray
146
+ Packet counter.
147
+
148
+ Returns
149
+ -------
150
+ time_data : dict
151
+ Coarse and fine time for Primary and Secondary Sensors.
152
+ """
153
+ pri_coarsetm = grouped_data["mag_acq_tm_coarse"][
154
+ (grouped_data["group"] == group).values
155
+ ][pkt_counter == 0]
156
+
157
+ pri_fintm = grouped_data["mag_acq_tm_fine"][
158
+ (grouped_data["group"] == group).values
159
+ ][pkt_counter == 0]
160
+
161
+ sec_coarsetm = grouped_data["mag_acq_tm_coarse"][
162
+ (grouped_data["group"] == group).values
163
+ ][pkt_counter == 2]
164
+
165
+ sec_fintm = grouped_data["mag_acq_tm_fine"][
166
+ (grouped_data["group"] == group).values
167
+ ][pkt_counter == 2]
168
+
169
+ time_data = {
170
+ "pri_coarsetm": int(pri_coarsetm),
171
+ "pri_fintm": int(pri_fintm),
172
+ "sec_coarsetm": int(sec_coarsetm),
173
+ "sec_fintm": int(sec_fintm),
174
+ }
175
+
176
+ return time_data
177
+
178
+
179
+ def parse_packet(accumulated_data: xr.Dataset) -> list[dict]:
180
+ """
181
+ Parse the MAG packets.
182
+
183
+ Parameters
184
+ ----------
185
+ accumulated_data : xr.Dataset
186
+ Packets dataset accumulated over 1 min.
187
+
188
+ Returns
189
+ -------
190
+ mag_data : list[dict]
191
+ Dictionaries of the parsed data product.
192
+ """
193
+ logger.info(
194
+ f"Parsing MAG for time: {accumulated_data['mag_acq_tm_coarse'].min().values} - "
195
+ f"{accumulated_data['mag_acq_tm_coarse'].max().values}."
196
+ )
197
+
198
+ # Note that the fine time second is split into 65535.
199
+ time_seconds = calculate_time(
200
+ accumulated_data["mag_acq_tm_coarse"],
201
+ accumulated_data["mag_acq_tm_fine"],
202
+ 65535,
203
+ )
204
+
205
+ # Add required parameters.
206
+ accumulated_data["time_seconds"] = time_seconds
207
+ sorted_data = accumulated_data.sortby("time_seconds", ascending=True)
208
+ pkt_counter = get_pkt_counter(sorted_data["mag_status"])
209
+ sorted_data["pkt_counter"] = pkt_counter
210
+
211
+ grouped_data = find_groups(sorted_data, (0, 3), "pkt_counter", "time_seconds")
212
+
213
+ unique_groups = np.unique(grouped_data["group"])
214
+ mag_data = []
215
+
216
+ for group in unique_groups:
217
+ # Get status values for each group.
218
+ status_values = grouped_data["mag_status"][
219
+ (grouped_data["group"] == group).values
220
+ ]
221
+ pkt_counter = grouped_data["pkt_counter"][
222
+ (grouped_data["group"] == group).values
223
+ ]
224
+
225
+ if not np.array_equal(pkt_counter, np.arange(4)):
226
+ logger.warning(
227
+ f"Group {group} does not contain all values from 0 to "
228
+ f"3 without duplicates."
229
+ )
230
+ continue
231
+
232
+ # Get decoded status data.
233
+ status_data = get_status_data(status_values, pkt_counter)
234
+
235
+ # Get science values for each group.
236
+ science_values = grouped_data["mag_data"][
237
+ (grouped_data["group"] == group).values
238
+ ]
239
+ science_data = extract_magnetic_vectors(science_values)
240
+
241
+ # Get time values for each group.
242
+ time_data = get_time(grouped_data, group, pkt_counter)
243
+
244
+ mag_data.append({**status_data, **science_data, **time_data})
245
+
246
+ return mag_data
@@ -0,0 +1,252 @@
1
+ """Functions to support I-ALiRT SWE packet parsing."""
2
+
3
+ import logging
4
+
5
+ import numpy as np
6
+ import pandas as pd
7
+ import xarray as xr
8
+ from numpy.typing import NDArray
9
+
10
+ from imap_processing.ialirt.utils.grouping import find_groups
11
+ from imap_processing.swe.l1a.swe_science import decompressed_counts
12
+ from imap_processing.swe.l1b.swe_l1b_science import (
13
+ deadtime_correction,
14
+ read_in_flight_cal_data,
15
+ )
16
+ from imap_processing.swe.utils.swe_constants import (
17
+ ESA_VOLTAGE_ROW_INDEX_DICT,
18
+ GEOMETRIC_FACTORS,
19
+ N_CEMS,
20
+ )
21
+ from imap_processing.swe.utils.swe_utils import combine_acquisition_time
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ def decompress_counts(raw_counts: NDArray) -> NDArray:
27
+ """
28
+ Perform decompression of raw counts using a predefined decompression table.
29
+
30
+ Parameters
31
+ ----------
32
+ raw_counts : np.ndarray
33
+ Array of raw compressed counts with shape (n_energy, n_cem, n_phi).
34
+
35
+ Returns
36
+ -------
37
+ counts : np.ndarray
38
+ Array of decompressed counts with the same shape as raw_counts.
39
+ """
40
+ decompression_table = np.array([decompressed_counts(i) for i in range(256)])
41
+
42
+ # Decompress using the precomputed table
43
+ counts = decompression_table[raw_counts]
44
+
45
+ return counts
46
+
47
+
48
+ def phi_to_bin(phi_values: NDArray) -> NDArray:
49
+ """
50
+ Convert phi values to corresponding bin indices.
51
+
52
+ Parameters
53
+ ----------
54
+ phi_values : NDArray
55
+ Array of phi values.
56
+
57
+ Returns
58
+ -------
59
+ bin_indices : NDArray
60
+ Array of bin indices.
61
+ """
62
+ # Ensure it wraps correctly within 0-29 bins
63
+ return ((phi_values - 12) // 12) % 30
64
+
65
+
66
+ def prepare_raw_counts(grouped: xr.Dataset, cem_number: int = N_CEMS) -> NDArray:
67
+ """
68
+ Reformat raw counts into a 3D array binned by phi.
69
+
70
+ Parameters
71
+ ----------
72
+ grouped : xr.Dataset
73
+ Dataset containing grouped i-ALiRT packet data for 30 seconds.
74
+ cem_number : int
75
+ Number of CEMs (default 7).
76
+
77
+ Returns
78
+ -------
79
+ raw_counts : NDArray
80
+ Raw counts with shape (8, 7, 30).
81
+
82
+ Notes
83
+ -----
84
+ Array of raw counts with shape (n_energy, n_cem, n_phi), where:
85
+ - 8 corresponds to the 8 energy steps.
86
+ - 7 corresponds to the 7 CEM detectors.
87
+ - 30 corresponds to the 30 phi bins.
88
+ """
89
+ raw_counts = np.zeros((8, cem_number, 30), dtype=np.uint8)
90
+
91
+ # Compute phi values and their corresponding bins
92
+ # Example: energy steps 0-1 have the same phi;
93
+ # energy steps 2-3 have the same phi, etc.
94
+ # A depiction of this is shown in Figure 7 of the SWE Algorithm Document.
95
+ phi_values = np.array(
96
+ [
97
+ (12 + 24 * grouped["swe_seq"].values) % 360, # Energy steps 0 and 1
98
+ (24 + 24 * grouped["swe_seq"].values) % 360, # Energy steps 2 and 3
99
+ ]
100
+ )
101
+ phi_bins = phi_to_bin(phi_values).astype(int) # Get phi bin indices
102
+
103
+ # Energy bin lookup table (indexed by quarter cycle)
104
+ energy_bins = np.array(
105
+ [
106
+ [1, 5, 7, 3], # 0-14 (first quarter cycle)
107
+ [2, 6, 4, 0], # 15-29 (second quarter cycle)
108
+ [3, 7, 5, 1], # 30-44 (third quarter cycle)
109
+ [0, 4, 6, 2], # 45-59 (fourth quarter cycle)
110
+ ]
111
+ )
112
+
113
+ # The first 15 seconds is the first quarter cycle, etc.
114
+ quarter_cycles = np.floor(grouped["swe_seq"] / 15).astype(int)
115
+ e_bins = energy_bins[quarter_cycles]
116
+
117
+ # Populate raw_counts
118
+ for cem in range(1, cem_number + 1): # 7 CEMs
119
+ e1 = grouped[f"swe_cem{cem}_e1"].values
120
+ e2 = grouped[f"swe_cem{cem}_e2"].values
121
+ e3 = grouped[f"swe_cem{cem}_e3"].values
122
+ e4 = grouped[f"swe_cem{cem}_e4"].values
123
+
124
+ # Phi bins 0, 2...(12, 36, ...)
125
+ raw_counts[e_bins[:, 0], cem - 1, phi_bins[0]] = e1
126
+ raw_counts[e_bins[:, 1], cem - 1, phi_bins[0]] = e2
127
+ # Phi bins 1, 3...(24, 48, ...)
128
+ raw_counts[e_bins[:, 2], cem - 1, phi_bins[1]] = e3
129
+ raw_counts[e_bins[:, 3], cem - 1, phi_bins[1]] = e4
130
+
131
+ return raw_counts
132
+
133
+
134
+ def get_ialirt_energies() -> list:
135
+ """
136
+ Get the ESA voltages for I-ALiRT.
137
+
138
+ Returns
139
+ -------
140
+ energy : list
141
+ List of ESA voltage for I-ALiRT.
142
+
143
+ Notes
144
+ -----
145
+ This is a subset of the ESA_VOLTAGE_ROW_INDEX_DICT.
146
+ """
147
+ energy = [k for k, v in ESA_VOLTAGE_ROW_INDEX_DICT.items() if 11 <= v <= 18]
148
+
149
+ return energy
150
+
151
+
152
+ def normalize_counts(counts: NDArray, latest_cal: pd.Series) -> NDArray:
153
+ """
154
+ Normalize the counts using the latest calibration factor.
155
+
156
+ Parameters
157
+ ----------
158
+ counts : np.ndarray
159
+ Array of counts.
160
+ latest_cal : pd.Series
161
+ Array of latest calibration factors.
162
+
163
+ Returns
164
+ -------
165
+ norm_counts : np.ndarray
166
+ Array of normalized counts.
167
+ """
168
+ latest_cal = latest_cal.to_numpy()
169
+
170
+ # Norm counts where counts are non-negative
171
+ # TODO: confirm fv is counts with Ruth
172
+ norm_counts = counts * (latest_cal / GEOMETRIC_FACTORS)[:, np.newaxis]
173
+ norm_counts[norm_counts < 0] = 0
174
+
175
+ return norm_counts
176
+
177
+
178
+ def process_swe(accumulated_data: xr.Dataset) -> list[dict]:
179
+ """
180
+ Create L1 data dictionary..
181
+
182
+ Parameters
183
+ ----------
184
+ accumulated_data : xr.Dataset
185
+ Packets dataset accumulated over 1 min.
186
+
187
+ Returns
188
+ -------
189
+ swe_data : list[dict]
190
+ Dictionaries of the parsed data product.
191
+ """
192
+ logger.info("Processing SWE.")
193
+
194
+ # Calculate time in seconds
195
+ time_seconds = combine_acquisition_time(
196
+ accumulated_data["swe_acq_sec"], accumulated_data["swe_acq_sub"]
197
+ )
198
+ accumulated_data["time_seconds"] = time_seconds
199
+
200
+ # Get total full cycle data available for processing.
201
+ # There are 60 packets in a set so (0, 59) is the range.
202
+ grouped_data = find_groups(accumulated_data, (0, 59), "swe_seq", "time_seconds")
203
+ unique_groups = np.unique(grouped_data["group"])
204
+ swe_data: list[dict] = []
205
+
206
+ for group in unique_groups:
207
+ # Sequence values for the group should be 0-59 with no duplicates.
208
+ seq_values = grouped_data["swe_seq"][(grouped_data["group"] == group).values]
209
+
210
+ # Ensure no duplicates and all values from 0 to 59 are present
211
+ if not np.array_equal(seq_values, np.arange(60)):
212
+ logger.warning(
213
+ f"Group {group} does not contain all values from 0 to "
214
+ f"59 without duplicates."
215
+ )
216
+ continue
217
+ # Prepare raw counts array just for this group
218
+ # (8 energy steps, 7 CEMs, 30 phi bins)
219
+ group_mask = grouped_data["group"] == group
220
+ grouped = grouped_data.sel(epoch=group_mask)
221
+
222
+ # Split into Q1 & Q2 (swe_seq 0-29) and Q3 & Q4 (swe_seq 30-59)
223
+ first_half = grouped.where(grouped["swe_seq"] < 30, drop=True)
224
+ second_half = grouped.where(grouped["swe_seq"] >= 30, drop=True)
225
+
226
+ # Prepare raw counts separately for both halves
227
+ raw_counts_first_half = prepare_raw_counts(first_half)
228
+ raw_counts_second_half = prepare_raw_counts(second_half)
229
+
230
+ # Decompress the raw counts
231
+ counts_first_half = decompress_counts(raw_counts_first_half)
232
+ counts_second_half = decompress_counts(raw_counts_second_half)
233
+
234
+ # Apply the deadtime correction
235
+ # acq_duration = 80 milliseconds
236
+ corrected_first_half = deadtime_correction(counts_first_half, 80 * 10**3)
237
+ corrected_second_half = deadtime_correction(counts_second_half, 80 * 10**3)
238
+
239
+ # Grab the latest calibration factor
240
+ in_flight_cal_df = read_in_flight_cal_data()
241
+ latest_cal = in_flight_cal_df.sort_values("met_time").iloc[-1][1::]
242
+
243
+ normalized_first_half = normalize_counts(corrected_first_half, latest_cal)
244
+ normalized_second_half = normalize_counts(corrected_second_half, latest_cal)
245
+
246
+ # Sum over the 7 detectors
247
+ summed_first_half = np.sum(normalized_first_half, axis=1) # noqa: F841
248
+ summed_second_half = np.sum(normalized_second_half, axis=1) # noqa: F841
249
+
250
+ # TODO: will continue here
251
+
252
+ return swe_data
@@ -428,8 +428,11 @@
428
428
  </xtce:Parameter>
429
429
  <!-- SWE -->
430
430
  <!-- MAG -->
431
- <xtce:Parameter name="MAG_ACQ" parameterTypeRef="uint48">
432
- <xtce:LongDescription>MAG Acquisition Time</xtce:LongDescription>
431
+ <xtce:Parameter name="MAG_ACQ_TM_COARSE" parameterTypeRef="uint32">
432
+ <xtce:LongDescription>MAG Coarse Acquisition Time</xtce:LongDescription>
433
+ </xtce:Parameter>
434
+ <xtce:Parameter name="MAG_ACQ_TM_FINE" parameterTypeRef="uint16">
435
+ <xtce:LongDescription>MAG Fine Acquisition Time</xtce:LongDescription>
433
436
  </xtce:Parameter>
434
437
  <xtce:Parameter name="MAG_STATUS" parameterTypeRef="uint24">
435
438
  <xtce:LongDescription>MAG Status</xtce:LongDescription>
@@ -674,7 +677,8 @@
674
677
  <xtce:ParameterRefEntry parameterRef="SC_SPARE_3"/>
675
678
  <!-- Spacecraft -->
676
679
  <!-- MAG -->
677
- <xtce:ParameterRefEntry parameterRef="MAG_ACQ"/>
680
+ <xtce:ParameterRefEntry parameterRef="MAG_ACQ_TM_COARSE"/>
681
+ <xtce:ParameterRefEntry parameterRef="MAG_ACQ_TM_FINE"/>
678
682
  <xtce:ParameterRefEntry parameterRef="MAG_STATUS"/>
679
683
  <xtce:ParameterRefEntry parameterRef="MAG_DATA"/>
680
684
  <!-- MAG -->