imap-processing 0.11.0__py3-none-any.whl → 0.13.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.

Potentially problematic release.


This version of imap-processing might be problematic. Click here for more details.

Files changed (415) hide show
  1. imap_processing/__init__.py +11 -11
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/ccsds_data.py +1 -2
  4. imap_processing/ccsds/excel_to_xtce.py +66 -18
  5. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +24 -40
  6. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +934 -42
  7. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
  8. imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +0 -5
  9. imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +10 -11
  10. imap_processing/cdf/config/imap_hi_variable_attrs.yaml +17 -19
  11. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +27 -14
  12. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +106 -116
  13. imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +120 -145
  14. imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +14 -0
  15. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +25 -9
  16. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +6 -4
  17. imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +3 -3
  18. imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +0 -12
  19. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +1 -1
  20. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +23 -20
  21. imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml +361 -0
  22. imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml +160 -0
  23. imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +160 -0
  24. imap_processing/cdf/config/imap_spacecraft_global_cdf_attrs.yaml +18 -0
  25. imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml +40 -0
  26. imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +1 -5
  27. imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
  28. imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +12 -4
  29. imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +16 -2
  30. imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +64 -52
  31. imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +71 -47
  32. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +180 -19
  33. imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
  34. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +80 -17
  35. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +32 -57
  36. imap_processing/cdf/utils.py +52 -38
  37. imap_processing/cli.py +477 -233
  38. imap_processing/codice/codice_l1a.py +466 -131
  39. imap_processing/codice/codice_l1b.py +51 -152
  40. imap_processing/codice/constants.py +1360 -569
  41. imap_processing/codice/decompress.py +2 -6
  42. imap_processing/ena_maps/ena_maps.py +1103 -146
  43. imap_processing/ena_maps/utils/coordinates.py +19 -0
  44. imap_processing/ena_maps/utils/map_utils.py +14 -17
  45. imap_processing/ena_maps/utils/spatial_utils.py +55 -52
  46. imap_processing/glows/l1a/glows_l1a.py +28 -99
  47. imap_processing/glows/l1a/glows_l1a_data.py +2 -2
  48. imap_processing/glows/l1b/glows_l1b.py +1 -4
  49. imap_processing/glows/l1b/glows_l1b_data.py +1 -3
  50. imap_processing/glows/l2/glows_l2.py +2 -5
  51. imap_processing/hi/l1a/hi_l1a.py +54 -29
  52. imap_processing/hi/l1a/histogram.py +0 -1
  53. imap_processing/hi/l1a/science_direct_event.py +6 -8
  54. imap_processing/hi/l1b/hi_l1b.py +111 -82
  55. imap_processing/hi/l1c/hi_l1c.py +416 -32
  56. imap_processing/hi/utils.py +58 -12
  57. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
  58. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt0-factors_20250219_v002.csv +205 -0
  59. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt1-factors_20250219_v002.csv +205 -0
  60. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt2-factors_20250219_v002.csv +205 -0
  61. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt3-factors_20250219_v002.csv +205 -0
  62. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-summed-dt0-factors_20250219_v002.csv +68 -0
  63. imap_processing/hit/hit_utils.py +235 -5
  64. imap_processing/hit/l0/constants.py +20 -11
  65. imap_processing/hit/l0/decom_hit.py +21 -5
  66. imap_processing/hit/l1a/hit_l1a.py +71 -75
  67. imap_processing/hit/l1b/constants.py +321 -0
  68. imap_processing/hit/l1b/hit_l1b.py +377 -67
  69. imap_processing/hit/l2/constants.py +318 -0
  70. imap_processing/hit/l2/hit_l2.py +723 -0
  71. imap_processing/hit/packet_definitions/hit_packet_definitions.xml +1323 -71
  72. imap_processing/ialirt/l0/mag_l0_ialirt_data.py +155 -0
  73. imap_processing/ialirt/l0/parse_mag.py +374 -0
  74. imap_processing/ialirt/l0/process_swapi.py +69 -0
  75. imap_processing/ialirt/l0/process_swe.py +548 -0
  76. imap_processing/ialirt/packet_definitions/ialirt.xml +216 -208
  77. imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +1 -1
  78. imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +1 -1
  79. imap_processing/ialirt/packet_definitions/ialirt_mag.xml +115 -0
  80. imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
  81. imap_processing/ialirt/utils/grouping.py +114 -0
  82. imap_processing/ialirt/utils/time.py +29 -0
  83. imap_processing/idex/atomic_masses.csv +22 -0
  84. imap_processing/idex/decode.py +2 -2
  85. imap_processing/idex/idex_constants.py +33 -0
  86. imap_processing/idex/idex_l0.py +22 -8
  87. imap_processing/idex/idex_l1a.py +81 -51
  88. imap_processing/idex/idex_l1b.py +13 -39
  89. imap_processing/idex/idex_l2a.py +823 -0
  90. imap_processing/idex/idex_l2b.py +120 -0
  91. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +11 -11
  92. imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
  93. imap_processing/lo/l0/lo_science.py +7 -2
  94. imap_processing/lo/l1a/lo_l1a.py +1 -5
  95. imap_processing/lo/l1b/lo_l1b.py +702 -29
  96. imap_processing/lo/l1b/tof_conversions.py +11 -0
  97. imap_processing/lo/l1c/lo_l1c.py +1 -4
  98. imap_processing/mag/constants.py +51 -0
  99. imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
  100. imap_processing/mag/l0/decom_mag.py +10 -3
  101. imap_processing/mag/l1a/mag_l1a.py +23 -19
  102. imap_processing/mag/l1a/mag_l1a_data.py +35 -10
  103. imap_processing/mag/l1b/mag_l1b.py +259 -50
  104. imap_processing/mag/l1c/interpolation_methods.py +388 -0
  105. imap_processing/mag/l1c/mag_l1c.py +621 -17
  106. imap_processing/mag/l2/mag_l2.py +140 -0
  107. imap_processing/mag/l2/mag_l2_data.py +288 -0
  108. imap_processing/quality_flags.py +1 -0
  109. imap_processing/spacecraft/packet_definitions/scid_x252.xml +538 -0
  110. imap_processing/spacecraft/quaternions.py +121 -0
  111. imap_processing/spice/geometry.py +19 -22
  112. imap_processing/spice/kernels.py +0 -276
  113. imap_processing/spice/pointing_frame.py +257 -0
  114. imap_processing/spice/repoint.py +149 -0
  115. imap_processing/spice/spin.py +38 -33
  116. imap_processing/spice/time.py +24 -0
  117. imap_processing/swapi/l1/swapi_l1.py +20 -12
  118. imap_processing/swapi/l2/swapi_l2.py +116 -5
  119. imap_processing/swapi/swapi_utils.py +32 -0
  120. imap_processing/swe/l1a/swe_l1a.py +44 -12
  121. imap_processing/swe/l1a/swe_science.py +13 -13
  122. imap_processing/swe/l1b/swe_l1b.py +898 -23
  123. imap_processing/swe/l2/swe_l2.py +75 -136
  124. imap_processing/swe/packet_definitions/swe_packet_definition.xml +1121 -1
  125. imap_processing/swe/utils/swe_constants.py +64 -0
  126. imap_processing/swe/utils/swe_utils.py +85 -28
  127. imap_processing/tests/ccsds/test_data/expected_output.xml +40 -1
  128. imap_processing/tests/ccsds/test_excel_to_xtce.py +24 -21
  129. imap_processing/tests/cdf/test_data/imap_instrument2_global_cdf_attrs.yaml +0 -2
  130. imap_processing/tests/cdf/test_utils.py +14 -16
  131. imap_processing/tests/codice/conftest.py +44 -33
  132. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  133. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  134. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-ialirt_20241110193700_v0.0.0.cdf +0 -0
  135. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-omni_20241110193700_v0.0.0.cdf +0 -0
  136. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
  137. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-priorities_20241110193700_v0.0.0.cdf +0 -0
  138. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-sectored_20241110193700_v0.0.0.cdf +0 -0
  139. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  140. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  141. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  142. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-angular_20241110193700_v0.0.0.cdf +0 -0
  143. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-priority_20241110193700_v0.0.0.cdf +0 -0
  144. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-species_20241110193700_v0.0.0.cdf +0 -0
  145. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
  146. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-angular_20241110193700_v0.0.0.cdf +0 -0
  147. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-priority_20241110193700_v0.0.0.cdf +0 -0
  148. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-species_20241110193700_v0.0.0.cdf +0 -0
  149. imap_processing/tests/codice/test_codice_l1a.py +126 -53
  150. imap_processing/tests/codice/test_codice_l1b.py +6 -7
  151. imap_processing/tests/codice/test_decompress.py +4 -4
  152. imap_processing/tests/conftest.py +239 -27
  153. imap_processing/tests/ena_maps/conftest.py +51 -0
  154. imap_processing/tests/ena_maps/test_ena_maps.py +1068 -110
  155. imap_processing/tests/ena_maps/test_map_utils.py +66 -43
  156. imap_processing/tests/ena_maps/test_spatial_utils.py +17 -21
  157. imap_processing/tests/glows/conftest.py +10 -14
  158. imap_processing/tests/glows/test_glows_decom.py +4 -4
  159. imap_processing/tests/glows/test_glows_l1a_cdf.py +6 -27
  160. imap_processing/tests/glows/test_glows_l1a_data.py +6 -8
  161. imap_processing/tests/glows/test_glows_l1b.py +11 -11
  162. imap_processing/tests/glows/test_glows_l1b_data.py +5 -5
  163. imap_processing/tests/glows/test_glows_l2.py +2 -8
  164. imap_processing/tests/hi/conftest.py +1 -1
  165. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208.bin +0 -0
  166. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208_verify.csv +205 -0
  167. imap_processing/tests/hi/test_hi_l1b.py +22 -27
  168. imap_processing/tests/hi/test_hi_l1c.py +249 -18
  169. imap_processing/tests/hi/test_l1a.py +35 -7
  170. imap_processing/tests/hi/test_science_direct_event.py +3 -3
  171. imap_processing/tests/hi/test_utils.py +24 -2
  172. imap_processing/tests/hit/helpers/l1_validation.py +74 -73
  173. imap_processing/tests/hit/test_data/hskp_sample.ccsds +0 -0
  174. imap_processing/tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts +0 -0
  175. imap_processing/tests/hit/test_decom_hit.py +5 -1
  176. imap_processing/tests/hit/test_hit_l1a.py +32 -36
  177. imap_processing/tests/hit/test_hit_l1b.py +300 -81
  178. imap_processing/tests/hit/test_hit_l2.py +716 -0
  179. imap_processing/tests/hit/test_hit_utils.py +184 -7
  180. imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
  181. imap_processing/tests/hit/validation_data/hskp_sample_eu_3_6_2025.csv +89 -0
  182. imap_processing/tests/hit/validation_data/hskp_sample_raw.csv +89 -88
  183. imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
  184. imap_processing/tests/ialirt/data/l0/461971383-404.bin +0 -0
  185. imap_processing/tests/ialirt/data/l0/461971384-405.bin +0 -0
  186. imap_processing/tests/ialirt/data/l0/461971385-406.bin +0 -0
  187. imap_processing/tests/ialirt/data/l0/461971386-407.bin +0 -0
  188. imap_processing/tests/ialirt/data/l0/461971387-408.bin +0 -0
  189. imap_processing/tests/ialirt/data/l0/461971388-409.bin +0 -0
  190. imap_processing/tests/ialirt/data/l0/461971389-410.bin +0 -0
  191. imap_processing/tests/ialirt/data/l0/461971390-411.bin +0 -0
  192. imap_processing/tests/ialirt/data/l0/461971391-412.bin +0 -0
  193. imap_processing/tests/ialirt/data/l0/sample_decoded_i-alirt_data.csv +383 -0
  194. imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
  195. imap_processing/tests/ialirt/unit/test_grouping.py +81 -0
  196. imap_processing/tests/ialirt/unit/test_parse_mag.py +223 -0
  197. imap_processing/tests/ialirt/unit/test_process_codicehi.py +3 -3
  198. imap_processing/tests/ialirt/unit/test_process_codicelo.py +3 -10
  199. imap_processing/tests/ialirt/unit/test_process_ephemeris.py +4 -4
  200. imap_processing/tests/ialirt/unit/test_process_hit.py +3 -3
  201. imap_processing/tests/ialirt/unit/test_process_swapi.py +24 -16
  202. imap_processing/tests/ialirt/unit/test_process_swe.py +319 -6
  203. imap_processing/tests/ialirt/unit/test_time.py +16 -0
  204. imap_processing/tests/idex/conftest.py +127 -6
  205. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231218_v001.pkts +0 -0
  206. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20241206_v001.pkts +0 -0
  207. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20250108_v001.pkts +0 -0
  208. imap_processing/tests/idex/test_data/impact_14_tof_high_data.txt +4508 -4508
  209. imap_processing/tests/idex/test_idex_l0.py +33 -11
  210. imap_processing/tests/idex/test_idex_l1a.py +92 -21
  211. imap_processing/tests/idex/test_idex_l1b.py +106 -27
  212. imap_processing/tests/idex/test_idex_l2a.py +399 -0
  213. imap_processing/tests/idex/test_idex_l2b.py +93 -0
  214. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20241022_v002.cdf +0 -0
  215. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20241022_v002.cdf +0 -0
  216. imap_processing/tests/lo/test_lo_l1a.py +3 -3
  217. imap_processing/tests/lo/test_lo_l1b.py +515 -6
  218. imap_processing/tests/lo/test_lo_l1c.py +1 -1
  219. imap_processing/tests/lo/test_lo_science.py +7 -7
  220. imap_processing/tests/lo/test_star_sensor.py +1 -1
  221. imap_processing/tests/mag/conftest.py +120 -2
  222. imap_processing/tests/mag/test_mag_decom.py +5 -4
  223. imap_processing/tests/mag/test_mag_l1a.py +51 -7
  224. imap_processing/tests/mag/test_mag_l1b.py +40 -59
  225. imap_processing/tests/mag/test_mag_l1c.py +354 -19
  226. imap_processing/tests/mag/test_mag_l2.py +130 -0
  227. imap_processing/tests/mag/test_mag_validation.py +247 -26
  228. imap_processing/tests/mag/validation/L1b/T009/MAGScience-normal-(2,2)-8s-20250204-16h39.csv +17 -0
  229. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-magi-out.csv +16 -16
  230. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-mago-out.csv +16 -16
  231. imap_processing/tests/mag/validation/L1b/T010/MAGScience-normal-(2,2)-8s-20250206-12h05.csv +17 -0
  232. imap_processing/tests/mag/validation/L1b/T011/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  233. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-magi-out.csv +16 -16
  234. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-mago-out.csv +16 -16
  235. imap_processing/tests/mag/validation/L1b/T012/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  236. imap_processing/tests/mag/validation/L1b/T012/data.bin +0 -0
  237. imap_processing/tests/mag/validation/L1b/T012/field_like_all_ranges.txt +19200 -0
  238. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-cal.cdf +0 -0
  239. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-in.csv +17 -0
  240. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-magi-out.csv +17 -0
  241. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-mago-out.csv +17 -0
  242. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-in.csv +1217 -0
  243. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-out.csv +1857 -0
  244. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-in.csv +1217 -0
  245. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-out.csv +1857 -0
  246. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-in.csv +1217 -0
  247. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-out.csv +1793 -0
  248. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-in.csv +1217 -0
  249. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-out.csv +1793 -0
  250. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-burst-in.csv +2561 -0
  251. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-in.csv +961 -0
  252. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-out.csv +1539 -0
  253. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-in.csv +1921 -0
  254. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-out.csv +2499 -0
  255. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-in.csv +865 -0
  256. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv +1196 -0
  257. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-in.csv +1729 -0
  258. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv +3053 -0
  259. imap_processing/tests/mag/validation/L2/imap_mag_l1b_norm-mago_20251017_v002.cdf +0 -0
  260. imap_processing/tests/mag/validation/calibration/imap_mag_l1b-calibration_20240229_v001.cdf +0 -0
  261. imap_processing/tests/mag/validation/calibration/imap_mag_l2-calibration-matrices_20251017_v004.cdf +0 -0
  262. imap_processing/tests/mag/validation/calibration/imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf +0 -0
  263. imap_processing/tests/spacecraft/data/SSR_2024_190_20_08_12_0483851794_2_DA_apid0594_1packet.pkts +0 -0
  264. imap_processing/tests/spacecraft/test_quaternions.py +71 -0
  265. imap_processing/tests/spice/test_data/fake_repoint_data.csv +5 -0
  266. imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
  267. imap_processing/tests/spice/test_geometry.py +9 -12
  268. imap_processing/tests/spice/test_kernels.py +1 -200
  269. imap_processing/tests/spice/test_pointing_frame.py +185 -0
  270. imap_processing/tests/spice/test_repoint.py +121 -0
  271. imap_processing/tests/spice/test_spin.py +50 -9
  272. imap_processing/tests/spice/test_time.py +14 -0
  273. imap_processing/tests/swapi/lut/imap_swapi_esa-unit-conversion_20250211_v000.csv +73 -0
  274. imap_processing/tests/swapi/lut/imap_swapi_lut-notes_20250211_v000.csv +1025 -0
  275. imap_processing/tests/swapi/test_swapi_l1.py +13 -11
  276. imap_processing/tests/swapi/test_swapi_l2.py +180 -8
  277. imap_processing/tests/swe/l0_data/2024051010_SWE_HK_packet.bin +0 -0
  278. imap_processing/tests/swe/l0_data/2024051011_SWE_CEM_RAW_packet.bin +0 -0
  279. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_APP_HK_20240510_092742.csv +49 -0
  280. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_CEM_RAW_20240510_092742.csv +593 -0
  281. imap_processing/tests/swe/lut/checker-board-indices.csv +24 -0
  282. imap_processing/tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv +385 -0
  283. imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv +3 -0
  284. imap_processing/tests/swe/test_swe_l1a.py +20 -2
  285. imap_processing/tests/swe/test_swe_l1a_cem_raw.py +52 -0
  286. imap_processing/tests/swe/test_swe_l1a_hk.py +68 -0
  287. imap_processing/tests/swe/test_swe_l1a_science.py +3 -3
  288. imap_processing/tests/swe/test_swe_l1b.py +162 -24
  289. imap_processing/tests/swe/test_swe_l2.py +153 -91
  290. imap_processing/tests/test_cli.py +171 -88
  291. imap_processing/tests/test_utils.py +140 -17
  292. imap_processing/tests/ultra/data/l0/FM45_UltraFM45_Functional_2024-01-22T0105_20240122T010548.CCSDS +0 -0
  293. imap_processing/tests/ultra/data/l0/ultra45_raw_sc_ultraimgrates_20220530_00.csv +164 -0
  294. imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3243 -3243
  295. imap_processing/tests/ultra/data/mock_data.py +369 -0
  296. imap_processing/tests/ultra/unit/conftest.py +115 -89
  297. imap_processing/tests/ultra/unit/test_badtimes.py +4 -4
  298. imap_processing/tests/ultra/unit/test_cullingmask.py +8 -6
  299. imap_processing/tests/ultra/unit/test_de.py +14 -13
  300. imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
  301. imap_processing/tests/ultra/unit/test_decom_apid_881.py +54 -11
  302. imap_processing/tests/ultra/unit/test_decom_apid_883.py +12 -10
  303. imap_processing/tests/ultra/unit/test_decom_apid_896.py +202 -55
  304. imap_processing/tests/ultra/unit/test_lookup_utils.py +23 -1
  305. imap_processing/tests/ultra/unit/test_spacecraft_pset.py +77 -0
  306. imap_processing/tests/ultra/unit/test_ultra_l1a.py +98 -305
  307. imap_processing/tests/ultra/unit/test_ultra_l1b.py +60 -14
  308. imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
  309. imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +26 -27
  310. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +239 -70
  311. imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
  312. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +114 -83
  313. imap_processing/tests/ultra/unit/test_ultra_l2.py +230 -0
  314. imap_processing/ultra/constants.py +1 -1
  315. imap_processing/ultra/l0/decom_tools.py +27 -39
  316. imap_processing/ultra/l0/decom_ultra.py +168 -204
  317. imap_processing/ultra/l0/ultra_utils.py +152 -136
  318. imap_processing/ultra/l1a/ultra_l1a.py +55 -271
  319. imap_processing/ultra/l1b/badtimes.py +1 -4
  320. imap_processing/ultra/l1b/cullingmask.py +2 -6
  321. imap_processing/ultra/l1b/de.py +116 -57
  322. imap_processing/ultra/l1b/extendedspin.py +20 -18
  323. imap_processing/ultra/l1b/lookup_utils.py +72 -9
  324. imap_processing/ultra/l1b/ultra_l1b.py +36 -16
  325. imap_processing/ultra/l1b/ultra_l1b_culling.py +66 -30
  326. imap_processing/ultra/l1b/ultra_l1b_extended.py +297 -94
  327. imap_processing/ultra/l1c/histogram.py +2 -6
  328. imap_processing/ultra/l1c/spacecraft_pset.py +84 -0
  329. imap_processing/ultra/l1c/ultra_l1c.py +8 -9
  330. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +206 -108
  331. imap_processing/ultra/l2/ultra_l2.py +299 -0
  332. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +526 -0
  333. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +526 -0
  334. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +526 -0
  335. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +526 -0
  336. imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -2
  337. imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
  338. imap_processing/ultra/packet_definitions/README.md +38 -0
  339. imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +15302 -482
  340. imap_processing/ultra/utils/ultra_l1_utils.py +31 -12
  341. imap_processing/utils.py +69 -29
  342. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +10 -6
  343. imap_processing-0.13.0.dist-info/RECORD +578 -0
  344. imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +0 -237
  345. imap_processing/hi/l1a/housekeeping.py +0 -27
  346. imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
  347. imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
  348. imap_processing/swe/l1b/swe_l1b_science.py +0 -652
  349. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-aggregated_20240429_v001.cdf +0 -0
  350. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-singles_20240429_v001.cdf +0 -0
  351. imap_processing/tests/codice/data/imap_codice_l1a_hi-omni_20240429_v001.cdf +0 -0
  352. imap_processing/tests/codice/data/imap_codice_l1a_hi-sectored_20240429_v001.cdf +0 -0
  353. imap_processing/tests/codice/data/imap_codice_l1a_hskp_20100101_v001.cdf +0 -0
  354. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-aggregated_20240429_v001.cdf +0 -0
  355. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-singles_20240429_v001.cdf +0 -0
  356. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-angular_20240429_v001.cdf +0 -0
  357. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-priority_20240429_v001.cdf +0 -0
  358. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-species_20240429_v001.cdf +0 -0
  359. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-angular_20240429_v001.cdf +0 -0
  360. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-priority_20240429_v001.cdf +0 -0
  361. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-species_20240429_v001.cdf +0 -0
  362. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-aggregated_20240429_v001.cdf +0 -0
  363. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-singles_20240429_v001.cdf +0 -0
  364. imap_processing/tests/codice/data/imap_codice_l1b_hi-omni_20240429_v001.cdf +0 -0
  365. imap_processing/tests/codice/data/imap_codice_l1b_hi-sectored_20240429_v001.cdf +0 -0
  366. imap_processing/tests/codice/data/imap_codice_l1b_hskp_20100101_v001.cdf +0 -0
  367. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-aggregated_20240429_v001.cdf +0 -0
  368. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-singles_20240429_v001.cdf +0 -0
  369. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-angular_20240429_v001.cdf +0 -0
  370. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-priority_20240429_v001.cdf +0 -0
  371. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-species_20240429_v001.cdf +0 -0
  372. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-angular_20240429_v001.cdf +0 -0
  373. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-priority_20240429_v001.cdf +0 -0
  374. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-species_20240429_v001.cdf +0 -0
  375. imap_processing/tests/hi/data/l1/imap_hi_l1b_45sensor-de_20250415_v999.cdf +0 -0
  376. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1251.pkts +0 -0
  377. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1252.pkts +0 -0
  378. imap_processing/tests/hit/validation_data/hskp_sample_eu.csv +0 -89
  379. imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +0 -29
  380. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231214_v001.pkts +0 -0
  381. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20100101_v001.cdf +0 -0
  382. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20100101_v001.cdf +0 -0
  383. imap_processing/tests/swe/test_swe_l1b_science.py +0 -84
  384. imap_processing/tests/ultra/test_data/mock_data.py +0 -161
  385. imap_processing/ultra/l1c/pset.py +0 -40
  386. imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
  387. imap_processing-0.11.0.dist-info/RECORD +0 -488
  388. /imap_processing/idex/packet_definitions/{idex_packet_definition.xml → idex_science_packet_definition.xml} +0 -0
  389. /imap_processing/tests/ialirt/{test_data → data}/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
  390. /imap_processing/tests/ialirt/{test_data → data}/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
  391. /imap_processing/tests/ialirt/{test_data → data}/l0/IALiRT Raw Packet Telemetry.txt +0 -0
  392. /imap_processing/tests/ialirt/{test_data → data}/l0/apid01152.tlm +0 -0
  393. /imap_processing/tests/ialirt/{test_data → data}/l0/eu_SWP_IAL_20240826_152033.csv +0 -0
  394. /imap_processing/tests/ialirt/{test_data → data}/l0/hi_fsw_view_1_ccsds.bin +0 -0
  395. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.ccsds +0 -0
  396. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.csv +0 -0
  397. /imap_processing/tests/ialirt/{test_data → data}/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +0 -0
  398. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
  399. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  400. /imap_processing/{mag/l1b → tests/spacecraft}/__init__.py +0 -0
  401. /imap_processing/{swe/l1b/engineering_unit_convert_table.csv → tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv} +0 -0
  402. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00_20240207T102740.CCSDS +0 -0
  403. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_7P_Phi0.0_BeamCal_LinearScan_phi0.04_theta-0.01_20230821T121304.CCSDS +0 -0
  404. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.CCSDS +0 -0
  405. /imap_processing/tests/ultra/{test_data → data}/l0/Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.CCSDS +0 -0
  406. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_auxdata_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  407. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_enaphxtofhangimg_FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.csv +0 -0
  408. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultraimgrates_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  409. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimgevent_FM45_7P_Phi00_BeamCal_LinearScan_phi004_theta-001_20230821T121304.csv +0 -0
  410. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E1.cdf +0 -0
  411. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E12.cdf +0 -0
  412. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E24.cdf +0 -0
  413. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
  414. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
  415. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,71 @@
1
+ from pathlib import Path
2
+
3
+ import numpy as np
4
+ import pytest
5
+ import xarray as xr
6
+
7
+ from imap_processing.spacecraft import quaternions
8
+
9
+
10
+ @pytest.fixture
11
+ def l1a_quaternion_ds():
12
+ time = np.arange(100)
13
+ data = np.linspace(-0.1, 0.1, 100)
14
+ data_vars = {"SCIENCEDATA1HZ_QUAT_10_HZ_TIME".lower(): time}
15
+ for i in range(4):
16
+ for j in range(10):
17
+ index = i * 10 + j
18
+ # 0-0.1, 0.1-0.2, 0.2-0.3, ... for each variable
19
+ data_vars[f"FSW_ACS_QUAT_10_HZ_BUFFERED_{index}".lower()] = data * j
20
+
21
+ ds = xr.Dataset(data_vars=data_vars)
22
+ return ds
23
+
24
+
25
+ def test_quaternion_packet_file():
26
+ # Single packet extracted with the following command:
27
+ # head --bytes 196 SSR_2024_190_20_08_12_0483851794_2_DA_apid0594.pkts > output.pkts
28
+ packet_file = (
29
+ Path(__file__).parent
30
+ / "data"
31
+ / "SSR_2024_190_20_08_12_0483851794_2_DA_apid0594_1packet.pkts"
32
+ )
33
+ l1a_ds = quaternions.load_quaternion_packets(packet_file)
34
+
35
+ # 1 packet
36
+ assert len(l1a_ds["epoch"]) == 1
37
+
38
+ # Make sure we have all of the expected variables
39
+ for i in range(40):
40
+ var = f"FSW_ACS_QUAT_10_HZ_BUFFERED_{i}".lower()
41
+ assert var in l1a_ds.data_vars
42
+ # Make sure it is a float32 between -1 and 1
43
+ assert l1a_ds[var].dtype == np.float32
44
+ assert -1 <= l1a_ds[var].values[0] <= 1
45
+
46
+
47
+ def test_quaternion_unpacking(l1a_quaternion_ds):
48
+ l1b_ds = quaternions.assemble_quaternions(l1a_quaternion_ds)
49
+
50
+ # Should be 10x the amount of data we got from the input dataset
51
+ # input was 0, 1, 2, ...
52
+ # expected is 0, 0.1, 0.2, ...
53
+ np.testing.assert_allclose(l1b_ds["epoch"], np.arange(0, 100, 0.1))
54
+
55
+ data = np.linspace(-0.1, 0.1, 100)
56
+ for var in ["quat_x", "quat_y", "quat_z", "quat_s"]:
57
+ # 10 increasing values, then reset and shift right by 0.2 / 99 for the linspace
58
+ # -0., -0.1, -0.2, ..., -0.9, -0., -0.09, -0.19, -0.29, ...
59
+ expected = np.stack([data * i for i in range(10)], axis=1).ravel()
60
+ np.testing.assert_allclose(l1b_ds[var], expected)
61
+
62
+
63
+ def test_process_quaternions():
64
+ packet_file = (
65
+ Path(__file__).parent
66
+ / "data"
67
+ / "SSR_2024_190_20_08_12_0483851794_2_DA_apid0594_1packet.pkts"
68
+ )
69
+ l1a_ds, l1b_ds = quaternions.process_quaternions(packet_file)
70
+ assert len(l1a_ds["epoch"]) == 1
71
+ assert len(l1b_ds["epoch"]) == 10
@@ -0,0 +1,5 @@
1
+ # This is a fake csv file for the sole purpose of testing repoint module functions
2
+ repoint_start_sec_sclk,repoint_start_subsec_sclk,repoint_end_sec_sclk,repoint_end_subsec_sclk,repoint_start_utc,repoint_end_utc,repoint_id
3
+ 0,100000,5,100000,2025-04-10 00:00:00.000000,2025-04-10T00:00:05.000000,0
4
+ 15,200000,20,200000,2025-04-10 00:00:15.000000,2025-04-10T00:00:20.000000,1
5
+ 25,300000,30,300000,2025-04-10 00:00:25.000000,2025-04-10T00:00:30.000000,2
@@ -1,19 +1,19 @@
1
1
  # This is a fake csv file for the sole purpose of testing the get_spacecraft_spin_phase function
2
- spin_number,spin_start_sec,spin_start_subsec,spin_period_sec,spin_period_valid,spin_phase_valid,spin_period_source,thruster_firing
2
+ spin_number,spin_start_sec_sclk,spin_start_subsec_sclk,spin_start_utc,spin_period_sec,spin_period_valid,spin_phase_valid,spin_period_source,thruster_firing
3
3
  # Start with thruster firing
4
- 0,0,0,15.0,1,1,0,1
4
+ 0,0,0,2024-04-11 00:00:00.000000,15.0,1,1,0,1
5
5
  # Turn thruster firing off then 3 valid spins
6
- 1,15,0,15.0,1,1,0,0
7
- 2,30,0,15.0,1,1,0,0
8
- 3,45,0,15.0,1,1,0,0
6
+ 1,15,0,2024-04-11 00:00:15.000000,15.0,1,1,0,0
7
+ 2,30,0,2024-04-11 00:00:30.000000,15.0,1,1,0,0
8
+ 3,45,0,2024-04-11 00:00:45.000000,15.0,1,1,0,0
9
9
  # Missing spin then 2 good spins
10
- 5,75,0,15.0,1,1,0,0
11
- 6,90,0,15.0,1,1,0,0
10
+ 5,75,0,2024-04-11 00:01:15.000000,15.0,1,1,0,0
11
+ 6,90,0,2024-04-11 00:01:30.000000,15.0,1,1,0,0
12
12
  # invalid spin period
13
- 7,105,0,15.0,0,1,0,0
13
+ 7,105,0,2024-04-11 00:01:45.000000,15.0,0,1,0,0
14
14
  # invalid spin phase
15
- 8,120,0,15.0,1,0,0,0
15
+ 8,120,0,2024-04-11 00:02:00.000000,15.0,1,0,0,0
16
16
  # 1 good spin
17
- 9,135,0,15.0,1,1,0,0
17
+ 9,135,0,2024-04-11 00:02:15.000000,15.0,1,1,0,0
18
18
  # Thruster firing on
19
- 10,150,0,15.0,1,1,0,1
19
+ 10,150,0,2024-04-11 00:02:30.000000,15.0,1,1,0,1
@@ -40,7 +40,7 @@ def test_imap_state(et, use_test_metakernel):
40
40
  assert state.shape == (6,)
41
41
 
42
42
 
43
- @pytest.mark.external_kernel()
43
+ @pytest.mark.external_kernel
44
44
  @pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
45
45
  def test_imap_state_ecliptic():
46
46
  """Tests retrieving IMAP state in the ECLIPJ2000 frame"""
@@ -51,7 +51,7 @@ def test_imap_state_ecliptic():
51
51
  @pytest.mark.parametrize(
52
52
  "instrument, expected_offset",
53
53
  [
54
- (SpiceFrame.IMAP_LO, 330 / 360),
54
+ (SpiceFrame.IMAP_LO_BASE, 330 / 360),
55
55
  (SpiceFrame.IMAP_HI_45, 255 / 360),
56
56
  (SpiceFrame.IMAP_HI_90, 285 / 360),
57
57
  (SpiceFrame.IMAP_ULTRA_45, 33 / 360),
@@ -208,8 +208,7 @@ def test_frame_transform_exceptions():
208
208
  SpiceFrame.ECLIPJ2000,
209
209
  ],
210
210
  )
211
- @pytest.mark.parametrize("degrees_bool", [True, False])
212
- def test_frame_transform_az_el_same_frame(spice_frame, degrees_bool):
211
+ def test_frame_transform_az_el_same_frame(spice_frame):
213
212
  """Test that frame_transform returns az/el when input/output frames are same."""
214
213
  az_el_points = np.array(
215
214
  [
@@ -231,10 +230,8 @@ def test_frame_transform_az_el_same_frame(spice_frame, degrees_bool):
231
230
  [360, 90],
232
231
  ]
233
232
  )
234
- if not degrees_bool:
235
- az_el_points = np.deg2rad(az_el_points)
236
233
  result = frame_transform_az_el(
237
- 0, az_el_points, spice_frame, spice_frame, degrees=degrees_bool
234
+ 0, az_el_points, spice_frame, spice_frame, degrees=True
238
235
  )
239
236
  np.testing.assert_allclose(result, az_el_points)
240
237
 
@@ -290,7 +287,7 @@ def test_instrument_pointing(furnish_kernels):
290
287
  assert ins_pointing.shape == (3, 3)
291
288
 
292
289
 
293
- @pytest.mark.external_kernel()
290
+ @pytest.mark.external_kernel
294
291
  @pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
295
292
  def test_basis_vectors():
296
293
  """Test coverage for basis_vectors()."""
@@ -360,12 +357,12 @@ def test_spherical_to_cartesian():
360
357
  # Convert elevation to colatitude for SPICE
361
358
  colat = np.pi / 2 - spherical_points[:, 2]
362
359
 
363
- cartesian_from_degrees = spherical_to_cartesian(
364
- spherical_points_degrees, degrees=True
365
- )
360
+ cartesian_from_degrees = spherical_to_cartesian(spherical_points_degrees)
366
361
 
367
362
  for i in range(len(colat)):
368
- cartesian_coords = spherical_to_cartesian(np.array([spherical_points[i]]))
363
+ cartesian_coords = spherical_to_cartesian(
364
+ np.array([spherical_points_degrees[i]])
365
+ )
369
366
  spice_coords = spiceypy.sphrec(r, colat[i], spherical_points[i, 1])
370
367
 
371
368
  np.testing.assert_allclose(cartesian_coords[0], spice_coords, atol=1e-5)
@@ -1,58 +1,10 @@
1
1
  """Tests coverage for imap_processing/spice/kernels.py"""
2
2
 
3
- import numpy as np
4
3
  import pytest
5
4
  import spiceypy
6
5
  from spiceypy.utils.exceptions import SpiceyError
7
6
 
8
- from imap_processing.spice.kernels import (
9
- _average_quaternions,
10
- _create_rotation_matrix,
11
- _get_et_times,
12
- create_pointing_frame,
13
- ensure_spice,
14
- )
15
-
16
-
17
- @pytest.fixture()
18
- def pointing_frame_kernels(spice_test_data_path):
19
- """List SPICE kernels."""
20
- required_kernels = [
21
- "imap_science_0001.tf",
22
- "imap_sclk_0000.tsc",
23
- "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
24
- "imap_wkcp.tf",
25
- "naif0012.tls",
26
- ]
27
- kernels = [str(spice_test_data_path / kernel) for kernel in required_kernels]
28
- return kernels
29
-
30
-
31
- @pytest.fixture()
32
- def multiple_pointing_kernels(spice_test_data_path):
33
- """List SPICE kernels."""
34
- required_kernels = [
35
- "imap_science_0001.tf",
36
- "imap_sclk_0000.tsc",
37
- "sim_1yr_imap_attitude.bc",
38
- "imap_wkcp.tf",
39
- "naif0012.tls",
40
- ]
41
- kernels = [str(spice_test_data_path / kernel) for kernel in required_kernels]
42
- return kernels
43
-
44
-
45
- @pytest.fixture()
46
- def et_times(pointing_frame_kernels):
47
- """Tests get_et_times function."""
48
- spiceypy.furnsh(pointing_frame_kernels)
49
-
50
- ck_kernel, _, _, _ = spiceypy.kdata(0, "ck")
51
- ck_cover = spiceypy.ckcov(ck_kernel, -43000, True, "INTERVAL", 0, "TDB")
52
- et_start, et_end = spiceypy.wnfetd(ck_cover, 0)
53
- et_times = _get_et_times(et_start, et_end)
54
-
55
- return et_times
7
+ from imap_processing.spice.kernels import ensure_spice
56
8
 
57
9
 
58
10
  @ensure_spice
@@ -119,154 +71,3 @@ def test_ensure_spice_key_error():
119
71
  # functions that it decorates.
120
72
  with pytest.raises(SpiceyError):
121
73
  _ = wrapped(577365941.184, "ISOC", 3) == "2018-04-18T23:24:31.998"
122
-
123
-
124
- def test_average_quaternions(et_times, pointing_frame_kernels):
125
- """Tests average_quaternions function."""
126
- spiceypy.furnsh(pointing_frame_kernels)
127
- q_avg = _average_quaternions(et_times)
128
-
129
- # Generated from MATLAB code results
130
- q_avg_expected = np.array([-0.6611, 0.4981, -0.5019, -0.2509])
131
- np.testing.assert_allclose(q_avg, q_avg_expected, atol=1e-4)
132
-
133
-
134
- def test_create_rotation_matrix(et_times, pointing_frame_kernels):
135
- """Tests create_rotation_matrix function."""
136
- spiceypy.furnsh(pointing_frame_kernels)
137
- rotation_matrix = _create_rotation_matrix(et_times)
138
- q_avg = _average_quaternions(et_times)
139
- z_avg = spiceypy.q2m(list(q_avg))[:, 2]
140
-
141
- rotation_matrix_expected = np.array(
142
- [[0.0000, 0.0000, 1.0000], [0.9104, -0.4136, 0.0000], [0.4136, 0.9104, 0.0000]]
143
- )
144
- z_avg_expected = np.array([0.4136, 0.9104, 0.0000])
145
-
146
- np.testing.assert_allclose(z_avg, z_avg_expected, atol=1e-4)
147
- np.testing.assert_allclose(rotation_matrix, rotation_matrix_expected, atol=1e-4)
148
-
149
-
150
- def test_create_pointing_frame(
151
- spice_test_data_path, pointing_frame_kernels, tmp_path, et_times
152
- ):
153
- """Tests create_pointing_frame function."""
154
- spiceypy.kclear()
155
- spiceypy.furnsh(pointing_frame_kernels)
156
- create_pointing_frame(
157
- pointing_frame_path=tmp_path / "imap_dps.bc",
158
- ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
159
- )
160
-
161
- # After imap_dps.bc has been created.
162
- dps_kernel = str(tmp_path / "imap_dps.bc")
163
-
164
- spiceypy.furnsh(dps_kernel)
165
- rotation_matrix_1 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[0] + 100)
166
- rotation_matrix_2 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[0] + 1000)
167
-
168
- # All the rotation matrices should be the same.
169
- assert np.array_equal(rotation_matrix_1, rotation_matrix_2)
170
-
171
- # Nick Dutton's MATLAB code result
172
- rotation_matrix_expected = np.array(
173
- [[0.0000, 0.0000, 1.0000], [0.9104, -0.4136, 0.0000], [0.4136, 0.9104, 0.0000]]
174
- )
175
- np.testing.assert_allclose(rotation_matrix_1, rotation_matrix_expected, atol=1e-4)
176
-
177
- # Verify imap_dps.bc has been created.
178
- assert (tmp_path / "imap_dps.bc").exists()
179
-
180
- # Tests error handling when incorrect kernel is loaded.
181
- spiceypy.furnsh(pointing_frame_kernels)
182
- with pytest.raises(
183
- ValueError, match="Error: Expected CK kernel badname_kernel.bc"
184
- ): # Replace match string with expected error message
185
- create_pointing_frame(
186
- pointing_frame_path=tmp_path / "imap_dps.bc", ck_path="badname_kernel.bc"
187
- )
188
-
189
-
190
- def test_et_times(pointing_frame_kernels):
191
- """Tests get_et_times function."""
192
- spiceypy.furnsh(pointing_frame_kernels)
193
-
194
- ck_kernel, _, _, _ = spiceypy.kdata(0, "ck")
195
- ck_cover = spiceypy.ckcov(ck_kernel, -43000, True, "INTERVAL", 0, "TDB")
196
- et_start, et_end = spiceypy.wnfetd(ck_cover, 0)
197
- et_times = _get_et_times(et_start, et_end)
198
-
199
- assert et_times[0] == et_start
200
- assert et_times[-1] == et_end
201
-
202
- return et_times
203
-
204
-
205
- def test_multiple_attempts(pointing_frame_kernels, tmp_path, spice_test_data_path):
206
- """Tests create_pointing_frame function with multiple pointing kernels."""
207
- spiceypy.furnsh(pointing_frame_kernels)
208
-
209
- # Check that a single segment is added regardless of how many times
210
- # create_pointing_frame is called.
211
- create_pointing_frame(
212
- pointing_frame_path=tmp_path / "imap_dps.bc",
213
- ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
214
- )
215
- ck_cover = spiceypy.ckcov(
216
- str(tmp_path / "imap_dps.bc"), -43901, True, "INTERVAL", 0, "TDB"
217
- )
218
- num_intervals = spiceypy.wncard(ck_cover)
219
- assert num_intervals == 1
220
-
221
- create_pointing_frame(
222
- pointing_frame_path=tmp_path / "imap_dps.bc",
223
- ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
224
- )
225
- ck_cover = spiceypy.ckcov(
226
- str(tmp_path / "imap_dps.bc"), -43901, True, "INTERVAL", 0, "TDB"
227
- )
228
- num_intervals = spiceypy.wncard(ck_cover)
229
- assert num_intervals == 1
230
-
231
-
232
- def test_multiple_pointings(pointing_frame_kernels, spice_test_data_path, tmp_path):
233
- """Tests create_pointing_frame function with multiple pointing kernels."""
234
- spiceypy.furnsh(pointing_frame_kernels)
235
-
236
- create_pointing_frame(
237
- pointing_frame_path=tmp_path / "imap_pointing_frame.bc",
238
- ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
239
- )
240
- ck_cover_pointing = spiceypy.ckcov(
241
- str(tmp_path / "imap_pointing_frame.bc"),
242
- -43901,
243
- True,
244
- "INTERVAL",
245
- 0,
246
- "TDB",
247
- )
248
- num_intervals = spiceypy.wncard(ck_cover_pointing)
249
- et_start_pointing, et_end_pointing = spiceypy.wnfetd(ck_cover_pointing, 0)
250
-
251
- ck_cover = spiceypy.ckcov(
252
- str(spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc"),
253
- -43000,
254
- True,
255
- "INTERVAL",
256
- 0,
257
- "TDB",
258
- )
259
- num_intervals_expected = spiceypy.wncard(ck_cover)
260
- et_start_expected, et_end_expected = spiceypy.wnfetd(ck_cover, 0)
261
-
262
- assert num_intervals == num_intervals_expected
263
- assert et_start_pointing == et_start_expected
264
- assert et_end_pointing == et_end_expected
265
-
266
- et_times = _get_et_times(et_start_pointing, et_end_pointing)
267
-
268
- spiceypy.furnsh(str(tmp_path / "imap_pointing_frame.bc"))
269
- rotation_matrix_1 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[100])
270
- rotation_matrix_2 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[1000])
271
-
272
- assert np.array_equal(rotation_matrix_1, rotation_matrix_2)
@@ -0,0 +1,185 @@
1
+ """Test coverage for imap_processing.spice.repoint.py"""
2
+
3
+ import numpy as np
4
+ import pytest
5
+ import spiceypy
6
+
7
+ from imap_processing.spice.pointing_frame import (
8
+ _average_quaternions,
9
+ _create_rotation_matrix,
10
+ create_pointing_frame,
11
+ )
12
+
13
+
14
+ @pytest.fixture
15
+ def pointing_frame_kernels(spice_test_data_path):
16
+ """List SPICE kernels."""
17
+ required_kernels = [
18
+ "imap_science_0001.tf",
19
+ "imap_sclk_0000.tsc",
20
+ "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
21
+ "imap_wkcp.tf",
22
+ "naif0012.tls",
23
+ ]
24
+ kernels = [str(spice_test_data_path / kernel) for kernel in required_kernels]
25
+ return kernels
26
+
27
+
28
+ @pytest.fixture
29
+ def et_times(pointing_frame_kernels):
30
+ """Tests get_et_times function."""
31
+ spiceypy.furnsh(pointing_frame_kernels)
32
+
33
+ ck_kernel, _, _, _ = spiceypy.kdata(0, "ck")
34
+ ck_cover = spiceypy.ckcov(ck_kernel, -43000, True, "INTERVAL", 0, "TDB")
35
+ et_start, et_end = spiceypy.wnfetd(ck_cover, 0)
36
+
37
+ # 1 spin/15 seconds; 10 quaternions / spin.
38
+ num_samples = (et_end - et_start) / 15 * 10
39
+ # There were rounding errors when using spiceypy.pxform so np.ceil and np.floor
40
+ # were used to ensure the start and end times were within the ck range.
41
+ et_times = np.linspace(
42
+ np.ceil(et_start * 1e6) / 1e6, np.floor(et_end * 1e6) / 1e6, int(num_samples)
43
+ )
44
+
45
+ return et_times
46
+
47
+
48
+ @pytest.fixture
49
+ def fake_repoint_data(monkeypatch, spice_test_data_path):
50
+ """Generate fake spin dataframe for testing"""
51
+ fake_repoint_path = spice_test_data_path / "fake_repoint_data.csv"
52
+ monkeypatch.setenv("REPOINT_DATA_FILEPATH", str(fake_repoint_path))
53
+ return fake_repoint_path
54
+
55
+
56
+ def test_average_quaternions(et_times, pointing_frame_kernels):
57
+ """Tests average_quaternions function."""
58
+ spiceypy.furnsh(pointing_frame_kernels)
59
+ q_avg = _average_quaternions(et_times)
60
+
61
+ # Generated from MATLAB code results
62
+ q_avg_expected = np.array([-0.6611, 0.4981, -0.5019, -0.2509])
63
+ np.testing.assert_allclose(q_avg, q_avg_expected, atol=1e-4)
64
+
65
+
66
+ def test_create_rotation_matrix(et_times, pointing_frame_kernels):
67
+ """Tests create_rotation_matrix function."""
68
+ spiceypy.furnsh(pointing_frame_kernels)
69
+ rotation_matrix = _create_rotation_matrix(et_times)
70
+ q_avg = _average_quaternions(et_times)
71
+ z_avg = spiceypy.q2m(list(q_avg))[:, 2]
72
+
73
+ rotation_matrix_expected = np.array(
74
+ [[0.0000, 0.0000, 1.0000], [0.9104, -0.4136, 0.0000], [0.4136, 0.9104, 0.0000]]
75
+ )
76
+ z_avg_expected = np.array([0.4136, 0.9104, 0.0000])
77
+
78
+ np.testing.assert_allclose(z_avg, z_avg_expected, atol=1e-4)
79
+ np.testing.assert_allclose(rotation_matrix, rotation_matrix_expected, atol=1e-4)
80
+
81
+
82
+ def test_create_pointing_frame(
83
+ spice_test_data_path, pointing_frame_kernels, tmp_path, et_times, fake_repoint_data
84
+ ):
85
+ """Tests create_pointing_frame function."""
86
+
87
+ # This is how the repoint data is generated.
88
+ # We will use fake data for now to match the coverage of the attitude kernel.
89
+ # repoint_df = get_repoint_data()
90
+ # repoint_start = repoint_df["repoint_end_met"].values[:-1]
91
+ # repoint_end_met = repoint_df["repoint_start_met"].values[1:]
92
+
93
+ spiceypy.kclear()
94
+ spiceypy.furnsh(pointing_frame_kernels)
95
+ create_pointing_frame(
96
+ tmp_path / "imap_dps.bc",
97
+ spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
98
+ np.array([486432004]), # repoint_df["repoint_start_met"].values
99
+ np.array([486439201]), # repoint_df["repoint_end_met"].values
100
+ )
101
+
102
+ # After imap_dps.bc has been created.
103
+ dps_kernel = str(tmp_path / "imap_dps.bc")
104
+
105
+ spiceypy.furnsh(dps_kernel)
106
+ rotation_matrix_1 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[0] + 100)
107
+ rotation_matrix_2 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[0] + 1000)
108
+
109
+ # All the rotation matrices should be the same.
110
+ assert np.array_equal(rotation_matrix_1, rotation_matrix_2)
111
+
112
+ # Nick Dutton's MATLAB code result
113
+ rotation_matrix_expected = np.array(
114
+ [[0.0000, 0.0000, 1.0000], [0.9104, -0.4136, 0.0000], [0.4136, 0.9104, 0.0000]]
115
+ )
116
+ np.testing.assert_allclose(rotation_matrix_1, rotation_matrix_expected, atol=1e-4)
117
+
118
+ # Verify imap_dps.bc has been created.
119
+ assert (tmp_path / "imap_dps.bc").exists()
120
+
121
+ # Tests error handling when incorrect kernel is loaded.
122
+ spiceypy.furnsh(pointing_frame_kernels)
123
+ with pytest.raises(
124
+ ValueError, match="Error: Expected CK kernel badname_kernel.bc"
125
+ ): # Replace match string with expected error message
126
+ create_pointing_frame(
127
+ tmp_path / "imap_dps.bc",
128
+ "badname_kernel.bc",
129
+ np.array([486432004]),
130
+ np.array([486439201]),
131
+ )
132
+
133
+
134
+ def test_multiple_pointings(pointing_frame_kernels, spice_test_data_path, tmp_path):
135
+ """Tests create_pointing_frame function with multiple pointing kernels."""
136
+ spiceypy.furnsh(pointing_frame_kernels)
137
+
138
+ create_pointing_frame(
139
+ tmp_path / "imap_pointing_frame.bc",
140
+ spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
141
+ np.array([486432003]), # repoint_df["repoint_start_met"].values
142
+ np.array([486439201]), # repoint_df["repoint_end_met"].values
143
+ )
144
+
145
+ ck_cover_pointing = spiceypy.ckcov(
146
+ str(tmp_path / "imap_pointing_frame.bc"),
147
+ -43901,
148
+ True,
149
+ "INTERVAL",
150
+ 0,
151
+ "TDB",
152
+ )
153
+ num_intervals = spiceypy.wncard(ck_cover_pointing)
154
+ et_start_pointing, et_end_pointing = spiceypy.wnfetd(ck_cover_pointing, 0)
155
+
156
+ ck_cover = spiceypy.ckcov(
157
+ str(spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc"),
158
+ -43000,
159
+ True,
160
+ "INTERVAL",
161
+ 0,
162
+ "TDB",
163
+ )
164
+ num_intervals_expected = spiceypy.wncard(ck_cover)
165
+ et_start_expected, et_end_expected = spiceypy.wnfetd(ck_cover, 0)
166
+
167
+ assert num_intervals == num_intervals_expected
168
+ np.testing.assert_allclose(et_start_pointing, et_start_expected, atol=1e-2)
169
+ np.testing.assert_allclose(et_end_pointing, et_end_expected, atol=1e-2)
170
+
171
+ # 1 spin/15 seconds; 10 quaternions / spin.
172
+ num_samples = (et_end_pointing - et_start_pointing) / 15 * 10
173
+ # There were rounding errors when using spiceypy.pxform so np.ceil and np.floor
174
+ # were used to ensure the start and end times were within the ck range.
175
+ et_times = np.linspace(
176
+ np.ceil(et_start_pointing * 1e6) / 1e6,
177
+ np.floor(et_end_pointing * 1e6) / 1e6,
178
+ int(num_samples),
179
+ )
180
+
181
+ spiceypy.furnsh(str(tmp_path / "imap_pointing_frame.bc"))
182
+ rotation_matrix_1 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[100])
183
+ rotation_matrix_2 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[1000])
184
+
185
+ assert np.array_equal(rotation_matrix_1, rotation_matrix_2)