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,34 @@
1
+ """Interstellar Mapping and Acceleration Probe (IMAP) data processing package.
2
+
3
+ This package contains the IMAP data processing software. The package is
4
+ organized into submodules for each instrument. Each instrument submodule
5
+ contains code for each processing level.
6
+
7
+ There are utilities to read and write IMAP data files in
8
+ the CDF file format, and to interact with the SPICE toolkit.
9
+ """
10
+
11
+ # When imap_processing is installed using pip, we need to be able to find the
12
+ # packet definitions directory path.
13
+ #
14
+ # This directory is used by the imap_processing package to find the packet definitions.
15
+ from pathlib import Path
16
+
17
+ from imap_processing._version import __version__, __version_tuple__ # noqa: F401
18
+
19
+ # Eg. imap_module_directory = /usr/local/lib/python3.11/site-packages/imap_processing
20
+ imap_module_directory = Path(__file__).parent
21
+
22
+ # TODO: should we move this to imap-data-access?
23
+ PROCESSING_LEVELS = {
24
+ "codice": ["l0", "l1a", "l1b", "l2"],
25
+ "glows": ["l0", "l1a", "l1b", "l2"],
26
+ "hi": ["l0", "l1a", "l1b", "l1c", "l2"],
27
+ "hit": ["l0", "l1a", "l1b", "l2"],
28
+ "idex": ["l0", "l1a", "l1b", "l2"],
29
+ "lo": ["l0", "l1a", "l1b", "l1c", "l2"],
30
+ "mag": ["l0", "l1a", "l1b", "l1c", "l2pre", "l2"],
31
+ "swapi": ["l0", "l1", "l2", "l3a", "l3b"],
32
+ "swe": ["l0", "l1a", "l1b", "l2"],
33
+ "ultra": ["l0", "l1a", "l1b", "l1c", "l2"],
34
+ }
@@ -0,0 +1,3 @@
1
+ # These version placeholders will be replaced later during substitution.
2
+ __version__ = "0.6.0"
3
+ __version_tuple__ = (0, 6, 0)
File without changes
@@ -0,0 +1,55 @@
1
+ """Contain a data class for CCSDS data."""
2
+
3
+ from dataclasses import dataclass, fields
4
+
5
+
6
+ @dataclass
7
+ class CcsdsData:
8
+ """
9
+ Data class for CCSDS header.
10
+
11
+ Parameters
12
+ ----------
13
+ packet_header : dict
14
+ Dictionary of packet headers.
15
+
16
+ Attributes
17
+ ----------
18
+ VERSION: int
19
+ CCSDS Packet Version Number.
20
+ TYPE: int
21
+ CCSDS Packet Type Indicator.
22
+ SEC_HDR_FLG: int
23
+ CCSDS Packet Secondary Header Flag.
24
+ PKT_APID: int
25
+ CCSDS Packet Application Process ID.
26
+ SEQ_FLGS: int
27
+ CCSDS Packet Grouping Flags.
28
+ SRC_SEQ_CTR: int
29
+ CCSDS Packet Sequence Count.
30
+ PKT_LEN: int
31
+ CCSDS Packet Length.
32
+ """
33
+
34
+ VERSION: int
35
+ TYPE: int
36
+ SEC_HDR_FLG: int
37
+ PKT_APID: int
38
+ SEQ_FLGS: int
39
+ SRC_SEQ_CTR: int
40
+ PKT_LEN: int
41
+
42
+ def __init__(self, packet_header: dict):
43
+ attributes = [field.name for field in fields(self)]
44
+
45
+ for key, item in packet_header.items():
46
+ value = (
47
+ item.derived_value if item.derived_value is not None else item.raw_value
48
+ )
49
+ if key in attributes:
50
+ setattr(self, key, value)
51
+ else:
52
+ raise KeyError(
53
+ f"Did not find matching attribute in Histogram data class for "
54
+ f"{key}"
55
+ )
@@ -0,0 +1,477 @@
1
+ """
2
+ Convert an Excel file of packet definitions into the XTCE format.
3
+
4
+ This script reads in an Excel file containing packet definitions and converts
5
+ them into an XTCE file.
6
+
7
+ .. code::
8
+ imap_xtce /path/to/excel_file.xlsx --output /path/to/output.xml
9
+ """
10
+
11
+ import argparse
12
+ import xml.etree.ElementTree as Et
13
+ from importlib.util import find_spec
14
+ from pathlib import Path
15
+
16
+ import pandas as pd
17
+
18
+ _CCSDS_PARAMETERS = [
19
+ {
20
+ "name": "VERSION",
21
+ "lengthInBits": 3,
22
+ "description": "CCSDS Packet Version Number (always 0)",
23
+ },
24
+ {
25
+ "name": "TYPE",
26
+ "lengthInBits": 1,
27
+ "description": "CCSDS Packet Type Indicator (0=telemetry)",
28
+ },
29
+ {
30
+ "name": "SEC_HDR_FLG",
31
+ "lengthInBits": 1,
32
+ "description": "CCSDS Packet Secondary Header Flag (always 1)",
33
+ },
34
+ {
35
+ "name": "PKT_APID",
36
+ "lengthInBits": 11,
37
+ "description": "CCSDS Packet Application Process ID",
38
+ },
39
+ {
40
+ "name": "SEQ_FLGS",
41
+ "lengthInBits": 2,
42
+ "description": "CCSDS Packet Grouping Flags (3=not part of group)",
43
+ },
44
+ {
45
+ "name": "SRC_SEQ_CTR",
46
+ "lengthInBits": 14,
47
+ "description": "CCSDS Packet Sequence Count "
48
+ "(increments with each new packet)",
49
+ },
50
+ {
51
+ "name": "PKT_LEN",
52
+ "lengthInBits": 16,
53
+ "description": "CCSDS Packet Length "
54
+ "(number of bytes after Packet length minus 1)",
55
+ },
56
+ ]
57
+
58
+
59
+ class XTCEGenerator:
60
+ """
61
+ Automatically generate XTCE files from excel definition files.
62
+
63
+ The excel file should have the following columns: mnemonic, sequence, lengthInBits,
64
+ startBit, dataType, convertAs, units, source, and either shortDescription or
65
+ longDescription.
66
+
67
+ This class will correctly generate a CCSDS header and the provided data types.
68
+
69
+ It is intended for use as a first pass of XTCE generation, and most cases, the
70
+ packet definitions will require manual updates.
71
+
72
+ Use ``to_xml`` to write the output xml file.
73
+
74
+ Parameters
75
+ ----------
76
+ path_to_excel_file : Path
77
+ Path to the excel file.
78
+ """
79
+
80
+ def __init__(self, path_to_excel_file: Path):
81
+ # Read in all sheets from the excel file
82
+ self.sheets = pd.read_excel(path_to_excel_file, sheet_name=None)
83
+ # Set up the packet mapping from packetName to Apid
84
+ packet_sheet = self.sheets["Packets"]
85
+ if "apId" not in packet_sheet.columns:
86
+ # Create the apId column from the apIdHex (base=0 works with the 0x prefix)
87
+ packet_sheet["apId"] = packet_sheet["apIdHex"].apply(int, base=0)
88
+ self._packet_mapping = packet_sheet.set_index("packetName")["apId"].to_dict()
89
+
90
+ # Create the XML containers that will be populated later
91
+ self._setup_xml_containers()
92
+ # Add the CCSDS Header information to the containers
93
+ self._setup_ccsds_header()
94
+ # Create the sequence containers (also adding parameters within)
95
+ self._create_container_sets()
96
+
97
+ def _setup_xml_containers(self) -> None:
98
+ """Create an XML representation of telemetry data."""
99
+ # Register the XML namespace
100
+ source_link = "http://www.omg.org/space/xtce"
101
+ Et.register_namespace("xtce", source_link)
102
+
103
+ # Create the root element and add namespaces
104
+ root = Et.Element("xtce:SpaceSystem")
105
+ self._root = root
106
+ root.attrib["xmlns:xtce"] = source_link
107
+ # Subsystem sheet name is used as the base name for this XTCE definition
108
+ subsystem = self.sheets["Subsystem"]
109
+ root.attrib["name"] = str(
110
+ subsystem.loc[subsystem["infoField"] == "subsystem", "infoValue"].values[0]
111
+ )
112
+ # Create the Header element with attributes 'date', 'version', and 'author'
113
+ # Versioning is used to keep track of changes to the XML file.
114
+ header = Et.SubElement(root, "xtce:Header")
115
+ header.attrib["date"] = str(
116
+ subsystem.loc[
117
+ subsystem["infoField"] == "sheetReleaseDate", "infoValue"
118
+ ].values[0]
119
+ )
120
+ header.attrib["version"] = str(
121
+ subsystem.loc[
122
+ subsystem["infoField"] == "sheetReleaseRev", "infoValue"
123
+ ].values[0]
124
+ )
125
+ header.attrib["author"] = "IMAP SDC"
126
+
127
+ # Create the TelemetryMetaData element
128
+ self._telemetry_metadata = Et.SubElement(root, "xtce:TelemetryMetaData")
129
+
130
+ # Create the ParameterTypeSet element
131
+ self._parameter_type_set = Et.SubElement(
132
+ self._telemetry_metadata, "xtce:ParameterTypeSet"
133
+ )
134
+
135
+ # Create the ParameterSet element
136
+ self._parameter_set = Et.SubElement(
137
+ self._telemetry_metadata, "xtce:ParameterSet"
138
+ )
139
+
140
+ # Create ContainerSet element
141
+ self._container_sets = Et.SubElement(
142
+ self._telemetry_metadata, "xtce:ContainerSet"
143
+ )
144
+
145
+ def _setup_ccsds_header(self) -> None:
146
+ """Fill in the default CCSDS header information."""
147
+ # Create CCSDSPacket SequenceContainer
148
+ ccsds_container = Et.SubElement(self._container_sets, "xtce:SequenceContainer")
149
+ ccsds_container.attrib["name"] = "CCSDSPacket"
150
+ ccsds_container.attrib["abstract"] = "true"
151
+ ccsds_entry_list = Et.SubElement(ccsds_container, "xtce:EntryList")
152
+
153
+ # Populate EntryList for CCSDSPacket SequenceContainer
154
+ for parameter_data in _CCSDS_PARAMETERS:
155
+ parameter_ref_entry = Et.SubElement(
156
+ ccsds_entry_list, "xtce:ParameterRefEntry"
157
+ )
158
+ name = str(parameter_data["name"])
159
+
160
+ parameter_ref_entry.attrib["parameterRef"] = name
161
+
162
+ # Add the parameter to the ParameterSet
163
+ parameter = Et.SubElement(self._parameter_set, "xtce:Parameter")
164
+ parameter.attrib["name"] = name
165
+ parameter.attrib["parameterTypeRef"] = name
166
+
167
+ description = Et.SubElement(parameter, "xtce:LongDescription")
168
+ description.text = str(parameter_data["description"])
169
+
170
+ # Add the typeref to the parameter type set
171
+ parameter_type = Et.SubElement(
172
+ self._parameter_type_set, "xtce:IntegerParameterType"
173
+ )
174
+ parameter_type.attrib["name"] = name
175
+ parameter_type.attrib["signed"] = "false"
176
+
177
+ encoding = Et.SubElement(parameter_type, "xtce:IntegerDataEncoding")
178
+ encoding.attrib["sizeInBits"] = str(parameter_data["lengthInBits"])
179
+ encoding.attrib["encoding"] = "unsigned"
180
+
181
+ def _create_container_sets(self) -> None:
182
+ """Create a container set for each packet in the Excel file."""
183
+ # Iterate over all packets and create Packet SequenceContainers
184
+ for packet_name, apid in self._packet_mapping.items():
185
+ # Populate EntryList for packet SequenceContainers
186
+ # The sheets are sometimes prefixed with P_, so we need to try both options
187
+ try:
188
+ packet_df = self.sheets[packet_name]
189
+ except KeyError:
190
+ try:
191
+ packet_df = self.sheets[f"P_{packet_name}"]
192
+ except KeyError:
193
+ print(
194
+ f"Packet definition for {packet_name} "
195
+ "not found in the excel file."
196
+ )
197
+ continue
198
+
199
+ # Create Packet SequenceContainer that use the CCSDSPacket SequenceContainer
200
+ # as the base container
201
+ science_container = Et.SubElement(
202
+ self._container_sets, "xtce:SequenceContainer"
203
+ )
204
+ science_container.attrib["name"] = packet_name
205
+
206
+ # Every container should inherit from the base container, CCSDSPacket
207
+ base_container = Et.SubElement(science_container, "xtce:BaseContainer")
208
+ base_container.attrib["containerRef"] = "CCSDSPacket"
209
+
210
+ # Add RestrictionCriteria element to use the given APID for comparison
211
+ restriction_criteria = Et.SubElement(
212
+ base_container, "xtce:RestrictionCriteria"
213
+ )
214
+ comparison = Et.SubElement(restriction_criteria, "xtce:Comparison")
215
+ comparison.attrib["parameterRef"] = "PKT_APID"
216
+ comparison.attrib["value"] = str(apid)
217
+ comparison.attrib["useCalibratedValue"] = "false"
218
+
219
+ packet_entry_list = Et.SubElement(science_container, "xtce:EntryList")
220
+ # Needed for dynamic binary packet length
221
+ total_packet_bits = int(packet_df["lengthInBits"].sum())
222
+ for i, row in packet_df.iterrows():
223
+ if i < 7:
224
+ # Skip first 7 rows as they are the CCSDS header elements
225
+ continue
226
+ if pd.isna(row.get("packetName")):
227
+ # This is a poorly formatted row, skip it
228
+ continue
229
+ # separate the packet name and mnemonic with a period
230
+ # a hyphen is sometimes in the packet name or mnemonic already
231
+ name = f"{row['packetName']}.{row['mnemonic']}"
232
+ parameter_ref_entry = Et.SubElement(
233
+ packet_entry_list, "xtce:ParameterRefEntry"
234
+ )
235
+ parameter_ref_entry.attrib["parameterRef"] = name
236
+ # Add this parameter to the ParameterSet too
237
+ self._add_parameter(row, total_packet_bits)
238
+
239
+ def _add_parameter(self, row: pd.Series, total_packet_bits: int) -> None:
240
+ """
241
+ Row from a packet definition to be added to the XTCE file.
242
+
243
+ Parameters
244
+ ----------
245
+ row : pandas.Row
246
+ Row to be added to the XTCE file, containing mnemonic, lengthInBits, ...
247
+ total_packet_bits : int
248
+ Total number of bits in the packet, as summed from the lengthInBits column.
249
+ """
250
+ parameter = Et.SubElement(self._parameter_set, "xtce:Parameter")
251
+ # Combine the packet name and mnemonic to create a unique parameter name
252
+ name = f"{row['packetName']}.{row['mnemonic']}"
253
+ parameter.attrib["name"] = name
254
+ parameter.attrib["parameterTypeRef"] = name
255
+
256
+ # Add descriptions if they exist
257
+ if pd.notna(row.get("shortDescription")):
258
+ parameter.attrib["shortDescription"] = row.get("shortDescription")
259
+ if pd.notna(row.get("longDescription")):
260
+ description = Et.SubElement(parameter, "xtce:LongDescription")
261
+ description.text = row.get("longDescription")
262
+
263
+ length_in_bits = int(row["lengthInBits"])
264
+
265
+ # Add the parameterTypeRef for this row
266
+ if "UINT" in row["dataType"] or "FILL" in row["dataType"]:
267
+ parameter_type = Et.SubElement(
268
+ self._parameter_type_set, "xtce:IntegerParameterType"
269
+ )
270
+ parameter_type.attrib["name"] = name
271
+ parameter_type.attrib["signed"] = "false"
272
+
273
+ encoding = Et.SubElement(parameter_type, "xtce:IntegerDataEncoding")
274
+ encoding.attrib["sizeInBits"] = str(length_in_bits)
275
+ encoding.attrib["encoding"] = "unsigned"
276
+
277
+ elif any(x in row["dataType"] for x in ["SINT", "INT"]):
278
+ parameter_type = Et.SubElement(
279
+ self._parameter_type_set, "xtce:IntegerParameterType"
280
+ )
281
+ parameter_type.attrib["name"] = name
282
+ parameter_type.attrib["signed"] = "true"
283
+ encoding = Et.SubElement(parameter_type, "xtce:IntegerDataEncoding")
284
+ encoding.attrib["sizeInBits"] = str(length_in_bits)
285
+ encoding.attrib["encoding"] = "signed"
286
+
287
+ elif "FLOAT" in row["dataType"]:
288
+ parameter_type = Et.SubElement(
289
+ self._parameter_type_set, "xtce:FloatParameterType"
290
+ )
291
+ parameter_type.attrib["name"] = name
292
+ encoding = Et.SubElement(parameter_type, "xtce:FloatDataEncoding")
293
+ encoding.attrib["sizeInBits"] = str(length_in_bits)
294
+ encoding.attrib["encoding"] = "IEEE-754"
295
+
296
+ elif "BYTE" in row["dataType"]:
297
+ parameter_type = Et.SubElement(
298
+ self._parameter_type_set, "xtce:BinaryParameterType"
299
+ )
300
+ parameter_type.attrib["name"] = name
301
+
302
+ encoding = Et.SubElement(parameter_type, "xtce:BinaryDataEncoding")
303
+ encoding.attrib["bitOrder"] = "mostSignificantBitFirst"
304
+
305
+ size_in_bits = Et.SubElement(encoding, "xtce:SizeInBits")
306
+
307
+ # If it is a byte field consider it a dynamic value.
308
+ dynamic_value = Et.SubElement(size_in_bits, "xtce:DynamicValue")
309
+ param_ref = Et.SubElement(dynamic_value, "xtce:ParameterInstanceRef")
310
+ param_ref.attrib["parameterRef"] = "PKT_LEN"
311
+ linear_adjustment = Et.SubElement(dynamic_value, "xtce:LinearAdjustment")
312
+ linear_adjustment.attrib["slope"] = str(8)
313
+ # The length of all other variables (other than this specific one)
314
+ other_variable_bits = total_packet_bits - length_in_bits
315
+ # PKT_LEN == number of bytes in the packet data field - 1
316
+ # So we need to subtract the header bytes plus 1 to get the offset
317
+ # The amount to subtract to get the intercept is then:
318
+ # number of other bits in the packet - (6 + 1) * 8
319
+ linear_adjustment.attrib["intercept"] = str(-int(other_variable_bits - 56))
320
+
321
+ # TODO: Do we want to allow fixed length values?
322
+ # fixed_value = Et.SubElement(size_in_bits, "xtce:FixedValue")
323
+ # fixed_value.text = str(row["lengthInBits"])
324
+ else:
325
+ raise ValueError(f"Unknown data type for {name}: {row['dataType']}")
326
+
327
+ if row["convertAs"] == "ANALOG":
328
+ # Go look up the conversion in the AnalogConversions tab
329
+ # and add it to the encoding
330
+ self._add_analog_conversion(row, encoding)
331
+ elif row["convertAs"] == "STATE":
332
+ # Go look up the states in the States tab
333
+ # and add them to the parameter type
334
+ self._add_state_conversion(row, parameter_type)
335
+
336
+ def _add_analog_conversion(self, row: pd.Series, encoding: Et.Element) -> None:
337
+ """
338
+ Add an analog conversion to the encoding element.
339
+
340
+ Parameters
341
+ ----------
342
+ row : pandas.Row
343
+ Row to be added to the XTCE file, containing mnemonic, packetName.
344
+ encoding : Element
345
+ The encoding element to add the conversion to.
346
+ """
347
+ # Look up the conversion in the AnalogConversions tab
348
+ analog_conversion = self.sheets["AnalogConversions"]
349
+ # conversion is a row from the AnalogConversions sheet
350
+ conversion = analog_conversion.loc[
351
+ (analog_conversion["mnemonic"] == row["mnemonic"])
352
+ & (analog_conversion["packetName"] == row["packetName"])
353
+ ].iloc[0]
354
+
355
+ # Create the Conversion element
356
+ default_calibrator = Et.SubElement(encoding, "xtce:DefaultCalibrator")
357
+ polynomial_calibrator = Et.SubElement(
358
+ default_calibrator, "xtce:PolynomialCalibrator"
359
+ )
360
+ # FIXME: Use lowValue / highValue from the conversion sheet
361
+ # FIXME: Handle segmented polynomials (only using first segment now)
362
+ for i in range(8):
363
+ col = f"c{i}"
364
+ if conversion[col] != 0:
365
+ term = Et.SubElement(polynomial_calibrator, "xtce:Term")
366
+ term.attrib["coefficient"] = str(conversion[col])
367
+ term.attrib["exponent"] = str(i)
368
+
369
+ def _add_state_conversion(self, row: pd.Series, parameter_type: Et.Element) -> None:
370
+ """
371
+ Add a state conversion to the parameter type.
372
+
373
+ Changing from an IntegerParameterType to an EnumeratedParameterType. Adding
374
+ the list of state mappings to the parameter type.
375
+
376
+ Parameters
377
+ ----------
378
+ row : pandas.Row
379
+ Row to be added to the XTCE file, containing mnemonic, packetName.
380
+ parameter_type : Element
381
+ The parameter type element to add the conversion to.
382
+ """
383
+ # It is an EnumeratedParameterType rather than an IntegerParameterType
384
+ parameter_type.tag = "xtce:EnumeratedParameterType"
385
+ enumeration_list = Et.SubElement(parameter_type, "xtce:EnumerationList")
386
+ # Lookup the enumeration states for this parameter from the States sheet
387
+ state_sheet = self.sheets["States"]
388
+ state_sheet = state_sheet.loc[
389
+ (state_sheet["packetName"] == row["packetName"])
390
+ & (state_sheet["mnemonic"] == row["mnemonic"])
391
+ ]
392
+ for _, state_row in state_sheet.iterrows():
393
+ enumeration = Et.SubElement(enumeration_list, "xtce:Enumeration")
394
+ enumeration.attrib["value"] = str(state_row["value"])
395
+ enumeration.attrib["label"] = str(state_row["state"])
396
+
397
+ def to_xml(self, output_xml_path: Path) -> None:
398
+ """
399
+ Create and output an XTCE file from the Element Tree representation.
400
+
401
+ Parameters
402
+ ----------
403
+ output_xml_path : Path
404
+ Path to the output XML file.
405
+ """
406
+ # Create the XML tree and save the document
407
+ tree = Et.ElementTree(self._root)
408
+ Et.indent(tree, space="\t", level=0)
409
+
410
+ # Use the provided output_xml_path
411
+ tree.write(output_xml_path, encoding="utf-8", xml_declaration=True)
412
+
413
+
414
+ # Function to parse command line arguments
415
+ def _parse_args() -> argparse.Namespace:
416
+ """
417
+ Parse the command line arguments.
418
+
419
+ The expected input format is a required argument of "/path/to/excel_file.xlsx"
420
+ with an optional argument containing the output path for the XTCE file
421
+ "/path/to/output.xml".
422
+
423
+ Returns
424
+ -------
425
+ args : argparse.Namespace
426
+ An object containing the parsed arguments and their values.
427
+ """
428
+ description = (
429
+ "This command line program generates an instrument specific XTCE file. "
430
+ "Example usage: imap_xtce "
431
+ "path/to/excel_packet_file.xlsx --output path/to/output_packet_definition.xml"
432
+ )
433
+ output_help = (
434
+ "Where to save the output XTCE file. "
435
+ "If not provided, the input file name will be used with a "
436
+ ".xml extension."
437
+ )
438
+ file_path_help = "Provide the full path to the input excel file."
439
+
440
+ parser = argparse.ArgumentParser(prog="imap_xtce", description=description)
441
+ parser.add_argument("excel_file", type=Path, help=file_path_help)
442
+ parser.add_argument("--output", type=Path, required=False, help=output_help)
443
+
444
+ if not find_spec("openpyxl"):
445
+ parser.error(
446
+ "The openpyxl package is required for this script. "
447
+ "Please install it using 'pip install openpyxl'."
448
+ )
449
+
450
+ args = parser.parse_args()
451
+
452
+ if not args.excel_file.exists():
453
+ parser.error(f"File not found: {args.excel_file}")
454
+
455
+ if not args.output:
456
+ args.output = args.excel_file.with_suffix(".xml")
457
+
458
+ return args
459
+
460
+
461
+ def main() -> None:
462
+ """
463
+ Generate xtce file from CLI information given.
464
+
465
+ The xtce file will be written in an instrument specific subfolder.
466
+ """
467
+ # Parse arguments from the command line
468
+ args = _parse_args()
469
+
470
+ xtce_generator = XTCEGenerator(
471
+ path_to_excel_file=args.excel_file,
472
+ )
473
+ xtce_generator.to_xml(args.output)
474
+
475
+
476
+ if __name__ == "__main__":
477
+ main()
File without changes