imap-processing 0.12.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 (272) hide show
  1. imap_processing/__init__.py +1 -0
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/ccsds_data.py +1 -2
  4. imap_processing/ccsds/excel_to_xtce.py +1 -2
  5. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +18 -12
  6. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +569 -0
  7. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
  8. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +5 -5
  9. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +20 -1
  10. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +6 -4
  11. imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +3 -3
  12. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +15 -0
  13. imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
  14. imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +16 -0
  15. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +178 -5
  16. imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
  17. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +33 -19
  18. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +8 -48
  19. imap_processing/cdf/utils.py +41 -33
  20. imap_processing/cli.py +463 -234
  21. imap_processing/codice/codice_l1a.py +260 -47
  22. imap_processing/codice/codice_l1b.py +51 -152
  23. imap_processing/codice/constants.py +38 -1
  24. imap_processing/ena_maps/ena_maps.py +658 -65
  25. imap_processing/ena_maps/utils/coordinates.py +1 -1
  26. imap_processing/ena_maps/utils/spatial_utils.py +10 -5
  27. imap_processing/glows/l1a/glows_l1a.py +28 -99
  28. imap_processing/glows/l1a/glows_l1a_data.py +2 -2
  29. imap_processing/glows/l1b/glows_l1b.py +1 -4
  30. imap_processing/glows/l1b/glows_l1b_data.py +1 -3
  31. imap_processing/glows/l2/glows_l2.py +2 -5
  32. imap_processing/hi/l1a/hi_l1a.py +31 -12
  33. imap_processing/hi/l1b/hi_l1b.py +80 -43
  34. imap_processing/hi/l1c/hi_l1c.py +12 -16
  35. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
  36. imap_processing/hit/hit_utils.py +93 -35
  37. imap_processing/hit/l0/decom_hit.py +3 -1
  38. imap_processing/hit/l1a/hit_l1a.py +30 -25
  39. imap_processing/hit/l1b/constants.py +6 -2
  40. imap_processing/hit/l1b/hit_l1b.py +279 -318
  41. imap_processing/hit/l2/constants.py +37 -0
  42. imap_processing/hit/l2/hit_l2.py +373 -264
  43. imap_processing/ialirt/l0/parse_mag.py +138 -10
  44. imap_processing/ialirt/l0/process_swapi.py +69 -0
  45. imap_processing/ialirt/l0/process_swe.py +318 -22
  46. imap_processing/ialirt/packet_definitions/ialirt.xml +216 -212
  47. imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +1 -1
  48. imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +1 -1
  49. imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
  50. imap_processing/ialirt/utils/grouping.py +1 -1
  51. imap_processing/idex/idex_constants.py +9 -1
  52. imap_processing/idex/idex_l0.py +22 -8
  53. imap_processing/idex/idex_l1a.py +75 -44
  54. imap_processing/idex/idex_l1b.py +9 -8
  55. imap_processing/idex/idex_l2a.py +79 -45
  56. imap_processing/idex/idex_l2b.py +120 -0
  57. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -39
  58. imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
  59. imap_processing/lo/l0/lo_science.py +1 -2
  60. imap_processing/lo/l1a/lo_l1a.py +1 -4
  61. imap_processing/lo/l1b/lo_l1b.py +527 -6
  62. imap_processing/lo/l1b/tof_conversions.py +11 -0
  63. imap_processing/lo/l1c/lo_l1c.py +1 -4
  64. imap_processing/mag/constants.py +43 -0
  65. imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
  66. imap_processing/mag/l1a/mag_l1a.py +2 -9
  67. imap_processing/mag/l1a/mag_l1a_data.py +10 -10
  68. imap_processing/mag/l1b/mag_l1b.py +84 -17
  69. imap_processing/mag/l1c/interpolation_methods.py +180 -3
  70. imap_processing/mag/l1c/mag_l1c.py +236 -70
  71. imap_processing/mag/l2/mag_l2.py +140 -0
  72. imap_processing/mag/l2/mag_l2_data.py +288 -0
  73. imap_processing/spacecraft/quaternions.py +1 -3
  74. imap_processing/spice/geometry.py +3 -3
  75. imap_processing/spice/kernels.py +0 -276
  76. imap_processing/spice/pointing_frame.py +257 -0
  77. imap_processing/spice/repoint.py +48 -19
  78. imap_processing/spice/spin.py +38 -33
  79. imap_processing/spice/time.py +24 -0
  80. imap_processing/swapi/l1/swapi_l1.py +16 -12
  81. imap_processing/swapi/l2/swapi_l2.py +116 -4
  82. imap_processing/swapi/swapi_utils.py +32 -0
  83. imap_processing/swe/l1a/swe_l1a.py +2 -9
  84. imap_processing/swe/l1a/swe_science.py +8 -11
  85. imap_processing/swe/l1b/swe_l1b.py +898 -23
  86. imap_processing/swe/l2/swe_l2.py +21 -77
  87. imap_processing/swe/utils/swe_constants.py +1 -0
  88. imap_processing/tests/ccsds/test_excel_to_xtce.py +1 -1
  89. imap_processing/tests/cdf/test_utils.py +14 -16
  90. imap_processing/tests/codice/conftest.py +44 -33
  91. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
  92. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
  93. imap_processing/tests/codice/test_codice_l1a.py +20 -11
  94. imap_processing/tests/codice/test_codice_l1b.py +6 -7
  95. imap_processing/tests/conftest.py +78 -22
  96. imap_processing/tests/ena_maps/test_ena_maps.py +462 -33
  97. imap_processing/tests/ena_maps/test_spatial_utils.py +1 -1
  98. imap_processing/tests/glows/conftest.py +10 -14
  99. imap_processing/tests/glows/test_glows_decom.py +4 -4
  100. imap_processing/tests/glows/test_glows_l1a_cdf.py +6 -27
  101. imap_processing/tests/glows/test_glows_l1a_data.py +6 -8
  102. imap_processing/tests/glows/test_glows_l1b.py +11 -11
  103. imap_processing/tests/glows/test_glows_l1b_data.py +5 -5
  104. imap_processing/tests/glows/test_glows_l2.py +2 -8
  105. imap_processing/tests/hi/conftest.py +1 -1
  106. imap_processing/tests/hi/test_hi_l1b.py +10 -12
  107. imap_processing/tests/hi/test_hi_l1c.py +27 -24
  108. imap_processing/tests/hi/test_l1a.py +7 -9
  109. imap_processing/tests/hi/test_science_direct_event.py +2 -2
  110. imap_processing/tests/hit/helpers/l1_validation.py +44 -43
  111. imap_processing/tests/hit/test_decom_hit.py +1 -1
  112. imap_processing/tests/hit/test_hit_l1a.py +9 -9
  113. imap_processing/tests/hit/test_hit_l1b.py +172 -217
  114. imap_processing/tests/hit/test_hit_l2.py +380 -118
  115. imap_processing/tests/hit/test_hit_utils.py +122 -55
  116. imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
  117. imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
  118. imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
  119. imap_processing/tests/ialirt/unit/test_grouping.py +2 -2
  120. imap_processing/tests/ialirt/unit/test_parse_mag.py +71 -16
  121. imap_processing/tests/ialirt/unit/test_process_codicehi.py +3 -3
  122. imap_processing/tests/ialirt/unit/test_process_codicelo.py +3 -10
  123. imap_processing/tests/ialirt/unit/test_process_ephemeris.py +4 -4
  124. imap_processing/tests/ialirt/unit/test_process_hit.py +3 -3
  125. imap_processing/tests/ialirt/unit/test_process_swapi.py +24 -16
  126. imap_processing/tests/ialirt/unit/test_process_swe.py +115 -7
  127. imap_processing/tests/idex/conftest.py +72 -7
  128. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20241206_v001.pkts +0 -0
  129. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20250108_v001.pkts +0 -0
  130. imap_processing/tests/idex/test_idex_l0.py +33 -11
  131. imap_processing/tests/idex/test_idex_l1a.py +50 -23
  132. imap_processing/tests/idex/test_idex_l1b.py +104 -25
  133. imap_processing/tests/idex/test_idex_l2a.py +48 -32
  134. imap_processing/tests/idex/test_idex_l2b.py +93 -0
  135. imap_processing/tests/lo/test_lo_l1a.py +3 -3
  136. imap_processing/tests/lo/test_lo_l1b.py +371 -6
  137. imap_processing/tests/lo/test_lo_l1c.py +1 -1
  138. imap_processing/tests/lo/test_lo_science.py +6 -7
  139. imap_processing/tests/lo/test_star_sensor.py +1 -1
  140. imap_processing/tests/mag/conftest.py +58 -9
  141. imap_processing/tests/mag/test_mag_decom.py +4 -3
  142. imap_processing/tests/mag/test_mag_l1a.py +13 -7
  143. imap_processing/tests/mag/test_mag_l1b.py +9 -9
  144. imap_processing/tests/mag/test_mag_l1c.py +151 -47
  145. imap_processing/tests/mag/test_mag_l2.py +130 -0
  146. imap_processing/tests/mag/test_mag_validation.py +144 -7
  147. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-in.csv +1217 -0
  148. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-out.csv +1857 -0
  149. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-in.csv +1217 -0
  150. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-out.csv +1857 -0
  151. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-in.csv +1217 -0
  152. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-out.csv +1793 -0
  153. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-in.csv +1217 -0
  154. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-out.csv +1793 -0
  155. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-burst-in.csv +2561 -0
  156. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-in.csv +961 -0
  157. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-out.csv +1539 -0
  158. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-in.csv +1921 -0
  159. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-out.csv +2499 -0
  160. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-in.csv +865 -0
  161. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv +1196 -0
  162. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-in.csv +1729 -0
  163. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv +3053 -0
  164. imap_processing/tests/mag/validation/L2/imap_mag_l1b_norm-mago_20251017_v002.cdf +0 -0
  165. imap_processing/tests/mag/validation/calibration/imap_mag_l2-calibration-matrices_20251017_v004.cdf +0 -0
  166. imap_processing/tests/mag/validation/calibration/imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf +0 -0
  167. imap_processing/tests/spacecraft/test_quaternions.py +1 -1
  168. imap_processing/tests/spice/test_data/fake_repoint_data.csv +4 -4
  169. imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
  170. imap_processing/tests/spice/test_geometry.py +3 -3
  171. imap_processing/tests/spice/test_kernels.py +1 -200
  172. imap_processing/tests/spice/test_pointing_frame.py +185 -0
  173. imap_processing/tests/spice/test_repoint.py +20 -10
  174. imap_processing/tests/spice/test_spin.py +50 -9
  175. imap_processing/tests/spice/test_time.py +14 -0
  176. imap_processing/tests/swapi/lut/imap_swapi_esa-unit-conversion_20250211_v000.csv +73 -0
  177. imap_processing/tests/swapi/lut/imap_swapi_lut-notes_20250211_v000.csv +1025 -0
  178. imap_processing/tests/swapi/test_swapi_l1.py +7 -9
  179. imap_processing/tests/swapi/test_swapi_l2.py +180 -8
  180. imap_processing/tests/swe/lut/checker-board-indices.csv +24 -0
  181. imap_processing/tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv +385 -0
  182. imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv +3 -0
  183. imap_processing/tests/swe/test_swe_l1a.py +6 -6
  184. imap_processing/tests/swe/test_swe_l1a_science.py +3 -3
  185. imap_processing/tests/swe/test_swe_l1b.py +162 -24
  186. imap_processing/tests/swe/test_swe_l2.py +82 -102
  187. imap_processing/tests/test_cli.py +171 -88
  188. imap_processing/tests/test_utils.py +2 -1
  189. imap_processing/tests/ultra/data/mock_data.py +49 -21
  190. imap_processing/tests/ultra/unit/conftest.py +53 -70
  191. imap_processing/tests/ultra/unit/test_badtimes.py +2 -4
  192. imap_processing/tests/ultra/unit/test_cullingmask.py +4 -6
  193. imap_processing/tests/ultra/unit/test_de.py +3 -10
  194. imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
  195. imap_processing/tests/ultra/unit/test_decom_apid_881.py +15 -16
  196. imap_processing/tests/ultra/unit/test_decom_apid_883.py +12 -10
  197. imap_processing/tests/ultra/unit/test_decom_apid_896.py +202 -55
  198. imap_processing/tests/ultra/unit/test_lookup_utils.py +23 -1
  199. imap_processing/tests/ultra/unit/test_spacecraft_pset.py +3 -4
  200. imap_processing/tests/ultra/unit/test_ultra_l1a.py +84 -307
  201. imap_processing/tests/ultra/unit/test_ultra_l1b.py +30 -12
  202. imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
  203. imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +4 -1
  204. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +163 -29
  205. imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
  206. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +32 -43
  207. imap_processing/tests/ultra/unit/test_ultra_l2.py +230 -0
  208. imap_processing/ultra/constants.py +1 -1
  209. imap_processing/ultra/l0/decom_tools.py +21 -34
  210. imap_processing/ultra/l0/decom_ultra.py +168 -204
  211. imap_processing/ultra/l0/ultra_utils.py +152 -136
  212. imap_processing/ultra/l1a/ultra_l1a.py +55 -243
  213. imap_processing/ultra/l1b/badtimes.py +1 -4
  214. imap_processing/ultra/l1b/cullingmask.py +2 -6
  215. imap_processing/ultra/l1b/de.py +62 -47
  216. imap_processing/ultra/l1b/extendedspin.py +8 -4
  217. imap_processing/ultra/l1b/lookup_utils.py +72 -9
  218. imap_processing/ultra/l1b/ultra_l1b.py +3 -8
  219. imap_processing/ultra/l1b/ultra_l1b_culling.py +4 -4
  220. imap_processing/ultra/l1b/ultra_l1b_extended.py +236 -78
  221. imap_processing/ultra/l1c/histogram.py +2 -6
  222. imap_processing/ultra/l1c/spacecraft_pset.py +2 -4
  223. imap_processing/ultra/l1c/ultra_l1c.py +1 -5
  224. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +107 -60
  225. imap_processing/ultra/l2/ultra_l2.py +299 -0
  226. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +526 -0
  227. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +526 -0
  228. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +526 -0
  229. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +526 -0
  230. imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -2
  231. imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
  232. imap_processing/ultra/packet_definitions/README.md +38 -0
  233. imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +15302 -482
  234. imap_processing/ultra/utils/ultra_l1_utils.py +13 -12
  235. imap_processing/utils.py +1 -1
  236. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +3 -2
  237. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/RECORD +264 -225
  238. imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
  239. imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +0 -6
  240. imap_processing/mag/l1b/__init__.py +0 -0
  241. imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
  242. imap_processing/swe/l1b/swe_l1b_science.py +0 -699
  243. imap_processing/tests/swe/test_swe_l1b_science.py +0 -103
  244. imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
  245. imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
  246. /imap_processing/idex/packet_definitions/{idex_packet_definition.xml → idex_science_packet_definition.xml} +0 -0
  247. /imap_processing/tests/ialirt/{test_data → data}/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
  248. /imap_processing/tests/ialirt/{test_data → data}/l0/461971383-404.bin +0 -0
  249. /imap_processing/tests/ialirt/{test_data → data}/l0/461971384-405.bin +0 -0
  250. /imap_processing/tests/ialirt/{test_data → data}/l0/461971385-406.bin +0 -0
  251. /imap_processing/tests/ialirt/{test_data → data}/l0/461971386-407.bin +0 -0
  252. /imap_processing/tests/ialirt/{test_data → data}/l0/461971387-408.bin +0 -0
  253. /imap_processing/tests/ialirt/{test_data → data}/l0/461971388-409.bin +0 -0
  254. /imap_processing/tests/ialirt/{test_data → data}/l0/461971389-410.bin +0 -0
  255. /imap_processing/tests/ialirt/{test_data → data}/l0/461971390-411.bin +0 -0
  256. /imap_processing/tests/ialirt/{test_data → data}/l0/461971391-412.bin +0 -0
  257. /imap_processing/tests/ialirt/{test_data → data}/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
  258. /imap_processing/tests/ialirt/{test_data → data}/l0/IALiRT Raw Packet Telemetry.txt +0 -0
  259. /imap_processing/tests/ialirt/{test_data → data}/l0/apid01152.tlm +0 -0
  260. /imap_processing/tests/ialirt/{test_data → data}/l0/eu_SWP_IAL_20240826_152033.csv +0 -0
  261. /imap_processing/tests/ialirt/{test_data → data}/l0/hi_fsw_view_1_ccsds.bin +0 -0
  262. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.ccsds +0 -0
  263. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.csv +0 -0
  264. /imap_processing/tests/ialirt/{test_data → data}/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +0 -0
  265. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
  266. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  267. /imap_processing/tests/ialirt/{test_data → data}/l0/sample_decoded_i-alirt_data.csv +0 -0
  268. /imap_processing/tests/mag/validation/{imap_calibration_mag_20240229_v01.cdf → calibration/imap_mag_l1b-calibration_20240229_v001.cdf} +0 -0
  269. /imap_processing/{swe/l1b/engineering_unit_convert_table.csv → tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv} +0 -0
  270. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
  271. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
  272. {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
@@ -7,7 +7,7 @@ import xarray as xr
7
7
  from imap_processing.spacecraft import quaternions
8
8
 
9
9
 
10
- @pytest.fixture()
10
+ @pytest.fixture
11
11
  def l1a_quaternion_ds():
12
12
  time = np.arange(100)
13
13
  data = np.linspace(-0.1, 0.1, 100)
@@ -1,5 +1,5 @@
1
1
  # This is a fake csv file for the sole purpose of testing repoint module functions
2
- repoint_start_time,repoint_end_time,repoint_id
3
- 0,5,0
4
- 15,20,1
5
- 25,30,2
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),
@@ -287,7 +287,7 @@ def test_instrument_pointing(furnish_kernels):
287
287
  assert ins_pointing.shape == (3, 3)
288
288
 
289
289
 
290
- @pytest.mark.external_kernel()
290
+ @pytest.mark.external_kernel
291
291
  @pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
292
292
  def test_basis_vectors():
293
293
  """Test coverage for basis_vectors()."""
@@ -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)
@@ -7,7 +7,7 @@ import pytest
7
7
  from imap_processing.spice.repoint import get_repoint_data, interpolate_repoint_data
8
8
 
9
9
 
10
- @pytest.fixture()
10
+ @pytest.fixture
11
11
  def fake_repoint_data(monkeypatch, spice_test_data_path):
12
12
  """Generate fake spin dataframe for testing"""
13
13
  fake_repoint_path = spice_test_data_path / "fake_repoint_data.csv"
@@ -16,12 +16,18 @@ def fake_repoint_data(monkeypatch, spice_test_data_path):
16
16
 
17
17
 
18
18
  def test_get_repoint_data(fake_repoint_data):
19
- """Test coverarge for get_repoint_data function."""
19
+ """Test coverage for get_repoint_data function."""
20
20
  repoint_df = get_repoint_data()
21
21
  assert isinstance(repoint_df, pd.DataFrame)
22
22
  assert set(repoint_df.columns) == {
23
- "repoint_start_time",
24
- "repoint_end_time",
23
+ "repoint_start_sec_sclk",
24
+ "repoint_start_subsec_sclk",
25
+ "repoint_start_met",
26
+ "repoint_start_utc",
27
+ "repoint_end_sec_sclk",
28
+ "repoint_end_subsec_sclk",
29
+ "repoint_end_met",
30
+ "repoint_end_utc",
25
31
  "repoint_id",
26
32
  }
27
33
 
@@ -36,10 +42,14 @@ def test_spin_data_no_table():
36
42
 
37
43
  def test_interpolate_repoint_data(fake_repoint_data):
38
44
  """Test coverage for get_repoint_data function."""
39
- query_times = np.array([0, 6, 32])
45
+ query_times = np.array([0.1, 6, 32])
40
46
  expected_vals = {
41
- "repoint_start_time": np.array([0, 0, 25]),
42
- "repoint_end_time": np.array([5, 5, 30]),
47
+ "repoint_start_sec_sclk": np.array([0, 0, 25]),
48
+ "repoint_start_subsec_sclk": np.array([100000, 100000, 300000]),
49
+ "repoint_start_met": np.array([0.1, 0.1, 25.3]),
50
+ "repoint_end_sec_sclk": np.array([5, 5, 30]),
51
+ "repoint_end_subsec_sclk": np.array([100000, 100000, 300000]),
52
+ "repoint_end_met": np.array([5.1, 5.1, 30.3]),
43
53
  "repoint_id": np.array([0, 0, 2]),
44
54
  "repoint_in_progress": np.array([True, False, False]),
45
55
  }
@@ -57,7 +67,7 @@ def test_interpolate_repoint_data(fake_repoint_data):
57
67
  "1 query times are before",
58
68
  ), # Query times before start of table
59
69
  (
60
- np.array([0, 24 * 60 * 60 + 26]),
70
+ np.array([1, 24 * 60 * 60 + 26]),
61
71
  "1 query times are after",
62
72
  ), # Query times after end of valid range
63
73
  ],
@@ -81,12 +91,12 @@ def test_interpolate_repoint_data_with_use_fake_fixture(use_fake_repoint_data_fo
81
91
 
82
92
  # Expected repoint_start_times are the seeded start times array repeated twice
83
93
  np.testing.assert_array_equal(
84
- repoint_df["repoint_start_time"].values,
94
+ repoint_df["repoint_start_met"].values,
85
95
  np.concat([repoint_start_times, repoint_start_times]),
86
96
  )
87
97
  # Expected repoint_end_times are the seeded start times + 15 minutes
88
98
  np.testing.assert_array_equal(
89
- repoint_df["repoint_end_time"].values,
99
+ repoint_df["repoint_end_met"].values,
90
100
  np.concat([repoint_start_times + 15 * 60, repoint_start_times + 15 * 60]),
91
101
  )
92
102
  # Expected repoint_id
@@ -14,7 +14,7 @@ from imap_processing.spice.spin import (
14
14
  )
15
15
 
16
16
 
17
- @pytest.fixture()
17
+ @pytest.fixture
18
18
  def fake_spin_data(monkeypatch, spice_test_data_path):
19
19
  """Generate fake spin dataframe for testing"""
20
20
  fake_spin_path = spice_test_data_path / "fake_spin_data.csv"
@@ -27,13 +27,51 @@ def fake_spin_data(monkeypatch, spice_test_data_path):
27
27
  [
28
28
  (
29
29
  15,
30
- [[1, 15, 0, 15.0, 1, 1, 0, 0, 15.0, 0.0]],
30
+ [
31
+ [
32
+ 1,
33
+ 15,
34
+ 0,
35
+ "2024-04-11 00:00:15.000000",
36
+ 15.0,
37
+ True,
38
+ 1,
39
+ 0,
40
+ False,
41
+ 15.0,
42
+ 0.0,
43
+ ]
44
+ ],
31
45
  ), # Scalar test at spin start time
32
46
  (
33
47
  np.array([15.1, 30.2]),
34
48
  [
35
- [1, 15, 0, 15.0, 1, 1, 0, 0, 15.0, 0.1 / 15],
36
- [2, 30, 0, 15.0, 1, 1, 0, 0, 30.0, 0.2 / 15],
49
+ [
50
+ 1,
51
+ 15,
52
+ 0,
53
+ "2024-04-11 00:00:15.000000",
54
+ 15.0,
55
+ True,
56
+ 1,
57
+ 0,
58
+ False,
59
+ 15.0,
60
+ 0.1 / 15,
61
+ ],
62
+ [
63
+ 2,
64
+ 30,
65
+ 0,
66
+ "2024-04-11 00:00:30.000000",
67
+ 15.0,
68
+ True,
69
+ 1,
70
+ 0,
71
+ False,
72
+ 30.0,
73
+ 0.2 / 15,
74
+ ],
37
75
  ],
38
76
  ), # Array test
39
77
  ],
@@ -45,7 +83,9 @@ def test_interpolate_spin_data(query_met_times, expected, fake_spin_data):
45
83
 
46
84
  # Test the value
47
85
  for i_row, row in enumerate(expected):
48
- np.testing.assert_array_almost_equal(spin_df.iloc[i_row].tolist(), row)
86
+ pd.testing.assert_series_equal(
87
+ spin_df.iloc[i_row], pd.Series(row), check_index=False, check_names=False
88
+ )
49
89
 
50
90
 
51
91
  @pytest.mark.parametrize(
@@ -144,21 +184,22 @@ def test_get_spin_data(use_fake_spin_data_for_time):
144
184
 
145
185
  assert set(spin_data.columns) == {
146
186
  "spin_number",
147
- "spin_start_sec",
148
- "spin_start_subsec",
187
+ "spin_start_sec_sclk",
188
+ "spin_start_subsec_sclk",
189
+ "spin_start_utc",
149
190
  "spin_period_sec",
150
191
  "spin_period_valid",
151
192
  "spin_phase_valid",
152
193
  "spin_period_source",
153
194
  "thruster_firing",
154
- "spin_start_time",
195
+ "spin_start_met",
155
196
  }, "Spin data must have the specified fields."
156
197
 
157
198
 
158
199
  @pytest.mark.parametrize(
159
200
  "instrument",
160
201
  [
161
- SpiceFrame.IMAP_LO,
202
+ SpiceFrame.IMAP_LO_BASE,
162
203
  SpiceFrame.IMAP_HI_45,
163
204
  SpiceFrame.IMAP_HI_90,
164
205
  SpiceFrame.IMAP_ULTRA_45,
@@ -7,6 +7,7 @@ import spiceypy
7
7
  from imap_processing.spice import IMAP_SC_ID
8
8
  from imap_processing.spice.time import (
9
9
  TICK_DURATION,
10
+ epoch_to_doy,
10
11
  et_to_utc,
11
12
  met_to_datetime64,
12
13
  met_to_sclkticks,
@@ -202,3 +203,16 @@ def test_et_to_utc(furnish_time_kernels):
202
203
  )
203
204
  actual_utc_array = et_to_utc(array_of_et)
204
205
  assert np.array_equal(expected_utc_array, actual_utc_array)
206
+
207
+
208
+ def test_epoch_to_doy():
209
+ """Tests that epoch_to_doy() produces expected doys."""
210
+ epoch = 756196488384840064
211
+ et = epoch * 1e-9
212
+ # Extract DOY from output date string
213
+ expected_doy = int(et_to_utc(et, "D").split("//")[0].split("-")[1])
214
+ example_epoch = np.full(10, epoch)
215
+ doy = epoch_to_doy(example_epoch)
216
+
217
+ # Assert that every calculated DOY is equal to the DOY extracted from the string.
218
+ assert np.all(doy == expected_doy)