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
@@ -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,374 @@
1
+ """Functions to support I-ALiRT MAG packet parsing."""
2
+
3
+ import logging
4
+ from typing import Union
5
+
6
+ import numpy as np
7
+ import xarray as xr
8
+
9
+ from imap_processing.ialirt.l0.mag_l0_ialirt_data import (
10
+ Packet0,
11
+ Packet1,
12
+ Packet2,
13
+ Packet3,
14
+ )
15
+ from imap_processing.ialirt.utils.grouping import find_groups
16
+ from imap_processing.ialirt.utils.time import calculate_time
17
+ from imap_processing.mag.l1a.mag_l1a_data import TimeTuple
18
+ from imap_processing.mag.l1b.mag_l1b import (
19
+ calibrate_vector,
20
+ retrieve_matrix_from_l1b_calibration,
21
+ shift_time,
22
+ )
23
+ from imap_processing.spice.time import met_to_ttj2000ns
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ def get_pkt_counter(status_values: xr.DataArray) -> xr.DataArray:
29
+ """
30
+ Get the packet counters.
31
+
32
+ Parameters
33
+ ----------
34
+ status_values : xr.DataArray
35
+ Status data.
36
+
37
+ Returns
38
+ -------
39
+ pkt_counters : xr.DataArray
40
+ Packet counters.
41
+ """
42
+ # mag_status is a 24 bit unsigned field
43
+ # The leading 2 bits of STATUS are a 2 bit 0-3 counter
44
+ pkt_counter = (status_values >> 22) & 0x03
45
+
46
+ return pkt_counter
47
+
48
+
49
+ def get_status_data(status_values: xr.DataArray, pkt_counters: xr.DataArray) -> dict:
50
+ """
51
+ Get the status data.
52
+
53
+ Parameters
54
+ ----------
55
+ status_values : xr.DataArray
56
+ Status data.
57
+ pkt_counters : xr.DataArray
58
+ Packet counters.
59
+
60
+ Returns
61
+ -------
62
+ combined_packets : dict
63
+ Decoded packets.
64
+ """
65
+ decoders = {
66
+ 0: Packet0,
67
+ 1: Packet1,
68
+ 2: Packet2,
69
+ 3: Packet3,
70
+ }
71
+
72
+ combined_packets = {}
73
+
74
+ for pkt_num, decoder in decoders.items():
75
+ status_subset = status_values[pkt_counters == pkt_num]
76
+ decoded_packet = decoder(int(status_subset))
77
+ combined_packets.update(vars(decoded_packet))
78
+
79
+ return combined_packets
80
+
81
+
82
+ def get_bytes(val: int) -> list[int]:
83
+ """
84
+ Extract three bytes from a 24-bit integer.
85
+
86
+ Parameters
87
+ ----------
88
+ val : int
89
+ 24-bit integer value.
90
+
91
+ Returns
92
+ -------
93
+ list[int]
94
+ List of three extracted bytes.
95
+ """
96
+ return [
97
+ (val >> 16) & 0xFF, # Most significant byte (Byte2)
98
+ (val >> 8) & 0xFF, # Middle byte (Byte1)
99
+ (val >> 0) & 0xFF, # Least significant byte (Byte0)
100
+ ]
101
+
102
+
103
+ def extract_magnetic_vectors(science_values: xr.DataArray) -> dict:
104
+ """
105
+ Extract the magnetic vectors.
106
+
107
+ Parameters
108
+ ----------
109
+ science_values : xr.DataArray
110
+ Science data.
111
+
112
+ Returns
113
+ -------
114
+ vectors : dict
115
+ Magnetic vectors.
116
+ """
117
+ # Primary sensor:
118
+ pri_x = (int(science_values[0]) >> 8) & 0xFFFF
119
+ pri_y = ((int(science_values[0]) << 8) & 0xFF00) | (
120
+ (int(science_values[1]) >> 16) & 0xFF
121
+ )
122
+ pri_z = int(science_values[1]) & 0xFFFF
123
+
124
+ # Secondary sensor:
125
+ sec_x = (int(science_values[2]) >> 8) & 0xFFFF
126
+ sec_y = ((int(science_values[2]) << 8) & 0xFF00) | (
127
+ (int(science_values[3]) >> 16) & 0xFF
128
+ )
129
+ sec_z = int(science_values[3]) & 0xFFFF
130
+
131
+ vectors = {
132
+ "pri_x": pri_x,
133
+ "pri_y": pri_y,
134
+ "pri_z": pri_z,
135
+ "sec_x": sec_x,
136
+ "sec_y": sec_y,
137
+ "sec_z": sec_z,
138
+ }
139
+
140
+ return vectors
141
+
142
+
143
+ def get_time(
144
+ grouped_data: xr.Dataset,
145
+ group: int,
146
+ pkt_counter: xr.DataArray,
147
+ time_shift_mago: xr.DataArray,
148
+ time_shift_magi: xr.DataArray,
149
+ ) -> dict:
150
+ """
151
+ Get the time for the grouped data.
152
+
153
+ Parameters
154
+ ----------
155
+ grouped_data : xr.Dataset
156
+ Grouped data.
157
+ group : int
158
+ Group number.
159
+ pkt_counter : xr.DataArray
160
+ Packet counter.
161
+ time_shift_mago : xr.DataArray
162
+ Time shift value mago.
163
+ time_shift_magi : xr.DataArray
164
+ Time shift value magi.
165
+
166
+ Returns
167
+ -------
168
+ time_data : dict
169
+ Coarse and fine time for Primary and Secondary Sensors.
170
+
171
+ Notes
172
+ -----
173
+ Packet id 0 is course and fine time for the primary sensor PRI.
174
+ Packet id 2 is the course time for the secondary sensor SEC.
175
+ """
176
+ # Get the coarse and fine time for the primary and secondary sensors.
177
+ pri_coarsetm = grouped_data["mag_acq_tm_coarse"][
178
+ (grouped_data["group"] == group).values
179
+ ][pkt_counter == 0]
180
+
181
+ pri_fintm = grouped_data["mag_acq_tm_fine"][
182
+ (grouped_data["group"] == group).values
183
+ ][pkt_counter == 0]
184
+
185
+ sec_coarsetm = grouped_data["mag_acq_tm_coarse"][
186
+ (grouped_data["group"] == group).values
187
+ ][pkt_counter == 2]
188
+
189
+ sec_fintm = grouped_data["mag_acq_tm_fine"][
190
+ (grouped_data["group"] == group).values
191
+ ][pkt_counter == 2]
192
+
193
+ time_data: dict[str, Union[int, float]] = {
194
+ "pri_coarsetm": int(pri_coarsetm.item()),
195
+ "pri_fintm": int(pri_fintm.item()),
196
+ "sec_coarsetm": int(sec_coarsetm.item()),
197
+ "sec_fintm": int(sec_fintm.item()),
198
+ }
199
+
200
+ primary_time = TimeTuple(int(pri_coarsetm.item()), int(pri_fintm.item()))
201
+ secondary_time = TimeTuple(int(sec_coarsetm.item()), int(sec_fintm.item()))
202
+ time_data_pri_met = primary_time.to_seconds()
203
+ time_data_primary_ttj2000ns = met_to_ttj2000ns(time_data_pri_met)
204
+ time_data["primary_epoch"] = shift_time(
205
+ time_data_primary_ttj2000ns, time_shift_mago
206
+ )
207
+ time_data_sec_met = secondary_time.to_seconds()
208
+ time_data_secondary_ttj2000ns = met_to_ttj2000ns(time_data_sec_met)
209
+ time_data["secondary_epoch"] = shift_time(
210
+ time_data_secondary_ttj2000ns, time_shift_magi
211
+ )
212
+
213
+ return time_data
214
+
215
+
216
+ def calculate_l1b(
217
+ grouped_data: xr.Dataset,
218
+ group: int,
219
+ pkt_counter: xr.DataArray,
220
+ science_data: dict,
221
+ status_data: dict,
222
+ calibration_dataset: xr.Dataset,
223
+ ) -> tuple[np.ndarray, np.ndarray, dict]:
224
+ """
225
+ Calculate equivalent of l1b data product.
226
+
227
+ Parameters
228
+ ----------
229
+ grouped_data : xr.Dataset
230
+ Grouped data.
231
+ group : int
232
+ Group number.
233
+ pkt_counter : xr.DataArray
234
+ Packet counter.
235
+ science_data : dict
236
+ Science data.
237
+ status_data : dict
238
+ Status data.
239
+ calibration_dataset : xr.Dataset
240
+ Calibration dataset.
241
+
242
+ Returns
243
+ -------
244
+ updated_vector_mago : numpy.ndarray
245
+ Calibrated mago vector.
246
+ updated_vector_magi : numpy.ndarray
247
+ Calibrated magi vector.
248
+ time_data : dict
249
+ Time data.
250
+ """
251
+ calibration_matrix_mago, time_shift_mago = retrieve_matrix_from_l1b_calibration(
252
+ calibration_dataset, is_mago=True
253
+ )
254
+ calibration_matrix_magi, time_shift_magi = retrieve_matrix_from_l1b_calibration(
255
+ calibration_dataset, is_mago=False
256
+ )
257
+
258
+ # Get time values for each group.
259
+ time_data = get_time(
260
+ grouped_data, group, pkt_counter, time_shift_mago, time_shift_magi
261
+ )
262
+
263
+ input_vector_mago = np.array(
264
+ [
265
+ science_data["pri_x"],
266
+ science_data["pri_y"],
267
+ science_data["pri_z"],
268
+ status_data["fob_range"],
269
+ ]
270
+ )
271
+ input_vector_magi = np.array(
272
+ [
273
+ science_data["sec_x"],
274
+ science_data["sec_y"],
275
+ science_data["sec_z"],
276
+ status_data["fib_range"],
277
+ ]
278
+ )
279
+
280
+ updated_vector_mago = calibrate_vector(input_vector_mago, calibration_matrix_mago)
281
+ updated_vector_magi = calibrate_vector(input_vector_magi, calibration_matrix_magi)
282
+
283
+ return updated_vector_mago, updated_vector_magi, time_data
284
+
285
+
286
+ def process_packet(
287
+ accumulated_data: xr.Dataset, calibration_dataset: xr.Dataset
288
+ ) -> list[dict]:
289
+ """
290
+ Parse the MAG packets.
291
+
292
+ Parameters
293
+ ----------
294
+ accumulated_data : xr.Dataset
295
+ Packets dataset accumulated over 1 min.
296
+ calibration_dataset : xr.Dataset
297
+ Calibration dataset.
298
+
299
+ Returns
300
+ -------
301
+ mag_data : list[dict]
302
+ Dictionaries of the parsed data product.
303
+ """
304
+ logger.info(
305
+ f"Parsing MAG for time: {accumulated_data['mag_acq_tm_coarse'].min().values} - "
306
+ f"{accumulated_data['mag_acq_tm_coarse'].max().values}."
307
+ )
308
+
309
+ # Note that the fine time second is split into 65535.
310
+ time_seconds = calculate_time(
311
+ accumulated_data["mag_acq_tm_coarse"],
312
+ accumulated_data["mag_acq_tm_fine"],
313
+ 65535,
314
+ )
315
+
316
+ # Add required parameters.
317
+ accumulated_data["time_seconds"] = time_seconds
318
+ sorted_data = accumulated_data.sortby("time_seconds", ascending=True)
319
+ pkt_counter = get_pkt_counter(sorted_data["mag_status"])
320
+ sorted_data["pkt_counter"] = pkt_counter
321
+
322
+ grouped_data = find_groups(sorted_data, (0, 3), "pkt_counter", "time_seconds")
323
+
324
+ unique_groups = np.unique(grouped_data["group"])
325
+ mag_data = []
326
+
327
+ for group in unique_groups:
328
+ # Get status values for each group.
329
+ status_values = grouped_data["mag_status"][
330
+ (grouped_data["group"] == group).values
331
+ ]
332
+ pkt_counter = grouped_data["pkt_counter"][
333
+ (grouped_data["group"] == group).values
334
+ ]
335
+
336
+ if not np.array_equal(pkt_counter, np.arange(4)):
337
+ logger.warning(
338
+ f"Group {group} does not contain all values from 0 to "
339
+ f"3 without duplicates."
340
+ )
341
+ continue
342
+
343
+ # Get decoded status data.
344
+ status_data = get_status_data(status_values, pkt_counter)
345
+
346
+ # Get science values for each group.
347
+ science_values = grouped_data["mag_data"][
348
+ (grouped_data["group"] == group).values
349
+ ]
350
+ science_data = extract_magnetic_vectors(science_values)
351
+ updated_vector_mago, updated_vector_magi, time_data = calculate_l1b(
352
+ grouped_data,
353
+ group,
354
+ pkt_counter,
355
+ science_data,
356
+ status_data,
357
+ calibration_dataset,
358
+ )
359
+
360
+ # Note: primary = MAGo, secondary = MAGi.
361
+ science_data.update(
362
+ {
363
+ "calibrated_pri_x": updated_vector_mago[0],
364
+ "calibrated_pri_y": updated_vector_mago[1],
365
+ "calibrated_pri_z": updated_vector_mago[2],
366
+ "calibrated_sec_x": updated_vector_magi[0],
367
+ "calibrated_sec_y": updated_vector_magi[1],
368
+ "calibrated_sec_z": updated_vector_magi[2],
369
+ }
370
+ )
371
+
372
+ mag_data.append({**status_data, **science_data, **time_data})
373
+
374
+ return mag_data
@@ -0,0 +1,69 @@
1
+ """Functions to support I-ALiRT SWAPI processing."""
2
+
3
+ import logging
4
+
5
+ import numpy as np
6
+ import xarray as xr
7
+ from xarray import DataArray
8
+
9
+ from imap_processing.ialirt.utils.grouping import find_groups
10
+
11
+ # from imap_processing.swapi.l1.swapi_l1 import process_sweep_data
12
+ # from imap_processing.swapi.l2.swapi_l2 import TIME_PER_BIN
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ def process_swapi_ialirt(unpacked_data: xr.Dataset) -> dict[str, DataArray]:
18
+ """
19
+ Extract I-ALiRT variables and calculate coincidence count rate.
20
+
21
+ Parameters
22
+ ----------
23
+ unpacked_data : xr.Dataset
24
+ SWAPI I-ALiRT data that has been parsed from the spacecraft packet.
25
+
26
+ Returns
27
+ -------
28
+ swapi_data : dict
29
+ Dictionary containing all data variables for SWAPI I-ALiRT product.
30
+ """
31
+ logger.info("Processing SWAPI.")
32
+
33
+ sci_dataset = unpacked_data.sortby("epoch", ascending=True)
34
+
35
+ grouped_dataset = find_groups(sci_dataset, (0, 11), "swapi_seq_number", "swapi_acq")
36
+
37
+ for group in np.unique(grouped_dataset["group"]):
38
+ # Sequence values for the group should be 0-11 with no duplicates.
39
+ seq_values = grouped_dataset["swapi_seq_number"][
40
+ (grouped_dataset["group"] == group)
41
+ ]
42
+
43
+ # Ensure no duplicates and all values from 0 to 11 are present
44
+ if not np.array_equal(seq_values.astype(int), np.arange(12)):
45
+ logger.info(
46
+ f"SWAPI group {group} does not contain all sequence values from 0 to "
47
+ f"11 without duplicates."
48
+ )
49
+ continue
50
+
51
+ total_packets = len(grouped_dataset["swapi_seq_number"].data)
52
+
53
+ # It takes 12 sequence data to make one full SWAPI sweep
54
+ total_sequence = 12
55
+ total_full_sweeps = total_packets // total_sequence
56
+
57
+ met_values = grouped_dataset["swapi_shcoarse"].data.reshape(total_full_sweeps, 12)[
58
+ :, 0
59
+ ]
60
+
61
+ # raw_coin_count = process_sweep_data(grouped_dataset, "coin_cnt")
62
+ # raw_coin_rate = raw_coin_count / TIME_PER_BIN
63
+
64
+ swapi_data = {
65
+ "met": met_values
66
+ # more variables to go here
67
+ }
68
+
69
+ return swapi_data