imap-processing 0.6.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.
Files changed (398) hide show
  1. imap_processing/__init__.py +34 -0
  2. imap_processing/_version.py +3 -0
  3. imap_processing/ccsds/__init__.py +0 -0
  4. imap_processing/ccsds/ccsds_data.py +55 -0
  5. imap_processing/ccsds/excel_to_xtce.py +477 -0
  6. imap_processing/cdf/__init__.py +0 -0
  7. imap_processing/cdf/cdf_attribute_manager.py +322 -0
  8. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +212 -0
  9. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +1358 -0
  10. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +391 -0
  11. imap_processing/cdf/config/imap_constant_attrs.yaml +33 -0
  12. imap_processing/cdf/config/imap_default_global_cdf_attrs.yaml +17 -0
  13. imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +41 -0
  14. imap_processing/cdf/config/imap_glows_l1a_variable_attrs.yaml +499 -0
  15. imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +334 -0
  16. imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +51 -0
  17. imap_processing/cdf/config/imap_hi_variable_attrs.yaml +435 -0
  18. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +27 -0
  19. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +493 -0
  20. imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +564 -0
  21. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +24 -0
  22. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +426 -0
  23. imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +90 -0
  24. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +487 -0
  25. imap_processing/cdf/config/imap_lo_l1b_variable_attrs.yaml +121 -0
  26. imap_processing/cdf/config/imap_lo_l1c_variable_attrs.yaml +179 -0
  27. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +97 -0
  28. imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +201 -0
  29. imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +33 -0
  30. imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +137 -0
  31. imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +24 -0
  32. imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +234 -0
  33. imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +273 -0
  34. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +100 -0
  35. imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +52 -0
  36. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +297 -0
  37. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +121 -0
  38. imap_processing/cdf/config/shared/default_global_cdf_attrs_schema.yaml +246 -0
  39. imap_processing/cdf/config/shared/default_variable_cdf_attrs_schema.yaml +466 -0
  40. imap_processing/cdf/imap_cdf_manager.py +64 -0
  41. imap_processing/cdf/utils.py +147 -0
  42. imap_processing/cli.py +863 -0
  43. imap_processing/codice/__init__.py +1 -0
  44. imap_processing/codice/codice_l0.py +54 -0
  45. imap_processing/codice/codice_l1a.py +558 -0
  46. imap_processing/codice/codice_l1b.py +194 -0
  47. imap_processing/codice/constants.py +986 -0
  48. imap_processing/codice/data/esa_sweep_values.csv +257 -0
  49. imap_processing/codice/data/lo_stepping_values.csv +129 -0
  50. imap_processing/codice/decompress.py +142 -0
  51. imap_processing/codice/packet_definitions/P_COD_NHK.xml +618 -0
  52. imap_processing/codice/packet_definitions/codice_packet_definition.xml +5073 -0
  53. imap_processing/codice/utils.py +95 -0
  54. imap_processing/decom.py +40 -0
  55. imap_processing/glows/__init__.py +1 -0
  56. imap_processing/glows/ancillary/l1b_conversion_table_v001.json +42 -0
  57. imap_processing/glows/l0/__init__.py +0 -0
  58. imap_processing/glows/l0/decom_glows.py +91 -0
  59. imap_processing/glows/l0/glows_l0_data.py +194 -0
  60. imap_processing/glows/l1a/glows_l1a.py +424 -0
  61. imap_processing/glows/l1a/glows_l1a_data.py +555 -0
  62. imap_processing/glows/l1b/glows_l1b.py +270 -0
  63. imap_processing/glows/l1b/glows_l1b_data.py +583 -0
  64. imap_processing/glows/packet_definitions/GLX_COMBINED.xml +254 -0
  65. imap_processing/glows/packet_definitions/P_GLX_TMSCDE.xml +97 -0
  66. imap_processing/glows/packet_definitions/P_GLX_TMSCHIST.xml +215 -0
  67. imap_processing/glows/utils/__init__.py +0 -0
  68. imap_processing/glows/utils/constants.py +105 -0
  69. imap_processing/hi/__init__.py +1 -0
  70. imap_processing/hi/l0/__init__.py +0 -0
  71. imap_processing/hi/l0/decom_hi.py +24 -0
  72. imap_processing/hi/l1a/__init__.py +0 -0
  73. imap_processing/hi/l1a/hi_l1a.py +73 -0
  74. imap_processing/hi/l1a/histogram.py +142 -0
  75. imap_processing/hi/l1a/housekeeping.py +27 -0
  76. imap_processing/hi/l1a/science_direct_event.py +341 -0
  77. imap_processing/hi/l1b/__init__.py +0 -0
  78. imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +154 -0
  79. imap_processing/hi/l1b/hi_l1b.py +127 -0
  80. imap_processing/hi/l1c/__init__.py +0 -0
  81. imap_processing/hi/l1c/hi_l1c.py +228 -0
  82. imap_processing/hi/packet_definitions/__init__.py +0 -0
  83. imap_processing/hi/packet_definitions/hi_packet_definition.xml +482 -0
  84. imap_processing/hi/utils.py +27 -0
  85. imap_processing/hit/__init__.py +1 -0
  86. imap_processing/hit/l0/__init__.py +0 -0
  87. imap_processing/hit/l0/data_classes/housekeeping.py +240 -0
  88. imap_processing/hit/l0/data_classes/science_packet.py +259 -0
  89. imap_processing/hit/l0/decom_hit.py +467 -0
  90. imap_processing/hit/l0/utils/hit_base.py +57 -0
  91. imap_processing/hit/l1a/__init__.py +0 -0
  92. imap_processing/hit/l1a/hit_l1a.py +254 -0
  93. imap_processing/hit/l1b/hit_l1b.py +179 -0
  94. imap_processing/hit/packet_definitions/hit_packet_definitions.xml +1276 -0
  95. imap_processing/ialirt/__init__.py +0 -0
  96. imap_processing/ialirt/l0/__init__.py +0 -0
  97. imap_processing/ialirt/l0/process_hit.py +220 -0
  98. imap_processing/ialirt/packet_definitions/__init__.py +0 -0
  99. imap_processing/ialirt/packet_definitions/ialirt.xml +778 -0
  100. imap_processing/ialirt/packet_definitions/ialirt_hit.xml +186 -0
  101. imap_processing/idex/__init__.py +2 -0
  102. imap_processing/idex/idex_constants.py +27 -0
  103. imap_processing/idex/idex_l0.py +31 -0
  104. imap_processing/idex/idex_l1a.py +631 -0
  105. imap_processing/idex/packet_definitions/idex_packet_definition.xml +3162 -0
  106. imap_processing/lo/__init__.py +1 -0
  107. imap_processing/lo/l0/__init__.py +0 -0
  108. imap_processing/lo/l0/data_classes/science_direct_events.py +215 -0
  109. imap_processing/lo/l0/data_classes/star_sensor.py +98 -0
  110. imap_processing/lo/l0/decompression_tables/12_to_16_bit.csv +4097 -0
  111. imap_processing/lo/l0/decompression_tables/8_to_12_bit.csv +257 -0
  112. imap_processing/lo/l0/decompression_tables/8_to_16_bit.csv +257 -0
  113. imap_processing/lo/l0/decompression_tables/decompression_tables.py +75 -0
  114. imap_processing/lo/l0/lo_apid.py +15 -0
  115. imap_processing/lo/l0/lo_science.py +150 -0
  116. imap_processing/lo/l0/utils/binary_string.py +59 -0
  117. imap_processing/lo/l0/utils/bit_decompression.py +62 -0
  118. imap_processing/lo/l0/utils/lo_base.py +57 -0
  119. imap_processing/lo/l1a/__init__.py +0 -0
  120. imap_processing/lo/l1a/lo_l1a.py +157 -0
  121. imap_processing/lo/l1b/lo_l1b.py +160 -0
  122. imap_processing/lo/l1c/lo_l1c.py +180 -0
  123. imap_processing/lo/packet_definitions/lo_xtce.xml +3541 -0
  124. imap_processing/mag/__init__.py +2 -0
  125. imap_processing/mag/constants.py +108 -0
  126. imap_processing/mag/l0/decom_mag.py +170 -0
  127. imap_processing/mag/l0/mag_l0_data.py +118 -0
  128. imap_processing/mag/l1a/mag_l1a.py +317 -0
  129. imap_processing/mag/l1a/mag_l1a_data.py +1007 -0
  130. imap_processing/mag/l1b/__init__.py +0 -0
  131. imap_processing/mag/l1b/imap_calibration_mag_20240229_v01.cdf +0 -0
  132. imap_processing/mag/l1b/mag_l1b.py +125 -0
  133. imap_processing/mag/l1c/mag_l1c.py +57 -0
  134. imap_processing/mag/packet_definitions/MAG_SCI_COMBINED.xml +235 -0
  135. imap_processing/quality_flags.py +91 -0
  136. imap_processing/spice/__init__.py +1 -0
  137. imap_processing/spice/geometry.py +322 -0
  138. imap_processing/spice/kernels.py +459 -0
  139. imap_processing/spice/time.py +72 -0
  140. imap_processing/swapi/__init__.py +1 -0
  141. imap_processing/swapi/l1/__init__.py +0 -0
  142. imap_processing/swapi/l1/swapi_l1.py +685 -0
  143. imap_processing/swapi/l2/__init__.py +0 -0
  144. imap_processing/swapi/l2/swapi_l2.py +107 -0
  145. imap_processing/swapi/packet_definitions/__init__.py +0 -0
  146. imap_processing/swapi/packet_definitions/swapi_packet_definition.xml +708 -0
  147. imap_processing/swapi/swapi_utils.py +25 -0
  148. imap_processing/swe/__init__.py +1 -0
  149. imap_processing/swe/l1a/__init__.py +0 -0
  150. imap_processing/swe/l1a/swe_l1a.py +48 -0
  151. imap_processing/swe/l1a/swe_science.py +223 -0
  152. imap_processing/swe/l1b/engineering_unit_convert_table.csv +65 -0
  153. imap_processing/swe/l1b/swe_esa_lookup_table.csv +1441 -0
  154. imap_processing/swe/l1b/swe_l1b.py +49 -0
  155. imap_processing/swe/l1b/swe_l1b_science.py +557 -0
  156. imap_processing/swe/packet_definitions/__init__.py +0 -0
  157. imap_processing/swe/packet_definitions/swe_packet_definition.xml +303 -0
  158. imap_processing/swe/utils/__init__.py +0 -0
  159. imap_processing/swe/utils/swe_utils.py +9 -0
  160. imap_processing/tests/__init__.py +0 -0
  161. imap_processing/tests/ccsds/test_data/expected_output.xml +171 -0
  162. imap_processing/tests/ccsds/test_excel_to_xtce.py +285 -0
  163. imap_processing/tests/cdf/__init__.py +0 -0
  164. imap_processing/tests/cdf/imap_default_global_cdf_attrs.yaml +8 -0
  165. imap_processing/tests/cdf/shared/default_global_cdf_attrs_schema.yaml +246 -0
  166. imap_processing/tests/cdf/shared/default_variable_cdf_attrs_schema.yaml +466 -0
  167. imap_processing/tests/cdf/test_cdf_attribute_manager.py +353 -0
  168. imap_processing/tests/cdf/test_data/imap_default_global_test_cdf_attrs.yaml +7 -0
  169. imap_processing/tests/cdf/test_data/imap_instrument1_global_cdf_attrs.yaml +14 -0
  170. imap_processing/tests/cdf/test_data/imap_instrument1_level1_variable_attrs.yaml +23 -0
  171. imap_processing/tests/cdf/test_data/imap_instrument2_global_cdf_attrs.yaml +23 -0
  172. imap_processing/tests/cdf/test_data/imap_instrument2_level2_variable_attrs.yaml +30 -0
  173. imap_processing/tests/cdf/test_data/imap_test_global.yaml +26 -0
  174. imap_processing/tests/cdf/test_data/imap_test_variable.yaml +41 -0
  175. imap_processing/tests/cdf/test_imap_cdf_manager.py +62 -0
  176. imap_processing/tests/cdf/test_utils.py +109 -0
  177. imap_processing/tests/codice/__init__.py +0 -0
  178. imap_processing/tests/codice/conftest.py +56 -0
  179. imap_processing/tests/codice/data/eu_unit_lookup_table.csv +101 -0
  180. imap_processing/tests/codice/data/idle_export_eu.COD_NHK_20230822_122700 2.csv +100 -0
  181. imap_processing/tests/codice/data/idle_export_raw.COD_NHK_20230822_122700.csv +100 -0
  182. imap_processing/tests/codice/data/imap_codice_l0_hi-counters-aggregated_20240429_v001.pkts +0 -0
  183. imap_processing/tests/codice/data/imap_codice_l0_hi-counters-singles_20240429_v001.pkts +0 -0
  184. imap_processing/tests/codice/data/imap_codice_l0_hi-omni_20240429_v001.pkts +0 -0
  185. imap_processing/tests/codice/data/imap_codice_l0_hi-pha_20240429_v001.pkts +0 -0
  186. imap_processing/tests/codice/data/imap_codice_l0_hi-sectored_20240429_v001.pkts +0 -0
  187. imap_processing/tests/codice/data/imap_codice_l0_hskp_20100101_v001.pkts +0 -0
  188. imap_processing/tests/codice/data/imap_codice_l0_lo-counters-aggregated_20240429_v001.pkts +0 -0
  189. imap_processing/tests/codice/data/imap_codice_l0_lo-counters-singles_20240429_v001.pkts +0 -0
  190. imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-angular_20240429_v001.pkts +0 -0
  191. imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-priority_20240429_v001.pkts +0 -0
  192. imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-species_20240429_v001.pkts +0 -0
  193. imap_processing/tests/codice/data/imap_codice_l0_lo-pha_20240429_v001.pkts +0 -0
  194. imap_processing/tests/codice/data/imap_codice_l0_lo-sw-angular_20240429_v001.pkts +0 -0
  195. imap_processing/tests/codice/data/imap_codice_l0_lo-sw-priority_20240429_v001.pkts +0 -0
  196. imap_processing/tests/codice/data/imap_codice_l0_lo-sw-species_20240429_v001.pkts +0 -0
  197. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-aggregated_20240429_v001.cdf +0 -0
  198. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-singles_20240429_v001.cdf +0 -0
  199. imap_processing/tests/codice/data/imap_codice_l1a_hi-omni_20240429_v001.cdf +0 -0
  200. imap_processing/tests/codice/data/imap_codice_l1a_hi-sectored_20240429_v001.cdf +0 -0
  201. imap_processing/tests/codice/data/imap_codice_l1a_hskp_20100101_v001.cdf +0 -0
  202. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-aggregated_20240429_v001.cdf +0 -0
  203. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-singles_20240429_v001.cdf +0 -0
  204. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-angular_20240429_v001.cdf +0 -0
  205. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-priority_20240429_v001.cdf +0 -0
  206. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-species_20240429_v001.cdf +0 -0
  207. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-angular_20240429_v001.cdf +0 -0
  208. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-priority_20240429_v001.cdf +0 -0
  209. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-species_20240429_v001.cdf +0 -0
  210. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-aggregated_20240429_v001.cdf +0 -0
  211. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-singles_20240429_v001.cdf +0 -0
  212. imap_processing/tests/codice/data/imap_codice_l1b_hi-omni_20240429_v001.cdf +0 -0
  213. imap_processing/tests/codice/data/imap_codice_l1b_hi-sectored_20240429_v001.cdf +0 -0
  214. imap_processing/tests/codice/data/imap_codice_l1b_hskp_20100101_v001.cdf +0 -0
  215. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-aggregated_20240429_v001.cdf +0 -0
  216. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-singles_20240429_v001.cdf +0 -0
  217. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-angular_20240429_v001.cdf +0 -0
  218. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-priority_20240429_v001.cdf +0 -0
  219. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-species_20240429_v001.cdf +0 -0
  220. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-angular_20240429_v001.cdf +0 -0
  221. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-priority_20240429_v001.cdf +0 -0
  222. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-species_20240429_v001.cdf +0 -0
  223. imap_processing/tests/codice/test_codice_l0.py +144 -0
  224. imap_processing/tests/codice/test_codice_l1a.py +187 -0
  225. imap_processing/tests/codice/test_codice_l1b.py +60 -0
  226. imap_processing/tests/codice/test_decompress.py +50 -0
  227. imap_processing/tests/conftest.py +372 -0
  228. imap_processing/tests/glows/direct_events_validation_data_l1a.csv +5704 -0
  229. imap_processing/tests/glows/glows_test_packet_20110921_v01.pkts +0 -0
  230. imap_processing/tests/glows/test_glows_decom.py +133 -0
  231. imap_processing/tests/glows/test_glows_l1a_cdf.py +85 -0
  232. imap_processing/tests/glows/test_glows_l1a_data.py +510 -0
  233. imap_processing/tests/glows/test_glows_l1b.py +348 -0
  234. imap_processing/tests/glows/test_glows_l1b_data.py +70 -0
  235. imap_processing/tests/hi/__init__.py +0 -0
  236. imap_processing/tests/hi/conftest.py +133 -0
  237. imap_processing/tests/hi/test_data/l0/20231030_H45_APP_NHK.bin +0 -0
  238. imap_processing/tests/hi/test_data/l0/20231030_H45_APP_NHK.csv +201 -0
  239. imap_processing/tests/hi/test_data/l0/20231030_H45_SCI_CNT.bin +0 -0
  240. imap_processing/tests/hi/test_data/l0/20231030_H45_SCI_DE.bin +0 -0
  241. imap_processing/tests/hi/test_data/l0/README.txt +54 -0
  242. imap_processing/tests/hi/test_decom.py +55 -0
  243. imap_processing/tests/hi/test_hi_l1b.py +31 -0
  244. imap_processing/tests/hi/test_hi_l1c.py +69 -0
  245. imap_processing/tests/hi/test_l1a.py +96 -0
  246. imap_processing/tests/hi/test_l1a_sci_de.py +72 -0
  247. imap_processing/tests/hi/test_utils.py +15 -0
  248. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1251.pkts +0 -0
  249. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1252.pkts +0 -0
  250. imap_processing/tests/hit/__init__.py +0 -0
  251. imap_processing/tests/hit/test_data/imap_hit_l0_hk_20100105_v001.pkts +0 -0
  252. imap_processing/tests/hit/test_data/sci_sample.ccsds +0 -0
  253. imap_processing/tests/hit/test_hit_decom.py +230 -0
  254. imap_processing/tests/hit/test_hit_l1a.py +224 -0
  255. imap_processing/tests/hit/test_hit_l1b.py +52 -0
  256. imap_processing/tests/hit/validation_data/hskp_sample_raw.csv +88 -0
  257. imap_processing/tests/ialirt/__init__.py +0 -0
  258. imap_processing/tests/ialirt/test_data/l0/IALiRT Raw Packet Telemetry.txt +33 -0
  259. imap_processing/tests/ialirt/test_data/l0/hit_ialirt_sample.ccsds +0 -0
  260. imap_processing/tests/ialirt/test_data/l0/hit_ialirt_sample.csv +1001 -0
  261. imap_processing/tests/ialirt/unit/__init__.py +0 -0
  262. imap_processing/tests/ialirt/unit/test_decom_ialirt.py +94 -0
  263. imap_processing/tests/ialirt/unit/test_process_hit.py +226 -0
  264. imap_processing/tests/idex/__init__.py +0 -0
  265. imap_processing/tests/idex/conftest.py +22 -0
  266. imap_processing/tests/idex/imap_idex_l0_raw_20230725_v001.pkts +0 -0
  267. imap_processing/tests/idex/impact_14_tof_high_data.txt +8189 -0
  268. imap_processing/tests/idex/test_idex_l0.py +45 -0
  269. imap_processing/tests/idex/test_idex_l1a.py +91 -0
  270. imap_processing/tests/lo/__init__.py +0 -0
  271. imap_processing/tests/lo/test_binary_string.py +21 -0
  272. imap_processing/tests/lo/test_bit_decompression.py +39 -0
  273. imap_processing/tests/lo/test_cdfs/imap_lo_l0_raw_20240627_v001.pkts +0 -0
  274. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20100101_v001.cdf +0 -0
  275. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20100101_v001.cdf +0 -0
  276. imap_processing/tests/lo/test_cdfs/imap_lo_l1b_de_20100101_v001.cdf +0 -0
  277. imap_processing/tests/lo/test_lo_l1a.py +66 -0
  278. imap_processing/tests/lo/test_lo_l1b.py +74 -0
  279. imap_processing/tests/lo/test_lo_l1c.py +66 -0
  280. imap_processing/tests/lo/test_science_counts.py +41 -0
  281. imap_processing/tests/lo/test_science_direct_events.py +209 -0
  282. imap_processing/tests/lo/test_star_sensor.py +35 -0
  283. imap_processing/tests/mag/imap_mag_l1a_burst-magi_20231025_v001.cdf +0 -0
  284. imap_processing/tests/mag/mag_l0_test_data.pkts +0 -0
  285. imap_processing/tests/mag/mag_l0_test_output.csv +37 -0
  286. imap_processing/tests/mag/mag_l1_test_data.pkts +0 -0
  287. imap_processing/tests/mag/mag_l1a_test_output.csv +97 -0
  288. imap_processing/tests/mag/test_mag_decom.py +117 -0
  289. imap_processing/tests/mag/test_mag_l1a.py +856 -0
  290. imap_processing/tests/mag/test_mag_l1b.py +77 -0
  291. imap_processing/tests/mag/test_mag_l1c.py +40 -0
  292. imap_processing/tests/spice/__init__.py +0 -0
  293. imap_processing/tests/spice/test_data/imap_ena_sim_metakernel.template +4 -0
  294. imap_processing/tests/spice/test_data/imap_science_0001.tf +171 -0
  295. imap_processing/tests/spice/test_data/imap_sclk_0000.tsc +156 -0
  296. imap_processing/tests/spice/test_data/imap_sim_ck_2hr_2secsampling_with_nutation.bc +0 -0
  297. imap_processing/tests/spice/test_data/imap_simple_metakernel.template +3 -0
  298. imap_processing/tests/spice/test_data/imap_spk_demo.bsp +0 -0
  299. imap_processing/tests/spice/test_data/imap_wkcp.tf +1806 -0
  300. imap_processing/tests/spice/test_data/naif0012.tls +150 -0
  301. imap_processing/tests/spice/test_data/sim_1yr_imap_attitude.bc +0 -0
  302. imap_processing/tests/spice/test_data/sim_1yr_imap_pointing_frame.bc +0 -0
  303. imap_processing/tests/spice/test_geometry.py +214 -0
  304. imap_processing/tests/spice/test_kernels.py +272 -0
  305. imap_processing/tests/spice/test_time.py +35 -0
  306. imap_processing/tests/swapi/__init__.py +0 -0
  307. imap_processing/tests/swapi/conftest.py +16 -0
  308. imap_processing/tests/swapi/l0_data/__init__.py +0 -0
  309. imap_processing/tests/swapi/l0_data/imap_swapi_l0_raw_20231012_v001.pkts +0 -0
  310. imap_processing/tests/swapi/l0_validation_data/__init__.py +0 -0
  311. imap_processing/tests/swapi/l0_validation_data/idle_export_eu.SWP_AUT_20231012_125245.csv +124 -0
  312. imap_processing/tests/swapi/l0_validation_data/idle_export_eu.SWP_HK_20231012_125245.csv +98 -0
  313. imap_processing/tests/swapi/l0_validation_data/idle_export_eu.SWP_MG_20231012_125245.csv +9 -0
  314. imap_processing/tests/swapi/l0_validation_data/idle_export_eu.SWP_SCI_20231012_125245.csv +72 -0
  315. imap_processing/tests/swapi/l0_validation_data/idle_export_raw.SWP_AUT_20231012_125245.csv +124 -0
  316. imap_processing/tests/swapi/l0_validation_data/idle_export_raw.SWP_HK_20231012_125245.csv +98 -0
  317. imap_processing/tests/swapi/l0_validation_data/idle_export_raw.SWP_MG_20231012_125245.csv +9 -0
  318. imap_processing/tests/swapi/l0_validation_data/idle_export_raw.SWP_SCI_20231012_125245.csv +72 -0
  319. imap_processing/tests/swapi/test_swapi_decom.py +135 -0
  320. imap_processing/tests/swapi/test_swapi_l1.py +354 -0
  321. imap_processing/tests/swapi/test_swapi_l2.py +21 -0
  322. imap_processing/tests/swe/__init__.py +0 -0
  323. imap_processing/tests/swe/conftest.py +35 -0
  324. imap_processing/tests/swe/decompressed/20230927173238_4th_quarter_decompressed.csv +181 -0
  325. imap_processing/tests/swe/decompressed/20230927173253_1st_quarter_decompressed.csv +181 -0
  326. imap_processing/tests/swe/decompressed/20230927173308_2nd_quarter_decompressed.csv +181 -0
  327. imap_processing/tests/swe/decompressed/20230927173323_3rd_quarter_decompressed.csv +181 -0
  328. imap_processing/tests/swe/l0_data/2024051010_SWE_SCIENCE_packet.bin +0 -0
  329. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_SCIENCE_20240510_092742.csv +544 -0
  330. imap_processing/tests/swe/l0_validation_data/idle_export_raw.SWE_SCIENCE_20240510_092742.csv +363 -0
  331. imap_processing/tests/swe/test_swe_l1a.py +12 -0
  332. imap_processing/tests/swe/test_swe_l1a_science.py +129 -0
  333. imap_processing/tests/swe/test_swe_l1b.py +61 -0
  334. imap_processing/tests/swe/test_swe_l1b_science.py +65 -0
  335. imap_processing/tests/test_cli.py +229 -0
  336. imap_processing/tests/test_decom.py +66 -0
  337. imap_processing/tests/test_quality_flags.py +71 -0
  338. imap_processing/tests/test_utils.py +107 -0
  339. imap_processing/tests/ultra/__init__.py +0 -0
  340. imap_processing/tests/ultra/test_data/l0/FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00_20240207T102740.CCSDS +0 -0
  341. imap_processing/tests/ultra/test_data/l0/FM45_7P_Phi0.0_BeamCal_LinearScan_phi0.04_theta-0.01_20230821T121304.CCSDS +0 -0
  342. imap_processing/tests/ultra/test_data/l0/FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.CCSDS +0 -0
  343. imap_processing/tests/ultra/test_data/l0/Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.CCSDS +0 -0
  344. imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_auxdata_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +24 -0
  345. imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_enaphxtofhangimg_FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.csv +105 -0
  346. imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultraimgrates_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +24 -0
  347. imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3314 -0
  348. imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultrarawimgevent_FM45_7P_Phi00_BeamCal_LinearScan_phi004_theta-001_20230821T121304.csv +702 -0
  349. imap_processing/tests/ultra/unit/__init__.py +0 -0
  350. imap_processing/tests/ultra/unit/conftest.py +210 -0
  351. imap_processing/tests/ultra/unit/test_decom_apid_880.py +98 -0
  352. imap_processing/tests/ultra/unit/test_decom_apid_881.py +50 -0
  353. imap_processing/tests/ultra/unit/test_decom_apid_883.py +44 -0
  354. imap_processing/tests/ultra/unit/test_decom_apid_896.py +104 -0
  355. imap_processing/tests/ultra/unit/test_lookup_utils.py +68 -0
  356. imap_processing/tests/ultra/unit/test_ultra_l1a.py +338 -0
  357. imap_processing/tests/ultra/unit/test_ultra_l1b.py +122 -0
  358. imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +57 -0
  359. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +342 -0
  360. imap_processing/tests/ultra/unit/test_ultra_l1c.py +104 -0
  361. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +35 -0
  362. imap_processing/ultra/__init__.py +1 -0
  363. imap_processing/ultra/constants.py +60 -0
  364. imap_processing/ultra/l0/__init__.py +0 -0
  365. imap_processing/ultra/l0/decom_tools.py +281 -0
  366. imap_processing/ultra/l0/decom_ultra.py +278 -0
  367. imap_processing/ultra/l0/ultra_utils.py +326 -0
  368. imap_processing/ultra/l1a/__init__.py +0 -0
  369. imap_processing/ultra/l1a/ultra_l1a.py +319 -0
  370. imap_processing/ultra/l1b/badtimes.py +26 -0
  371. imap_processing/ultra/l1b/cullingmask.py +26 -0
  372. imap_processing/ultra/l1b/de.py +59 -0
  373. imap_processing/ultra/l1b/extendedspin.py +45 -0
  374. imap_processing/ultra/l1b/lookup_utils.py +165 -0
  375. imap_processing/ultra/l1b/ultra_l1b.py +65 -0
  376. imap_processing/ultra/l1b/ultra_l1b_annotated.py +54 -0
  377. imap_processing/ultra/l1b/ultra_l1b_extended.py +764 -0
  378. imap_processing/ultra/l1c/histogram.py +36 -0
  379. imap_processing/ultra/l1c/pset.py +36 -0
  380. imap_processing/ultra/l1c/ultra_l1c.py +52 -0
  381. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +54 -0
  382. imap_processing/ultra/lookup_tables/EgyNorm.mem.csv +32769 -0
  383. imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
  384. imap_processing/ultra/lookup_tables/ultra45_back-pos-luts.csv +4097 -0
  385. imap_processing/ultra/lookup_tables/ultra45_tdc_norm.csv +2050 -0
  386. imap_processing/ultra/lookup_tables/ultra90_back-pos-luts.csv +4097 -0
  387. imap_processing/ultra/lookup_tables/ultra90_tdc_norm.csv +2050 -0
  388. imap_processing/ultra/lookup_tables/yadjust.csv +257 -0
  389. imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +547 -0
  390. imap_processing/ultra/packet_definitions/__init__.py +0 -0
  391. imap_processing/ultra/utils/__init__.py +0 -0
  392. imap_processing/ultra/utils/ultra_l1_utils.py +50 -0
  393. imap_processing/utils.py +413 -0
  394. imap_processing-0.6.0.dist-info/LICENSE +21 -0
  395. imap_processing-0.6.0.dist-info/METADATA +107 -0
  396. imap_processing-0.6.0.dist-info/RECORD +398 -0
  397. imap_processing-0.6.0.dist-info/WHEEL +4 -0
  398. imap_processing-0.6.0.dist-info/entry_points.txt +4 -0
@@ -0,0 +1,467 @@
1
+ """Decommutate HIT CCSDS science data."""
2
+
3
+ from collections import namedtuple
4
+
5
+ import numpy as np
6
+ import xarray as xr
7
+
8
+ # TODO: Consider moving global values into a config file
9
+
10
+ # Structure to hold binary details for a
11
+ # section of science data. Used to unpack
12
+ # binary data.
13
+ HITPacking = namedtuple(
14
+ "HITPacking",
15
+ [
16
+ "bit_length",
17
+ "section_length",
18
+ "shape",
19
+ ],
20
+ )
21
+
22
+ # Define data structure for counts rates data
23
+ COUNTS_DATA_STRUCTURE = {
24
+ # field: bit_length, section_length, shape
25
+ # ------------------------------------------
26
+ # science frame header
27
+ "hdr_unit_num": HITPacking(2, 2, (1,)),
28
+ "hdr_frame_version": HITPacking(6, 6, (1,)),
29
+ "hdr_status_bits": HITPacking(8, 8, (1,)),
30
+ "hdr_minute_cnt": HITPacking(8, 8, (1,)),
31
+ # ------------------------------------------
32
+ # spare bits. Contains no data
33
+ "spare": HITPacking(24, 24, (1,)),
34
+ # ------------------------------------------
35
+ # erates - contains livetime counters
36
+ "livetime": HITPacking(16, 16, (1,)), # livetime counter
37
+ "num_trig": HITPacking(16, 16, (1,)), # number of triggers
38
+ "num_reject": HITPacking(16, 16, (1,)), # number of rejected events
39
+ "num_acc_w_pha": HITPacking(
40
+ 16, 16, (1,)
41
+ ), # number of accepted events with PHA data
42
+ "num_acc_no_pha": HITPacking(16, 16, (1,)), # number of events without PHA data
43
+ "num_haz_trig": HITPacking(16, 16, (1,)), # number of triggers with hazard flag
44
+ "num_haz_reject": HITPacking(
45
+ 16, 16, (1,)
46
+ ), # number of rejected events with hazard flag
47
+ "num_haz_acc_w_pha": HITPacking(
48
+ 16, 16, (1,)
49
+ ), # number of accepted hazard events with PHA data
50
+ "num_haz_acc_no_pha": HITPacking(
51
+ 16, 16, (1,)
52
+ ), # number of hazard events without PHA data
53
+ # -------------------------------------------
54
+ "sngrates": HITPacking(16, 1856, (2, 58)), # single rates
55
+ # -------------------------------------------
56
+ # evprates - contains event processing rates
57
+ "nread": HITPacking(16, 16, (1,)), # events read from event fifo
58
+ "nhazard": HITPacking(16, 16, (1,)), # events tagged with hazard flag
59
+ "nadcstim": HITPacking(16, 16, (1,)), # adc-stim events
60
+ "nodd": HITPacking(16, 16, (1,)), # odd events
61
+ "noddfix": HITPacking(16, 16, (1,)), # odd events that were fixed in sw
62
+ "nmulti": HITPacking(
63
+ 16, 16, (1,)
64
+ ), # events with multiple hits in a single detector
65
+ "nmultifix": HITPacking(16, 16, (1,)), # multi events that were fixed in sw
66
+ "nbadtraj": HITPacking(16, 16, (1,)), # bad trajectory
67
+ "nl2": HITPacking(16, 16, (1,)), # events sorted into L12 event category
68
+ "nl3": HITPacking(16, 16, (1,)), # events sorted into L123 event category
69
+ "nl4": HITPacking(16, 16, (1,)), # events sorted into L1423 event category
70
+ "npen": HITPacking(16, 16, (1,)), # events sorted into penetrating event category
71
+ "nformat": HITPacking(16, 16, (1,)), # nothing currently goes in this slot
72
+ "naside": HITPacking(16, 16, (1,)), # A-side events
73
+ "nbside": HITPacking(16, 16, (1,)), # B-side events
74
+ "nerror": HITPacking(16, 16, (1,)), # events that caused a processing error
75
+ "nbadtags": HITPacking(
76
+ 16, 16, (1,)
77
+ ), # events with inconsistent tags vs pulse heights
78
+ # -------------------------------------------
79
+ # other count rates
80
+ "coinrates": HITPacking(16, 416, (26,)), # coincidence rates
81
+ "bufrates": HITPacking(16, 512, (32,)), # priority buffer rates
82
+ "l2fgrates": HITPacking(16, 2112, (132,)), # range 2 foreground rates
83
+ "l2bgrates": HITPacking(16, 192, (12,)), # range 2 background rates
84
+ "l3fgrates": HITPacking(16, 2672, (167,)), # range 3 foreground rates
85
+ "l3bgrates": HITPacking(16, 192, (12,)), # range 3 background rates
86
+ "penfgrates": HITPacking(16, 528, (33,)), # range 4 foreground rates
87
+ "penbgrates": HITPacking(16, 240, (15,)), # range 4 background rates
88
+ "ialirtrates": HITPacking(16, 320, (20,)), # ialirt rates
89
+ "sectorates": HITPacking(16, 1920, (120,)), # sectored rates
90
+ "l4fgrates": HITPacking(16, 768, (48,)), # all range foreground rates
91
+ "l4bgrates": HITPacking(16, 384, (24,)), # all range foreground rates
92
+ }
93
+
94
+ # Define data structure for pulse height event data
95
+ PHA_DATA_STRUCTURE = {
96
+ # field: bit_length, section_length, shape
97
+ "pha_records": HITPacking(2, 29344, (917,)),
98
+ }
99
+
100
+ # Define the pattern of grouping flags in a complete science frame.
101
+ FLAG_PATTERN = np.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2])
102
+
103
+ # Define size of science frame (num of packets)
104
+ FRAME_SIZE = len(FLAG_PATTERN)
105
+
106
+
107
+ def parse_data(bin_str: str, bits_per_index: int, start: int, end: int) -> list:
108
+ """
109
+ Parse binary data.
110
+
111
+ Parameters
112
+ ----------
113
+ bin_str : str
114
+ Binary string to be unpacked.
115
+ bits_per_index : int
116
+ Number of bits per index of the data section.
117
+ start : int
118
+ Starting index for slicing the binary string.
119
+ end : int
120
+ Ending index for slicing the binary string.
121
+
122
+ Returns
123
+ -------
124
+ parsed_data : list
125
+ Integers parsed from the binary string.
126
+ """
127
+ parsed_data = [
128
+ int(bin_str[i : i + bits_per_index], 2)
129
+ for i in range(start, end, bits_per_index)
130
+ ]
131
+ return parsed_data
132
+
133
+
134
+ def parse_count_rates(sci_dataset: xr.Dataset) -> None:
135
+ """
136
+ Parse binary count rates data and update dataset.
137
+
138
+ This function parses the binary count rates data,
139
+ stored as count_rates_binary in the dataset,
140
+ according to data structure details provided in
141
+ COUNTS_DATA_STRUCTURE. The parsed data, representing
142
+ integers, is added to the dataset as new data
143
+ fields.
144
+
145
+ Note: count_rates_binary is added to the dataset by
146
+ the assemble_science_frames function, which organizes
147
+ the binary science data packets by science frames.
148
+
149
+ Parameters
150
+ ----------
151
+ sci_dataset : xr.Dataset
152
+ Xarray dataset containing HIT science packets
153
+ from a CCSDS file.
154
+ """
155
+ counts_binary = sci_dataset.count_rates_binary
156
+ # initialize the starting bit for the sections of data
157
+ section_start = 0
158
+ # Decommutate binary data for each counts data field
159
+ for field, field_meta in COUNTS_DATA_STRUCTURE.items():
160
+ section_end = section_start + field_meta.section_length
161
+ bits_per_index = field_meta.bit_length
162
+ parsed_data = [
163
+ parse_data(bin_str, bits_per_index, section_start, section_end)
164
+ for bin_str in counts_binary.values
165
+ ]
166
+ if field_meta.shape[0] == 1:
167
+ # flatten data into a 1D array
168
+ parsed_data = list(np.array(parsed_data).flat)
169
+
170
+ if field == "sngrates":
171
+ # Split into high and low gain arrays
172
+ for i, data in enumerate(parsed_data):
173
+ high_gain = data[::2] # Items at even indices 0, 2, 4, etc.
174
+ low_gain = data[1::2] # Items at odd indices 1, 3, 5, etc.
175
+ parsed_data[i] = [high_gain, low_gain]
176
+
177
+ # TODO
178
+ # - status bits needs to be further parsed (table 10 in algorithm doc)
179
+ # - subcommutate sectorates
180
+ # - decompress data
181
+ # - Follow up with HIT team about erates and evrates.
182
+ # (i.e.Should these be arrays containing all the sub fields
183
+ # or should each subfield be it's own data field/array)
184
+
185
+ # Get dims for data variables (yaml file not created yet)
186
+ if len(field_meta.shape) > 1:
187
+ dims = ["epoch", "gain", f"{field}_index"]
188
+ elif field_meta.shape[0] > 1:
189
+ dims = ["epoch", f"{field}_index"]
190
+ else:
191
+ dims = ["epoch"]
192
+
193
+ sci_dataset[field] = xr.DataArray(parsed_data, dims=dims, name=field)
194
+ # increment the start of the next section of data to parse
195
+ section_start += field_meta.section_length
196
+
197
+
198
+ def is_sequential(counters: np.ndarray) -> np.bool_:
199
+ """
200
+ Check if an array of packet sequence counters is sequential.
201
+
202
+ Parameters
203
+ ----------
204
+ counters : np.ndarray
205
+ Array of packet sequence counters.
206
+
207
+ Returns
208
+ -------
209
+ bool
210
+ True if the sequence counters are sequential, False otherwise.
211
+ """
212
+ return np.all(np.diff(counters) == 1)
213
+
214
+
215
+ def find_valid_starting_indices(flags: np.ndarray, counters: np.ndarray) -> np.ndarray:
216
+ """
217
+ Find valid starting indices for science frames.
218
+
219
+ This function finds the starting indices of valid science frames.
220
+ A valid science frame has the following packet grouping flags:
221
+
222
+ First packet: 1
223
+ Next 18 packets: 0
224
+ Last packet: 2
225
+
226
+ The packet sequence counters for the identified science frames must
227
+ be sequential. Only the starting indices of valid science frames are
228
+ returned.
229
+
230
+ Parameters
231
+ ----------
232
+ flags : np.ndarray
233
+ Array of packet grouping flags.
234
+ counters : np.ndarray
235
+ Array of packet sequence counters.
236
+
237
+ Returns
238
+ -------
239
+ valid_indices : np.ndarray
240
+ Array of valid indices for science frames.
241
+ """
242
+ # TODO: consider combining functions to get valid indices to reduce
243
+ # code tracing
244
+
245
+ # Use sliding windows to compare segments of the array (20 packets) with the
246
+ # pattern. This generates an array of overlapping sub-arrays, each of length
247
+ # 20, from the flags array and is used to slide the "window" across the array
248
+ # and compare the sub-arrays with the predefined pattern.
249
+ windows = np.lib.stride_tricks.sliding_window_view(flags, FRAME_SIZE)
250
+ # Find where the windows match the pattern
251
+ matches = np.all(windows == FLAG_PATTERN, axis=1)
252
+ # Get the starting indices of matches
253
+ match_indices = np.where(matches)[0]
254
+ # Filter for only indices from valid science frames with sequential counters
255
+ valid_indices = get_valid_indices(match_indices, counters, FRAME_SIZE)
256
+ return valid_indices
257
+
258
+
259
+ def get_valid_indices(
260
+ indices: np.ndarray, counters: np.ndarray, size: int
261
+ ) -> np.ndarray:
262
+ """
263
+ Get valid indices for science frames.
264
+
265
+ Check if the packet sequence counters for the science frames
266
+ are sequential. If they are, the science frame is valid and
267
+ an updated array of valid indices is returned.
268
+
269
+ Parameters
270
+ ----------
271
+ indices : np.ndarray
272
+ Array of indices where the packet grouping flags match the pattern.
273
+ counters : np.ndarray
274
+ Array of packet sequence counters.
275
+ size : int
276
+ Size of science frame. 20 packets per science frame.
277
+
278
+ Returns
279
+ -------
280
+ valid_indices : np.ndarray
281
+ Array of valid indices for science frames.
282
+ """
283
+ # Check if the packet sequence counters are sequential by getting an array
284
+ # of boolean values where True indicates the counters are sequential.
285
+ sequential_check = [is_sequential(counters[idx : idx + size]) for idx in indices]
286
+ return indices[sequential_check]
287
+
288
+
289
+ def update_ccsds_header_dims(sci_dataset: xr.Dataset) -> xr.Dataset:
290
+ """
291
+ Update dimensions of CCSDS header fields.
292
+
293
+ The CCSDS header fields contain 1D arrays with
294
+ values from all the packets in the file.
295
+ While the epoch dimension contains time per packet,
296
+ it will be updated later in the process to represent
297
+ time per science frame, so another time dimension is
298
+ needed for the ccsds header fields.This function
299
+ updates the dimension for these fields to use sc_tick
300
+ instead of epoch. sc_tick is the time the packet was
301
+ created.
302
+
303
+ Parameters
304
+ ----------
305
+ sci_dataset : xr.Dataset
306
+ Xarray dataset containing HIT science packets
307
+ from a CCSDS file.
308
+
309
+ Returns
310
+ -------
311
+ sci_dataset : xr.Dataset
312
+ Updated xarray dataset.
313
+ """
314
+ # sc_tick contains spacecraft time per packet
315
+ sci_dataset.coords["sc_tick"] = sci_dataset["sc_tick"]
316
+ sci_dataset = sci_dataset.swap_dims({"epoch": "sc_tick"})
317
+ return sci_dataset
318
+
319
+
320
+ def assemble_science_frames(sci_dataset: xr.Dataset) -> xr.Dataset:
321
+ """
322
+ Group packets into science frames.
323
+
324
+ HIT science frames (data from 1 minute) consist of 20 packets.
325
+ These are assembled from the binary science_data field in the
326
+ xarray dataset, which is a 1D array of science data from all
327
+ packets in the file, by using packet grouping flags.
328
+
329
+ The science frame is further categorized into
330
+ L1A data products -> count rates and event data.
331
+
332
+ The first six packets contain count rates data
333
+ The last 14 packets contain pulse height event data
334
+
335
+ These groups are added to the dataset as count_rates_binary
336
+ and pha_binary.
337
+
338
+ Parameters
339
+ ----------
340
+ sci_dataset : xr.Dataset
341
+ Xarray Dataset for science data (APID 1252).
342
+
343
+ Returns
344
+ -------
345
+ sci_dataset : xr.Dataset
346
+ Updated xarray dataset with binary count rates and pulse
347
+ height event data per valid science frame added as new
348
+ data variables.
349
+ """
350
+ # TODO: Figure out how to handle partial science frames at the
351
+ # beginning and end of CCSDS files. These science frames are split
352
+ # across CCSDS files and still need to be processed with packets
353
+ # from the previous file. Only discard incomplete science frames
354
+ # in the middle of the CCSDS file. The code currently skips all
355
+ # incomplete science frames.
356
+
357
+ # Convert sequence flags and counters to NumPy arrays for vectorized operations
358
+ seq_flgs = sci_dataset.seq_flgs.values
359
+ seq_ctrs = sci_dataset.src_seq_ctr.values
360
+ science_data = sci_dataset.science_data.values
361
+ epoch_data = sci_dataset.epoch.values
362
+
363
+ # Number of packets in the file
364
+ total_packets = len(epoch_data)
365
+
366
+ # Find starting indices for valid science frames
367
+ starting_indices = find_valid_starting_indices(seq_flgs, seq_ctrs)
368
+
369
+ # Check for extra packets at start and end of file
370
+ # TODO: Will need to handle these extra packets when processing multiple files
371
+ if starting_indices[0] != 0:
372
+ # The first science frame start index is not at the beginning of the file.
373
+ print(
374
+ f"{starting_indices[0]} packets at start of file belong to science frame "
375
+ f"from previous day's ccsds file"
376
+ )
377
+ last_index_of_last_frame = starting_indices[-1] + FRAME_SIZE
378
+ if last_index_of_last_frame:
379
+ remaining_packets = total_packets - last_index_of_last_frame
380
+ if 0 < remaining_packets < FRAME_SIZE:
381
+ print(
382
+ f"{remaining_packets} packets at end of file belong to science frame "
383
+ f"from next day's ccsds file"
384
+ )
385
+
386
+ # Extract data per science frame and organize by L1A data products
387
+ count_rates = []
388
+ pha = []
389
+ epoch_per_science_frame = np.array([])
390
+ for idx in starting_indices:
391
+ # Data from 20 packets in a science frame
392
+ science_data_frame = science_data[idx : idx + FRAME_SIZE]
393
+ # First 6 packets contain count rates data in binary
394
+ count_rates.append("".join(science_data_frame[:6]))
395
+ # Last 14 packets contain pulse height event data in binary
396
+ pha.append("".join(science_data_frame[6:]))
397
+ # Get first packet's epoch for the science frame
398
+ epoch_per_science_frame = np.append(epoch_per_science_frame, epoch_data[idx])
399
+ # TODO: Filter ccsds header fields to only include packets from the
400
+ # valid science frames. Doesn't need to be grouped by frames though
401
+
402
+ # Add new data variables to the dataset
403
+ sci_dataset = sci_dataset.drop_vars("epoch")
404
+ sci_dataset.coords["epoch"] = epoch_per_science_frame
405
+ sci_dataset["count_rates_binary"] = xr.DataArray(
406
+ count_rates, dims=["epoch"], name="count_rates_binary"
407
+ )
408
+ sci_dataset["pha_binary"] = xr.DataArray(pha, dims=["epoch"], name="pha_binary")
409
+ return sci_dataset
410
+
411
+
412
+ def decom_hit(sci_dataset: xr.Dataset) -> xr.Dataset:
413
+ """
414
+ Group and decode HIT science data packets.
415
+
416
+ This function updates the science dataset with
417
+ organized, decommutated, and decompressed data.
418
+
419
+ The dataset that is passed in contains the unpacked
420
+ CCSDS header and the science data as bytes as follows:
421
+
422
+ <xarray.Dataset>
423
+ Dimensions: epoch
424
+ Coordinates:
425
+ * epoch (epoch) int64
426
+ Data variables:
427
+ sc_tick (epoch) uint32
428
+ science_data (epoch) <U2096
429
+ version (epoch) uint8
430
+ type (epoch) uint8
431
+ sec_hdr_flg (epoch) uint8
432
+ pkt_apid (epoch) uint16
433
+ seq_flgs (epoch) uint8
434
+ src_seq_ctr (epoch) uint16
435
+ pkt_len (epoch) uint16
436
+
437
+ The science data for a science frame (i.e. 1 minute of data)
438
+ is spread across 20 packets. This function groups the
439
+ data into science frames and decommutates and decompresses
440
+ binary into integers.
441
+
442
+ Parameters
443
+ ----------
444
+ sci_dataset : xr.Dataset
445
+ Xarray dataset containing HIT science packets
446
+ from a CCSDS file.
447
+
448
+ Returns
449
+ -------
450
+ sci_dataset : xr.Dataset
451
+ Updated xarray dataset with new fields for all count
452
+ rates and pulse height event data per valid science frame
453
+ needed for creating an L1A product.
454
+ """
455
+ # Update ccsds header fields to use sc_tick as dimension
456
+ sci_dataset = update_ccsds_header_dims(sci_dataset)
457
+
458
+ # Group science packets into groups of 20
459
+ sci_dataset = assemble_science_frames(sci_dataset)
460
+
461
+ # Parse count rates data from binary and add to dataset
462
+ parse_count_rates(sci_dataset)
463
+
464
+ # TODO:
465
+ # Parse binary PHA data and add to dataset (function call)
466
+
467
+ return sci_dataset
@@ -0,0 +1,57 @@
1
+ """General HIT L0 data class used for parsing data and setting attributes."""
2
+
3
+ from dataclasses import dataclass, fields
4
+
5
+ import space_packet_parser
6
+
7
+ from imap_processing.ccsds.ccsds_data import CcsdsData
8
+
9
+
10
+ @dataclass
11
+ class HITBase:
12
+ """
13
+ Data structure for common values across HIT.
14
+
15
+ Attributes
16
+ ----------
17
+ ground_sw_version : str
18
+ Ground software version.
19
+ packet_file_name : str
20
+ File name of the source packet.
21
+ ccsds_header : CcsdsData
22
+ CCSDS header data.
23
+
24
+ Methods
25
+ -------
26
+ parse_data(packet):
27
+ Parse the packet and assign to class variable using the xtce defined named.
28
+ """
29
+
30
+ ground_sw_version: str
31
+ packet_file_name: str
32
+ ccsds_header: CcsdsData
33
+
34
+ def parse_data(self, packet: space_packet_parser.parser.Packet) -> None:
35
+ """
36
+ Parse Lo L0 packet data.
37
+
38
+ Parameters
39
+ ----------
40
+ packet : space_packet_parser.parser.Packet
41
+ A single Lo L0 packet from space packet parser.
42
+ """
43
+ attributes = [field.name for field in fields(self)]
44
+
45
+ # For each item in packet, assign it to the matching attribute in the class.
46
+ for key, item in packet.data.items():
47
+ value = (
48
+ item.derived_value if item.derived_value is not None else item.raw_value
49
+ )
50
+ if "SPARE" in key:
51
+ continue
52
+ if key not in attributes:
53
+ raise KeyError(
54
+ f"Did not find matching attribute in {self.__class__} data class"
55
+ f"for {key}"
56
+ )
57
+ setattr(self, key, value)
File without changes