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,631 @@
1
+ """
2
+ Perform IDEX L1a Processing.
3
+
4
+ This module processes decommutated IDEX packets and creates L1a data products.
5
+ """
6
+
7
+ import logging
8
+ from collections import namedtuple
9
+ from enum import IntEnum
10
+ from pathlib import Path
11
+ from typing import Union
12
+
13
+ import numpy as np
14
+ import numpy.typing as npt
15
+ import space_packet_parser
16
+ import xarray as xr
17
+
18
+ from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
19
+ from imap_processing.idex.idex_l0 import decom_packets
20
+ from imap_processing.spice.time import met_to_j2000ns
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+ # TODO: Generate quicklook plots
25
+
26
+ # Create a large dictionary of values from the FPGA header that need to be
27
+ # captured into the CDF file. They are lumped together because they share
28
+ # similar attributes.
29
+ # Notes about the variables are set here, acting as comments and will also be
30
+ # placed into the CDF in the VAR_NOTES attribute.
31
+ TRIGGER_DESCRIPTION = namedtuple(
32
+ "TRIGGER_DESCRIPTION",
33
+ ["name", "packet_name"],
34
+ )
35
+ TRIGGER_DESCRIPTION_DICT = {
36
+ trigger.name: trigger
37
+ for trigger in [
38
+ TRIGGER_DESCRIPTION("event_number", "IDX__TXHDREVTNUM"),
39
+ TRIGGER_DESCRIPTION("tof_high_trigger_level", "IDX__TXHDRHGTRIGLVL"),
40
+ TRIGGER_DESCRIPTION("tof_high_trigger_num_max_1_2", "IDX__TXHDRHGTRIGNMAX12"),
41
+ TRIGGER_DESCRIPTION("tof_high_trigger_num_min_1_2", "IDX__TXHDRHGTRIGNMIN12"),
42
+ TRIGGER_DESCRIPTION("tof_high_trigger_num_min_1", "IDX__TXHDRHGTRIGNMIN1"),
43
+ TRIGGER_DESCRIPTION("tof_high_trigger_num_max_1", "IDX__TXHDRHGTRIGNMAX1"),
44
+ TRIGGER_DESCRIPTION("tof_high_trigger_num_min_2", "IDX__TXHDRHGTRIGNMIN2"),
45
+ TRIGGER_DESCRIPTION("tof_high_trigger_num_max_2", "IDX__TXHDRHGTRIGNMAX2"),
46
+ TRIGGER_DESCRIPTION("tof_low_trigger_level", "IDX__TXHDRLGTRIGLVL"),
47
+ TRIGGER_DESCRIPTION("tof_low_trigger_num_max_1_2", "IDX__TXHDRLGTRIGNMAX12"),
48
+ TRIGGER_DESCRIPTION("tof_low_trigger_num_min_1_2", "IDX__TXHDRLGTRIGNMIN12"),
49
+ TRIGGER_DESCRIPTION("tof_low_trigger_num_min_1", "IDX__TXHDRLGTRIGNMIN1"),
50
+ TRIGGER_DESCRIPTION("tof_low_trigger_num_max_1", "IDX__TXHDRLGTRIGNMAX1"),
51
+ TRIGGER_DESCRIPTION("tof_low_trigger_num_min_2", "IDX__TXHDRLGTRIGNMIN2"),
52
+ TRIGGER_DESCRIPTION("tof_low_trigger_num_max_2", "IDX__TXHDRLGTRIGNMAX2"),
53
+ TRIGGER_DESCRIPTION("tof_mid_trigger_level", "IDX__TXHDRMGTRIGLVL"),
54
+ TRIGGER_DESCRIPTION("tof_mid_trigger_num_max_1_2", "IDX__TXHDRMGTRIGNMAX12"),
55
+ TRIGGER_DESCRIPTION("tof_mid_trigger_num_min_1_2", "IDX__TXHDRMGTRIGNMIN12"),
56
+ TRIGGER_DESCRIPTION("tof_mid_trigger_num_min_1", "IDX__TXHDRMGTRIGNMIN1"),
57
+ TRIGGER_DESCRIPTION("tof_mid_trigger_num_max_1", "IDX__TXHDRMGTRIGNMAX1"),
58
+ TRIGGER_DESCRIPTION("tof_mid_trigger_num_min_2", "IDX__TXHDRMGTRIGNMIN2"),
59
+ TRIGGER_DESCRIPTION("tof_mid_trigger_num_max_2", "IDX__TXHDRMGTRIGNMAX2"),
60
+ TRIGGER_DESCRIPTION("low_sample_coincidence_mode_blocks", "IDX__TXHDRLSTRIGCMBLOCKS"), # noqa
61
+ TRIGGER_DESCRIPTION("low_sample_trigger_polarity", "IDX__TXHDRLSTRIGPOL"),
62
+ TRIGGER_DESCRIPTION("low_sample_trigger_level", "IDX__TXHDRLSTRIGLVL"),
63
+ TRIGGER_DESCRIPTION("low_sample_trigger_num_min", "IDX__TXHDRLSTRIGNMIN"),
64
+ TRIGGER_DESCRIPTION("low_sample_trigger_mode", "IDX__TXHDRLSTRIGMODE"),
65
+ TRIGGER_DESCRIPTION("tof_low_trigger_mode", "IDX__TXHDRLSTRIGMODE"),
66
+ TRIGGER_DESCRIPTION("tof_mid_trigger_mode", "IDX__TXHDRMGTRIGMODE"),
67
+ TRIGGER_DESCRIPTION("tof_high_trigger_mode", "IDX__TXHDRHGTRIGMODE"),
68
+ TRIGGER_DESCRIPTION("detector_voltage", "IDX__TXHDRHVPSHKCH0"),
69
+ TRIGGER_DESCRIPTION("sensor_voltage", "IDX__TXHDRHVPSHKCH1"),
70
+ TRIGGER_DESCRIPTION("target_voltage", "IDX__TXHDRHVPSHKCH2"),
71
+ TRIGGER_DESCRIPTION("reflectron_voltage", "IDX__TXHDRHVPSHKCH3"),
72
+ TRIGGER_DESCRIPTION("rejection_voltage", "IDX__TXHDRHVPSHKCH4"),
73
+ TRIGGER_DESCRIPTION("detector_current", "IDX__TXHDRHVPSHKCH5"),
74
+ ]
75
+ } # fmt: skip
76
+
77
+
78
+ class Scitype(IntEnum):
79
+ """Define parameters for IDEX Science Type."""
80
+
81
+ FIRST_PACKET = 1
82
+ TOF_HIGH = 2
83
+ TOF_LOW = 4
84
+ TOF_MID = 8
85
+ TARGET_LOW = 16
86
+ TARGET_HIGH = 32
87
+ ION_GRID = 64
88
+
89
+
90
+ class PacketParser:
91
+ """
92
+ IDEX L1a packet parsing class.
93
+
94
+ Encapsulates the decom work needed to decom a daily file of IDEX L0 data
95
+ received from the POC. The class is instantiated with a reference to a L0
96
+ file as it exists on the local file system.
97
+
98
+ Parameters
99
+ ----------
100
+ packet_file : str
101
+ The path and filename to the L0 file to read.
102
+ data_version : str
103
+ The version of the data product being created.
104
+
105
+ Examples
106
+ --------
107
+ .. code-block:: python
108
+
109
+ from imap_processing.idex.idex_l1a import PacketParser
110
+ l0_file = "imap_processing/tests/idex/imap_idex_l0_sci_20230725_v001.pkts"
111
+ l1a_data = PacketParser(l0_file, data_version)
112
+ l1a_data.write_l1a_cdf()
113
+ """
114
+
115
+ def __init__(self, packet_file: Union[str, Path], data_version: str) -> None:
116
+ """
117
+ Read a L0 pkts file and perform all of the decom work.
118
+
119
+ Parameters
120
+ ----------
121
+ packet_file : pathlib.Path | str
122
+ The path and filename to the L0 file to read.
123
+ data_version : str
124
+ The version of the data product being created.
125
+
126
+ Notes
127
+ -----
128
+ Currently assumes one L0 file will generate exactly one L1a file.
129
+ """
130
+ decom_packet_list = decom_packets(packet_file)
131
+
132
+ dust_events = {}
133
+ for packet in decom_packet_list:
134
+ if "IDX__SCI0TYPE" in packet.data:
135
+ scitype = packet.data["IDX__SCI0TYPE"].raw_value
136
+ event_number = packet.data["IDX__SCI0EVTNUM"].derived_value
137
+ if scitype == Scitype.FIRST_PACKET:
138
+ # Initial packet for new dust event
139
+ # Further packets will fill in data
140
+ dust_events[event_number] = RawDustEvent(packet, data_version)
141
+ elif event_number not in dust_events:
142
+ raise KeyError(
143
+ f"Have not receive header information from event number\
144
+ {event_number}. Packets are possibly out of order!"
145
+ )
146
+ else:
147
+ # Populate the IDEXRawDustEvent with 1's and 0's
148
+ dust_events[event_number]._populate_bit_strings(packet)
149
+ else:
150
+ logger.warning(f"Unhandled packet received: {packet}")
151
+
152
+ processed_dust_impact_list = [
153
+ dust_event.process() for dust_event in dust_events.values()
154
+ ]
155
+
156
+ self.data = xr.concat(processed_dust_impact_list, dim="epoch")
157
+ idex_attrs = get_idex_attrs(data_version)
158
+ self.data.attrs = idex_attrs.get_global_attributes("imap_idex_l1a_sci")
159
+
160
+
161
+ class RawDustEvent:
162
+ """
163
+ Encapsulate IDEX Raw Dust Event.
164
+
165
+ Encapsulates the work needed to convert a single dust event into a processed
166
+ ``xarray`` ``dateset`` object.
167
+
168
+ Parameters
169
+ ----------
170
+ header_packet : space_packet_parser.parser.Packet
171
+ The FPGA metadata event header.
172
+ data_version : str
173
+ The version of the data product being created.
174
+
175
+ Attributes
176
+ ----------
177
+ HIGH_SAMPLE_RATE: float
178
+ The high sample rate in microseconds per sample.
179
+ LOW_SAMPLE_RATE: float
180
+ The low sample rate in microseconds per sample.
181
+ NUMBER_SAMPLES_PER_LOW_SAMPLE_BLOCK: int
182
+ The number of samples in a "block" of low sample data.
183
+ NUMBER_SAMPLES_PER_HIGH_SAMPLE_BLOCK: int
184
+ The number of samples in a "block" of high sample data.
185
+
186
+ Methods
187
+ -------
188
+ _append_raw_data(scitype, bits)
189
+ Append data to the appropriate bit string.
190
+ _set_impact_time(packet)
191
+ Calculate the datetime64 from the FPGA header information.
192
+ _set_sample_trigger_times(packet)
193
+ Calculate the actual sample trigger time.
194
+ _parse_high_sample_waveform(waveform_raw)
195
+ Will process the high sample waveform.
196
+ _parse_low_sample_waveform(waveform_raw)
197
+ Will process the low sample waveform.
198
+ _calc_low_sample_resolution(num_samples)
199
+ Calculate the resolution of the low samples.
200
+ _calc_high_sample_resolution(num_samples)
201
+ Calculate the resolution of high samples.
202
+ _populate_bit_strings(packet)
203
+ Parse IDEX data packets to populate bit strings.
204
+ process()
205
+ Will process the raw data into a xarray.Dataset.
206
+ """
207
+
208
+ # Constants
209
+ HIGH_SAMPLE_RATE = 1 / 260 # microseconds per sample
210
+ LOW_SAMPLE_RATE = 1 / 4.0625 # microseconds per sample
211
+
212
+ NUMBER_SAMPLES_PER_LOW_SAMPLE_BLOCK = (
213
+ 8 # The number of samples in a "block" of low sample data
214
+ )
215
+ NUMBER_SAMPLES_PER_HIGH_SAMPLE_BLOCK = (
216
+ 512 # The number of samples in a "block" of high sample data
217
+ )
218
+
219
+ def __init__(
220
+ self, header_packet: space_packet_parser.parser.Packet, data_version: str
221
+ ) -> None:
222
+ """
223
+ Initialize a raw dust event, with an FPGA Header Packet from IDEX.
224
+
225
+ The values we care about are:
226
+
227
+ self.impact_time - When the impact occurred.
228
+ self.low_sample_trigger_time - When the low sample stuff actually triggered.
229
+ self.high_sample_trigger_time - When the high sample stuff actually triggered.
230
+
231
+ Parameters
232
+ ----------
233
+ header_packet : space_packet_parser.parser.Packet
234
+ The FPGA metadata event header.
235
+ data_version : str
236
+ Data version for CDF filename, in the format ``vXXX``.
237
+ """
238
+ # Calculate the impact time in seconds since epoch
239
+ self.impact_time = 0
240
+ self._set_impact_time(header_packet)
241
+
242
+ # The actual trigger time for the low and high sample rate in
243
+ # microseconds since the impact time
244
+ self.low_sample_trigger_time = 0
245
+ self.high_sample_trigger_time = 0
246
+ self._set_sample_trigger_times(header_packet)
247
+
248
+ # Iterate through the trigger description dictionary and pull out the values
249
+ self.trigger_values = {
250
+ trigger.name: header_packet.data[trigger.packet_name].raw_value
251
+ for trigger in TRIGGER_DESCRIPTION_DICT.values()
252
+ }
253
+ logger.debug(
254
+ f"trigger_values:\n{self.trigger_values}"
255
+ ) # Log values here in case of error
256
+
257
+ # Initialize the binary data received from future packets
258
+ self.TOF_High_bits = ""
259
+ self.TOF_Mid_bits = ""
260
+ self.TOF_Low_bits = ""
261
+ self.Target_Low_bits = ""
262
+ self.Target_High_bits = ""
263
+ self.Ion_Grid_bits = ""
264
+
265
+ self.cdf_attrs = get_idex_attrs(data_version)
266
+
267
+ def _append_raw_data(self, scitype: Scitype, bits: str) -> None:
268
+ """
269
+ Append data to the appropriate bit string.
270
+
271
+ This function determines which variable to append the bits to, given a
272
+ specific scitype.
273
+
274
+ Parameters
275
+ ----------
276
+ scitype : Scitype
277
+ The science type of the data.
278
+ bits : str
279
+ The binary data to append.
280
+ """
281
+ if scitype == Scitype.TOF_HIGH:
282
+ self.TOF_High_bits += bits
283
+ elif scitype == Scitype.TOF_LOW:
284
+ self.TOF_Low_bits += bits
285
+ elif scitype == Scitype.TOF_MID:
286
+ self.TOF_Mid_bits += bits
287
+ elif scitype == Scitype.TARGET_LOW:
288
+ self.Target_Low_bits += bits
289
+ elif scitype == Scitype.TARGET_HIGH:
290
+ self.Target_High_bits += bits
291
+ elif scitype == Scitype.ION_GRID:
292
+ self.Ion_Grid_bits += bits
293
+ else:
294
+ logger.warning("Unknown science type received: [%s]", scitype)
295
+
296
+ def _set_impact_time(self, packet: space_packet_parser.parser.Packet) -> None:
297
+ """
298
+ Calculate the impact time from the FPGA header information.
299
+
300
+ We are given the MET seconds, we need convert it to UTC in type
301
+ ``np.datetime64``.
302
+
303
+ Parameters
304
+ ----------
305
+ packet : space_packet_parser.parser.Packet
306
+ The IDEX FPGA header packet.
307
+
308
+ Notes
309
+ -----
310
+ TODO: This conversion is temporary for now, and will need SPICE in the
311
+ future. IDEX has set the time launch to Jan 1 2012 for calibration
312
+ testing.
313
+ """
314
+ # Number of seconds since epoch (nominally the launch time)
315
+ seconds_since_launch = packet.data["SHCOARSE"].derived_value
316
+ # Number of 20 microsecond "ticks" since the last second
317
+ num_of_20_microsecond_increments = packet.data["SHFINE"].derived_value
318
+ # Number of microseconds since the last second
319
+ microseconds_since_last_second = 20 * num_of_20_microsecond_increments
320
+ # Get the datetime of Jan 1 2012 as the start date
321
+ met = seconds_since_launch + microseconds_since_last_second * 1e-6
322
+
323
+ self.impact_time = met_to_j2000ns(met)
324
+
325
+ def _set_sample_trigger_times(
326
+ self, packet: space_packet_parser.parser.Packet
327
+ ) -> None:
328
+ """
329
+ Calculate the actual sample trigger time.
330
+
331
+ Determines how many samples of data are included before the dust impact
332
+ triggered the instrument.
333
+
334
+ Parameters
335
+ ----------
336
+ packet : space_packet_parser.parser.Packet
337
+ The IDEX FPGA header packet info.
338
+
339
+ Notes
340
+ -----
341
+ A "sample" is one single data point.
342
+
343
+ A "block" is ~1.969 microseconds of data collection (8/4.0625). The only
344
+ time that a block of data matters is in this function.
345
+
346
+ Because the low sample data are taken every 1/4.0625 microseconds, there
347
+ are 8 samples in one block of data.
348
+
349
+ Because the high sample data are taken every 1/260 microseconds, there
350
+ are 512 samples in one block of High Sample data.
351
+
352
+ The header has information about the number of blocks before triggering,
353
+ rather than the number of samples before triggering.
354
+ """
355
+ # Retrieve the number of samples of high gain delay
356
+ high_gain_delay = packet.data["IDX__TXHDRADC0IDELAY"].raw_value
357
+
358
+ # Retrieve number of low/high sample pre-trigger blocks
359
+ num_low_sample_pretrigger_blocks = packet.data[
360
+ "IDX__TXHDRLSPREBLOCKS"
361
+ ].derived_value
362
+ num_high_sample_pretrigger_blocks = packet.data[
363
+ "IDX__TXHDRHSPREBLOCKS"
364
+ ].derived_value
365
+
366
+ # Calculate the low and high sample trigger times based on the high gain delay
367
+ # and the number of high sample/low sample pretrigger blocks
368
+ self.low_sample_trigger_time = (
369
+ self.LOW_SAMPLE_RATE
370
+ * (num_low_sample_pretrigger_blocks + 1)
371
+ * self.NUMBER_SAMPLES_PER_LOW_SAMPLE_BLOCK
372
+ - self.HIGH_SAMPLE_RATE * high_gain_delay
373
+ )
374
+ self.high_sample_trigger_time = (
375
+ self.HIGH_SAMPLE_RATE
376
+ * (num_high_sample_pretrigger_blocks + 1)
377
+ * self.NUMBER_SAMPLES_PER_HIGH_SAMPLE_BLOCK
378
+ )
379
+
380
+ def _parse_high_sample_waveform(self, waveform_raw: str) -> list[int]:
381
+ """
382
+ Will process the high sample waveform.
383
+
384
+ Parse a binary string representing a high sample waveform.
385
+ Data arrives in 32 bit chunks, divided up into:
386
+ * 2 bits of padding
387
+ * 3x10 bits of integer data.
388
+
389
+ The very last 4 numbers are bad usually, so remove those.
390
+
391
+ Parameters
392
+ ----------
393
+ waveform_raw : str
394
+ The binary string representing the high sample waveform.
395
+
396
+ Returns
397
+ -------
398
+ ints : list
399
+ List of the high sample waveform.
400
+ """
401
+ ints = []
402
+ for i in range(0, len(waveform_raw), 32):
403
+ # 32 bit chunks, divided up into 2, 10, 10, 10
404
+ # skip first two bits
405
+ ints += [
406
+ int(waveform_raw[i + 2 : i + 12], 2),
407
+ int(waveform_raw[i + 12 : i + 22], 2),
408
+ int(waveform_raw[i + 22 : i + 32], 2),
409
+ ]
410
+ return ints[:-4] # Remove last 4 numbers
411
+
412
+ def _parse_low_sample_waveform(self, waveform_raw: str) -> list[int]:
413
+ """
414
+ Will process the low sample waveform.
415
+
416
+ Parse a binary string representing a low sample waveform
417
+ Data arrives in 32 bit chunks, divided up into:
418
+ * 8 bits of padding
419
+ * 2x12 bits of integer data.
420
+
421
+ Parameters
422
+ ----------
423
+ waveform_raw : str
424
+ The binary string representing the low sample waveform.
425
+
426
+ Returns
427
+ -------
428
+ ints : list
429
+ List of processed low sample waveform.
430
+ """
431
+ ints = []
432
+ for i in range(0, len(waveform_raw), 32):
433
+ ints += [
434
+ int(waveform_raw[i + 8 : i + 20], 2),
435
+ int(waveform_raw[i + 20 : i + 32], 2),
436
+ ]
437
+ return ints
438
+
439
+ def _calc_low_sample_resolution(self, num_samples: int) -> npt.NDArray:
440
+ """
441
+ Calculate the resolution of the low samples.
442
+
443
+ Calculates the low sample time array based on the number
444
+ of samples of data taken.
445
+
446
+ Multiply a linear array by the sample rate.
447
+ Subtract the calculated trigger time.
448
+
449
+ Parameters
450
+ ----------
451
+ num_samples : int
452
+ The number of samples.
453
+
454
+ Returns
455
+ -------
456
+ time_low_sr_data : numpy.ndarray
457
+ Low time sample data array.
458
+ """
459
+ time_low_sr_init = np.linspace(0, num_samples, num_samples)
460
+ time_low_sr_data = (
461
+ self.LOW_SAMPLE_RATE * time_low_sr_init - self.low_sample_trigger_time
462
+ )
463
+ return time_low_sr_data
464
+
465
+ def _calc_high_sample_resolution(self, num_samples: int) -> npt.NDArray:
466
+ """
467
+ Calculate the resolution of high samples.
468
+
469
+ Calculates the high sample time array based on the number
470
+ of samples of data taken.
471
+
472
+ Multiply a linear array by the sample rate.
473
+ Subtract the calculated trigger time.
474
+
475
+ Parameters
476
+ ----------
477
+ num_samples : int
478
+ The number of samples.
479
+
480
+ Returns
481
+ -------
482
+ time_high_sr_data : numpy.ndarray
483
+ High sample time data array.
484
+ """
485
+ time_high_sr_init = np.linspace(0, num_samples, num_samples)
486
+ time_high_sr_data = (
487
+ self.HIGH_SAMPLE_RATE * time_high_sr_init - self.high_sample_trigger_time
488
+ )
489
+ return time_high_sr_data
490
+
491
+ def _populate_bit_strings(self, packet: space_packet_parser.parser.Packet) -> None:
492
+ """
493
+ Parse IDEX data packets to populate bit strings.
494
+
495
+ Parameters
496
+ ----------
497
+ packet : space_packet_parser.parser.Packet
498
+ A single science data packet for one of the 6.
499
+ IDEX observables.
500
+ """
501
+ scitype = packet.data["IDX__SCI0TYPE"].raw_value
502
+ raw_science_bits = packet.data["IDX__SCI0RAW"].raw_value
503
+ self._append_raw_data(scitype, raw_science_bits)
504
+
505
+ def process(self) -> xr.Dataset:
506
+ """
507
+ Will process the raw data into a ``xarray.Dataset``.
508
+
509
+ To be called after all packets for the IDEX event have been parsed.
510
+ Parses the binary data into numpy integer arrays, and combines them into
511
+ a ``xarray.Dataset`` object.
512
+
513
+ Returns
514
+ -------
515
+ dataset : xarray.Dataset
516
+ A Dataset object containing the data from a single impact.
517
+ """
518
+ # Create object for CDF attrs
519
+ idex_attrs = self.cdf_attrs
520
+
521
+ # Gather the huge number of trigger info metadata
522
+ trigger_vars = {}
523
+ for var, value in self.trigger_values.items():
524
+ trigger_desc = TRIGGER_DESCRIPTION_DICT[var]
525
+ trigger_vars[var] = xr.DataArray(
526
+ name=var,
527
+ data=[value],
528
+ dims=("epoch"),
529
+ attrs=idex_attrs.get_variable_attributes(trigger_desc.name),
530
+ )
531
+
532
+ # Process the 6 primary data variables
533
+ tof_high_xr = xr.DataArray(
534
+ name="TOF_High",
535
+ data=[self._parse_high_sample_waveform(self.TOF_High_bits)],
536
+ dims=("epoch", "time_high_ssr_dim"),
537
+ attrs=idex_attrs.get_variable_attributes("tof_high_attrs"),
538
+ )
539
+ tof_low_xr = xr.DataArray(
540
+ name="TOF_Low",
541
+ data=[self._parse_high_sample_waveform(self.TOF_Low_bits)],
542
+ dims=("epoch", "time_high_sr"),
543
+ attrs=idex_attrs.get_variable_attributes("tof_low_attrs"),
544
+ )
545
+ tof_mid_xr = xr.DataArray(
546
+ name="TOF_Mid",
547
+ data=[self._parse_high_sample_waveform(self.TOF_Mid_bits)],
548
+ dims=("epoch", "time_high_sr"),
549
+ attrs=idex_attrs.get_variable_attributes("tof_mid_attrs"),
550
+ )
551
+ target_high_xr = xr.DataArray(
552
+ name="Target_High",
553
+ data=[self._parse_low_sample_waveform(self.Target_High_bits)],
554
+ dims=("epoch", "time_low_sr"),
555
+ attrs=idex_attrs.get_variable_attributes("target_high_attrs"),
556
+ )
557
+ target_low_xr = xr.DataArray(
558
+ name="Target_Low",
559
+ data=[self._parse_low_sample_waveform(self.Target_Low_bits)],
560
+ dims=("epoch", "time_low_sr"),
561
+ attrs=idex_attrs.get_variable_attributes("target_low_attrs"),
562
+ )
563
+ ion_grid_xr = xr.DataArray(
564
+ name="Ion_Grid",
565
+ data=[self._parse_low_sample_waveform(self.Ion_Grid_bits)],
566
+ dims=("epoch", "time_low_sr"),
567
+ attrs=idex_attrs.get_variable_attributes("ion_grid_attrs"),
568
+ )
569
+
570
+ # Determine the 3 coordinate variables
571
+ epoch_xr = xr.DataArray(
572
+ name="epoch",
573
+ data=[self.impact_time],
574
+ dims=("epoch"),
575
+ attrs=idex_attrs.get_variable_attributes("epoch"),
576
+ )
577
+
578
+ time_low_sr_xr = xr.DataArray(
579
+ name="time_low_sr",
580
+ data=[self._calc_low_sample_resolution(len(target_low_xr[0]))],
581
+ dims=("epoch", "time_low_sr_dim"),
582
+ attrs=idex_attrs.get_variable_attributes("low_sr_attrs"),
583
+ )
584
+
585
+ time_high_sr_xr = xr.DataArray(
586
+ name="time_high_sr",
587
+ data=[self._calc_high_sample_resolution(len(tof_low_xr[0]))],
588
+ dims=("epoch", "time_high_sr_dim"),
589
+ attrs=idex_attrs.get_variable_attributes("high_sr_attrs"),
590
+ )
591
+
592
+ # Combine to return a dataset object
593
+ dataset = xr.Dataset(
594
+ data_vars={
595
+ "TOF_Low": tof_low_xr,
596
+ "TOF_High": tof_high_xr,
597
+ "TOF_Mid": tof_mid_xr,
598
+ "Target_High": target_high_xr,
599
+ "Target_Low": target_low_xr,
600
+ "Ion_Grid": ion_grid_xr,
601
+ }
602
+ | trigger_vars,
603
+ coords={
604
+ "epoch": epoch_xr,
605
+ "time_low_sr": time_low_sr_xr,
606
+ "time_high_sr": time_high_sr_xr,
607
+ },
608
+ )
609
+
610
+ return dataset
611
+
612
+
613
+ def get_idex_attrs(data_version: str) -> ImapCdfAttributes:
614
+ """
615
+ Load in CDF attributes for IDEX instrument.
616
+
617
+ Parameters
618
+ ----------
619
+ data_version : str
620
+ Data version for CDF filename, in the format "vXXX".
621
+
622
+ Returns
623
+ -------
624
+ idex_attrs : ImapCdfAttributes
625
+ The IDEX L1a CDF attributes.
626
+ """
627
+ idex_attrs = ImapCdfAttributes()
628
+ idex_attrs.add_instrument_global_attrs("idex")
629
+ idex_attrs.add_instrument_variable_attrs("idex", "l1a")
630
+ idex_attrs.add_global_attribute("Data_version", data_version)
631
+ return idex_attrs