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
@@ -1,7 +1,9 @@
1
1
  """IMAP-HIT L1B data processing."""
2
2
 
3
3
  import logging
4
+ from typing import NamedTuple
4
5
 
6
+ import numpy as np
5
7
  import xarray as xr
6
8
 
7
9
  from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
@@ -11,6 +13,10 @@ from imap_processing.hit.hit_utils import (
11
13
  get_datasets_by_apid,
12
14
  process_housekeeping_data,
13
15
  )
16
+ from imap_processing.hit.l1b.constants import (
17
+ PARTICLE_ENERGY_RANGE_MAPPING,
18
+ livestim_pulses,
19
+ )
14
20
 
15
21
  logger = logging.getLogger(__name__)
16
22
 
@@ -46,16 +52,19 @@ def hit_l1b(dependencies: dict, data_version: str) -> list[xr.Dataset]:
46
52
  # Unpack ccsds file to xarray datasets
47
53
  packet_file = dependencies["imap_hit_l0_raw"]
48
54
  datasets_by_apid = get_datasets_by_apid(packet_file, derived=True)
49
- # Process housekeeping to L1B.
50
- l1b_datasets.append(
51
- process_housekeeping_data(
52
- datasets_by_apid[HitAPID.HIT_HSKP], attr_mgr, "imap_hit_l1b_hk"
55
+ # TODO: update to raise error after all APIDs are included in the same
56
+ # raw files. currently science and housekeeping are in separate files.
57
+ if HitAPID.HIT_HSKP in datasets_by_apid:
58
+ # Process housekeeping to L1B.
59
+ l1b_datasets.append(
60
+ process_housekeeping_data(
61
+ datasets_by_apid[HitAPID.HIT_HSKP], attr_mgr, "imap_hit_l1b_hk"
62
+ )
53
63
  )
54
- )
55
- logger.info("HIT L1B housekeeping dataset created")
56
- if "imap_hit_l1a_count-rates" in dependencies:
64
+ logger.info("HIT L1B housekeeping dataset created")
65
+ if "imap_hit_l1a_counts" in dependencies:
57
66
  # Process science data to L1B datasets
58
- l1a_counts_dataset = dependencies["imap_hit_l1a_count-rates"]
67
+ l1a_counts_dataset = dependencies["imap_hit_l1a_counts"]
59
68
  l1b_datasets.extend(process_science_data(l1a_counts_dataset, attr_mgr))
60
69
  logger.info("HIT L1B science datasets created")
61
70
 
@@ -91,19 +100,26 @@ def process_science_data(
91
100
 
92
101
  # Logical sources for the three L1B science products.
93
102
  # TODO: add logical sources for other l1b products once processing functions
94
- # are written. "imap_hit_l1b_summed-rates", "imap_hit_l1b_sectored-rates"
95
- logical_sources = ["imap_hit_l1b_standard-rates"]
103
+ # are written. ""imap_hit_l1b_sectored-rates"
104
+ logical_sources = ["imap_hit_l1b_standard-rates", "imap_hit_l1b_summed-rates"]
96
105
 
97
106
  # TODO: Write functions to create the following datasets
98
- # Process summed rates dataset
99
107
  # Process sectored rates dataset
100
108
 
109
+ # Calculate fractional livetime from the livetime counter
110
+ livetime = raw_counts_dataset["livetime_counter"] / livestim_pulses
111
+
101
112
  # Create a standard rates dataset
102
- standard_rates_dataset = process_standard_rates_data(raw_counts_dataset)
113
+ standard_rates_dataset = process_standard_rates_data(raw_counts_dataset, livetime)
114
+
115
+ # Create a summed rates dataset
116
+ summed_rates_dataset = process_summed_rates_data(raw_counts_dataset, livetime)
103
117
 
104
118
  l1b_science_datasets = []
105
119
  # Update attributes and dimensions
106
- for dataset, logical_source in zip([standard_rates_dataset], logical_sources):
120
+ for dataset, logical_source in zip(
121
+ [standard_rates_dataset, summed_rates_dataset], logical_sources
122
+ ):
107
123
  dataset.attrs = attr_mgr.get_global_attributes(logical_source)
108
124
 
109
125
  # TODO: Add CDF attributes to yaml once they're defined for L1B science data
@@ -136,7 +152,9 @@ def process_science_data(
136
152
  return l1b_science_datasets
137
153
 
138
154
 
139
- def process_standard_rates_data(raw_counts_dataset: xr.Dataset) -> xr.Dataset:
155
+ def process_standard_rates_data(
156
+ raw_counts_dataset: xr.Dataset, livetime: xr.DataArray
157
+ ) -> xr.Dataset:
140
158
  """
141
159
  Will process L1B standard rates data from raw L1A counts data.
142
160
 
@@ -145,6 +163,10 @@ def process_standard_rates_data(raw_counts_dataset: xr.Dataset) -> xr.Dataset:
145
163
  raw_counts_dataset : xr.Dataset
146
164
  The L1A counts dataset.
147
165
 
166
+ livetime : xr.DataArray
167
+ 1D array of livetime values calculated from the livetime counter.
168
+ Shape equals the number of epochs in the dataset.
169
+
148
170
  Returns
149
171
  -------
150
172
  xr.Dataset
@@ -172,10 +194,13 @@ def process_standard_rates_data(raw_counts_dataset: xr.Dataset) -> xr.Dataset:
172
194
  {coord: raw_counts_dataset.coords[coord] for coord in coords}
173
195
  )
174
196
 
175
- # Add dynamic threshold field
197
+ # Add dynamic threshold variable from the L1A raw counts dataset
176
198
  l1b_standard_rates_dataset["dynamic_threshold_state"] = raw_counts_dataset[
177
199
  "hdr_dynamic_threshold_state"
178
200
  ]
201
+ l1b_standard_rates_dataset["dynamic_threshold_state"].attrs = raw_counts_dataset[
202
+ "hdr_dynamic_threshold_state"
203
+ ].attrs
179
204
 
180
205
  # Define fields from the raw_counts_dataset to calculate standard rates from
181
206
  standard_rate_fields = [
@@ -193,9 +218,6 @@ def process_standard_rates_data(raw_counts_dataset: xr.Dataset) -> xr.Dataset:
193
218
  "l4bgrates",
194
219
  ]
195
220
 
196
- # Calculate livetime from the livetime counter
197
- livetime = raw_counts_dataset["livetime_counter"] / 270
198
-
199
221
  # Calculate standard rates by dividing the raw counts by livetime for
200
222
  # data variables with names that contain a substring from a defined
201
223
  # list of field names.
@@ -206,3 +228,330 @@ def process_standard_rates_data(raw_counts_dataset: xr.Dataset) -> xr.Dataset:
206
228
  l1b_standard_rates_dataset[var] = raw_counts_dataset[var] / livetime
207
229
 
208
230
  return l1b_standard_rates_dataset
231
+
232
+
233
+ def create_particle_data_arrays(
234
+ dataset: xr.Dataset,
235
+ particle: str,
236
+ num_energy_ranges: int,
237
+ epoch_size: int,
238
+ ) -> xr.Dataset:
239
+ """
240
+ Create empty data arrays for a given particle.
241
+
242
+ Parameters
243
+ ----------
244
+ dataset : xr.Dataset
245
+ The dataset to add the data arrays to.
246
+
247
+ particle : str
248
+ The abbreviated particle name. Valid names are:
249
+ h
250
+ he3
251
+ he4
252
+ he
253
+ c
254
+ n
255
+ o
256
+ ne
257
+ na
258
+ mg
259
+ al
260
+ si
261
+ s
262
+ ar
263
+ ca
264
+ fe
265
+ ni
266
+
267
+ num_energy_ranges : int
268
+ Number of energy ranges for the particle.
269
+ Used to define the shape of the data arrays.
270
+
271
+ epoch_size : int
272
+ Used to define the shape of the data arrays.
273
+
274
+ Returns
275
+ -------
276
+ dataset : xr.Dataset
277
+ The dataset with the added data arrays.
278
+ """
279
+ dataset[f"{particle}"] = xr.DataArray(
280
+ data=np.zeros((epoch_size, num_energy_ranges), dtype=np.float32),
281
+ dims=["epoch", f"{particle}_energy_index"],
282
+ name=f"{particle}",
283
+ )
284
+ dataset[f"{particle}_delta_minus"] = xr.DataArray(
285
+ data=np.zeros((epoch_size, num_energy_ranges), dtype=np.float32),
286
+ dims=["epoch", f"{particle}_energy_index"],
287
+ name=f"{particle}_delta_minus",
288
+ )
289
+ dataset[f"{particle}_delta_plus"] = xr.DataArray(
290
+ data=np.zeros((epoch_size, num_energy_ranges), dtype=np.float32),
291
+ dims=["epoch", f"{particle}_energy_index"],
292
+ name=f"{particle}_delta_plus",
293
+ )
294
+ dataset.coords[f"{particle}_energy_index"] = xr.DataArray(
295
+ np.arange(num_energy_ranges, dtype=np.int8),
296
+ dims=[f"{particle}_energy_index"],
297
+ name=f"{particle}_energy_index",
298
+ )
299
+ return dataset
300
+
301
+
302
+ def calculate_summed_counts(
303
+ raw_counts_dataset: xr.Dataset, count_indices: dict
304
+ ) -> tuple[xr.DataArray, xr.DataArray, xr.DataArray]:
305
+ """
306
+ Calculate summed counts for a given energy range.
307
+
308
+ Parameters
309
+ ----------
310
+ raw_counts_dataset : xr.Dataset
311
+ The L1A counts dataset that contains the l2fgrates, l3fgrates,
312
+ and penfgrates data variables with the particle counts data
313
+ needed for the calculation.
314
+
315
+ count_indices : dict
316
+ A dictionary containing the indices for particle counts to sum for a given
317
+ energy range.
318
+ R2=Indices for L2FGRATES, R3=Indices for L3FGRATES, R4=Indices for PENFGRATES.
319
+
320
+ Returns
321
+ -------
322
+ summed_counts : xr.DataArray
323
+ The summed counts.
324
+
325
+ summed_counts_delta_minus : xr.DataArray
326
+ The summed counts for delta minus uncertainty.
327
+
328
+ summed_counts_delta_plus : xr.DataArray
329
+ The summed counts for delta plus uncertainty.
330
+ """
331
+ summed_counts = (
332
+ raw_counts_dataset["l2fgrates"][:, count_indices["R2"]].sum(axis=1)
333
+ + raw_counts_dataset["l3fgrates"][:, count_indices["R3"]].sum(axis=1)
334
+ + raw_counts_dataset["penfgrates"][:, count_indices["R4"]].sum(axis=1)
335
+ )
336
+
337
+ summed_counts_delta_minus = (
338
+ raw_counts_dataset["l2fgrates_delta_minus"][:, count_indices["R2"]].sum(axis=1)
339
+ + raw_counts_dataset["l3fgrates_delta_minus"][:, count_indices["R3"]].sum(
340
+ axis=1
341
+ )
342
+ + raw_counts_dataset["penfgrates_delta_minus"][:, count_indices["R4"]].sum(
343
+ axis=1
344
+ )
345
+ )
346
+
347
+ summed_counts_delta_plus = (
348
+ raw_counts_dataset["l2fgrates_delta_plus"][:, count_indices["R2"]].sum(axis=1)
349
+ + raw_counts_dataset["l3fgrates_delta_plus"][:, count_indices["R3"]].sum(axis=1)
350
+ + raw_counts_dataset["penfgrates_delta_plus"][:, count_indices["R4"]].sum(
351
+ axis=1
352
+ )
353
+ )
354
+
355
+ return summed_counts, summed_counts_delta_minus, summed_counts_delta_plus
356
+
357
+
358
+ class SummedCounts(NamedTuple):
359
+ """A namedtuple to store summed counts and uncertainties."""
360
+
361
+ summed_counts: xr.DataArray
362
+ summed_counts_delta_minus: xr.DataArray
363
+ summed_counts_delta_plus: xr.DataArray
364
+
365
+
366
+ def add_rates_to_dataset(
367
+ dataset: xr.Dataset,
368
+ particle: str,
369
+ index: int,
370
+ summed_counts: SummedCounts,
371
+ livetime: xr.DataArray,
372
+ ) -> xr.Dataset:
373
+ """
374
+ Add summed rates to the dataset.
375
+
376
+ This function divides the summed counts by livetime to calculate
377
+ the rates for a given particle then adds the rates to the dataset.
378
+
379
+ Parameters
380
+ ----------
381
+ dataset : xr.Dataset
382
+ The dataset to add the rates to.
383
+
384
+ particle : str
385
+ The abbreviated particle name. Valid names are:
386
+ h
387
+ he3
388
+ he4
389
+ he
390
+ c
391
+ n
392
+ o
393
+ ne
394
+ na
395
+ mg
396
+ al
397
+ si
398
+ s
399
+ ar
400
+ ca
401
+ fe
402
+ ni
403
+
404
+ index : int
405
+ The index of the energy range.
406
+
407
+ summed_counts : namedtuple
408
+ A namedtuple containing the summed counts.
409
+ SummedCounts(summed_counts, summed_counts_delta_minus,
410
+ summed_counts_delta_plus).
411
+
412
+ livetime : xr.DataArray
413
+ 1D array of livetime values. Shape equals the number of epochs in the dataset.
414
+
415
+ Returns
416
+ -------
417
+ dataset: xr.Dataset
418
+ The dataset with the added rates.
419
+ """
420
+ dataset[f"{particle}"][:, index] = (summed_counts.summed_counts / livetime).astype(
421
+ np.float32
422
+ )
423
+ dataset[f"{particle}_delta_minus"][:, index] = (
424
+ summed_counts.summed_counts_delta_minus / livetime
425
+ ).astype(np.float32)
426
+ dataset[f"{particle}_delta_plus"][:, index] = (
427
+ summed_counts.summed_counts_delta_plus / livetime
428
+ ).astype(np.float32)
429
+ return dataset
430
+
431
+
432
+ def add_energy_variables(
433
+ dataset: xr.Dataset,
434
+ particle: str,
435
+ energy_min_values: np.ndarray,
436
+ energy_max_values: np.ndarray,
437
+ ) -> xr.Dataset:
438
+ """
439
+ Add energy min and max variables to the dataset.
440
+
441
+ Parameters
442
+ ----------
443
+ dataset : xr.Dataset
444
+ The dataset to add the energy variables to.
445
+ particle : str
446
+ The particle name.
447
+ energy_min_values : np.ndarray
448
+ The minimum energy values for each energy range.
449
+ energy_max_values : np.ndarray
450
+ The maximum energy values for each energy range.
451
+
452
+ Returns
453
+ -------
454
+ xr.Dataset
455
+ The dataset with the added energy variables.
456
+ """
457
+ dataset[f"{particle}_energy_min"] = xr.DataArray(
458
+ data=np.array(energy_min_values, dtype=np.float32),
459
+ dims=[f"{particle}_energy_index"],
460
+ name=f"{particle}_energy_min",
461
+ )
462
+ dataset[f"{particle}_energy_max"] = xr.DataArray(
463
+ data=np.array(energy_max_values, dtype=np.float32),
464
+ dims=[f"{particle}_energy_index"],
465
+ name=f"{particle}_energy_max",
466
+ )
467
+ return dataset
468
+
469
+
470
+ def process_summed_rates_data(
471
+ raw_counts_dataset: xr.Dataset, livetime: xr.DataArray
472
+ ) -> xr.Dataset:
473
+ """
474
+ Will process L1B summed rates data from raw L1A counts data.
475
+
476
+ This function calculates summed rates for each particle type and energy range.
477
+ The counts that are summed come from the l2fgrates, l3fgrates, and penfgrates
478
+ data variables in the L1A counts data. These variables represent counts
479
+ of different detector penetration ranges (Range 2, Range 3, and Range 4
480
+ respectively). Only the energy ranges specified in the
481
+ PARTICLE_ENERGY_RANGE_MAPPING dictionary are included in this product.
482
+
483
+ The summed rates are calculated by summing the counts for each energy range and
484
+ dividing by the livetime.
485
+
486
+ Parameters
487
+ ----------
488
+ raw_counts_dataset : xr.Dataset
489
+ The L1A counts dataset.
490
+
491
+ livetime : xr.DataArray
492
+ 1D array of livetime values calculated from the livetime counter.
493
+ Shape equals the number of epochs in the dataset.
494
+
495
+ Returns
496
+ -------
497
+ xr.Dataset
498
+ The processed L1B summed rates dataset.
499
+ """
500
+ # Create a new dataset to store the L1B standard rates
501
+ l1b_summed_rates_dataset = xr.Dataset()
502
+
503
+ # Assign the epoch coordinate from the l1a dataset
504
+ l1b_summed_rates_dataset = l1b_summed_rates_dataset.assign_coords(
505
+ {"epoch": raw_counts_dataset.coords["epoch"]}
506
+ )
507
+
508
+ # TODO: dynamic threshold might not be needed for this product.
509
+ # Need confirmation from HIT
510
+ # Add dynamic threshold variable from L1A raw counts dataset
511
+ l1b_summed_rates_dataset["dynamic_threshold_state"] = raw_counts_dataset[
512
+ "hdr_dynamic_threshold_state"
513
+ ]
514
+ l1b_summed_rates_dataset["dynamic_threshold_state"].attrs = raw_counts_dataset[
515
+ "hdr_dynamic_threshold_state"
516
+ ].attrs
517
+
518
+ # Calculate summed rates for each particle and add them to the dataset
519
+ for particle, energy_ranges in PARTICLE_ENERGY_RANGE_MAPPING.items():
520
+ l1b_summed_rates_dataset = create_particle_data_arrays(
521
+ l1b_summed_rates_dataset,
522
+ particle,
523
+ len(energy_ranges),
524
+ raw_counts_dataset.sizes["epoch"],
525
+ )
526
+
527
+ energy_min, energy_max = (
528
+ np.zeros(len(energy_ranges), dtype=np.float32),
529
+ np.zeros(len(energy_ranges), dtype=np.float32),
530
+ )
531
+ for i, energy_range in enumerate(energy_ranges):
532
+ summed_counts, summed_counts_delta_minus, summed_counts_delta_plus = (
533
+ calculate_summed_counts(raw_counts_dataset, energy_range)
534
+ )
535
+
536
+ # Create namedtuple to store summed counts and uncertainties
537
+ summed_counts = SummedCounts(
538
+ summed_counts, summed_counts_delta_minus, summed_counts_delta_plus
539
+ )
540
+
541
+ l1b_summed_rates_dataset = add_rates_to_dataset(
542
+ l1b_summed_rates_dataset,
543
+ particle,
544
+ i,
545
+ summed_counts,
546
+ livetime,
547
+ )
548
+ energy_min[i], energy_max[i] = (
549
+ energy_range["energy_min"],
550
+ energy_range["energy_max"],
551
+ )
552
+
553
+ l1b_summed_rates_dataset = add_energy_variables(
554
+ l1b_summed_rates_dataset, particle, energy_min, energy_max
555
+ )
556
+
557
+ return l1b_summed_rates_dataset