imap-processing 0.12.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 (272) hide show
  1. imap_processing/__init__.py +1 -0
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/ccsds_data.py +1 -2
  4. imap_processing/ccsds/excel_to_xtce.py +1 -2
  5. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +18 -12
  6. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +569 -0
  7. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
  8. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +5 -5
  9. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +20 -1
  10. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +6 -4
  11. imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +3 -3
  12. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +15 -0
  13. imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
  14. imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +16 -0
  15. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +178 -5
  16. imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
  17. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +33 -19
  18. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +8 -48
  19. imap_processing/cdf/utils.py +41 -33
  20. imap_processing/cli.py +463 -234
  21. imap_processing/codice/codice_l1a.py +260 -47
  22. imap_processing/codice/codice_l1b.py +51 -152
  23. imap_processing/codice/constants.py +38 -1
  24. imap_processing/ena_maps/ena_maps.py +658 -65
  25. imap_processing/ena_maps/utils/coordinates.py +1 -1
  26. imap_processing/ena_maps/utils/spatial_utils.py +10 -5
  27. imap_processing/glows/l1a/glows_l1a.py +28 -99
  28. imap_processing/glows/l1a/glows_l1a_data.py +2 -2
  29. imap_processing/glows/l1b/glows_l1b.py +1 -4
  30. imap_processing/glows/l1b/glows_l1b_data.py +1 -3
  31. imap_processing/glows/l2/glows_l2.py +2 -5
  32. imap_processing/hi/l1a/hi_l1a.py +31 -12
  33. imap_processing/hi/l1b/hi_l1b.py +80 -43
  34. imap_processing/hi/l1c/hi_l1c.py +12 -16
  35. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
  36. imap_processing/hit/hit_utils.py +93 -35
  37. imap_processing/hit/l0/decom_hit.py +3 -1
  38. imap_processing/hit/l1a/hit_l1a.py +30 -25
  39. imap_processing/hit/l1b/constants.py +6 -2
  40. imap_processing/hit/l1b/hit_l1b.py +279 -318
  41. imap_processing/hit/l2/constants.py +37 -0
  42. imap_processing/hit/l2/hit_l2.py +373 -264
  43. imap_processing/ialirt/l0/parse_mag.py +138 -10
  44. imap_processing/ialirt/l0/process_swapi.py +69 -0
  45. imap_processing/ialirt/l0/process_swe.py +318 -22
  46. imap_processing/ialirt/packet_definitions/ialirt.xml +216 -212
  47. imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +1 -1
  48. imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +1 -1
  49. imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
  50. imap_processing/ialirt/utils/grouping.py +1 -1
  51. imap_processing/idex/idex_constants.py +9 -1
  52. imap_processing/idex/idex_l0.py +22 -8
  53. imap_processing/idex/idex_l1a.py +75 -44
  54. imap_processing/idex/idex_l1b.py +9 -8
  55. imap_processing/idex/idex_l2a.py +79 -45
  56. imap_processing/idex/idex_l2b.py +120 -0
  57. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -39
  58. imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
  59. imap_processing/lo/l0/lo_science.py +1 -2
  60. imap_processing/lo/l1a/lo_l1a.py +1 -4
  61. imap_processing/lo/l1b/lo_l1b.py +527 -6
  62. imap_processing/lo/l1b/tof_conversions.py +11 -0
  63. imap_processing/lo/l1c/lo_l1c.py +1 -4
  64. imap_processing/mag/constants.py +43 -0
  65. imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
  66. imap_processing/mag/l1a/mag_l1a.py +2 -9
  67. imap_processing/mag/l1a/mag_l1a_data.py +10 -10
  68. imap_processing/mag/l1b/mag_l1b.py +84 -17
  69. imap_processing/mag/l1c/interpolation_methods.py +180 -3
  70. imap_processing/mag/l1c/mag_l1c.py +236 -70
  71. imap_processing/mag/l2/mag_l2.py +140 -0
  72. imap_processing/mag/l2/mag_l2_data.py +288 -0
  73. imap_processing/spacecraft/quaternions.py +1 -3
  74. imap_processing/spice/geometry.py +3 -3
  75. imap_processing/spice/kernels.py +0 -276
  76. imap_processing/spice/pointing_frame.py +257 -0
  77. imap_processing/spice/repoint.py +48 -19
  78. imap_processing/spice/spin.py +38 -33
  79. imap_processing/spice/time.py +24 -0
  80. imap_processing/swapi/l1/swapi_l1.py +16 -12
  81. imap_processing/swapi/l2/swapi_l2.py +116 -4
  82. imap_processing/swapi/swapi_utils.py +32 -0
  83. imap_processing/swe/l1a/swe_l1a.py +2 -9
  84. imap_processing/swe/l1a/swe_science.py +8 -11
  85. imap_processing/swe/l1b/swe_l1b.py +898 -23
  86. imap_processing/swe/l2/swe_l2.py +21 -77
  87. imap_processing/swe/utils/swe_constants.py +1 -0
  88. imap_processing/tests/ccsds/test_excel_to_xtce.py +1 -1
  89. imap_processing/tests/cdf/test_utils.py +14 -16
  90. imap_processing/tests/codice/conftest.py +44 -33
  91. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
  92. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
  93. imap_processing/tests/codice/test_codice_l1a.py +20 -11
  94. imap_processing/tests/codice/test_codice_l1b.py +6 -7
  95. imap_processing/tests/conftest.py +78 -22
  96. imap_processing/tests/ena_maps/test_ena_maps.py +462 -33
  97. imap_processing/tests/ena_maps/test_spatial_utils.py +1 -1
  98. imap_processing/tests/glows/conftest.py +10 -14
  99. imap_processing/tests/glows/test_glows_decom.py +4 -4
  100. imap_processing/tests/glows/test_glows_l1a_cdf.py +6 -27
  101. imap_processing/tests/glows/test_glows_l1a_data.py +6 -8
  102. imap_processing/tests/glows/test_glows_l1b.py +11 -11
  103. imap_processing/tests/glows/test_glows_l1b_data.py +5 -5
  104. imap_processing/tests/glows/test_glows_l2.py +2 -8
  105. imap_processing/tests/hi/conftest.py +1 -1
  106. imap_processing/tests/hi/test_hi_l1b.py +10 -12
  107. imap_processing/tests/hi/test_hi_l1c.py +27 -24
  108. imap_processing/tests/hi/test_l1a.py +7 -9
  109. imap_processing/tests/hi/test_science_direct_event.py +2 -2
  110. imap_processing/tests/hit/helpers/l1_validation.py +44 -43
  111. imap_processing/tests/hit/test_decom_hit.py +1 -1
  112. imap_processing/tests/hit/test_hit_l1a.py +9 -9
  113. imap_processing/tests/hit/test_hit_l1b.py +172 -217
  114. imap_processing/tests/hit/test_hit_l2.py +380 -118
  115. imap_processing/tests/hit/test_hit_utils.py +122 -55
  116. imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
  117. imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
  118. imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
  119. imap_processing/tests/ialirt/unit/test_grouping.py +2 -2
  120. imap_processing/tests/ialirt/unit/test_parse_mag.py +71 -16
  121. imap_processing/tests/ialirt/unit/test_process_codicehi.py +3 -3
  122. imap_processing/tests/ialirt/unit/test_process_codicelo.py +3 -10
  123. imap_processing/tests/ialirt/unit/test_process_ephemeris.py +4 -4
  124. imap_processing/tests/ialirt/unit/test_process_hit.py +3 -3
  125. imap_processing/tests/ialirt/unit/test_process_swapi.py +24 -16
  126. imap_processing/tests/ialirt/unit/test_process_swe.py +115 -7
  127. imap_processing/tests/idex/conftest.py +72 -7
  128. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20241206_v001.pkts +0 -0
  129. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20250108_v001.pkts +0 -0
  130. imap_processing/tests/idex/test_idex_l0.py +33 -11
  131. imap_processing/tests/idex/test_idex_l1a.py +50 -23
  132. imap_processing/tests/idex/test_idex_l1b.py +104 -25
  133. imap_processing/tests/idex/test_idex_l2a.py +48 -32
  134. imap_processing/tests/idex/test_idex_l2b.py +93 -0
  135. imap_processing/tests/lo/test_lo_l1a.py +3 -3
  136. imap_processing/tests/lo/test_lo_l1b.py +371 -6
  137. imap_processing/tests/lo/test_lo_l1c.py +1 -1
  138. imap_processing/tests/lo/test_lo_science.py +6 -7
  139. imap_processing/tests/lo/test_star_sensor.py +1 -1
  140. imap_processing/tests/mag/conftest.py +58 -9
  141. imap_processing/tests/mag/test_mag_decom.py +4 -3
  142. imap_processing/tests/mag/test_mag_l1a.py +13 -7
  143. imap_processing/tests/mag/test_mag_l1b.py +9 -9
  144. imap_processing/tests/mag/test_mag_l1c.py +151 -47
  145. imap_processing/tests/mag/test_mag_l2.py +130 -0
  146. imap_processing/tests/mag/test_mag_validation.py +144 -7
  147. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-in.csv +1217 -0
  148. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-out.csv +1857 -0
  149. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-in.csv +1217 -0
  150. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-out.csv +1857 -0
  151. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-in.csv +1217 -0
  152. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-out.csv +1793 -0
  153. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-in.csv +1217 -0
  154. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-out.csv +1793 -0
  155. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-burst-in.csv +2561 -0
  156. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-in.csv +961 -0
  157. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-out.csv +1539 -0
  158. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-in.csv +1921 -0
  159. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-out.csv +2499 -0
  160. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-in.csv +865 -0
  161. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv +1196 -0
  162. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-in.csv +1729 -0
  163. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv +3053 -0
  164. imap_processing/tests/mag/validation/L2/imap_mag_l1b_norm-mago_20251017_v002.cdf +0 -0
  165. imap_processing/tests/mag/validation/calibration/imap_mag_l2-calibration-matrices_20251017_v004.cdf +0 -0
  166. imap_processing/tests/mag/validation/calibration/imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf +0 -0
  167. imap_processing/tests/spacecraft/test_quaternions.py +1 -1
  168. imap_processing/tests/spice/test_data/fake_repoint_data.csv +4 -4
  169. imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
  170. imap_processing/tests/spice/test_geometry.py +3 -3
  171. imap_processing/tests/spice/test_kernels.py +1 -200
  172. imap_processing/tests/spice/test_pointing_frame.py +185 -0
  173. imap_processing/tests/spice/test_repoint.py +20 -10
  174. imap_processing/tests/spice/test_spin.py +50 -9
  175. imap_processing/tests/spice/test_time.py +14 -0
  176. imap_processing/tests/swapi/lut/imap_swapi_esa-unit-conversion_20250211_v000.csv +73 -0
  177. imap_processing/tests/swapi/lut/imap_swapi_lut-notes_20250211_v000.csv +1025 -0
  178. imap_processing/tests/swapi/test_swapi_l1.py +7 -9
  179. imap_processing/tests/swapi/test_swapi_l2.py +180 -8
  180. imap_processing/tests/swe/lut/checker-board-indices.csv +24 -0
  181. imap_processing/tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv +385 -0
  182. imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv +3 -0
  183. imap_processing/tests/swe/test_swe_l1a.py +6 -6
  184. imap_processing/tests/swe/test_swe_l1a_science.py +3 -3
  185. imap_processing/tests/swe/test_swe_l1b.py +162 -24
  186. imap_processing/tests/swe/test_swe_l2.py +82 -102
  187. imap_processing/tests/test_cli.py +171 -88
  188. imap_processing/tests/test_utils.py +2 -1
  189. imap_processing/tests/ultra/data/mock_data.py +49 -21
  190. imap_processing/tests/ultra/unit/conftest.py +53 -70
  191. imap_processing/tests/ultra/unit/test_badtimes.py +2 -4
  192. imap_processing/tests/ultra/unit/test_cullingmask.py +4 -6
  193. imap_processing/tests/ultra/unit/test_de.py +3 -10
  194. imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
  195. imap_processing/tests/ultra/unit/test_decom_apid_881.py +15 -16
  196. imap_processing/tests/ultra/unit/test_decom_apid_883.py +12 -10
  197. imap_processing/tests/ultra/unit/test_decom_apid_896.py +202 -55
  198. imap_processing/tests/ultra/unit/test_lookup_utils.py +23 -1
  199. imap_processing/tests/ultra/unit/test_spacecraft_pset.py +3 -4
  200. imap_processing/tests/ultra/unit/test_ultra_l1a.py +84 -307
  201. imap_processing/tests/ultra/unit/test_ultra_l1b.py +30 -12
  202. imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
  203. imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +4 -1
  204. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +163 -29
  205. imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
  206. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +32 -43
  207. imap_processing/tests/ultra/unit/test_ultra_l2.py +230 -0
  208. imap_processing/ultra/constants.py +1 -1
  209. imap_processing/ultra/l0/decom_tools.py +21 -34
  210. imap_processing/ultra/l0/decom_ultra.py +168 -204
  211. imap_processing/ultra/l0/ultra_utils.py +152 -136
  212. imap_processing/ultra/l1a/ultra_l1a.py +55 -243
  213. imap_processing/ultra/l1b/badtimes.py +1 -4
  214. imap_processing/ultra/l1b/cullingmask.py +2 -6
  215. imap_processing/ultra/l1b/de.py +62 -47
  216. imap_processing/ultra/l1b/extendedspin.py +8 -4
  217. imap_processing/ultra/l1b/lookup_utils.py +72 -9
  218. imap_processing/ultra/l1b/ultra_l1b.py +3 -8
  219. imap_processing/ultra/l1b/ultra_l1b_culling.py +4 -4
  220. imap_processing/ultra/l1b/ultra_l1b_extended.py +236 -78
  221. imap_processing/ultra/l1c/histogram.py +2 -6
  222. imap_processing/ultra/l1c/spacecraft_pset.py +2 -4
  223. imap_processing/ultra/l1c/ultra_l1c.py +1 -5
  224. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +107 -60
  225. imap_processing/ultra/l2/ultra_l2.py +299 -0
  226. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +526 -0
  227. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +526 -0
  228. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +526 -0
  229. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +526 -0
  230. imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -2
  231. imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
  232. imap_processing/ultra/packet_definitions/README.md +38 -0
  233. imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +15302 -482
  234. imap_processing/ultra/utils/ultra_l1_utils.py +13 -12
  235. imap_processing/utils.py +1 -1
  236. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +3 -2
  237. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/RECORD +264 -225
  238. imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
  239. imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +0 -6
  240. imap_processing/mag/l1b/__init__.py +0 -0
  241. imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
  242. imap_processing/swe/l1b/swe_l1b_science.py +0 -699
  243. imap_processing/tests/swe/test_swe_l1b_science.py +0 -103
  244. imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
  245. imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
  246. /imap_processing/idex/packet_definitions/{idex_packet_definition.xml → idex_science_packet_definition.xml} +0 -0
  247. /imap_processing/tests/ialirt/{test_data → data}/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
  248. /imap_processing/tests/ialirt/{test_data → data}/l0/461971383-404.bin +0 -0
  249. /imap_processing/tests/ialirt/{test_data → data}/l0/461971384-405.bin +0 -0
  250. /imap_processing/tests/ialirt/{test_data → data}/l0/461971385-406.bin +0 -0
  251. /imap_processing/tests/ialirt/{test_data → data}/l0/461971386-407.bin +0 -0
  252. /imap_processing/tests/ialirt/{test_data → data}/l0/461971387-408.bin +0 -0
  253. /imap_processing/tests/ialirt/{test_data → data}/l0/461971388-409.bin +0 -0
  254. /imap_processing/tests/ialirt/{test_data → data}/l0/461971389-410.bin +0 -0
  255. /imap_processing/tests/ialirt/{test_data → data}/l0/461971390-411.bin +0 -0
  256. /imap_processing/tests/ialirt/{test_data → data}/l0/461971391-412.bin +0 -0
  257. /imap_processing/tests/ialirt/{test_data → data}/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
  258. /imap_processing/tests/ialirt/{test_data → data}/l0/IALiRT Raw Packet Telemetry.txt +0 -0
  259. /imap_processing/tests/ialirt/{test_data → data}/l0/apid01152.tlm +0 -0
  260. /imap_processing/tests/ialirt/{test_data → data}/l0/eu_SWP_IAL_20240826_152033.csv +0 -0
  261. /imap_processing/tests/ialirt/{test_data → data}/l0/hi_fsw_view_1_ccsds.bin +0 -0
  262. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.ccsds +0 -0
  263. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.csv +0 -0
  264. /imap_processing/tests/ialirt/{test_data → data}/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +0 -0
  265. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
  266. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  267. /imap_processing/tests/ialirt/{test_data → data}/l0/sample_decoded_i-alirt_data.csv +0 -0
  268. /imap_processing/tests/mag/validation/{imap_calibration_mag_20240229_v01.cdf → calibration/imap_mag_l1b-calibration_20240229_v001.cdf} +0 -0
  269. /imap_processing/{swe/l1b/engineering_unit_convert_table.csv → tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv} +0 -0
  270. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
  271. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
  272. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
@@ -42,7 +42,7 @@ SPIN_PHASE_BIN_CENTERS = (SPIN_PHASE_BIN_EDGES[:-1] + SPIN_PHASE_BIN_EDGES[1:])
42
42
  logger = logging.getLogger(__name__)
43
43
 
44
44
 
45
- def hi_l1c(dependencies: list, data_version: str) -> xr.Dataset:
45
+ def hi_l1c(dependencies: list) -> list[xr.Dataset]:
46
46
  """
47
47
  High level IMAP-Hi l1c processing function.
48
48
 
@@ -56,10 +56,6 @@ def hi_l1c(dependencies: list, data_version: str) -> xr.Dataset:
56
56
  dependencies : list
57
57
  Input dependencies needed for l1c processing.
58
58
 
59
- data_version : str
60
- Data version to write to CDF files and the Data_version CDF attribute.
61
- Should be in the format Vxxx.
62
-
63
59
  Returns
64
60
  -------
65
61
  l1c_dataset : xarray.Dataset
@@ -76,9 +72,7 @@ def hi_l1c(dependencies: list, data_version: str) -> xr.Dataset:
76
72
  "Input dependencies not recognized for l1c pset processing."
77
73
  )
78
74
 
79
- # TODO: revisit this
80
- l1c_dataset.attrs["Data_version"] = data_version
81
- return l1c_dataset
75
+ return [l1c_dataset]
82
76
 
83
77
 
84
78
  def generate_pset_dataset(
@@ -108,14 +102,11 @@ def generate_pset_dataset(
108
102
  config_df = CalibrationProductConfig.from_csv(calibration_prod_config_path)
109
103
 
110
104
  pset_dataset = empty_pset_dataset(
105
+ de_dataset.epoch.data[0],
111
106
  de_dataset.esa_energy_step.data,
112
107
  config_df.cal_prod_config.number_of_products,
113
108
  logical_source_parts["sensor"],
114
109
  )
115
- # For ISTP, epoch should be the center of the time bin.
116
- pset_dataset.epoch.data[0] = np.mean(de_dataset.epoch.data[[0, -1]]).astype(
117
- np.int64
118
- )
119
110
  pset_et = ttj2000ns_to_et(pset_dataset.epoch.data[0])
120
111
  # Calculate and add despun_z, hae_latitude, and hae_longitude variables to
121
112
  # the pset_dataset
@@ -144,13 +135,15 @@ def generate_pset_dataset(
144
135
 
145
136
 
146
137
  def empty_pset_dataset(
147
- l1b_energy_steps: np.ndarray, n_cal_prods: int, sensor_str: str
138
+ epoch_val: int, l1b_energy_steps: np.ndarray, n_cal_prods: int, sensor_str: str
148
139
  ) -> xr.Dataset:
149
140
  """
150
141
  Allocate an empty xarray.Dataset with appropriate pset coordinates.
151
142
 
152
143
  Parameters
153
144
  ----------
145
+ epoch_val : int
146
+ The starting epoch in J2000 TT nanoseconds for data in the PSET.
154
147
  l1b_energy_steps : np.ndarray
155
148
  The array of esa_energy_step data from the L1B DE product.
156
149
  n_cal_prods : int
@@ -170,12 +163,12 @@ def empty_pset_dataset(
170
163
  # preallocate coordinates xr.DataArrays
171
164
  coords = dict()
172
165
  # epoch coordinate has only 1 entry for pointing set
173
- epoch_attrs = attr_mgr.get_variable_attributes("epoch")
166
+ epoch_attrs = attr_mgr.get_variable_attributes("epoch", check_schema=False)
174
167
  epoch_attrs.update(
175
168
  attr_mgr.get_variable_attributes("hi_pset_epoch", check_schema=False)
176
169
  )
177
170
  coords["epoch"] = xr.DataArray(
178
- np.empty(1, dtype=np.int64), # TODO: get dtype from cdf attrs?
171
+ np.array([epoch_val], dtype=np.int64), # TODO: get dtype from cdf attrs?
179
172
  name="epoch",
180
173
  dims=["epoch"],
181
174
  attrs=epoch_attrs,
@@ -526,6 +519,9 @@ def pset_exposure(
526
519
  )[0]
527
520
  exposure_var["exposure_times"].values[:, i_esa] += new_exposure_times
528
521
 
522
+ # Convert exposure clock ticks to seconds
523
+ exposure_var["exposure_times"].values *= DE_CLOCK_TICK_S
524
+
529
525
  return exposure_var
530
526
 
531
527
 
@@ -604,7 +600,7 @@ def get_de_clock_ticks_for_esa_step(
604
600
  # The CCSDS packet gets created just AFTER the final spin in the 8-spin
605
601
  # ESA step group so this match is the end time. The start time is
606
602
  # 8-spins earlier.
607
- spin_start_mets = spin_df.spin_start_time.to_numpy()
603
+ spin_start_mets = spin_df.spin_start_met.to_numpy()
608
604
  # CCSDS MET has one second resolution, add one to it to make sure it is
609
605
  # greater than the spin start time it ended on.
610
606
  end_time_ind = np.flatnonzero(ccsds_met + 1 >= spin_start_mets).max()
@@ -0,0 +1,81 @@
1
+ Species, Sector, Lower Energy (MeV), Upper Energy (MeV), Delta E (MeV), Geometry Factor (cm2 sr), Efficiency, b
2
+ H ,0,1.8,4,2.2,0.41686,1,0
3
+ H ,1,1.8,4,2.2,0.49253,1,0
4
+ H ,2,1.8,4,2.2,0.45156,1,0
5
+ H ,3,1.8,4,2.2,0.35599,1,0
6
+ H ,4,1.8,4,2.2,0.33312,1,0
7
+ H ,5,1.8,4,2.2,0.47444,1,0
8
+ H ,6,1.8,4,2.2,0.49253,1,0
9
+ H ,7,1.8,4,2.2,0.41686,1,0
10
+ H ,0,4,6,2,0.42008,1,0
11
+ H ,1,4,6,2,0.49746,1,0
12
+ H ,2,4,6,2,0.45515,1,0
13
+ H ,3,4,6,2,0.35921,1,0
14
+ H ,4,4,6,2,0.33619,1,0
15
+ H ,5,4,6,2,0.47817,1,0
16
+ H ,6,4,6,2,0.49746,1,0
17
+ H ,7,4,6,2,0.42008,1,0
18
+ H ,0,6,10,4,0.39177,1,0
19
+ H ,1,6,10,4,0.47095,1,0
20
+ H ,2,6,10,4,0.42764,1,0
21
+ H ,3,6,10,4,0.33171,1,0
22
+ H ,4,6,10,4,0.31091,1,0
23
+ H ,5,6,10,4,0.44844,1,0
24
+ H ,6,6,10,4,0.47095,1,0
25
+ H ,7,6,10,4,0.39177,1,0
26
+ He4 ,0,4,6,2,0.41995,1,0
27
+ He4 ,1,4,6,2,0.49964,1,0
28
+ He4 ,2,4,6,2,0.45649,1,0
29
+ He4 ,3,4,6,2,0.3584,1,0
30
+ He4 ,4,4,6,2,0.33563,1,0
31
+ He4 ,5,4,6,2,0.47925,1,0
32
+ He4 ,6,4,6,2,0.49964,1,0
33
+ He4 ,7,4,6,2,0.41995,1,0
34
+ He4 ,0,6,12,6,0.42404,1,0
35
+ He4 ,1,6,12,6,0.5045,1,0
36
+ He4 ,2,6,12,6,0.45897,1,0
37
+ He4 ,3,6,12,6,0.36098,1,0
38
+ He4 ,4,6,12,6,0.33793,1,0
39
+ He4 ,5,6,12,6,0.48202,1,0
40
+ He4 ,6,6,12,6,0.5045,1,0
41
+ He4 ,7,6,12,6,0.42404,1,0
42
+ CNO ,0,4,6,2,0.41976,1,0
43
+ CNO ,1,4,6,2,0.49594,1,0
44
+ CNO ,2,4,6,2,0.45356,1,0
45
+ CNO ,3,4,6,2,0.35698,1,0
46
+ CNO ,4,4,6,2,0.33409,1,0
47
+ CNO ,5,4,6,2,0.47645,1,0
48
+ CNO ,6,4,6,2,0.49594,1,0
49
+ CNO ,7,4,6,2,0.41976,1,0
50
+ CNO ,0,6,12,6,0.42026,1,0
51
+ CNO ,1,6,12,6,0.49871,1,0
52
+ CNO ,2,6,12,6,0.45567,1,0
53
+ CNO ,3,6,12,6,0.35809,1,0
54
+ CNO ,4,6,12,6,0.3351,1,0
55
+ CNO ,5,6,12,6,0.47866,1,0
56
+ CNO ,6,6,12,6,0.49871,1,0
57
+ CNO ,7,6,12,6,0.42026,1,0
58
+ NeMgSi ,0,4,6,2,0.37544,1,0
59
+ NeMgSi ,1,4,6,2,0.43535,1,0
60
+ NeMgSi ,2,4,6,2,0.40251,1,0
61
+ NeMgSi ,3,4,6,2,0.32308,1,0
62
+ NeMgSi ,4,4,6,2,0.30221,1,0
63
+ NeMgSi ,5,4,6,2,0.42339,1,0
64
+ NeMgSi ,6,4,6,2,0.43535,1,0
65
+ NeMgSi ,7,4,6,2,0.37544,1,0
66
+ NeMgSi ,0,6,12,6,0.42046,1,0
67
+ NeMgSi ,1,6,12,6,0.49714,1,0
68
+ NeMgSi ,2,6,12,6,0.45432,1,0
69
+ NeMgSi ,3,6,12,6,0.35764,1,0
70
+ NeMgSi ,4,6,12,6,0.33475,1,0
71
+ NeMgSi ,5,6,12,6,0.47721,1,0
72
+ NeMgSi ,6,6,12,6,0.49714,1,0
73
+ NeMgSi ,7,6,12,6,0.42046,1,0
74
+ Fe ,0,4,12,8,0.2752,1,0
75
+ Fe ,1,4,12,8,0.31996,1,0
76
+ Fe ,2,4,12,8,0.29577,1,0
77
+ Fe ,3,4,12,8,0.23669,1,0
78
+ Fe ,4,4,12,8,0.2213,1,0
79
+ Fe ,5,4,12,8,0.31118,1,0
80
+ Fe ,6,4,12,8,0.31996,1,0
81
+ Fe ,7,4,12,8,0.2752,1,0
@@ -66,14 +66,12 @@ def get_datasets_by_apid(
66
66
  return datasets_by_apid
67
67
 
68
68
 
69
- def get_attribute_manager(data_version: str, level: str) -> ImapCdfAttributes:
69
+ def get_attribute_manager(level: str) -> ImapCdfAttributes:
70
70
  """
71
71
  Create an attribute manager for the HIT data products.
72
72
 
73
73
  Parameters
74
74
  ----------
75
- data_version : str
76
- Version of the data product being created.
77
75
  level : str
78
76
  Data level of the product being created.
79
77
 
@@ -86,7 +84,6 @@ def get_attribute_manager(data_version: str, level: str) -> ImapCdfAttributes:
86
84
  attr_mgr = ImapCdfAttributes()
87
85
  attr_mgr.add_instrument_global_attrs(instrument="hit")
88
86
  attr_mgr.add_instrument_variable_attrs(instrument="hit", level=level)
89
- attr_mgr.add_global_attribute("Data_version", data_version)
90
87
  return attr_mgr
91
88
 
92
89
 
@@ -227,7 +224,7 @@ def initialize_particle_data_arrays(
227
224
  epoch_size: int,
228
225
  ) -> xr.Dataset:
229
226
  """
230
- Create empty data arrays for a given particle.
227
+ Add empty data arrays for a given particle.
231
228
 
232
229
  Valid particle names:
233
230
  h
@@ -252,44 +249,43 @@ def initialize_particle_data_arrays(
252
249
  ----------
253
250
  dataset : xr.Dataset
254
251
  The dataset to add the data arrays to.
255
-
256
252
  particle : str
257
253
  The abbreviated particle name.
258
-
259
254
  num_energy_ranges : int
260
255
  Number of energy ranges for the particle.
261
256
  Used to define the shape of the data arrays.
262
-
263
257
  epoch_size : int
264
258
  Used to define the shape of the data arrays.
265
259
 
266
260
  Returns
267
261
  -------
268
- dataset : xr.Dataset
269
- The dataset with the added empty data arrays.
262
+ updated_ds : xr.Dataset
263
+ The updated dataset with the particle data arrays added.
270
264
  """
271
- dataset[f"{particle}"] = xr.DataArray(
265
+ updated_ds = dataset.copy()
266
+
267
+ updated_ds[f"{particle}"] = xr.DataArray(
272
268
  data=np.zeros((epoch_size, num_energy_ranges), dtype=np.float32),
273
269
  dims=["epoch", f"{particle}_energy_mean"],
274
270
  name=f"{particle}",
275
271
  )
276
- dataset[f"{particle}_delta_minus"] = xr.DataArray(
272
+ updated_ds[f"{particle}_stat_uncert_minus"] = xr.DataArray(
277
273
  data=np.zeros((epoch_size, num_energy_ranges), dtype=np.float32),
278
274
  dims=["epoch", f"{particle}_energy_mean"],
279
- name=f"{particle}_delta_minus",
275
+ name=f"{particle}_stat_uncert_minus",
280
276
  )
281
- dataset[f"{particle}_delta_plus"] = xr.DataArray(
277
+ updated_ds[f"{particle}_stat_uncert_plus"] = xr.DataArray(
282
278
  data=np.zeros((epoch_size, num_energy_ranges), dtype=np.float32),
283
279
  dims=["epoch", f"{particle}_energy_mean"],
284
- name=f"{particle}_delta_plus",
280
+ name=f"{particle}_stat_uncert_plus",
285
281
  )
286
-
287
- dataset.coords[f"{particle}_energy_mean"] = xr.DataArray(
282
+ updated_ds.coords[f"{particle}_energy_mean"] = xr.DataArray(
288
283
  np.zeros(num_energy_ranges, dtype=np.int8),
289
284
  dims=[f"{particle}_energy_mean"],
290
285
  name=f"{particle}_energy_mean",
291
286
  )
292
- return dataset
287
+
288
+ return updated_ds
293
289
 
294
290
 
295
291
  def sum_particle_data(
@@ -318,10 +314,10 @@ def sum_particle_data(
318
314
  summed_data : xr.DataArray
319
315
  The summed data for the given energy range.
320
316
 
321
- summed_uncertainty_delta_minus : xr.DataArray
317
+ summed_uncertainty_minus : xr.DataArray
322
318
  The summed data for delta minus statistical uncertainty.
323
319
 
324
- summed_uncertainty_delta_plus : xr.DataArray
320
+ summed_uncertainty_plus : xr.DataArray
325
321
  The summed data for delta plus statistical uncertainty.
326
322
  """
327
323
  summed_data = (
@@ -330,19 +326,19 @@ def sum_particle_data(
330
326
  + dataset["penfgrates"][:, indices["R4"]].sum(axis=1)
331
327
  )
332
328
 
333
- summed_uncertainty_delta_minus = (
334
- dataset["l2fgrates_delta_minus"][:, indices["R2"]].sum(axis=1)
335
- + dataset["l3fgrates_delta_minus"][:, indices["R3"]].sum(axis=1)
336
- + dataset["penfgrates_delta_minus"][:, indices["R4"]].sum(axis=1)
329
+ summed_uncertainty_minus = (
330
+ dataset["l2fgrates_stat_uncert_minus"][:, indices["R2"]].sum(axis=1)
331
+ + dataset["l3fgrates_stat_uncert_minus"][:, indices["R3"]].sum(axis=1)
332
+ + dataset["penfgrates_stat_uncert_minus"][:, indices["R4"]].sum(axis=1)
337
333
  )
338
334
 
339
- summed_uncertainty_delta_plus = (
340
- dataset["l2fgrates_delta_plus"][:, indices["R2"]].sum(axis=1)
341
- + dataset["l3fgrates_delta_plus"][:, indices["R3"]].sum(axis=1)
342
- + dataset["penfgrates_delta_plus"][:, indices["R4"]].sum(axis=1)
335
+ summed_uncertainty_plus = (
336
+ dataset["l2fgrates_stat_uncert_plus"][:, indices["R2"]].sum(axis=1)
337
+ + dataset["l3fgrates_stat_uncert_plus"][:, indices["R3"]].sum(axis=1)
338
+ + dataset["penfgrates_stat_uncert_plus"][:, indices["R4"]].sum(axis=1)
343
339
  )
344
340
 
345
- return summed_data, summed_uncertainty_delta_minus, summed_uncertainty_delta_plus
341
+ return summed_data, summed_uncertainty_minus, summed_uncertainty_plus
346
342
 
347
343
 
348
344
  def add_energy_variables(
@@ -367,27 +363,89 @@ def add_energy_variables(
367
363
 
368
364
  Returns
369
365
  -------
370
- xr.Dataset
371
- The dataset with the added energy variables.
366
+ updated_ds : xr.Dataset
367
+ The updated dataset with the energy variables added.
372
368
  """
369
+ updated_ds = dataset.copy()
370
+
373
371
  energy_mean = np.mean(
374
372
  np.array([energy_min_values, energy_max_values]), axis=0
375
373
  ).astype(np.float32)
376
374
 
377
- dataset[f"{particle}_energy_mean"] = xr.DataArray(
375
+ updated_ds[f"{particle}_energy_mean"] = xr.DataArray(
378
376
  data=energy_mean,
379
377
  dims=[f"{particle}_energy_mean"],
380
378
  name=f"{particle}_energy_mean",
381
379
  )
382
- dataset[f"{particle}_energy_delta_minus"] = xr.DataArray(
380
+ updated_ds[f"{particle}_energy_delta_minus"] = xr.DataArray(
383
381
  data=np.array(energy_mean - np.array(energy_min_values), dtype=np.float32),
384
382
  dims=[f"{particle}_energy_mean"],
385
383
  name=f"{particle}_energy_delta_minus",
386
384
  )
387
- dataset[f"{particle}_energy_delta_plus"] = xr.DataArray(
385
+ updated_ds[f"{particle}_energy_delta_plus"] = xr.DataArray(
388
386
  data=np.array(energy_max_values - energy_mean, dtype=np.float32),
389
387
  dims=[f"{particle}_energy_mean"],
390
388
  name=f"{particle}_energy_delta_plus",
391
389
  )
390
+ return updated_ds
392
391
 
393
- return dataset
392
+
393
+ def add_summed_particle_data_to_dataset(
394
+ dataset: xr.Dataset,
395
+ source_dataset: xr.Dataset,
396
+ particle: str,
397
+ energy_ranges: list,
398
+ ) -> xr.Dataset:
399
+ """
400
+ Add summed particle data to the dataset.
401
+
402
+ Parameters
403
+ ----------
404
+ dataset : xr.Dataset
405
+ The dataset to add the rates to (not modified in-place).
406
+ source_dataset : xr.Dataset
407
+ The dataset containing data to sum (counts or rates).
408
+ particle : str
409
+ The particle name.
410
+ energy_ranges : list
411
+ A list of energy range dictionaries for the particle.
412
+
413
+ Returns
414
+ -------
415
+ xr.Dataset
416
+ A new dataset with summed particle data added.
417
+ """
418
+ # Make a copy of the dataset to update
419
+ ds = dataset.copy()
420
+
421
+ # Initialize particle data arrays
422
+ ds = initialize_particle_data_arrays(
423
+ ds, particle, len(energy_ranges), source_dataset.sizes["epoch"]
424
+ )
425
+
426
+ # Initialize arrays for energy values
427
+ energy_min = np.zeros(len(energy_ranges), dtype=np.float32)
428
+ energy_max = np.zeros(len(energy_ranges), dtype=np.float32)
429
+
430
+ # Compute summed data and update the dataset
431
+ for i, energy_range_dict in enumerate(energy_ranges):
432
+ summed_data, summed_data_uncert_minus, summed_data_uncert_plus = (
433
+ sum_particle_data(source_dataset, energy_range_dict)
434
+ )
435
+
436
+ ds[f"{particle}"][:, i] = summed_data.astype(np.float32)
437
+ ds[f"{particle}_stat_uncert_minus"][:, i] = summed_data_uncert_minus.astype(
438
+ np.float32
439
+ )
440
+ ds[f"{particle}_stat_uncert_plus"][:, i] = summed_data_uncert_plus.astype(
441
+ np.float32
442
+ )
443
+
444
+ # Store energy range values
445
+ energy_min[i] = energy_range_dict["energy_min"]
446
+ energy_max[i] = energy_range_dict["energy_max"]
447
+
448
+ # Add energy variables
449
+ ds = add_energy_variables(ds, particle, energy_min, energy_max)
450
+
451
+ return ds
@@ -113,7 +113,9 @@ def parse_count_rates(sci_dataset: xr.Dataset) -> None:
113
113
  else:
114
114
  dims = ["epoch"]
115
115
 
116
- sci_dataset[field] = xr.DataArray(parsed_data, dims=dims, name=field)
116
+ sci_dataset[field] = xr.DataArray(
117
+ np.array(parsed_data, dtype=np.int64), dims=dims, name=field
118
+ )
117
119
  # Add dimensions to coordinates
118
120
  for dim in dims:
119
121
  if dim not in sci_dataset.coords:
@@ -24,7 +24,7 @@ logger = logging.getLogger(__name__)
24
24
  fillval = -9223372036854775808
25
25
 
26
26
 
27
- def hit_l1a(packet_file: str, data_version: str) -> list[xr.Dataset]:
27
+ def hit_l1a(packet_file: str) -> list[xr.Dataset]:
28
28
  """
29
29
  Will process HIT L0 data into L1A data products.
30
30
 
@@ -32,8 +32,6 @@ def hit_l1a(packet_file: str, data_version: str) -> list[xr.Dataset]:
32
32
  ----------
33
33
  packet_file : str
34
34
  Path to the CCSDS data packet file.
35
- data_version : str
36
- Version of the data product being created.
37
35
 
38
36
  Returns
39
37
  -------
@@ -44,7 +42,7 @@ def hit_l1a(packet_file: str, data_version: str) -> list[xr.Dataset]:
44
42
  datasets_by_apid = get_datasets_by_apid(packet_file)
45
43
 
46
44
  # Create the attribute manager for this data level
47
- attr_mgr = get_attribute_manager(data_version, "l1a")
45
+ attr_mgr = get_attribute_manager("l1a")
48
46
 
49
47
  l1a_datasets = []
50
48
 
@@ -63,7 +61,7 @@ def hit_l1a(packet_file: str, data_version: str) -> list[xr.Dataset]:
63
61
  return l1a_datasets
64
62
 
65
63
 
66
- def subcom_sectorates(sci_dataset: xr.Dataset) -> None:
64
+ def subcom_sectorates(sci_dataset: xr.Dataset) -> xr.Dataset:
67
65
  """
68
66
  Subcommutate sectorates data.
69
67
 
@@ -94,9 +92,16 @@ def subcom_sectorates(sci_dataset: xr.Dataset) -> None:
94
92
  ----------
95
93
  sci_dataset : xarray.Dataset
96
94
  Xarray dataset containing parsed HIT science data.
95
+
96
+ Returns
97
+ -------
98
+ sci_dataset : xarray.Dataset
99
+ Xarray dataset with sectored rates data organized by species.
97
100
  """
101
+ updated_dataset = sci_dataset.copy()
102
+
98
103
  # Calculate mod 10 values
99
- hdr_min_count_mod_10 = sci_dataset.hdr_minute_cnt.values % 10
104
+ hdr_min_count_mod_10 = updated_dataset.hdr_minute_cnt.values % 10
100
105
 
101
106
  # Reference mod 10 mapping to initialize data structure for species and
102
107
  # energy ranges and add 15x8 arrays with fill values for each science frame.
@@ -111,7 +116,7 @@ def subcom_sectorates(sci_dataset: xr.Dataset) -> None:
111
116
 
112
117
  # Update counts for science frames where data is available
113
118
  for i, mod_10 in enumerate(hdr_min_count_mod_10):
114
- data_by_species_and_energy_range[mod_10]["counts"][i] = sci_dataset[
119
+ data_by_species_and_energy_range[mod_10]["counts"][i] = updated_dataset[
115
120
  "sectorates"
116
121
  ].values[i]
117
122
 
@@ -136,24 +141,26 @@ def subcom_sectorates(sci_dataset: xr.Dataset) -> None:
136
141
  # shape: epoch, energy_mean, azimuth, declination
137
142
  rates_data = np.transpose(np.array(data["counts"]), axes=(1, 0, 2, 3))
138
143
 
139
- sci_dataset[f"{species}_sectored_counts"] = xr.DataArray(
144
+ updated_dataset[f"{species}_sectored_counts"] = xr.DataArray(
140
145
  data=rates_data,
141
146
  dims=["epoch", f"{species}_energy_mean", "azimuth", "declination"],
142
147
  name=f"{species}_counts_sectored",
143
148
  )
144
149
 
145
150
  # Add energy mean and deltas for each species
146
- sci_dataset = add_energy_variables(
147
- sci_dataset,
151
+ updated_dataset = add_energy_variables(
152
+ updated_dataset,
148
153
  species,
149
154
  np.array(data["energy_min"]),
150
155
  np.array(data["energy_max"]),
151
156
  )
152
157
 
158
+ return updated_dataset
159
+
153
160
 
154
161
  def calculate_uncertainties(dataset: xr.Dataset) -> xr.Dataset:
155
162
  """
156
- Calculate uncertainties for each counts data variable in the dataset.
163
+ Calculate statistical uncertainties.
157
164
 
158
165
  Calculate the upper and lower uncertainties. The uncertainty for
159
166
  the raw Lev1A HIT data will be calculated as asymmetric Poisson
@@ -161,10 +168,10 @@ def calculate_uncertainties(dataset: xr.Dataset) -> xr.Dataset:
161
168
  See section 5.5 in the algorithm document for details.
162
169
 
163
170
  The upper uncertainty will be calculated as
164
- DELTA_PLUS = sqrt(counts + 1) + 1
171
+ uncert_plus = sqrt(counts + 1) + 1
165
172
 
166
173
  The lower uncertainty will be calculated as
167
- DELTA_MINUS = sqrt(counts)
174
+ uncert_minus = sqrt(counts)
168
175
 
169
176
  Parameters
170
177
  ----------
@@ -217,13 +224,13 @@ def calculate_uncertainties(dataset: xr.Dataset) -> xr.Dataset:
217
224
  safe_values_plus = np.maximum(dataset[var] + 1, 0).astype(np.float32)
218
225
  safe_values_minus = np.maximum(dataset[var], 0).astype(np.float32)
219
226
 
220
- dataset[f"{var}_delta_plus"] = xr.DataArray(
227
+ dataset[f"{var}_stat_uncert_plus"] = xr.DataArray(
221
228
  np.where(
222
229
  mask, np.sqrt(safe_values_plus) + 1, dataset[var].astype(np.float32)
223
230
  ),
224
231
  dims=dataset[var].dims,
225
232
  )
226
- dataset[f"{var}_delta_minus"] = xr.DataArray(
233
+ dataset[f"{var}_stat_uncert_minus"] = xr.DataArray(
227
234
  np.where(mask, np.sqrt(safe_values_minus), dataset[var].astype(np.float32)),
228
235
  dims=dataset[var].dims,
229
236
  )
@@ -261,7 +268,7 @@ def process_science(
261
268
  sci_dataset = decom_hit(dataset)
262
269
 
263
270
  # Organize sectored rates by species type
264
- subcom_sectorates(sci_dataset)
271
+ sci_dataset = subcom_sectorates(sci_dataset)
265
272
 
266
273
  # Split the science data into count rates and event datasets
267
274
  pha_raw_dataset = xr.Dataset(
@@ -277,14 +284,14 @@ def process_science(
277
284
 
278
285
  datasets = []
279
286
  # Update attributes and dimensions
280
- for dataset, logical_source in zip(
287
+ for ds, logical_source in zip(
281
288
  [count_rates_dataset, pha_raw_dataset], logical_sources
282
289
  ):
283
- dataset.attrs = attr_mgr.get_global_attributes(logical_source)
290
+ ds.attrs = attr_mgr.get_global_attributes(logical_source)
284
291
 
285
292
  # TODO: Add CDF attributes to yaml once they're defined for L1A science data
286
293
  # Assign attributes and dimensions to each data array in the Dataset
287
- for field in dataset.data_vars.keys():
294
+ for field in ds.data_vars.keys():
288
295
  try:
289
296
  # Create a dict of dimensions using the DEPEND_I keys in the
290
297
  # attributes
@@ -293,19 +300,17 @@ def process_science(
293
300
  for key, value in attr_mgr.get_variable_attributes(field).items()
294
301
  if "DEPEND" in key
295
302
  }
296
- dataset[field].attrs = attr_mgr.get_variable_attributes(field)
297
- dataset[field].assign_coords(dims)
303
+ ds[field].attrs = attr_mgr.get_variable_attributes(field)
304
+ ds[field].assign_coords(dims)
298
305
  except KeyError:
299
306
  print(f"Field {field} not found in attribute manager.")
300
307
  logger.warning(f"Field {field} not found in attribute manager.")
301
308
 
302
309
  # Skip schema check for epoch to prevent attr_mgr from adding the
303
310
  # DEPEND_0 attribute which isn't required for epoch
304
- dataset.epoch.attrs = attr_mgr.get_variable_attributes(
305
- "epoch", check_schema=False
306
- )
311
+ ds.epoch.attrs = attr_mgr.get_variable_attributes("epoch", check_schema=False)
307
312
 
308
- datasets.append(dataset)
313
+ datasets.append(ds)
309
314
 
310
315
  logger.info(f"HIT L1A dataset created for {logical_source}")
311
316
 
@@ -2,7 +2,11 @@
2
2
 
3
3
  # Expected number of livestim pulses per integration time.
4
4
  # This is used to calculate the fractional livetime
5
- livestim_pulses = 270
5
+ LIVESTIM_PULSES = 270
6
+
7
+ # Fill values for missing data
8
+ FILLVAL_FLOAT32 = -1.00e31
9
+ FILLVAL_INT64 = -9223372036854775808
6
10
 
7
11
  # For the L1B summed rates product, counts are summed by particle type,
8
12
  # energy range, and detector penetration range (Range 2, Range 3, and Range 4).
@@ -20,7 +24,7 @@ livestim_pulses = 270
20
24
  # R4 = Indices for Range 4 (PENFGRATES)
21
25
  # energy_units: MeV/n
22
26
 
23
- PARTICLE_ENERGY_RANGE_MAPPING = {
27
+ SUMMED_PARTICLE_ENERGY_RANGE_MAPPING = {
24
28
  "h": [
25
29
  {
26
30
  "energy_min": 1.8,