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
@@ -2,22 +2,30 @@
2
2
 
3
3
  import logging
4
4
 
5
+ import numpy as np
5
6
  import xarray as xr
6
7
 
7
8
  from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
8
9
  from imap_processing.hit.hit_utils import (
9
10
  HitAPID,
11
+ add_summed_particle_data_to_dataset,
10
12
  get_attribute_manager,
11
13
  get_datasets_by_apid,
12
14
  process_housekeeping_data,
13
15
  )
16
+ from imap_processing.hit.l1b.constants import (
17
+ FILLVAL_FLOAT32,
18
+ FILLVAL_INT64,
19
+ LIVESTIM_PULSES,
20
+ SUMMED_PARTICLE_ENERGY_RANGE_MAPPING,
21
+ )
14
22
 
15
23
  logger = logging.getLogger(__name__)
16
24
 
17
25
  # TODO review logging levels to use (debug vs. info)
18
26
 
19
27
 
20
- def hit_l1b(dependencies: dict, data_version: str) -> list[xr.Dataset]:
28
+ def hit_l1b(dependencies: dict) -> list[xr.Dataset]:
21
29
  """
22
30
  Will process HIT data to L1B.
23
31
 
@@ -29,8 +37,6 @@ def hit_l1b(dependencies: dict, data_version: str) -> list[xr.Dataset]:
29
37
  Dictionary of dependencies that are L1A xarray datasets
30
38
  for science data and a file path string to an L0 file
31
39
  for housekeeping data.
32
- data_version : str
33
- Version of the data product being created.
34
40
 
35
41
  Returns
36
42
  -------
@@ -38,7 +44,7 @@ def hit_l1b(dependencies: dict, data_version: str) -> list[xr.Dataset]:
38
44
  List of four L1B datasets.
39
45
  """
40
46
  # Create the attribute manager for this data level
41
- attr_mgr = get_attribute_manager(data_version, "l1b")
47
+ attr_mgr = get_attribute_manager("l1b")
42
48
 
43
49
  # Create L1B datasets
44
50
  l1b_datasets: list = []
@@ -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
 
@@ -63,7 +72,7 @@ def hit_l1b(dependencies: dict, data_version: str) -> list[xr.Dataset]:
63
72
 
64
73
 
65
74
  def process_science_data(
66
- raw_counts_dataset: xr.Dataset, attr_mgr: ImapCdfAttributes
75
+ l1a_counts_dataset: xr.Dataset, attr_mgr: ImapCdfAttributes
67
76
  ) -> list[xr.Dataset]:
68
77
  """
69
78
  Will create L1B science datasets for CDF products.
@@ -77,7 +86,7 @@ def process_science_data(
77
86
 
78
87
  Parameters
79
88
  ----------
80
- raw_counts_dataset : xr.Dataset
89
+ l1a_counts_dataset : xr.Dataset
81
90
  The L1A counts dataset.
82
91
  attr_mgr : AttributeManager
83
92
  The attribute manager for the L1B data level.
@@ -89,21 +98,27 @@ def process_science_data(
89
98
  """
90
99
  logger.info("Creating HIT L1B science datasets")
91
100
 
92
- # Logical sources for the three L1B science products.
93
- # 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"]
96
-
97
101
  # TODO: Write functions to create the following datasets
98
- # Process summed rates dataset
99
102
  # Process sectored rates dataset
100
103
 
101
- # Create a standard rates dataset
102
- standard_rates_dataset = process_standard_rates_data(raw_counts_dataset)
104
+ # Calculate fractional livetime from the livetime counter
105
+ livetime = l1a_counts_dataset["livetime_counter"] / LIVESTIM_PULSES
106
+ livetime = livetime.rename("livetime")
107
+
108
+ # Process counts data to L1B datasets
109
+ l1b_datasets: dict = {}
110
+ l1b_datasets["imap_hit_l1b_standard-rates"] = process_standard_rates_data(
111
+ l1a_counts_dataset, livetime
112
+ )
113
+ l1b_datasets["imap_hit_l1b_summed-rates"] = process_summed_rates_data(
114
+ l1a_counts_dataset, livetime
115
+ )
116
+ l1b_datasets["imap_hit_l1b_sectored-rates"] = process_sectored_rates_data(
117
+ l1a_counts_dataset, livetime
118
+ )
103
119
 
104
- l1b_science_datasets = []
105
120
  # Update attributes and dimensions
106
- for dataset, logical_source in zip([standard_rates_dataset], logical_sources):
121
+ for logical_source, dataset in l1b_datasets.items():
107
122
  dataset.attrs = attr_mgr.get_global_attributes(logical_source)
108
123
 
109
124
  # TODO: Add CDF attributes to yaml once they're defined for L1B science data
@@ -129,55 +144,79 @@ def process_science_data(
129
144
  "epoch", check_schema=False
130
145
  )
131
146
 
132
- l1b_science_datasets.append(dataset)
133
-
134
147
  logger.info(f"HIT L1B dataset created for {logical_source}")
135
148
 
136
- return l1b_science_datasets
149
+ return list(l1b_datasets.values())
137
150
 
138
151
 
139
- def process_standard_rates_data(raw_counts_dataset: xr.Dataset) -> xr.Dataset:
152
+ def initialize_l1b_dataset(l1a_counts_dataset: xr.Dataset, coords: list) -> xr.Dataset:
140
153
  """
141
- Will process L1B standard rates data from raw L1A counts data.
154
+ Initialize the L1B dataset.
155
+
156
+ Create a dataset and add coordinates and the dynamic threshold state data array
157
+ from the L1A counts dataset.
142
158
 
143
159
  Parameters
144
160
  ----------
145
- raw_counts_dataset : xr.Dataset
161
+ l1a_counts_dataset : xr.Dataset
146
162
  The L1A counts dataset.
163
+ coords : list
164
+ A list of coordinates to assign to the L1B dataset.
147
165
 
148
166
  Returns
149
167
  -------
150
- xr.Dataset
151
- The processed L1B standard rates dataset.
168
+ l1b_dataset : xr.Dataset
169
+ An L1B dataset with coordinates and dynamic threshold state.
152
170
  """
153
- # Create a new dataset to store the L1B standard rates
154
- l1b_standard_rates_dataset = xr.Dataset()
155
-
156
- # Add required coordinates from the raw_counts_dataset
157
- coords = [
158
- "epoch",
159
- "gain",
160
- "sngrates_index",
161
- "coinrates_index",
162
- "pbufrates_index",
163
- "l2fgrates_index",
164
- "l2bgrates_index",
165
- "l3fgrates_index",
166
- "l3bgrates_index",
167
- "penfgrates_index",
168
- "penbgrates_index",
169
- "ialirtrates_index",
170
- ]
171
- l1b_standard_rates_dataset = l1b_standard_rates_dataset.assign_coords(
172
- {coord: raw_counts_dataset.coords[coord] for coord in coords}
171
+ l1b_dataset = xr.Dataset(
172
+ coords={coord: l1a_counts_dataset.coords[coord] for coord in coords}
173
173
  )
174
-
175
- # Add dynamic threshold field
176
- l1b_standard_rates_dataset["dynamic_threshold_state"] = raw_counts_dataset[
174
+ l1b_dataset["dynamic_threshold_state"] = l1a_counts_dataset[
177
175
  "hdr_dynamic_threshold_state"
178
176
  ]
177
+ return l1b_dataset
178
+
179
179
 
180
- # Define fields from the raw_counts_dataset to calculate standard rates from
180
+ def process_standard_rates_data(
181
+ l1a_counts_dataset: xr.Dataset, livetime: xr.DataArray
182
+ ) -> xr.Dataset:
183
+ """
184
+ Will process L1B standard rates data from L1A raw counts data.
185
+
186
+ Parameters
187
+ ----------
188
+ l1a_counts_dataset : xr.Dataset
189
+ The L1A counts dataset.
190
+
191
+ livetime : xr.DataArray
192
+ 1D array of livetime values calculated from the livetime counter.
193
+ Shape equals the number of epochs in the dataset.
194
+
195
+ Returns
196
+ -------
197
+ xr.Dataset
198
+ The processed L1B standard rates dataset.
199
+ """
200
+ # Initialize the L1B standard rates dataset with coordinates from the L1A dataset
201
+ l1b_standard_rates_dataset = initialize_l1b_dataset(
202
+ l1a_counts_dataset,
203
+ coords=[
204
+ "epoch",
205
+ "gain",
206
+ "sngrates_index",
207
+ "coinrates_index",
208
+ "pbufrates_index",
209
+ "l2fgrates_index",
210
+ "l2bgrates_index",
211
+ "l3fgrates_index",
212
+ "l3bgrates_index",
213
+ "penfgrates_index",
214
+ "penbgrates_index",
215
+ "ialirtrates_index",
216
+ ],
217
+ )
218
+
219
+ # Define fields from the L1A counts dataset to calculate standard rates from
181
220
  standard_rate_fields = [
182
221
  "sngrates",
183
222
  "coinrates",
@@ -193,16 +232,287 @@ def process_standard_rates_data(raw_counts_dataset: xr.Dataset) -> xr.Dataset:
193
232
  "l4bgrates",
194
233
  ]
195
234
 
196
- # Calculate livetime from the livetime counter
197
- livetime = raw_counts_dataset["livetime_counter"] / 270
198
-
199
- # Calculate standard rates by dividing the raw counts by livetime for
200
- # data variables with names that contain a substring from a defined
201
- # list of field names.
202
- for var in raw_counts_dataset.data_vars:
203
- if var != "livetime_counter" and any(
204
- base_var in var for base_var in standard_rate_fields
205
- ):
206
- l1b_standard_rates_dataset[var] = raw_counts_dataset[var] / livetime
235
+ for var in standard_rate_fields:
236
+ # Add counts and uncertainty data to the dataset
237
+ l1b_standard_rates_dataset[var] = l1a_counts_dataset[var]
238
+ l1b_standard_rates_dataset[f"{var}_stat_uncert_minus"] = l1a_counts_dataset[
239
+ f"{var}_stat_uncert_minus"
240
+ ]
241
+ l1b_standard_rates_dataset[f"{var}_stat_uncert_plus"] = l1a_counts_dataset[
242
+ f"{var}_stat_uncert_plus"
243
+ ]
244
+ # Calculate rates using livetime
245
+ l1b_standard_rates_dataset = calculate_rates(
246
+ l1b_standard_rates_dataset, var, livetime
247
+ )
207
248
 
208
249
  return l1b_standard_rates_dataset
250
+
251
+
252
+ def calculate_rates(
253
+ dataset: xr.Dataset,
254
+ var: str,
255
+ livetime: xr.DataArray,
256
+ ) -> xr.Dataset:
257
+ """
258
+ Calculate rates by dividing counts by livetime.
259
+
260
+ Parameters
261
+ ----------
262
+ dataset : xr.Dataset
263
+ The L1B dataset containing counts data.
264
+ var : str
265
+ The name of the variable to calculate rates for.
266
+ livetime : xr.DataArray
267
+ 1D array of livetime values. Shape equals the
268
+ number of epochs in the dataset.
269
+
270
+ Returns
271
+ -------
272
+ xr.Dataset
273
+ The dataset with rates.
274
+ """
275
+ dataset[f"{var}"] = (dataset[f"{var}"] / livetime).astype(np.float32)
276
+ dataset[f"{var}_stat_uncert_minus"] = (
277
+ dataset[f"{var}_stat_uncert_minus"] / livetime
278
+ ).astype(np.float32)
279
+ dataset[f"{var}_stat_uncert_plus"] = (
280
+ dataset[f"{var}_stat_uncert_plus"] / livetime
281
+ ).astype(np.float32)
282
+
283
+ return dataset
284
+
285
+
286
+ def sum_livetime_10min(livetime: xr.DataArray) -> xr.DataArray:
287
+ """
288
+ Sum livetime values in 10-minute intervals.
289
+
290
+ Parameters
291
+ ----------
292
+ livetime : xr.DataArray
293
+ 1D array of livetime values. Shape equals the number of epochs in the dataset.
294
+
295
+ Returns
296
+ -------
297
+ xr.DataArray
298
+ Livetime summed over 10-minute intervals. Values repeated for each epoch in the
299
+ 10-minute intervals to match the original livetime array shape.
300
+ [5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7].
301
+ """
302
+ livetime_10min_sum = [
303
+ livetime[i : i + 10].sum().item() for i in range(0, len(livetime) - 9, 10)
304
+ ]
305
+ livetime_expanded = np.repeat(livetime_10min_sum, 10)
306
+ return xr.DataArray(livetime_expanded, dims=livetime.dims, coords=livetime.coords)
307
+
308
+
309
+ def process_summed_rates_data(
310
+ l1a_counts_dataset: xr.Dataset, livetime: xr.DataArray
311
+ ) -> xr.Dataset:
312
+ """
313
+ Will process L1B summed rates data from L1A raw counts data.
314
+
315
+ This function calculates summed rates for each particle type and energy range.
316
+ The counts that are summed come from the l2fgrates, l3fgrates, and penfgrates
317
+ data variables in the L1A counts data. These variables represent counts
318
+ of different detector penetration ranges (Range 2, Range 3, and Range 4
319
+ respectively). Only the energy ranges specified in the
320
+ SUMMED_PARTICLE_ENERGY_RANGE_MAPPING dictionary are included in this product.
321
+
322
+ The summed rates are calculated by summing the counts for each energy range and
323
+ dividing by the livetime.
324
+
325
+ Parameters
326
+ ----------
327
+ l1a_counts_dataset : xr.Dataset
328
+ The L1A counts dataset.
329
+
330
+ livetime : xr.DataArray
331
+ 1D array of livetime values calculated from the livetime counter.
332
+ Shape equals the number of epochs in the dataset.
333
+
334
+ Returns
335
+ -------
336
+ xr.Dataset
337
+ The processed L1B summed rates dataset.
338
+ """
339
+ # Initialize the L1B summed rates dataset with coordinates from the L1A dataset
340
+ l1b_summed_rates_dataset = initialize_l1b_dataset(
341
+ l1a_counts_dataset, coords=["epoch"]
342
+ )
343
+
344
+ for particle, energy_ranges in SUMMED_PARTICLE_ENERGY_RANGE_MAPPING.items():
345
+ # Sum counts for each energy range and add to dataset
346
+ l1b_summed_rates_dataset = add_summed_particle_data_to_dataset(
347
+ l1b_summed_rates_dataset,
348
+ l1a_counts_dataset,
349
+ particle,
350
+ energy_ranges,
351
+ )
352
+ # Calculate rates using livetime
353
+ l1b_summed_rates_dataset = calculate_rates(
354
+ l1b_summed_rates_dataset, particle, livetime
355
+ )
356
+
357
+ return l1b_summed_rates_dataset
358
+
359
+
360
+ def subset_data_for_sectored_counts(
361
+ l1a_counts_dataset: xr.Dataset, livetime: xr.DataArray
362
+ ) -> tuple[xr.Dataset, xr.DataArray]:
363
+ """
364
+ Subset data for complete sets of sectored counts and corresponding livetime values.
365
+
366
+ A set of sectored data starts with hydrogen and ends with iron and correspond to
367
+ the mod 10 values 0-9. The livetime values from the previous 10 minutes are used
368
+ to calculate the rates for each set since those counts are transmitted 10 minutes
369
+ after they were collected.
370
+
371
+ Parameters
372
+ ----------
373
+ l1a_counts_dataset : xr.Dataset
374
+ The L1A counts dataset.
375
+ livetime : xr.DataArray
376
+ 1D array of livetime values calculated from the livetime counter.
377
+
378
+ Returns
379
+ -------
380
+ tuple[xr.Dataset, xr.DataArray]
381
+ Subsetted L1A counts dataset and corresponding livetime values.
382
+ """
383
+ # Identify 10-minute intervals of complete sectored counts.
384
+ bin_size = 10
385
+ mod_10 = l1a_counts_dataset.hdr_minute_cnt.values % 10
386
+ pattern = np.arange(bin_size)
387
+
388
+ # Use sliding windows to find pattern matches
389
+ matches = np.all(
390
+ np.lib.stride_tricks.sliding_window_view(mod_10, bin_size) == pattern, axis=1
391
+ )
392
+ start_indices = np.where(matches)[0]
393
+
394
+ # Filter out start indices that are less than or equal to the bin size
395
+ # since the previous 10 minutes are needed
396
+ start_indices = start_indices[start_indices > bin_size]
397
+ data_slice = slice(start_indices[0], start_indices[-1] + bin_size)
398
+
399
+ # Subset data to include only complete sets of sectored counts
400
+ l1b_sectored_rates_dataset = l1a_counts_dataset.isel(epoch=data_slice)
401
+
402
+ # Subset livetime staggered from sectored counts by 10 minutes
403
+ livetime_slice = slice(start_indices[0] - bin_size, start_indices[-1])
404
+ livetime = livetime[livetime_slice]
405
+
406
+ return l1b_sectored_rates_dataset, livetime
407
+
408
+
409
+ def process_sectored_rates_data(
410
+ l1a_counts_dataset: xr.Dataset, livetime: xr.DataArray
411
+ ) -> xr.Dataset:
412
+ """
413
+ Will process L1B sectored rates data from L1A raw counts data.
414
+
415
+ A complete set of sectored counts is taken over 10 science frames (10 minutes)
416
+ where each science frame contains counts for one species and energy range.
417
+
418
+ Species and energy ranges are as follows:
419
+
420
+ H 1.8 - 3.6 MeV, 4.0 - 6.0 MeV, 6.0 - 10 MeV
421
+ 4He 4.0 - 6.0 MeV, 6.0 - 12.0 MeV
422
+ CNO 4.0 - 6.0 MeV, 6.0 - 12.0 MeV
423
+ NeMgSi 4.0 - 6.0 MeV, 6.0 - 12.0 MeV
424
+ Fe 4.0 - 12.0 MeV
425
+
426
+ Sectored counts data is transmitted 10 minutes after they are collected.
427
+ To calculate rates, the sectored counts over 10 minutes need to be divided by
428
+ the sum of livetime values from the previous 10 minutes.
429
+
430
+ Parameters
431
+ ----------
432
+ l1a_counts_dataset : xr.Dataset
433
+ The L1A counts dataset.
434
+
435
+ livetime : xr.DataArray
436
+ 1D array of livetime values calculated from the livetime counter.
437
+ Shape equals the number of epochs in the dataset.
438
+
439
+ Returns
440
+ -------
441
+ xr.Dataset
442
+ The processed L1B sectored rates dataset.
443
+ """
444
+ # TODO
445
+ # -filter by epoch values in day being processed.
446
+ # middle epoch (or mod 5 value for 6th frame)
447
+ # -consider refactoring calculate_rates function to handle sectored rates
448
+
449
+ # Define particles and coordinates
450
+ particles = ["h", "he4", "cno", "nemgsi", "fe"]
451
+
452
+ # Extract relevant data variable names that start with a particle name
453
+ data_vars = [
454
+ str(var)
455
+ for var in l1a_counts_dataset.data_vars
456
+ if any(str(var).startswith(f"{p}_") for p in particles)
457
+ ]
458
+
459
+ # Subset data for complete sets of sectored counts and corresponding livetime values
460
+ l1a_counts_dataset, livetime = subset_data_for_sectored_counts(
461
+ l1a_counts_dataset, livetime
462
+ )
463
+
464
+ # Sum livetime over 10 minute intervals
465
+ livetime_10min = sum_livetime_10min(livetime)
466
+
467
+ # Initialize the L1B dataset with coordinates from the subset L1A dataset
468
+ l1b_sectored_rates_dataset = initialize_l1b_dataset(
469
+ l1a_counts_dataset,
470
+ coords=[
471
+ "epoch",
472
+ "declination",
473
+ "azimuth",
474
+ "h_energy_mean",
475
+ "he4_energy_mean",
476
+ "cno_energy_mean",
477
+ "nemgsi_energy_mean",
478
+ "fe_energy_mean",
479
+ ],
480
+ )
481
+
482
+ # Dictionary to store variable rename mappings for L1B dataset
483
+ rename_map = {}
484
+
485
+ # # Compute rates, skipping fill values, and add to the L1B dataset
486
+ for var in data_vars:
487
+ if "sectored_counts" in var:
488
+ # Determine the new variable name for the L1B dataset
489
+ if "_sectored_counts" in var:
490
+ new_var = var.replace("_sectored_counts", "")
491
+ else:
492
+ new_var = None
493
+ if new_var:
494
+ rename_map[var] = new_var
495
+
496
+ # Since epoch times don't align, convert xarray data arrays to numpy arrays
497
+ # to avoid rates being calculated along the epoch dimension.
498
+ # Reshape livetime to match 4D shape of counts.
499
+ counts = l1a_counts_dataset[var].values
500
+ livetime_10min_reshaped = livetime_10min.values[:, None, None, None]
501
+ rates = xr.DataArray(
502
+ np.where(
503
+ counts != FILLVAL_INT64,
504
+ (counts / livetime_10min_reshaped).astype(np.float32),
505
+ FILLVAL_FLOAT32,
506
+ ),
507
+ dims=l1a_counts_dataset[var].dims,
508
+ )
509
+ l1b_sectored_rates_dataset[var] = rates
510
+ else:
511
+ # Add other data variables to the dataset
512
+ l1b_sectored_rates_dataset[var] = l1a_counts_dataset[var]
513
+
514
+ # Rename variables in L1B dataset
515
+ if rename_map:
516
+ l1b_sectored_rates_dataset = l1b_sectored_rates_dataset.rename(rename_map)
517
+
518
+ return l1b_sectored_rates_dataset