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,60 @@
1
+ """Tests the L1b processing for CoDICE L1a data"""
2
+
3
+ import pytest
4
+ import xarray as xr
5
+
6
+ from imap_processing.cdf.utils import load_cdf
7
+ from imap_processing.codice.codice_l1b import process_codice_l1b
8
+
9
+ from .conftest import TEST_L1A_FILES
10
+
11
+ EXPECTED_LOGICAL_SOURCE = [
12
+ "imap_codice_l1b_hskp",
13
+ "imap_codice_l1b_hi-counters-aggregated",
14
+ "imap_codice_l1b_hi-counters-singles",
15
+ "imap_codice_l1b_hi-omni",
16
+ "imap_codice_l1b_hi-sectored",
17
+ "imap_codice_l1b_lo-counters-aggregated",
18
+ "imap_codice_l1b_lo-counters-singles",
19
+ "imap_codice_l1b_lo-sw-angular",
20
+ "imap_codice_l1b_lo-nsw-angular",
21
+ "imap_codice_l1b_lo-sw-priority",
22
+ "imap_codice_l1b_lo-nsw-priority",
23
+ "imap_codice_l1b_lo-sw-species",
24
+ "imap_codice_l1b_lo-nsw-species",
25
+ ]
26
+
27
+
28
+ @pytest.fixture(params=TEST_L1A_FILES)
29
+ def test_l1b_data(request) -> xr.Dataset:
30
+ """Return a ``xarray`` dataset containing test data.
31
+
32
+ Returns
33
+ -------
34
+ dataset : xr.Dataset
35
+ A ``xarray`` dataset containing the test data
36
+ """
37
+ input_dataset = load_cdf(request.param)
38
+ dataset = process_codice_l1b(input_dataset, data_version="001")
39
+ return dataset
40
+
41
+
42
+ @pytest.mark.parametrize(
43
+ "test_l1b_data, expected_logical_source",
44
+ list(zip(TEST_L1A_FILES, EXPECTED_LOGICAL_SOURCE)),
45
+ indirect=["test_l1b_data"],
46
+ )
47
+ def test_l1b_cdf_filenames(test_l1b_data: xr.Dataset, expected_logical_source: str):
48
+ """Tests that the ``process_codice_l1b`` function generates datasets
49
+ with the expected logical source.
50
+
51
+ Parameters
52
+ ----------
53
+ test_l1b_data : xr.Dataset
54
+ A ``xarray`` dataset containing the test data
55
+ expected_filename : str
56
+ The expected CDF filename
57
+ """
58
+
59
+ dataset = test_l1b_data
60
+ assert dataset.attrs["Logical_source"] == expected_logical_source
@@ -0,0 +1,50 @@
1
+ """Tests the decompression algorithms for CoDICE science data"""
2
+
3
+ import lzma
4
+ from enum import IntEnum
5
+
6
+ import pytest
7
+
8
+ from imap_processing.codice.decompress import decompress
9
+ from imap_processing.codice.utils import CoDICECompression
10
+
11
+ # Test the algorithms using input value of 234 (picked randomly)
12
+ lzma_bytes = lzma.compress((234).to_bytes(1, byteorder="big"))
13
+ LZMA_EXAMPLE = "".join(format(byte, "08b") for byte in lzma_bytes)
14
+ TEST_DATA = [
15
+ ("11101010", CoDICECompression.NO_COMPRESSION, [234]),
16
+ ("11101010", CoDICECompression.LOSSY_A, [221184]),
17
+ ("11101010", CoDICECompression.LOSSY_B, [1441792]),
18
+ (LZMA_EXAMPLE, CoDICECompression.LOSSLESS, [234]),
19
+ (LZMA_EXAMPLE, CoDICECompression.LOSSY_A_LOSSLESS, [221184]),
20
+ (LZMA_EXAMPLE, CoDICECompression.LOSSY_B_LOSSLESS, [1441792]),
21
+ ]
22
+
23
+
24
+ @pytest.mark.parametrize(
25
+ ("compressed_binary", "algorithm", "expected_result"), TEST_DATA
26
+ )
27
+ def test_decompress(
28
+ compressed_binary: str, algorithm: IntEnum, expected_result: list[int]
29
+ ):
30
+ """Tests the ``decompress`` function
31
+
32
+ Parameters
33
+ ----------
34
+ compressed_binary : str
35
+ The compressed binary string to test decompression on
36
+ algorithm : IntEnum
37
+ The algorithm to use in decompression
38
+ expected_result : list[int]
39
+ The expected, decompressed value
40
+ """
41
+
42
+ decompressed_value = decompress(compressed_binary, algorithm)
43
+ assert decompressed_value == expected_result
44
+
45
+
46
+ def test_decompress_raises():
47
+ """Tests that the ``decompress`` function raises with an unknown algorithm"""
48
+
49
+ with pytest.raises(ValueError, match="some_unsupported_algorithm"):
50
+ decompress("11101010", "some_unsupported_algorithm")
@@ -0,0 +1,372 @@
1
+ """Global pytest configuration for the package."""
2
+
3
+ import logging
4
+ import os
5
+ import re
6
+ import time
7
+ from contextlib import contextmanager
8
+ from pathlib import Path
9
+ from typing import Optional
10
+
11
+ import cdflib
12
+ import imap_data_access
13
+ import numpy as np
14
+ import pandas as pd
15
+ import pytest
16
+ import requests
17
+ import spiceypy as spice
18
+
19
+ from imap_processing import imap_module_directory
20
+ from imap_processing.spice.time import met_to_j2000ns
21
+
22
+
23
+ @pytest.fixture(autouse=True)
24
+ def _set_global_config(monkeypatch, tmp_path):
25
+ """Set the global data directory to a temporary directory."""
26
+ monkeypatch.setitem(imap_data_access.config, "DATA_DIR", tmp_path)
27
+ monkeypatch.setitem(
28
+ imap_data_access.config, "DATA_ACCESS_URL", "https://api.test.com"
29
+ )
30
+
31
+
32
+ @pytest.fixture(scope="session")
33
+ def imap_tests_path():
34
+ return imap_module_directory / "tests"
35
+
36
+
37
+ # Furnishing fixtures for testing kernels
38
+ # ---------------------------------------
39
+ @pytest.fixture(autouse=True)
40
+ def _autoclear_spice():
41
+ """Automatically clears out all SPICE remnants after every single test to
42
+ prevent the kernel pool from interfering with future tests. Option autouse
43
+ ensures this is run after every test."""
44
+ yield
45
+ spice.kclear()
46
+
47
+
48
+ @pytest.fixture(scope="session")
49
+ def _download_de440s(spice_test_data_path):
50
+ """This fixture downloads the de440s.bsp kernel into the
51
+ tests/spice/test_data directory if it does not already exist there. The
52
+ fixture is not intended to be used directly. It is automatically added to
53
+ tests marked with "external_kernel" in the hook below."""
54
+ logger = logging.getLogger(__name__)
55
+ kernel_url = (
56
+ "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de440s.bsp"
57
+ )
58
+ kernel_name = kernel_url.split("/")[-1]
59
+ local_filepath = spice_test_data_path / kernel_name
60
+
61
+ if local_filepath.exists():
62
+ return
63
+ allowed_attempts = 3
64
+ for attempt_number in range(allowed_attempts):
65
+ try:
66
+ with requests.get(kernel_url, stream=True, timeout=30) as r:
67
+ r.raise_for_status()
68
+ with open(local_filepath, "wb") as f:
69
+ for chunk in r.iter_content(chunk_size=8192):
70
+ f.write(chunk)
71
+ logger.info("Cached kernel file to %s", local_filepath)
72
+ break
73
+ except requests.exceptions.RequestException as error:
74
+ logger.info(f"Request failed. {error}")
75
+ if attempt_number < allowed_attempts:
76
+ logger.info(
77
+ f"Trying again, retries left "
78
+ f"{allowed_attempts - attempt_number}, "
79
+ f"Exception: {error}"
80
+ )
81
+ time.sleep(1)
82
+ else:
83
+ logger.error(
84
+ f"Failed to download file after {allowed_attempts} "
85
+ f"attempts, Final Error: {error}"
86
+ )
87
+ raise
88
+
89
+
90
+ def pytest_collection_modifyitems(items):
91
+ """
92
+ The use of this hook allows modification of test `Items` after tests have
93
+ been collected. In this case, it automatically adds the _download_de440s
94
+ fixture to any test marked with the `external_kernel`.
95
+ https://docs.pytest.org/en/stable/reference/reference.html#pytest.hookspec.pytest_collection_modifyitems
96
+ """
97
+ for item in items:
98
+ if item.get_closest_marker("external_kernel") is not None:
99
+ item.fixturenames.append("_download_de440s")
100
+
101
+
102
+ @pytest.fixture(scope="session")
103
+ def spice_test_data_path(imap_tests_path):
104
+ return imap_tests_path / "spice/test_data"
105
+
106
+
107
+ @pytest.fixture()
108
+ def furnish_time_kernels(spice_test_data_path):
109
+ """Furnishes (temporarily) the testing LSK and SCLK"""
110
+ spice.kclear()
111
+ test_lsk = spice_test_data_path / "naif0012.tls"
112
+ test_sclk = spice_test_data_path / "imap_sclk_0000.tsc"
113
+ spice.furnsh(str(test_lsk))
114
+ spice.furnsh(str(test_sclk))
115
+ yield test_lsk, test_sclk
116
+ spice.kclear()
117
+
118
+
119
+ @pytest.fixture()
120
+ def furnish_sclk(spice_test_data_path):
121
+ """Furnishes (temporarily) the SCLK for JPSS stored in the package data directory"""
122
+ test_sclk = spice_test_data_path / "imap_sclk_0000.tsc"
123
+ spice.furnsh(str(test_sclk))
124
+ yield test_sclk
125
+ spice.kclear()
126
+
127
+
128
+ @pytest.fixture()
129
+ def furnish_kernels(spice_test_data_path):
130
+ """Return a function that will furnish an arbitrary list of kernels."""
131
+
132
+ @contextmanager
133
+ def furnish_kernels(kernels: list[Path]):
134
+ with spice.KernelPool([str(spice_test_data_path / k) for k in kernels]) as pool:
135
+ yield pool
136
+
137
+ return furnish_kernels
138
+
139
+
140
+ @pytest.fixture(scope="session")
141
+ def monkeypatch_session():
142
+ from _pytest.monkeypatch import MonkeyPatch
143
+
144
+ m = MonkeyPatch()
145
+ yield m
146
+ m.undo()
147
+
148
+
149
+ def make_metakernel_from_kernels(metakernel, kernels):
150
+ """Helper function that writes a test metakernel from a list of filenames"""
151
+ with open(metakernel, "w") as mk:
152
+ mk.writelines(
153
+ [
154
+ "\n",
155
+ "\\begintext\n",
156
+ "\n",
157
+ "This is a temporary metakernel for imap_processing"
158
+ " unit and integration testing.\n",
159
+ "\n",
160
+ "\\begindata\n",
161
+ "\n",
162
+ "KERNELS_TO_LOAD = (\n",
163
+ ]
164
+ )
165
+ # Put single quotes around every kernel name
166
+ kernels_with_quotes = [" '" + kern + "'" for kern in kernels]
167
+ # Add a comma and EOL to the end of each kernel path except the last.
168
+ formatted_kernels = [kern + ",\n" for kern in kernels_with_quotes[0:-1]]
169
+ # Add ')' to the last kernel
170
+ formatted_kernels.append(kernels_with_quotes[-1] + "\n)\n\n")
171
+ mk.writelines(formatted_kernels)
172
+
173
+
174
+ def get_test_kernels_to_load(template_path, kernel_dir_path):
175
+ """
176
+ Helper function for grabbing a list of kernel filenames from the test
177
+ metakernel template. This is necessary in order to get absolute paths on
178
+ any system. Formats the absolute paths using the test data path fixture
179
+ value.
180
+ """
181
+ kernels_to_load = []
182
+ max_line_length = 80
183
+ with open(template_path) as mk:
184
+ for k in mk:
185
+ kernel = k.rstrip("\n").format(
186
+ **{"SPICE_TEST_DATA_PATH": str(kernel_dir_path.absolute())}
187
+ )
188
+ while len(kernel) > 0:
189
+ if len(kernel) <= max_line_length:
190
+ kernels_to_load.append(kernel)
191
+ break
192
+ else:
193
+ slash_positions = np.array(
194
+ [m.start() for m in re.finditer("/", kernel)]
195
+ )
196
+ stop_idx = (
197
+ slash_positions[slash_positions < max_line_length - 1].max() + 1
198
+ )
199
+ kernels_to_load.append(kernel[0:stop_idx] + "+")
200
+ kernel = kernel[stop_idx:]
201
+ return kernels_to_load
202
+
203
+
204
+ @pytest.fixture(scope="session", autouse=True)
205
+ def session_test_metakernel(monkeypatch_session, tmpdir_factory, spice_test_data_path):
206
+ """Generate a metakernel from the template metakernel by injecting the local
207
+ path into the metakernel and set the SPICE_METAKERNEL environment variable.
208
+
209
+ Notes
210
+ -----
211
+ - This fixture needs to `scope=session` so that the SPICE_METAKERNEL
212
+ environment variable is available for other fixtures that require time
213
+ conversions using spice.
214
+ - No furnishing of kernels occur as part of this fixture. This allows other
215
+ fixtures with lesser scope or individual tests to override the environment
216
+ variable as needed. Use the `metakernel_path_not_set` fixture in tests that
217
+ need to override the environment variable.
218
+ """
219
+ template_path = spice_test_data_path / "imap_simple_metakernel.template"
220
+ kernels_to_load = get_test_kernels_to_load(template_path, spice_test_data_path)
221
+ metakernel_path = tmpdir_factory.mktemp("spice") / "imap_2024_v001.tm"
222
+ make_metakernel_from_kernels(metakernel_path, kernels_to_load)
223
+ monkeypatch_session.setenv("SPICE_METAKERNEL", str(metakernel_path))
224
+ yield str(metakernel_path)
225
+ spice.kclear()
226
+
227
+
228
+ @pytest.fixture()
229
+ def use_test_metakernel(
230
+ request, monkeypatch, spice_test_data_path, session_test_metakernel
231
+ ):
232
+ """
233
+ Generate a metakernel and set SPICE_METAKERNEL environment variable.
234
+
235
+ This fixture generates a metakernel in the directory pointed to by
236
+ `imap_data_access.config["DATA_DIR"]` and sets the SPICE_METAKERNEL
237
+ environment variable to point to it for use by the `@ensure_spice` decorator.
238
+ The default metekernel is named "imap_simple_metakernel.template". Other
239
+ metakerels can be specified by marking the test with metakernel. See
240
+ examples below.
241
+
242
+ Parameters
243
+ ----------
244
+ request : fixture
245
+ monkeypatch : fixture
246
+ spice_test_data_path : fixture
247
+ session_test_metakernel : fixture
248
+
249
+ Yields
250
+ ------
251
+ metakernel_path : Path
252
+
253
+ Examples
254
+ --------
255
+ 1. Use the default metakernel template
256
+ >>> def test_my_spicey_func(use_test_metakernel):
257
+ ... pass
258
+
259
+ 2. Specify a different metakernel template
260
+ >>> @pytest.mark.metakernel("other_template_mk.template")
261
+ ... def test_my_spicey_func(use_test_metakernel):
262
+ ... pass
263
+ """
264
+ marker = request.node.get_closest_marker("metakernel")
265
+ if marker is None:
266
+ yield session_test_metakernel
267
+ else:
268
+ template_name = marker.args[0]
269
+ template_path = spice_test_data_path / template_name
270
+ metakernel_path = imap_data_access.config["DATA_DIR"] / "imap_2024_v001.tm"
271
+ kernels_to_load = get_test_kernels_to_load(template_path, spice_test_data_path)
272
+ make_metakernel_from_kernels(metakernel_path, kernels_to_load)
273
+ monkeypatch.setenv("SPICE_METAKERNEL", str(metakernel_path))
274
+ yield str(metakernel_path)
275
+ spice.kclear()
276
+
277
+
278
+ @pytest.fixture()
279
+ def _unset_metakernel_path(monkeypatch):
280
+ """Temporarily unsets the SPICE_METAKERNEL environment variable"""
281
+ if os.getenv("SPICE_METAKERNEL", None) is not None:
282
+ monkeypatch.delenv("SPICE_METAKERNEL")
283
+
284
+
285
+ @pytest.fixture()
286
+ def _set_spin_data_filepath(monkeypatch, tmpdir, generate_spin_data):
287
+ """Set the SPIN_DATA_FILEPATH environment variable"""
288
+ # SWE test data time minus 56120 seconds to get mid-night time
289
+ start_time = 453051323.0 - 56120
290
+ spin_df = generate_spin_data(start_time)
291
+ spin_csv_file_path = tmpdir / "spin_data.spin.csv"
292
+ spin_df.to_csv(spin_csv_file_path, index=False)
293
+ monkeypatch.setenv("SPIN_DATA_FILEPATH", str(spin_csv_file_path))
294
+
295
+
296
+ @pytest.fixture()
297
+ def generate_spin_data():
298
+ def make_data(start_met: int, end_met: Optional[int] = None) -> pd.DataFrame:
299
+ """
300
+ Generate a spin table CSV covering one or more days.
301
+ Spin table contains the following fields:
302
+ (
303
+ spin_number,
304
+ spin_start_sec,
305
+ spin_start_subsec,
306
+ spin_period_sec,
307
+ spin_period_valid,
308
+ spin_phase_valid,
309
+ spin_period_source,
310
+ thruster_firing
311
+ )
312
+ This function creates spin data using start MET and end MET time.
313
+ Each spin start data uses the nominal 15 second spin period. The spins that
314
+ occur from 00:00(Mid-night) to 00:10 UTC are marked with flags for
315
+ thruster firing, invalid spin period, and invalid spin phase.
316
+ Parameters
317
+ ----------
318
+ start_met : int
319
+ Provides the start time in Mission Elapsed Time (MET).
320
+ end_met : int
321
+ Provides the end time in MET. If not provided, default to one day
322
+ from start time.
323
+ Returns
324
+ -------
325
+ spin_df : pd.DataFrame
326
+ Spin data.
327
+ """
328
+ if end_met is None:
329
+ # end_time is one day after start_time
330
+ end_met = start_met + 86400
331
+
332
+ # Create spin start second data of 15 seconds increment
333
+ spin_start_sec = np.arange(start_met, end_met + 1, 15)
334
+
335
+ nspins = len(spin_start_sec)
336
+
337
+ spin_df = pd.DataFrame.from_dict(
338
+ {
339
+ "spin_number": np.arange(nspins, dtype=np.uint32),
340
+ "spin_start_sec": spin_start_sec,
341
+ "spin_start_subsec": np.zeros(nspins, dtype=np.uint32),
342
+ "spin_period_sec": np.full(nspins, 15.0, dtype=np.float32),
343
+ "spin_period_valid": np.ones(nspins, dtype=np.uint8),
344
+ "spin_phase_valid": np.ones(nspins, dtype=np.uint8),
345
+ "spin_period_source": np.zeros(nspins, dtype=np.uint8),
346
+ "thruster_firing": np.zeros(nspins, dtype=np.uint8),
347
+ }
348
+ )
349
+
350
+ # Convert spin_start_sec to datetime to set repointing times flags
351
+ spin_start_dates = met_to_j2000ns(spin_start_sec)
352
+ spin_start_dates = cdflib.cdfepoch.to_datetime(spin_start_dates)
353
+
354
+ # Convert DatetimeIndex to Series for using .dt accessor
355
+ spin_start_dates_series = pd.Series(spin_start_dates)
356
+
357
+ # Find index of all timestamps that fall within 10 minutes after midnight
358
+ repointing_times = spin_start_dates_series[
359
+ (spin_start_dates_series.dt.time >= pd.Timestamp("00:00:00").time())
360
+ & (spin_start_dates_series.dt.time < pd.Timestamp("00:10:00").time())
361
+ ]
362
+
363
+ repointing_times_index = repointing_times.index
364
+
365
+ # Use the repointing times to set thruster firing flag and spin period valid
366
+ spin_df.loc[repointing_times_index.values, "thruster_firing"] = 1
367
+ spin_df.loc[repointing_times_index.values, "spin_period_valid"] = 0
368
+ spin_df.loc[repointing_times_index.values, "spin_phase_valid"] = 0
369
+
370
+ return spin_df
371
+
372
+ return make_data