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,19 @@
1
+ """Define utils and classes related to coordinates of the ENA maps."""
2
+
3
+ from enum import Enum
4
+
5
+
6
+ class CoordNames(Enum):
7
+ """Enumeration of the names of the coordinates in the L1C and L2 ENA datasets."""
8
+
9
+ GENERIC_PIXEL = "pixel"
10
+
11
+ TIME = "epoch"
12
+ ENERGY = "energy"
13
+ HEALPIX_INDEX = "healpix_index"
14
+
15
+ # The names of the az/el angular coordinates may differ between L1C and L2 data
16
+ AZIMUTH_L1C = "longitude"
17
+ ELEVATION_L1C = "latitude"
18
+ AZIMUTH_L2 = "longitude"
19
+ ELEVATION_L2 = "latitude"
@@ -12,20 +12,22 @@ logger = logging.getLogger(__name__)
12
12
 
13
13
  def bin_single_array_at_indices(
14
14
  value_array: NDArray,
15
- projection_grid_shape: tuple[int, int],
15
+ projection_grid_shape: tuple[int, ...],
16
16
  projection_indices: NDArray,
17
17
  input_indices: NDArray | None = None,
18
18
  ) -> NDArray:
19
19
  """
20
20
  Bin an array of values at the given indices.
21
21
 
22
+ NOTE: The output array's spatial axis is always the final (-1) axis.
23
+
22
24
  Parameters
23
25
  ----------
24
26
  value_array : NDArray
25
- Array of values to bin. The 0th axis must be the one and only spatial axis.
27
+ Array of values to bin. The final axis be the one and only spatial axis.
26
28
  If other axes are present, they will be binned independently
27
- along the 0th (spatial) axis.
28
- projection_grid_shape : tuple[int]
29
+ along the spatial axis.
30
+ projection_grid_shape : tuple[int, ...]
29
31
  The shape of the grid onto which values are projected
30
32
  (rows, columns) if the grid is rectangular,
31
33
  or just (number of bins,) if the grid is 1D.
@@ -36,7 +38,7 @@ def bin_single_array_at_indices(
36
38
  Ordered indices for input grid, corresponding to indices in projection grid.
37
39
  1 dimensional. May be non-unique, depending on the projection method.
38
40
  If None (default), an arange of the same length as the
39
- 0th axis of value_array is used.
41
+ final axis of value_array is used.
40
42
 
41
43
  Returns
42
44
  -------
@@ -52,7 +54,7 @@ def bin_single_array_at_indices(
52
54
  If the input value_array has dimensionality less than 1.
53
55
  """
54
56
  if input_indices is None:
55
- input_indices = np.arange(value_array.shape[0])
57
+ input_indices = np.arange(value_array.shape[-1])
56
58
 
57
59
  # Both sets of indices must be 1D with the same number of elements
58
60
  if input_indices.ndim != 1 or projection_indices.ndim != 1:
@@ -80,23 +82,18 @@ def bin_single_array_at_indices(
80
82
  binned_values = np.apply_along_axis(
81
83
  lambda x: np.bincount(
82
84
  projection_indices,
83
- weights=x[input_indices, ...],
85
+ weights=x[..., input_indices],
84
86
  minlength=num_projection_indices,
85
87
  ),
86
- axis=0,
88
+ axis=-1,
87
89
  arr=value_array,
88
90
  )
89
- else:
90
- raise NotImplementedError(
91
- "Only 1+ Dimensional arrays are supported for binning. "
92
- f"Received array with shape {value_array.shape}."
93
- )
94
91
  return binned_values
95
92
 
96
93
 
97
94
  def bin_values_at_indices(
98
95
  input_values_to_bin: dict[str, NDArray],
99
- projection_grid_shape: tuple[int, int],
96
+ projection_grid_shape: tuple[int, ...],
100
97
  projection_indices: NDArray,
101
98
  input_indices: NDArray | None = None,
102
99
  ) -> dict[str, NDArray]:
@@ -107,10 +104,10 @@ def bin_values_at_indices(
107
104
  ----------
108
105
  input_values_to_bin : dict[str, NDArray]
109
106
  Dict matching variable names to arrays of values to bin.
110
- The 0th axis of each array must be the one and only spatial axis,
107
+ The final (-1) axis of each array must be the one and only spatial axis,
111
108
  which the indices correspond to and on which the values will be binned.
112
- The other axes will be binned independently along this 0th axis.
113
- projection_grid_shape : tuple[int, int]
109
+ The other axes will be binned independently along this final spatial axis.
110
+ projection_grid_shape : tuple[int, ...]
114
111
  The shape of the grid onto which values are projected (rows, columns).
115
112
  This size of the resulting grid (rows * columns) will be the size of the
116
113
  projected values contained in the output dictionary.
@@ -15,8 +15,7 @@ def build_spatial_bins(
15
15
  """
16
16
  Build spatial bin boundaries for azimuth and elevation.
17
17
 
18
- Input angles in degrees for consistency with map inputs,
19
- output angles in radians for internal use.
18
+ Input/output angles in degrees.
20
19
 
21
20
  Parameters
22
21
  ----------
@@ -28,13 +27,13 @@ def build_spatial_bins(
28
27
  Returns
29
28
  -------
30
29
  az_bin_edges : np.ndarray
31
- Array of azimuth bin boundary values in radians.
30
+ Array of azimuth bin boundary values in degrees.
32
31
  el_bin_edges : np.ndarray
33
- Array of elevation bin boundary values in radians.
32
+ Array of elevation bin boundary values in degrees.
34
33
  az_bin_midpoints : np.ndarray
35
- Array of azimuth bin midpoint values in radians.
34
+ Array of azimuth bin midpoint values in degrees.
36
35
  el_bin_midpoints : np.ndarray
37
- Array of elevation bin midpoint values in radians.
36
+ Array of elevation bin midpoint values in degrees.
38
37
  """
39
38
  # Azimuth bins from 0 to 360 degrees.
40
39
  az_bin_edges = np.arange(0, 360 + az_spacing_deg, az_spacing_deg)
@@ -44,12 +43,11 @@ def build_spatial_bins(
44
43
  el_bin_edges = np.arange(-90, 90 + el_spacing_deg, el_spacing_deg)
45
44
  el_bin_midpoints = el_bin_edges[:-1] + el_spacing_deg / 2 # Midpoints between edges
46
45
 
47
- # Convert all angles to radians and return them
48
46
  return (
49
- np.deg2rad(az_bin_edges),
50
- np.deg2rad(el_bin_edges),
51
- np.deg2rad(az_bin_midpoints),
52
- np.deg2rad(el_bin_midpoints),
47
+ az_bin_edges,
48
+ el_bin_edges,
49
+ az_bin_midpoints,
50
+ el_bin_midpoints,
53
51
  )
54
52
 
55
53
 
@@ -59,6 +57,10 @@ def build_solid_angle_map(
59
57
  """
60
58
  Build a solid angle map in steradians for a given spacing in degrees.
61
59
 
60
+ NOTE: This function works in radians internally and returns steradians, while other
61
+ functions in this module work in degrees. Expressing solid angles in steradians
62
+ is the preferred unit for ENA Maps.
63
+
62
64
  Parameters
63
65
  ----------
64
66
  spacing_deg : float
@@ -96,23 +98,26 @@ def build_solid_angle_map(
96
98
  @typing.no_type_check
97
99
  def rewrap_even_spaced_az_el_grid(
98
100
  raveled_values: NDArray,
99
- shape: tuple[int] | None = None,
101
+ grid_shape: tuple[int] | None = None,
100
102
  order: typing.Literal["C"] | typing.Literal["F"] = "C",
101
103
  ) -> NDArray:
102
104
  """
103
105
  Take an unwrapped (raveled) 1D array and reshapes it into a 2D az/el grid.
104
106
 
107
+ In the input, unwrapped grid, the spatial axis is the final (-1) axis.
108
+ In the output, the spatial axes are the -2 (azimuth) and -1 (elevation) axes.
109
+
105
110
  Assumes the following must be true of the original grid:
106
111
  1. Grid was evenly spaced in angular space,
107
112
  2. Grid had the same spacing in both azimuth and elevation.
108
- 3. Azimuth is axis 0 (and extends a total of 360 degrees).
109
- 4. Elevation is axis 1 (and extends a total of 180 degrees),
113
+ 3. Azimuth is the first spatial axis (and extends a total of 360 degrees).
114
+ 4. Elevation is the second spatial axis (and extends a total of 180 degrees).
110
115
 
111
116
  Parameters
112
117
  ----------
113
118
  raveled_values : NDArray
114
119
  1D array of values to be reshaped into a 2D grid.
115
- shape : tuple[int], optional
120
+ grid_shape : tuple[int], optional
116
121
  The shape of the original grid, if known, by default None.
117
122
  If None, the shape will be inferred from the size of the input array.
118
123
  order : {'C', 'F'}, optional
@@ -121,35 +126,27 @@ def rewrap_even_spaced_az_el_grid(
121
126
  Returns
122
127
  -------
123
128
  NDArray
124
- The reshaped 2D grid of values.
125
-
126
- Raises
127
- ------
128
- ValueError
129
- If the input is not a 1D array or 2D array with an 'extra' non-spatial axis.
129
+ The reshaped 2D grid of values with (azimuth, elevation) as the final 2 axes.
130
130
  """
131
- if raveled_values.ndim > 2:
132
- raise ValueError(
133
- "Input must be a 1D array or 2D array with only one spatial axis as axis 0."
134
- )
135
-
136
131
  # We can infer the shape if its evenly spaced and 2D
137
- if not shape:
138
- spacing_deg = 1 / np.sqrt(raveled_values.shape[0] / (360 * 180))
139
- shape = (int(360 // spacing_deg), int(180 // spacing_deg))
132
+ if not grid_shape:
133
+ spacing_deg = 1 / np.sqrt(raveled_values.shape[-1] / (360 * 180))
134
+ grid_shape = (int(360 // spacing_deg), int(180 // spacing_deg))
140
135
 
141
- if raveled_values.ndim == 2:
142
- shape = (shape[0], shape[1], raveled_values.shape[1])
143
- return raveled_values.reshape(shape, order=order)
136
+ if raveled_values.ndim == 1:
137
+ array_shape = grid_shape
138
+ else:
139
+ array_shape = (*raveled_values.shape[:-1], *grid_shape)
140
+ return raveled_values.reshape(array_shape, order=order)
144
141
 
145
142
 
146
143
  class AzElSkyGrid:
147
144
  """
148
145
  Representation of a 2D grid of azimuth and elevation angles covering the sky.
149
146
 
150
- All angles are stored internally in radians.
151
- Azimuth is within the range [0, 2*pi) radians,
152
- elevation is within the range [-pi/2, pi/2) radians.
147
+ All angles are stored internally in degrees.
148
+ Azimuth is within the range [0, 360) degrees,
149
+ elevation is within the range [-90, 90) degrees.
153
150
 
154
151
  Parameters
155
152
  ----------
@@ -157,13 +154,13 @@ class AzElSkyGrid:
157
154
  Spacing of the grid in degrees, by default 0.5.
158
155
  reversed_elevation : bool, optional
159
156
  Whether the elevation grid should be reversed, by default False.
160
- If False, the elevation grid will be from -pi/2 to pi/2 radians (-90 to 90 deg).
161
- If True, the elevation grid will be from pi/2 to -pi/2 radians (90 to -90 deg).
157
+ If False, the elevation grid will be from -90 to 90 deg.
158
+ If True, the elevation grid will be from 90 to -90 deg.
162
159
 
163
160
  Raises
164
161
  ------
165
162
  ValueError
166
- If the spacing is not positive or does not divide evenly into pi radians.
163
+ If the spacing is not positive or does not divide evenly into 180 degrees.
167
164
  """
168
165
 
169
166
  def __init__(
@@ -174,25 +171,26 @@ class AzElSkyGrid:
174
171
  # Store grid properties
175
172
  self.reversed_elevation = reversed_elevation
176
173
 
177
- # Internally, work in radians, regardless of desired output units
178
- self.spacing = np.deg2rad(spacing_deg)
174
+ # Internally, work in degrees
175
+ self.spacing_deg = spacing_deg
179
176
 
180
- # Ensure valid grid spacing (positive, divides evenly into pi radians)
181
- if self.spacing <= 0:
177
+ # Ensure valid grid spacing (positive, divides evenly into 180 degrees)
178
+ if self.spacing_deg <= 0:
182
179
  raise ValueError("Spacing must be positive valued, non-zero.")
183
180
 
184
- if not np.isclose((np.pi / self.spacing) % 1, 0):
185
- raise ValueError("Spacing must divide evenly into pi radians.")
181
+ if not np.isclose((180 / self.spacing_deg) % 1, 0):
182
+ raise ValueError("Spacing must divide evenly into 180 degrees.")
186
183
 
187
184
  # build_spacial_bins creates the bin edges and centers for azimuth and elevation
188
185
  # E.g. for spacing=1, az_bin_edges = [0, 1, 2, ..., 359, 360] deg.
189
- # However returned values are in radians.
190
186
  (
191
187
  self.az_bin_edges,
192
188
  self.el_bin_edges,
193
189
  self.az_bin_midpoints,
194
190
  self.el_bin_midpoints,
195
- ) = build_spatial_bins(az_spacing_deg=spacing_deg, el_spacing_deg=spacing_deg)
191
+ ) = build_spatial_bins(
192
+ az_spacing_deg=self.spacing_deg, el_spacing_deg=self.spacing_deg
193
+ )
196
194
 
197
195
  # If desired, reverse the elevation range so that the grid is in the order
198
196
  # defined by the Ultra prototype code (`build_dps_grid.m`).
@@ -221,6 +219,6 @@ class AzElSkyGrid:
221
219
  A string representation of the AzElSkyGrid.
222
220
  """
223
221
  return (
224
- f"AzElSkyGrid with a spacing of {self.spacing:.4e} radians. "
222
+ f"AzElSkyGrid with a spacing of {self.spacing_deg:.4e} degrees. "
225
223
  f"{self.grid_shape} Grid."
226
224
  )
@@ -7,8 +7,8 @@ from typing import Union
7
7
  import xarray as xr
8
8
 
9
9
  from imap_processing import imap_module_directory
10
+ from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
10
11
  from imap_processing.hi.l1a.histogram import create_dataset as hist_create_dataset
11
- from imap_processing.hi.l1a.housekeeping import process_housekeeping
12
12
  from imap_processing.hi.l1a.science_direct_event import science_direct_event
13
13
  from imap_processing.hi.utils import HIAPID
14
14
  from imap_processing.utils import packet_file_to_datasets
@@ -42,30 +42,36 @@ def hi_l1a(packet_file_path: Union[str, Path], data_version: str) -> list[xr.Dat
42
42
  # Process science to l1a.
43
43
  processed_data = []
44
44
  for apid in datasets_by_apid:
45
- if apid in [HIAPID.H45_SCI_CNT, HIAPID.H90_SCI_CNT]:
46
- logger.info(
47
- "Processing histogram data for [%s] packets", HIAPID.H45_SCI_CNT.name
48
- )
49
- data = hist_create_dataset(datasets_by_apid[apid])
50
- elif apid in [HIAPID.H45_SCI_DE, HIAPID.H90_SCI_DE]:
51
- logger.info(
52
- "Processing direct event data for [%s] packets", HIAPID.H45_SCI_DE.name
53
- )
45
+ try:
46
+ apid_enum = HIAPID(apid)
47
+ except ValueError as err:
48
+ raise RuntimeError(f"Encountered unexpected APID [{apid}]") from err
49
+
50
+ logger.info(f"Processing IMAP-Hi data for {apid_enum.name} packets")
54
51
 
52
+ if apid_enum in [HIAPID.H45_SCI_CNT, HIAPID.H90_SCI_CNT]:
53
+ data = hist_create_dataset(datasets_by_apid[apid])
54
+ gattr_key = "imap_hi_l1a_hist_attrs"
55
+ elif apid_enum in [HIAPID.H45_SCI_DE, HIAPID.H90_SCI_DE]:
55
56
  data = science_direct_event(datasets_by_apid[apid])
56
- elif apid in [HIAPID.H45_APP_NHK, HIAPID.H90_APP_NHK]:
57
- logger.info(
58
- "Processing housekeeping data for [%s] packets", HIAPID.H45_APP_NHK.name
59
- )
60
- data = process_housekeeping(datasets_by_apid[apid])
61
- else:
62
- raise RuntimeError(f"Encountered unexpected APID [{apid}]")
57
+ gattr_key = "imap_hi_l1a_de_attrs"
58
+ elif apid_enum in [HIAPID.H45_APP_NHK, HIAPID.H90_APP_NHK]:
59
+ data = datasets_by_apid[apid]
60
+ gattr_key = "imap_hi_l1a_hk_attrs"
61
+ elif apid_enum in [HIAPID.H45_DIAG_FEE, HIAPID.H90_DIAG_FEE]:
62
+ data = datasets_by_apid[apid]
63
+ gattr_key = "imap_hi_l1a_diagfee_attrs"
64
+
65
+ # Update dataset global attributes
66
+ attr_mgr = ImapCdfAttributes()
67
+ attr_mgr.add_instrument_global_attrs("hi")
68
+ data.attrs.update(attr_mgr.get_global_attributes(gattr_key))
63
69
 
64
70
  # TODO: revisit this
65
71
  data.attrs["Data_version"] = data_version
66
72
 
67
73
  # set the sensor string in Logical_source
68
- sensor_str = HIAPID(apid).sensor
74
+ sensor_str = apid_enum.sensor
69
75
  data.attrs["Logical_source"] = data.attrs["Logical_source"].format(
70
76
  sensor=sensor_str
71
77
  )
@@ -116,7 +116,6 @@ def create_dataset(input_ds: xr.Dataset) -> xr.Dataset:
116
116
  )
117
117
 
118
118
  dataset.update(new_vars)
119
- dataset.attrs.update(attr_mgr.get_global_attributes("imap_hi_l1a_hist_attrs"))
120
119
 
121
120
  return dataset
122
121
 
@@ -31,11 +31,11 @@ def parse_direct_events(de_data: bytes) -> dict[str, npt.ArrayLike]:
31
31
  IMAP-Hi direct event data information is stored in
32
32
  48-bits as follows:
33
33
 
34
- | Read 48-bits into 2, 16, 10, 10, 10, bits. Each of these breaks
34
+ | Read 48-bits into 16, 2, 10, 10, 10, bits. Each of these breaks
35
35
  | down as:
36
36
  |
37
- | start_bitmask_data - 2 bits (tA=1, tB=2, tC1=3, META=0)
38
37
  | de_tag - 16 bits
38
+ | start_bitmask_data - 2 bits (tA=1, tB=2, tC1=3)
39
39
  | tof_1 - 10 bit counter
40
40
  | tof_2 - 10 bit counter
41
41
  | tof_3 - 10 bit counter
@@ -70,16 +70,16 @@ def parse_direct_events(de_data: bytes) -> dict[str, npt.ArrayLike]:
70
70
  # direct events.
71
71
  # Considering the 6-bytes of data for each DE as 3 2-byte words,
72
72
  # each word contains the following:
73
- # word_0: 2-bits of Trigger ID, upper 14-bits of de_tag
74
- # word_1: lower 2-bits of de_tag, 10-bits tof_1, upper 4-bits of tof_2
73
+ # word_0: full 16-bits is the de_tag
74
+ # word_1: 2-bits of Trigger ID, 10-bits tof_1, upper 4-bits of tof_2
75
75
  # word_2: lower 6-bits of tof_2, 10-bits of tof_3
76
76
  data_uint16 = np.reshape(
77
77
  np.frombuffer(de_data, dtype=">u2"), (3, -1), order="F"
78
78
  ).astype(np.uint16)
79
79
 
80
80
  de_dict = dict()
81
- de_dict["trigger_id"] = (data_uint16[0] >> 14).astype(np.uint8)
82
- de_dict["de_tag"] = (data_uint16[0] << 2) + (data_uint16[1] >> 14)
81
+ de_dict["de_tag"] = data_uint16[0]
82
+ de_dict["trigger_id"] = (data_uint16[1] >> 14).astype(np.uint8)
83
83
  de_dict["tof_1"] = (data_uint16[1] & int(b"00111111_11110000", 2)) >> 4
84
84
  de_dict["tof_2"] = ((data_uint16[1] & int(b"00000000_00001111", 2)) << 6) + (
85
85
  data_uint16[2] >> 10
@@ -147,10 +147,8 @@ def create_dataset(de_data_dict: dict[str, npt.ArrayLike]) -> xr.Dataset:
147
147
  attrs=event_met_attrs,
148
148
  )
149
149
 
150
- de_global_attrs = attr_mgr.get_global_attributes("imap_hi_l1a_de_attrs")
151
150
  dataset = xr.Dataset(
152
151
  coords={"epoch": epoch, "event_met": event_met},
153
- attrs=de_global_attrs,
154
152
  )
155
153
 
156
154
  for var_name, data in de_data_dict.items():
@@ -12,6 +12,7 @@ from imap_processing.cdf.utils import parse_filename_like
12
12
  from imap_processing.hi.l1a.science_direct_event import HALF_CLOCK_TICK_S
13
13
  from imap_processing.hi.utils import (
14
14
  HIAPID,
15
+ CoincidenceBitmap,
15
16
  HiConstants,
16
17
  create_dataset_variables,
17
18
  parse_sensor_number,
@@ -36,15 +37,6 @@ class TriggerId(IntEnum):
36
37
  C = 3
37
38
 
38
39
 
39
- class CoincidenceBitmap(IntEnum):
40
- """IntEnum class for coincidence type bitmap values."""
41
-
42
- A = 2**3
43
- B = 2**2
44
- C1 = 2**1
45
- C2 = 2**0
46
-
47
-
48
40
  logger = logging.getLogger(__name__)
49
41
  ATTR_MGR = ImapCdfAttributes()
50
42
  ATTR_MGR.add_instrument_global_attrs("hi")
@@ -124,7 +116,7 @@ def annotate_direct_events(l1a_dataset: xr.Dataset) -> xr.Dataset:
124
116
  """
125
117
  l1b_dataset = l1a_dataset.copy()
126
118
  l1b_dataset.update(de_esa_energy_step(l1b_dataset))
127
- l1b_dataset.update(compute_coincidence_type_and_time_deltas(l1b_dataset))
119
+ l1b_dataset.update(compute_coincidence_type_and_tofs(l1b_dataset))
128
120
  l1b_dataset.update(de_nominal_bin_and_spin_phase(l1b_dataset))
129
121
  l1b_dataset.update(compute_hae_coordinates(l1b_dataset))
130
122
  l1b_dataset.update(
@@ -154,14 +146,14 @@ def annotate_direct_events(l1a_dataset: xr.Dataset) -> xr.Dataset:
154
146
  return l1b_dataset
155
147
 
156
148
 
157
- def compute_coincidence_type_and_time_deltas(
149
+ def compute_coincidence_type_and_tofs(
158
150
  dataset: xr.Dataset,
159
151
  ) -> dict[str, xr.DataArray]:
160
152
  """
161
- Compute coincidence type and time deltas.
153
+ Compute coincidence type and time of flights.
162
154
 
163
- Generates the new variables "coincidence_type", "delta_t_ab", "delta_t_ac1",
164
- "delta_t_bc1", and "delta_t_c1c2" and returns a dictionary with the new
155
+ Generates the new variables "coincidence_type", "tof_ab", "tof_ac1",
156
+ "tof_bc1", and "tof_c1c2" and returns a dictionary with the new
165
157
  variables that can be added to the input dataset by calling the
166
158
  xarray.Dataset.update method.
167
159
 
@@ -178,16 +170,16 @@ def compute_coincidence_type_and_time_deltas(
178
170
  new_vars = create_dataset_variables(
179
171
  [
180
172
  "coincidence_type",
181
- "delta_t_ab",
182
- "delta_t_ac1",
183
- "delta_t_bc1",
184
- "delta_t_c1c2",
173
+ "tof_ab",
174
+ "tof_ac1",
175
+ "tof_bc1",
176
+ "tof_c1c2",
185
177
  ],
186
178
  len(dataset.event_met),
187
179
  att_manager_lookup_str="hi_de_{0}",
188
180
  )
189
181
 
190
- # compute masks needed for coincidence type and delta t calculations
182
+ # compute masks needed for coincidence type and ToF calculations
191
183
  a_first = dataset.trigger_id.values == TriggerId.A
192
184
  b_first = dataset.trigger_id.values == TriggerId.B
193
185
  c_first = dataset.trigger_id.values == TriggerId.C
@@ -221,56 +213,56 @@ def compute_coincidence_type_and_time_deltas(
221
213
  # | 2 | B | t_a - t_b | t_c1 - t_b | t_c2 - t_c1 |
222
214
  # | 3 | C | t_a - t_c1 | t_b - t_c1 | t_c2 - t_c1 |
223
215
 
224
- # Prepare for delta_t calculations by converting TOF values to nanoseconds
216
+ # Prepare for L1B ToF calculations by converting L1A TOF values to nanoseconds
225
217
  tof_1_ns = (dataset.tof_1.values * HiConstants.TOF1_TICK_DUR).astype(np.int32)
226
218
  tof_2_ns = (dataset.tof_2.values * HiConstants.TOF2_TICK_DUR).astype(np.int32)
227
219
  tof_3_ns = (dataset.tof_3.values * HiConstants.TOF3_TICK_DUR).astype(np.int32)
228
220
 
229
- # # ********** delta_t_ab = (t_b - t_a) **********
221
+ # # ********** tof_ab = (t_b - t_a) **********
230
222
  # Table: row 1, column 1
231
223
  a_and_tof1 = a_first & tof1_valid
232
- new_vars["delta_t_ab"].values[a_and_tof1] = tof_1_ns[a_and_tof1]
224
+ new_vars["tof_ab"].values[a_and_tof1] = tof_1_ns[a_and_tof1]
233
225
  # Table: row 2, column 1
234
226
  b_and_tof1 = b_first & tof1_valid
235
- new_vars["delta_t_ab"].values[b_and_tof1] = -1 * tof_1_ns[b_and_tof1]
227
+ new_vars["tof_ab"].values[b_and_tof1] = -1 * tof_1_ns[b_and_tof1]
236
228
  # Table: row 3, column 1 and 2
237
- # delta_t_ab = (t_b - t_c1) - (t_a - t_c1) = (t_b - t_a)
229
+ # tof_ab = (t_b - t_c1) - (t_a - t_c1) = (t_b - t_a)
238
230
  c_and_tof1and2 = c_first & tof1and2_valid
239
- new_vars["delta_t_ab"].values[c_and_tof1and2] = (
231
+ new_vars["tof_ab"].values[c_and_tof1and2] = (
240
232
  tof_2_ns[c_and_tof1and2] - tof_1_ns[c_and_tof1and2]
241
233
  )
242
234
 
243
- # ********** delta_t_ac1 = (t_c1 - t_a) **********
235
+ # ********** tof_ac1 = (t_c1 - t_a) **********
244
236
  # Table: row 1, column 2
245
237
  a_and_tof2 = a_first & tof2_valid
246
- new_vars["delta_t_ac1"].values[a_and_tof2] = tof_2_ns[a_and_tof2]
238
+ new_vars["tof_ac1"].values[a_and_tof2] = tof_2_ns[a_and_tof2]
247
239
  # Table: row 2, column 1 and 2
248
- # delta_t_ac1 = (t_c1 - t_b) - (t_a - t_b) = (t_c1 - t_a)
240
+ # tof_ac1 = (t_c1 - t_b) - (t_a - t_b) = (t_c1 - t_a)
249
241
  b_and_tof1and2 = b_first & tof1and2_valid
250
- new_vars["delta_t_ac1"].values[b_and_tof1and2] = (
242
+ new_vars["tof_ac1"].values[b_and_tof1and2] = (
251
243
  tof_2_ns[b_and_tof1and2] - tof_1_ns[b_and_tof1and2]
252
244
  )
253
245
  # Table: row 3, column 1
254
246
  c_and_tof1 = c_first & tof1_valid
255
- new_vars["delta_t_ac1"].values[c_and_tof1] = -1 * tof_1_ns[c_and_tof1]
247
+ new_vars["tof_ac1"].values[c_and_tof1] = -1 * tof_1_ns[c_and_tof1]
256
248
 
257
- # ********** delta_t_bc1 = (t_c1 - t_b) **********
249
+ # ********** tof_bc1 = (t_c1 - t_b) **********
258
250
  # Table: row 1, column 1 and 2
259
- # delta_t_bc1 = (t_c1 - t_a) - (t_b - t_a) => (t_c1 - t_b)
251
+ # tof_bc1 = (t_c1 - t_a) - (t_b - t_a) => (t_c1 - t_b)
260
252
  a_and_tof1and2 = a_first & tof1and2_valid
261
- new_vars["delta_t_bc1"].values[a_and_tof1and2] = (
253
+ new_vars["tof_bc1"].values[a_and_tof1and2] = (
262
254
  tof_2_ns[a_and_tof1and2] - tof_1_ns[a_and_tof1and2]
263
255
  )
264
256
  # Table: row 2, column 2
265
257
  b_and_tof2 = b_first & tof2_valid
266
- new_vars["delta_t_bc1"].values[b_and_tof2] = tof_2_ns[b_and_tof2]
258
+ new_vars["tof_bc1"].values[b_and_tof2] = tof_2_ns[b_and_tof2]
267
259
  # Table: row 3, column 2
268
260
  c_and_tof2 = c_first & tof2_valid
269
- new_vars["delta_t_bc1"].values[c_and_tof2] = -1 * tof_2_ns[c_and_tof2]
261
+ new_vars["tof_bc1"].values[c_and_tof2] = -1 * tof_2_ns[c_and_tof2]
270
262
 
271
- # ********** delta_t_c1c2 = (t_c2 - t_c1) **********
263
+ # ********** tof_c1c2 = (t_c2 - t_c1) **********
272
264
  # Table: all rows, column 3
273
- new_vars["delta_t_c1c2"].values[tof3_valid] = tof_3_ns[tof3_valid]
265
+ new_vars["tof_c1c2"].values[tof3_valid] = tof_3_ns[tof3_valid]
274
266
 
275
267
  return new_vars
276
268
 
@@ -325,8 +317,8 @@ def compute_hae_coordinates(dataset: xr.Dataset) -> dict[str, xr.DataArray]:
325
317
  Parameters
326
318
  ----------
327
319
  dataset : xarray.Dataset
328
- The partial L1B dataset that has had coincidence type, time deltas, and
329
- spin phase computed and added to the L1A data.
320
+ The partial L1B dataset that has had coincidence type, times of flight,
321
+ and spin phase computed and added to the L1A data.
330
322
 
331
323
  Returns
332
324
  -------