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,281 @@
1
+ """Ultra Decompression Tools."""
2
+
3
+ import numpy as np
4
+ import numpy.typing as npt
5
+ import space_packet_parser
6
+
7
+ from imap_processing.ultra.l0.ultra_utils import (
8
+ EVENT_FIELD_RANGES,
9
+ append_fillval,
10
+ parse_event,
11
+ )
12
+
13
+
14
+ def read_and_advance(
15
+ binary_data: str, n: int, current_position: int
16
+ ) -> tuple[int, int]:
17
+ """
18
+ Extract the specified number of bits from a binary string.
19
+
20
+ Starting from the current position, it reads n bits. This is used twice.
21
+ The first time it reads the first 5 bits to determine the width.
22
+ The second time it uses the width to determine the value of the bitstring.
23
+
24
+ Parameters
25
+ ----------
26
+ binary_data : str
27
+ The string of binary data from which bits will be read.
28
+ This is a string of 0's and 1's.
29
+ n : int
30
+ Number of bits to read from the binary string.
31
+ current_position : int
32
+ The starting position in the binary string from which bits will be read.
33
+
34
+ Returns
35
+ -------
36
+ value : int
37
+ The integer representation of the read bits or None if the end of the
38
+ string is reached before reading 'n' bits.
39
+ current_position + n
40
+ - The updated position in the binary string after reading the bits.
41
+ """
42
+ # Ensure we don't read past the end
43
+ if current_position + n > len(binary_data):
44
+ raise IndexError(
45
+ f"Attempted to read past the end of binary string. "
46
+ f"Current position: {current_position}, "
47
+ f"Requested bits: {n}, String length: {len(binary_data)}"
48
+ )
49
+
50
+ value = int(binary_data[current_position : current_position + n], 2)
51
+ return value, current_position + n
52
+
53
+
54
+ def log_decompression(value: int, mantissa_bit_length: int) -> int:
55
+ """
56
+ Perform logarithmic decompression on an integer.
57
+
58
+ Supports both 16-bit and 8-bit formats based on the specified
59
+ mantissa bit length.
60
+
61
+ Parameters
62
+ ----------
63
+ value : int
64
+ An integer comprised of a 4-bit exponent followed by a variable-length mantissa.
65
+ mantissa_bit_length : int
66
+ The bit length of the mantissa (default is 12 for 16-bit format).
67
+
68
+ Returns
69
+ -------
70
+ int
71
+ The decompressed integer value.
72
+ """
73
+ # Determine the base value and mask based on mantissa bit length
74
+ if mantissa_bit_length == 12:
75
+ base_value = 4096
76
+ mantissa_mask = 0xFFF
77
+ elif mantissa_bit_length == 4:
78
+ base_value = 16
79
+ mantissa_mask = 0x0F
80
+ else:
81
+ raise ValueError("Unsupported mantissa bit length")
82
+
83
+ # Extract the exponent and mantissa
84
+ e = value >> mantissa_bit_length # Extract the exponent
85
+ m = value & mantissa_mask # Extract the mantissa
86
+
87
+ if e == 0:
88
+ return m
89
+ else:
90
+ return (base_value + m) << (e - 1)
91
+
92
+
93
+ def decompress_binary(
94
+ binary: str, width_bit: int, block: int, array_length: int, mantissa_bit_length: int
95
+ ) -> list:
96
+ """
97
+ Will decompress a binary string.
98
+
99
+ Decompress a binary string based on block-width encoding and
100
+ logarithmic compression.
101
+
102
+ This function interprets a binary string where the value of 'width_bits'
103
+ specifies the width of the following bits. Each value is then extracted and
104
+ subjected to logarithmic decompression.
105
+
106
+ Parameters
107
+ ----------
108
+ binary : str
109
+ A binary string containing the compressed data.
110
+ width_bit : int
111
+ The bit width that describes the width of data in the block.
112
+ block : int
113
+ Number of values in each block.
114
+ array_length : int
115
+ The length of the array to be decompressed.
116
+ mantissa_bit_length : int
117
+ The bit length of the mantissa.
118
+
119
+ Returns
120
+ -------
121
+ list
122
+ A list of decompressed values.
123
+
124
+ Notes
125
+ -----
126
+ Equations from Section 1.2.1.1 Data Compression and Decompression Algorithms
127
+ in Ultra_algorithm_doc_rev2.pdf.
128
+ """
129
+ current_position = 0
130
+ decompressed_values: list = []
131
+
132
+ while current_position < len(binary):
133
+ # Read the width of the block
134
+ width, current_position = read_and_advance(binary, width_bit, current_position)
135
+ # If width is 0 or None, we don't have enough bits left
136
+ if width is None or len(decompressed_values) >= array_length:
137
+ break
138
+
139
+ # For each block, read 16 values of the given width
140
+ for _ in range(block):
141
+ # Ensure there are enough bits left to read the width
142
+ if len(binary) - current_position < width:
143
+ break
144
+
145
+ value, current_position = read_and_advance(binary, width, current_position)
146
+
147
+ # Log decompression
148
+ decompressed_values.append(log_decompression(value, mantissa_bit_length))
149
+
150
+ return decompressed_values
151
+
152
+
153
+ def decompress_image(
154
+ pixel0: int,
155
+ binary_data: str,
156
+ width_bit: int,
157
+ mantissa_bit_length: int,
158
+ ) -> npt.NDArray:
159
+ """
160
+ Will decompress a binary string representing an image into a matrix of pixel values.
161
+
162
+ It starts with an initial pixel value and decompresses the rest of the image using
163
+ block-wise decompression and logarithmic decompression based on provided bit widths
164
+ and lengths.
165
+
166
+ Parameters
167
+ ----------
168
+ pixel0 : int
169
+ The first, unmodified pixel p0,0.
170
+ binary_data : str
171
+ Binary string.
172
+ width_bit : int
173
+ The bit width that describes the width of data in the block.
174
+ mantissa_bit_length : int
175
+ The bit length of the mantissa.
176
+
177
+ Returns
178
+ -------
179
+ p_decom : numpy.ndarray
180
+ A 2D numpy array representing pixel values.
181
+ Each pixel is stored as an unsigned 16-bit integer (uint16).
182
+
183
+ Notes
184
+ -----
185
+ This process is described starting on page 168 in IMAP-Ultra Flight
186
+ Software Specification document (7523-9009_Rev_-.pdf).
187
+ """
188
+ rows = 54
189
+ cols = 180
190
+ pixels_per_block = 15
191
+
192
+ blocks_per_row = cols // pixels_per_block
193
+
194
+ # Compressed pixel matrix
195
+ p = np.zeros((rows, cols), dtype=np.uint16)
196
+ # Decompressed pixel matrix
197
+ p_decom = np.zeros((rows, cols), dtype=np.int16)
198
+
199
+ pos = 0 # Starting position in the binary string
200
+
201
+ for i in range(rows):
202
+ for j in range(blocks_per_row):
203
+ # Read the width for the block.
204
+ w, pos = read_and_advance(binary_data, width_bit, pos)
205
+ for k in range(pixels_per_block):
206
+ # Handle the special case in which the width is 0
207
+ if w == 0:
208
+ value = 0
209
+ else:
210
+ # Find the value of each pixel in the block
211
+ value, pos = read_and_advance(binary_data, w, pos)
212
+
213
+ # if the least significant bit of value is set (odd)
214
+ if value & 0x01:
215
+ # value >> 1: shifts bits of value one place to the right
216
+ # ~: bitwise NOT operator (flips bits)
217
+ delta_f = ~(value >> 1)
218
+ else:
219
+ delta_f = value >> 1
220
+
221
+ # Calculate the new pixel value and update pixel0
222
+ column_index = j * pixels_per_block + k
223
+ # 0xff is the hexadecimal representation of the number 255,
224
+ # Keeps only the last 8 bits of the result of pixel0 - delta_f
225
+ # This operation ensures that the result is within the range
226
+ # of an 8-bit byte (0-255)
227
+ # Use np.int16 for the arithmetic operation to avoid overflow
228
+ # Then implicitly cast back to the p's uint16 dtype for storage
229
+ p[i][column_index] = np.int16(pixel0) - delta_f
230
+ # Perform logarithmic decompression on the pixel value
231
+ p_decom[i][column_index] = log_decompression(
232
+ p[i][column_index], mantissa_bit_length
233
+ )
234
+ pixel0 = p[i][column_index]
235
+ pixel0 = p[i][0]
236
+
237
+ return p_decom
238
+
239
+
240
+ def read_image_raw_events_binary(
241
+ packet: space_packet_parser.parser.Packet, decom_data: dict
242
+ ) -> dict:
243
+ """
244
+ Convert contents of binary string 'EVENTDATA' into values.
245
+
246
+ Parameters
247
+ ----------
248
+ packet : space_packet_parser.parser.Packet
249
+ Packet.
250
+ decom_data : dict
251
+ Parsed data.
252
+
253
+ Returns
254
+ -------
255
+ decom_data : dict
256
+ Each for loop appends to the existing dictionary.
257
+ """
258
+ binary = packet.data["EVENTDATA"].raw_value
259
+ count = packet.data["COUNT"].derived_value
260
+ # 166 bits per event
261
+ event_length = 166 if count else 0
262
+
263
+ # Uses fill value for all packets that do not contain event data.
264
+ if count == 0:
265
+ # if decom_data is empty, append fill values to all fields
266
+ if not decom_data:
267
+ for field in EVENT_FIELD_RANGES.keys():
268
+ decom_data[field] = []
269
+ append_fillval(decom_data, packet)
270
+
271
+ # For all packets with event data, parses the binary string
272
+ else:
273
+ for i in range(count):
274
+ start_index = i * event_length
275
+ event_binary = binary[start_index : start_index + event_length]
276
+ event_data = parse_event(event_binary)
277
+
278
+ for key, value in event_data.items():
279
+ decom_data[key].append(value)
280
+
281
+ return decom_data
@@ -0,0 +1,278 @@
1
+ """Decommutates Ultra CCSDS packets."""
2
+
3
+ import collections
4
+ import logging
5
+ from collections import defaultdict
6
+ from typing import Any, Union
7
+
8
+ import numpy as np
9
+ from space_packet_parser.parser import Packet
10
+
11
+ from imap_processing.ccsds.ccsds_data import CcsdsData
12
+ from imap_processing.ultra.l0.decom_tools import (
13
+ decompress_binary,
14
+ decompress_image,
15
+ read_image_raw_events_binary,
16
+ )
17
+ from imap_processing.ultra.l0.ultra_utils import (
18
+ RATES_KEYS,
19
+ ULTRA_AUX,
20
+ ULTRA_EVENTS,
21
+ ULTRA_RATES,
22
+ ULTRA_TOF,
23
+ append_ccsds_fields,
24
+ )
25
+ from imap_processing.utils import sort_by_time
26
+
27
+ logging.basicConfig(level=logging.INFO)
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ def append_tof_params(
32
+ decom_data: dict,
33
+ packet: Packet,
34
+ decompressed_data: np.ndarray,
35
+ data_dict: dict,
36
+ stacked_dict: dict,
37
+ ) -> None:
38
+ """
39
+ Append parsed items to a dictionary, including decompressed data if available.
40
+
41
+ Parameters
42
+ ----------
43
+ decom_data : dict
44
+ Dictionary to which the data is appended.
45
+ packet : space_packet_parser.parser.Packet
46
+ Individual packet.
47
+ decompressed_data : list
48
+ Data that has been decompressed.
49
+ data_dict : dict
50
+ Dictionary used for stacking in SID dimension.
51
+ stacked_dict : dict
52
+ Dictionary used for stacking in time dimension.
53
+ """
54
+ # TODO: add error handling to make certain every timestamp has 8 SID values
55
+
56
+ for key in packet.data.keys():
57
+ # Keep appending packet data until SID = 7
58
+ if key == "PACKETDATA":
59
+ data_dict[key].append(decompressed_data)
60
+ # Keep appending all other data until SID = 7
61
+ else:
62
+ data_dict[key].append(packet.data[key].derived_value)
63
+
64
+ # Append CCSDS fields to the dictionary
65
+ ccsds_data = CcsdsData(packet.header)
66
+ append_ccsds_fields(data_dict, ccsds_data)
67
+
68
+ # Once "SID" reaches 7, we have all the images and data for the single timestamp
69
+ if packet.data["SID"].derived_value == 7:
70
+ decom_data["SHCOARSE"].extend(list(set(data_dict["SHCOARSE"])))
71
+ data_dict["SHCOARSE"].clear()
72
+
73
+ for key in packet.data.keys():
74
+ if key != "SHCOARSE":
75
+ stacked_dict[key].append(np.stack(data_dict[key]))
76
+ data_dict[key].clear()
77
+ for key in packet.header.keys():
78
+ stacked_dict[key].append(np.stack(data_dict[key]))
79
+ data_dict[key].clear()
80
+
81
+
82
+ def append_params(decom_data: dict, packet: Packet) -> None:
83
+ # Todo Update what packet type is.
84
+ """
85
+ Append parsed items to a dictionary, including decompressed data if available.
86
+
87
+ Parameters
88
+ ----------
89
+ decom_data : dict
90
+ Dictionary to which the data is appended.
91
+ packet : space_packet_parser.parser.Packet
92
+ Individual packet.
93
+ """
94
+ for key, item in packet.data.items():
95
+ decom_data[key].append(item.derived_value)
96
+
97
+ ccsds_data = CcsdsData(packet.header)
98
+ append_ccsds_fields(decom_data, ccsds_data)
99
+
100
+
101
+ def process_ultra_apids(data: list, apid: int) -> Union[dict[Any, Any], bool]:
102
+ """
103
+ Unpack and decode Ultra packets using CCSDS format and XTCE packet definitions.
104
+
105
+ Parameters
106
+ ----------
107
+ data : list
108
+ Grouped data.
109
+ apid : int
110
+ The APID to process.
111
+
112
+ Returns
113
+ -------
114
+ decom_data : dict
115
+ A dictionary containing the decoded data.
116
+ """
117
+ # Strategy dict maps APIDs to their respective processing functions
118
+ strategy_dict = {
119
+ ULTRA_TOF.apid[0]: process_ultra_tof,
120
+ ULTRA_EVENTS.apid[0]: process_ultra_events,
121
+ ULTRA_AUX.apid[0]: process_ultra_aux,
122
+ ULTRA_RATES.apid[0]: process_ultra_rates,
123
+ }
124
+
125
+ sorted_packets = sort_by_time(data, "SHCOARSE")
126
+
127
+ process_function = strategy_dict.get(apid, lambda *args: False)
128
+ decom_data = process_function(sorted_packets, defaultdict(list))
129
+
130
+ return decom_data
131
+
132
+
133
+ def process_ultra_tof(
134
+ sorted_packets: list, decom_data: collections.defaultdict
135
+ ) -> dict:
136
+ """
137
+ Unpack and decode Ultra TOF packets.
138
+
139
+ Parameters
140
+ ----------
141
+ sorted_packets : list
142
+ TOF packets sorted by time.
143
+ decom_data : collections.defaultdict
144
+ Empty dictionary.
145
+
146
+ Returns
147
+ -------
148
+ decom_data : dict
149
+ A dictionary containing the decoded data.
150
+ """
151
+ stacked_dict: dict = defaultdict(list)
152
+ data_dict: dict = defaultdict(list)
153
+
154
+ # For TOF we need to sort by time and then SID
155
+ sorted_packets = sorted(
156
+ sorted_packets,
157
+ key=lambda x: (x.data["SHCOARSE"].raw_value, x.data["SID"].raw_value),
158
+ )
159
+ if isinstance(ULTRA_TOF.mantissa_bit_length, int) and isinstance(
160
+ ULTRA_TOF.width, int
161
+ ):
162
+ for packet in sorted_packets:
163
+ # Decompress the image data
164
+ decompressed_data = decompress_image(
165
+ packet.data["P00"].derived_value,
166
+ packet.data["PACKETDATA"].raw_value,
167
+ ULTRA_TOF.width,
168
+ ULTRA_TOF.mantissa_bit_length,
169
+ )
170
+
171
+ # Append the decompressed data and other derived data
172
+ # to the dictionary
173
+ append_tof_params(
174
+ decom_data,
175
+ packet,
176
+ decompressed_data=decompressed_data,
177
+ data_dict=data_dict,
178
+ stacked_dict=stacked_dict,
179
+ )
180
+
181
+ # Stack the data to create required dimensions
182
+ for key in stacked_dict.keys():
183
+ decom_data[key] = np.stack(stacked_dict[key])
184
+
185
+ return decom_data
186
+
187
+
188
+ def process_ultra_events(sorted_packets: list, decom_data: dict) -> dict:
189
+ """
190
+ Unpack and decode Ultra EVENTS packets.
191
+
192
+ Parameters
193
+ ----------
194
+ sorted_packets : list
195
+ EVENTS packets sorted by time.
196
+ decom_data : collections.defaultdict
197
+ Empty dictionary.
198
+
199
+ Returns
200
+ -------
201
+ decom_data : dict
202
+ A dictionary containing the decoded data.
203
+ """
204
+ for packet in sorted_packets:
205
+ # Here there are multiple images in a single packet,
206
+ # so we need to loop through each image and decompress it.
207
+ decom_data = read_image_raw_events_binary(packet, decom_data)
208
+ count = packet.data["COUNT"].derived_value
209
+
210
+ if count == 0:
211
+ append_params(decom_data, packet)
212
+ else:
213
+ for i in range(count):
214
+ logging.info(f"Appending image #{i}")
215
+ append_params(decom_data, packet)
216
+
217
+ return decom_data
218
+
219
+
220
+ def process_ultra_aux(sorted_packets: list, decom_data: dict) -> dict:
221
+ """
222
+ Unpack and decode Ultra AUX packets.
223
+
224
+ Parameters
225
+ ----------
226
+ sorted_packets : list
227
+ AUX packets sorted by time.
228
+ decom_data : collections.defaultdict
229
+ Empty dictionary.
230
+
231
+ Returns
232
+ -------
233
+ decom_data : dict
234
+ A dictionary containing the decoded data.
235
+ """
236
+ for packet in sorted_packets:
237
+ append_params(decom_data, packet)
238
+
239
+ return decom_data
240
+
241
+
242
+ def process_ultra_rates(sorted_packets: list, decom_data: dict) -> dict:
243
+ """
244
+ Unpack and decode Ultra RATES packets.
245
+
246
+ Parameters
247
+ ----------
248
+ sorted_packets : list
249
+ RATES packets sorted by time.
250
+ decom_data : collections.defaultdict
251
+ Empty dictionary.
252
+
253
+ Returns
254
+ -------
255
+ decom_data : dict
256
+ A dictionary containing the decoded data.
257
+ """
258
+ if (
259
+ isinstance(ULTRA_RATES.mantissa_bit_length, int)
260
+ and isinstance(ULTRA_RATES.len_array, int)
261
+ and isinstance(ULTRA_RATES.block, int)
262
+ and isinstance(ULTRA_RATES.width, int)
263
+ ):
264
+ for packet in sorted_packets:
265
+ decompressed_data = decompress_binary(
266
+ packet.data["FASTDATA_00"].raw_value,
267
+ ULTRA_RATES.width,
268
+ ULTRA_RATES.block,
269
+ ULTRA_RATES.len_array,
270
+ ULTRA_RATES.mantissa_bit_length,
271
+ )
272
+
273
+ for index in range(ULTRA_RATES.len_array):
274
+ decom_data[RATES_KEYS[index]].append(decompressed_data[index])
275
+
276
+ append_params(decom_data, packet)
277
+
278
+ return decom_data