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
@@ -17,7 +17,7 @@ from imap_processing.tests.mag.conftest import (
17
17
  )
18
18
 
19
19
 
20
- def test_mag_processing(mag_test_calibration_data):
20
+ def test_mag_processing(mag_test_l1b_calibration_data):
21
21
  # All specific test values come from MAG team to accommodate various cases.
22
22
  # Each vector is multiplied by the matrix in the calibration data for the given
23
23
  # range to get the calibrated vector.
@@ -31,7 +31,7 @@ def test_mag_processing(mag_test_calibration_data):
31
31
  mag_attributes.add_instrument_variable_attrs("mag", "l1b")
32
32
  mag_l1b = mag_l1b_processing(
33
33
  mag_l1a_dataset,
34
- mag_test_calibration_data,
34
+ mag_test_l1b_calibration_data,
35
35
  mag_attributes,
36
36
  "imap_mag_l1b_norm-mago",
37
37
  )
@@ -50,7 +50,7 @@ def test_mag_processing(mag_test_calibration_data):
50
50
 
51
51
  mag_l1b = mag_l1b_processing(
52
52
  mag_l1a_dataset,
53
- mag_test_calibration_data,
53
+ mag_test_l1b_calibration_data,
54
54
  mag_attributes,
55
55
  "imap_mag_l1b_norm-magi",
56
56
  )
@@ -67,12 +67,12 @@ def test_mag_attributes():
67
67
 
68
68
  mag_l1a_dataset.attrs["Logical_source"] = ["imap_mag_l1a_norm-mago"]
69
69
 
70
- output = mag_l1b(mag_l1a_dataset, "v001")
70
+ output = mag_l1b(mag_l1a_dataset)
71
71
  assert output.attrs["Logical_source"] == "imap_mag_l1b_norm-mago"
72
72
 
73
73
  mag_l1a_dataset.attrs["Logical_source"] = ["imap_mag_l1a_burst-magi"]
74
74
 
75
- output = mag_l1b(mag_l1a_dataset, "v001")
75
+ output = mag_l1b(mag_l1a_dataset)
76
76
  assert output.attrs["Logical_source"] == "imap_mag_l1b_burst-magi"
77
77
 
78
78
 
@@ -82,7 +82,7 @@ def test_cdf_output():
82
82
  / "validation"
83
83
  / "imap_mag_l1a_norm-magi_20251017_v001.cdf"
84
84
  )
85
- l1b_dataset = mag_l1b(l1a_cdf, "v001")
85
+ l1b_dataset = mag_l1b(l1a_cdf)
86
86
 
87
87
  output_path = write_cdf(l1b_dataset)
88
88
 
@@ -110,7 +110,7 @@ def test_mag_compression_scale():
110
110
  mag_l1a_dataset["compression_flags"][3, :] = np.array([1, 14], dtype=np.int8)
111
111
 
112
112
  mag_l1a_dataset.attrs["Logical_source"] = ["imap_mag_l1a_norm-mago"]
113
- output = mag_l1b(mag_l1a_dataset, "v001")
113
+ output = mag_l1b(mag_l1a_dataset)
114
114
 
115
115
  calibrated_vectors = np.matmul(test_calibration, np.array([1, 1, 1]))
116
116
  # 16 bit width is the standard
@@ -187,9 +187,9 @@ def test_calibrate_vector():
187
187
  def test_l1a_to_l1b(validation_l1a):
188
188
  # Convert l1a input validation packet file to l1b
189
189
  with pytest.raises(ValueError, match="Raw L1A"):
190
- mag_l1b(validation_l1a[0], "v000")
190
+ mag_l1b(validation_l1a[0])
191
191
 
192
- l1b = [mag_l1b(i, "v000") for i in validation_l1a[1:]]
192
+ l1b = [mag_l1b(i) for i in validation_l1a[1:]]
193
193
 
194
194
  assert len(l1b) == len(validation_l1a) - 1
195
195
 
@@ -1,11 +1,14 @@
1
- from pathlib import Path
2
-
3
1
  import numpy as np
4
2
  import pytest
5
3
  import xarray as xr
6
- import yaml
7
4
 
8
- from imap_processing.mag.l1c.interpolation_methods import InterpolationFunction
5
+ from imap_processing.mag import imap_mag_sdc_configuration_v001 as configuration
6
+ from imap_processing.mag.constants import VecSec
7
+ from imap_processing.mag.l1c.interpolation_methods import (
8
+ InterpolationFunction,
9
+ cic_filter,
10
+ estimate_rate,
11
+ )
9
12
  from imap_processing.mag.l1c.mag_l1c import (
10
13
  fill_normal_data,
11
14
  find_all_gaps,
@@ -14,6 +17,7 @@ from imap_processing.mag.l1c.mag_l1c import (
14
17
  interpolate_gaps,
15
18
  mag_l1c,
16
19
  process_mag_l1c,
20
+ vectors_per_second_from_string,
17
21
  )
18
22
  from imap_processing.tests.mag.conftest import (
19
23
  generate_test_epoch,
@@ -35,10 +39,19 @@ def mag_l1b_dataset():
35
39
  return output_dataset
36
40
 
37
41
 
38
- @pytest.fixture()
42
+ @pytest.fixture
39
43
  def norm_dataset():
40
44
  dataset = mag_l1a_dataset_generator(10)
41
- epoch_vals = generate_test_epoch(6, [2, 4, 4], 0, [[2, 4], [4.25, 5.5]])
45
+ epoch_vals = generate_test_epoch(
46
+ 6,
47
+ [
48
+ VecSec.TWO_VECS_PER_S,
49
+ VecSec.FOUR_VECS_PER_S,
50
+ VecSec.FOUR_VECS_PER_S,
51
+ ],
52
+ 0,
53
+ [[2, 4], [4.25, 5.5]],
54
+ )
42
55
  vectors_per_second_attr = "0:2,4000000000:4"
43
56
  dataset.attrs["vectors_per_second"] = vectors_per_second_attr
44
57
  dataset["epoch"] = epoch_vals
@@ -49,34 +62,49 @@ def norm_dataset():
49
62
  return dataset
50
63
 
51
64
 
52
- @pytest.fixture()
65
+ @pytest.fixture
53
66
  def burst_dataset():
54
- dataset = mag_l1a_dataset_generator(17)
55
- epoch_vals = generate_test_epoch(5.1, [5], 1.9)
67
+ dataset = mag_l1a_dataset_generator(27)
68
+ epoch_vals = generate_test_epoch(5.1, [VecSec.EIGHT_VECS_PER_S], 1.9)
56
69
  dataset["epoch"] = epoch_vals
57
70
  dataset.attrs["Logical_source"] = ["imap_mag_l1b_burst-mago"]
58
- vectors = np.array([[i, i, i, 2] for i in range(1, 18)])
71
+ vectors = np.array([[i, i, i, 2] for i in range(1, 28)])
59
72
  dataset["vectors"].data = vectors
73
+
74
+ vectors_per_second_attr = "0:8"
75
+ dataset.attrs["vectors_per_second"] = vectors_per_second_attr
76
+
60
77
  return dataset
61
78
 
62
79
 
63
80
  def test_configuration_file():
64
- with open(
65
- Path(__file__).parent.parent.parent
66
- / "mag"
67
- / "imap_mag_sdc-configuration_v001.yaml"
68
- ) as f:
69
- configuration = yaml.safe_load(f)
70
-
71
- assert configuration["L1C_interpolation_method"] in [
81
+ assert configuration.L1C_INTERPOLATION_METHOD in [
72
82
  e.name for e in InterpolationFunction
73
83
  ]
74
84
 
75
- # should not raise an error
76
- configuration_file = InterpolationFunction[
77
- configuration["L1C_interpolation_method"]
78
- ]
79
- configuration_file([1], [1], [1])
85
+
86
+ def test_interpolation_methods():
87
+ # very basic test of all methods
88
+ vectors = np.random.rand(200, 4)
89
+ input_timestamps = np.arange(0, 50, step=0.25) * 1e9
90
+ output_timestamps = np.arange(10, 20, step=0.5) * 1e9
91
+ for method in InterpolationFunction:
92
+ output = method(
93
+ vectors,
94
+ input_timestamps,
95
+ output_timestamps,
96
+ input_rate=VecSec.FOUR_VECS_PER_S,
97
+ output_rate=VecSec.TWO_VECS_PER_S,
98
+ )
99
+ assert len(output) == 20
100
+ output = method(
101
+ vectors,
102
+ input_timestamps,
103
+ output_timestamps,
104
+ input_rate=None,
105
+ output_rate=None,
106
+ )
107
+ assert len(output) == 20
80
108
 
81
109
 
82
110
  def test_process_mag_l1c(norm_dataset, burst_dataset):
@@ -86,15 +114,18 @@ def test_process_mag_l1c(norm_dataset, burst_dataset):
86
114
  * 1e9
87
115
  )
88
116
  assert np.array_equal(l1c[:, 0], expected_output_timeline)
89
- # Every new timestamp should have data
117
+ # Last new timestamp is missing data because burst mode only goes to 5.15
118
+ # Don't generate data if there's no burst data to interpolate
90
119
  assert (
91
120
  np.count_nonzero([np.sum(l1c[i, 1:4]) for i in range(l1c.shape[0])])
92
- == l1c.shape[0]
121
+ == l1c.shape[0] - 1
93
122
  )
94
123
  expected_flags = np.zeros(15)
95
124
  # filled sections should have 1 as a flag
96
125
  expected_flags[5:8] = 1
97
- expected_flags[10:12] = 1
126
+ expected_flags[10:11] = 1
127
+ # last datapoint in the gap is missing a value
128
+ expected_flags[11] = -1
98
129
  assert np.array_equal(l1c[:, 5], expected_flags)
99
130
  assert np.array_equal(l1c[:5, 1:5], norm_dataset["vectors"].data[:5, :])
100
131
  for i in range(5, 8):
@@ -107,7 +138,7 @@ def test_process_mag_l1c(norm_dataset, burst_dataset):
107
138
  assert np.allclose(l1c[i, 1:5], burst_vectors, rtol=0, atol=1)
108
139
 
109
140
  assert np.array_equal(l1c[8:10, 1:5], norm_dataset["vectors"].data[5:7, :])
110
- for i in range(10, 12):
141
+ for i in range(10, 11):
111
142
  e = l1c[i, 0]
112
143
  burst_vectors = burst_dataset.sel(epoch=int(e), method="nearest")[
113
144
  "vectors"
@@ -116,13 +147,15 @@ def test_process_mag_l1c(norm_dataset, burst_dataset):
116
147
  # identical.
117
148
  assert np.allclose(l1c[i, 1:5], burst_vectors, rtol=0, atol=1)
118
149
 
150
+ assert np.array_equal(l1c[11, 1:5], [0, 0, 0, 0])
151
+
119
152
 
120
153
  def test_interpolate_gaps(norm_dataset, mag_l1b_dataset):
121
154
  # np.array([0, 0.5, 1, 1.5, 2, 4, 4.25, 5.5, 5.75, 6]) * 1e9
122
- gaps = np.array([[2, 4], [4.25, 5.5]]) * 1e9
155
+ gaps = np.array([[2 * 1e9, 4 * 1e9, 2], [4.25 * 1e9, 5.5 * 1e9, 2]])
123
156
  generated_timeline = generate_timeline(norm_dataset["epoch"].data, gaps)
124
157
  norm_timeline = fill_normal_data(norm_dataset, generated_timeline)
125
- gaps = np.array([[2, 4]]) * 1e9
158
+ gaps = np.array([[2 * 1e9, 4 * 1e9, 2]])
126
159
  output = interpolate_gaps(
127
160
  mag_l1b_dataset, gaps, norm_timeline, InterpolationFunction.linear
128
161
  )
@@ -169,7 +202,7 @@ def test_interpolate_gaps(norm_dataset, mag_l1b_dataset):
169
202
 
170
203
 
171
204
  def test_mag_l1c(norm_dataset, burst_dataset):
172
- l1c = mag_l1c(burst_dataset, norm_dataset, "v001")
205
+ l1c = mag_l1c(burst_dataset, norm_dataset)
173
206
  assert l1c["vector_magnitude"].shape == (len(l1c["epoch"].data),)
174
207
  assert l1c["vector_magnitude"].data[0] == np.linalg.norm(l1c["vectors"].data[0][:4])
175
208
  assert l1c["vector_magnitude"].data[-1] == np.linalg.norm(
@@ -188,7 +221,7 @@ def test_mag_l1c(norm_dataset, burst_dataset):
188
221
 
189
222
 
190
223
  def test_mag_attributes(norm_dataset, burst_dataset):
191
- output = mag_l1c(norm_dataset, burst_dataset, "v001")
224
+ output = mag_l1c(norm_dataset, burst_dataset)
192
225
  assert output.attrs["Logical_source"] == "imap_mag_l1c_norm-mago"
193
226
 
194
227
  expected_attrs = ["missing_sequences", "interpolation_method"]
@@ -196,58 +229,91 @@ def test_mag_attributes(norm_dataset, burst_dataset):
196
229
  assert attr in output.attrs
197
230
 
198
231
 
232
+ def test_missing_burst_file(norm_dataset, burst_dataset):
233
+ # Should run with only normal mode data or only burst mode data.
234
+ output = mag_l1c(norm_dataset, None)
235
+ assert output.attrs["Logical_source"] == "imap_mag_l1c_norm-mago"
236
+
237
+ # Should pass through normal mode data only
238
+ assert np.array_equal(output["vectors"].data, norm_dataset["vectors"].data)
239
+ assert np.array_equal(output["epoch"].data, norm_dataset["epoch"].data)
240
+
241
+
242
+ @pytest.mark.xfail(reason="Burst mode only not implemented yet")
243
+ def test_missing_norm_file(norm_dataset, burst_dataset):
244
+ # Should run with only normal mode data or only burst mode data.
245
+ burst_dataset.attrs["Logical_source"] = "imap_mag_l1b_burst-magi"
246
+ output = mag_l1c(burst_dataset, None)
247
+
248
+ assert output.attrs["Logical_source"] == "imap_mag_l1c_norm-magi"
249
+ # TODO: test that the output is downsampled
250
+ # TODO: How to test against previous day's file?
251
+
252
+
199
253
  def test_find_all_gaps():
200
- epoch_test = generate_test_epoch(5.5, [2, 2], 0, [[2, 5]])
254
+ epoch_test = generate_test_epoch(
255
+ 5.5, [VecSec.TWO_VECS_PER_S, VecSec.TWO_VECS_PER_S], 0, [[2, 5]]
256
+ )
201
257
 
202
- vectors_per_second_attr = "0:2"
203
- output = find_all_gaps(epoch_test, vectors_per_second_attr)
204
- expected_gaps = np.array([[2, 5]]) * 1e9
258
+ vectors_per_second = vectors_per_second_from_string("0:2")
259
+
260
+ output = find_all_gaps(epoch_test, vectors_per_second)
261
+ expected_gaps = np.array([[2 * 1e9, 5 * 1e9, 2]])
205
262
  assert np.array_equal(output, expected_gaps)
206
263
 
207
264
  epoch_test = np.array([0, 0.5, 1, 1.5, 2, 4, 4.25, 4.5, 4.75, 5.5]) * 1e9
208
- vectors_per_second_attr = "0:2,4000000000:4"
209
- expected_gaps = np.array([[2, 4], [4.75, 5.5]]) * 1e9
265
+ vectors_per_second_attr = vectors_per_second_from_string("0:2,4000000000:4")
266
+ expected_gaps = np.array([[2 * 1e9, 4 * 1e9, 2], [4.75 * 1e9, 5.5 * 1e9, 4]])
210
267
  output = find_all_gaps(epoch_test, vectors_per_second_attr)
211
268
  assert np.array_equal(output, expected_gaps)
212
269
 
213
270
 
214
271
  def test_find_gaps():
215
272
  # Test should be in ns
216
- epoch_test = generate_test_epoch(3.5, [2], 0, [[0.5, 2], [2, 3.5]])
217
- print(epoch_test)
273
+ epoch_test = generate_test_epoch(
274
+ 3.5, [VecSec.TWO_VECS_PER_S], 0, [[0.5, 2], [2, 3.5]]
275
+ )
218
276
  gaps = find_gaps(epoch_test, 2)
219
- expected_return = np.array([[0.5, 2], [2, 3.5]]) * 1e9
277
+ expected_return = np.array([[0.5 * 1e9, 2 * 1e9, 2], [2 * 1e9, 3.5 * 1e9, 2]])
220
278
 
221
279
  assert np.array_equal(gaps, expected_return)
222
280
 
223
- epoch_test = generate_test_epoch(5, [2], gaps=[[0.5, 2], [3, 4]])
281
+ epoch_test = generate_test_epoch(
282
+ 5, [VecSec.TWO_VECS_PER_S], gaps=[[0.5, 2], [3, 4]]
283
+ )
224
284
  gaps = find_gaps(epoch_test, 2)
225
- expected_return = np.array([[0.5, 2], [3, 4]]) * 1e9
285
+ expected_return = np.array([[0.5 * 1e9, 2 * 1e9, 2], [3 * 1e9, 4 * 1e9, 2]])
226
286
 
227
287
  assert np.array_equal(gaps, expected_return)
228
288
 
229
- epoch_test = generate_test_epoch(3, [4], gaps=[[0.5, 1], [2, 3]])
289
+ epoch_test = generate_test_epoch(
290
+ 3, [VecSec.FOUR_VECS_PER_S], gaps=[[0.5, 1], [2, 3]]
291
+ )
230
292
  gaps = find_gaps(epoch_test, 4)
231
- expected_return = np.array([[0.5, 1], [2, 3]]) * 1e9
293
+ expected_return = np.array([[0.5 * 1e9, 1 * 1e9, 4], [2 * 1e9, 3 * 1e9, 4]])
232
294
 
233
295
  assert np.array_equal(gaps, expected_return)
234
296
 
235
297
 
236
298
  def test_generate_timeline():
237
- epoch_test = generate_test_epoch(3, [4], gaps=[[0.5, 1], [2, 3]])
299
+ epoch_test = generate_test_epoch(
300
+ 3, [VecSec.FOUR_VECS_PER_S], gaps=[[0.5, 1], [2, 3]]
301
+ )
238
302
 
239
303
  gaps = np.array([[0.5, 1], [2, 3]]) * 1e9
240
304
  expected_output = np.array([0, 0.25, 0.5, 1, 1.25, 1.5, 1.75, 2, 2.5, 3]) * 1e9
241
305
  output = generate_timeline(epoch_test, gaps)
242
306
  assert np.array_equal(output, expected_output)
243
307
 
244
- epoch_test = generate_test_epoch(5, [2], starting_point=1)
308
+ epoch_test = generate_test_epoch(5, [VecSec.TWO_VECS_PER_S], starting_point=1)
245
309
  # Expected output from find_gaps if none are found
246
310
  gaps = np.zeros((0, 2))
247
311
  output = generate_timeline(epoch_test, gaps)
248
312
  assert np.array_equal(output, epoch_test)
249
313
 
250
- epoch_test = generate_test_epoch(5, [2], starting_point=1, gaps=[[3, 5]])
314
+ epoch_test = generate_test_epoch(
315
+ 5, [VecSec.TWO_VECS_PER_S], starting_point=1, gaps=[[3, 5]]
316
+ )
251
317
  gaps = np.array([[3, 5]]) * 1e9
252
318
 
253
319
  expected_output = np.array([1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5]) * 1e9
@@ -269,3 +335,41 @@ def test_fill_normal_data(mag_l1b_dataset):
269
335
  assert np.array_equal(output[0, 1:5], mag_l1b_dataset["vectors"].data[0, :])
270
336
  assert np.array_equal(output[5, 1:5], mag_l1b_dataset["vectors"].data[5, :])
271
337
  assert np.array_equal(output[9, 1:5], mag_l1b_dataset["vectors"].data[9, :])
338
+
339
+
340
+ def test_cic_filter():
341
+ input_vectors = np.array(
342
+ [
343
+ [1, 1, 1],
344
+ [2, 2, 2],
345
+ [3, 3, 3],
346
+ [4, 4, 4],
347
+ [5, 5, 5],
348
+ [6, 6, 6],
349
+ [7, 7, 7],
350
+ [8, 8, 8],
351
+ ]
352
+ )
353
+ input_timestamps = generate_test_epoch(2, [VecSec.FOUR_VECS_PER_S], 0)
354
+ output_timestamps = generate_test_epoch(2, [VecSec.TWO_VECS_PER_S], 0)
355
+
356
+ output = cic_filter(
357
+ input_vectors,
358
+ input_timestamps,
359
+ output_timestamps,
360
+ VecSec.FOUR_VECS_PER_S,
361
+ VecSec.TWO_VECS_PER_S,
362
+ )
363
+ assert len(output) != 0
364
+ # TODO: How to test this?
365
+
366
+
367
+ def test_estimate_rate():
368
+ input_timestamps = generate_test_epoch(2, [VecSec.FOUR_VECS_PER_S], 0)
369
+ output_timestamps = generate_test_epoch(2, [VecSec.TWO_VECS_PER_S], 0)
370
+
371
+ input = estimate_rate(input_timestamps)
372
+ assert input == VecSec.FOUR_VECS_PER_S
373
+
374
+ output = estimate_rate(output_timestamps)
375
+ assert output == VecSec.TWO_VECS_PER_S
@@ -0,0 +1,130 @@
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from imap_processing.mag.l2.mag_l2 import mag_l2
5
+ from imap_processing.mag.l2.mag_l2_data import MagL2
6
+ from imap_processing.tests.mag.conftest import mag_l1a_dataset_generator
7
+
8
+
9
+ @pytest.fixture
10
+ def norm_dataset(mag_test_l2_data):
11
+ offsets = mag_test_l2_data[1]
12
+ dataset = mag_l1a_dataset_generator(3504)
13
+ epoch_vals = offsets["epoch"].data
14
+ vectors_per_second_attr = "0:2,4000000000:4"
15
+ dataset.attrs["vectors_per_second"] = vectors_per_second_attr
16
+ dataset["epoch"] = epoch_vals
17
+ dataset.attrs["Logical_source"] = "imap_mag_l1c_norm-mago"
18
+ vectors = np.array([[i, i, i, 2] for i in range(1, 3505)])
19
+ dataset["vectors"].data = vectors
20
+
21
+ return dataset
22
+
23
+
24
+ def test_mag_l2(norm_dataset, mag_test_l2_data):
25
+ calibration_dataset = mag_test_l2_data[0]
26
+
27
+ offset_dataset = mag_test_l2_data[1]
28
+ l2 = mag_l2(calibration_dataset, offset_dataset, norm_dataset)
29
+ assert "vectors" in l2[0].data_vars
30
+
31
+
32
+ def test_failure_on_mismatch_files():
33
+ # input_offsets =
34
+ pass
35
+
36
+
37
+ def test_offset_application(norm_dataset, mag_test_l2_data):
38
+ # Test against zeros
39
+ offsets = mag_test_l2_data[1]
40
+ output = MagL2(
41
+ norm_dataset["vectors"].data[:, :3],
42
+ norm_dataset["epoch"].data,
43
+ norm_dataset["vectors"].data[:, 3],
44
+ {},
45
+ None,
46
+ None,
47
+ None,
48
+ offsets=offsets["offsets"].data,
49
+ timedelta=offsets["timedeltas"].data,
50
+ )
51
+
52
+ expected_vectors = norm_dataset["vectors"].data[:, :3]
53
+ assert np.allclose(output.vectors, expected_vectors, atol=1e-9)
54
+ assert np.allclose(output.epoch, norm_dataset["epoch"], atol=1e-9)
55
+
56
+ new_offsets = np.zeros((len(norm_dataset["epoch"]), 3))
57
+ new_offsets[0] = [1, 1, 1]
58
+ new_offsets[1] = [-1, -1, -1]
59
+ new_offsets[-1] = [1, 0, -1]
60
+
61
+ new_timeshift = np.zeros(len(norm_dataset["epoch"]))
62
+ new_timeshift[0] = 0.00001
63
+ new_timeshift[1] = -0.00001
64
+ new_timeshift[2] = 1e-9
65
+
66
+ expected_timeshift = norm_dataset["epoch"].data
67
+ # Timeshift is provided in seconds, epoch is in nanoseconds
68
+ expected_timeshift[0] = expected_timeshift[0] + 10000
69
+ expected_timeshift[1] = expected_timeshift[1] - 10000
70
+ expected_timeshift[2] = expected_timeshift[2] + 1
71
+
72
+ output = MagL2(
73
+ norm_dataset["vectors"].data[:, :3],
74
+ norm_dataset["epoch"].data,
75
+ norm_dataset["vectors"].data[:, 3],
76
+ {},
77
+ None,
78
+ None,
79
+ None,
80
+ offsets=new_offsets,
81
+ timedelta=new_timeshift,
82
+ )
83
+
84
+ expected_vectors = norm_dataset["vectors"].data[:, :3]
85
+ expected_vectors[0] = [2, 2, 2]
86
+ expected_vectors[1] = [1, 1, 1]
87
+ expected_vectors[-1] = [3505, 3504, 3503]
88
+
89
+ assert np.allclose(output.vectors, expected_vectors, atol=1e-9)
90
+ assert np.allclose(output.epoch, expected_timeshift, atol=1e-9)
91
+
92
+
93
+ def test_error_raises(mag_test_l2_data):
94
+ dataset = mag_l1a_dataset_generator(3504)
95
+ with pytest.raises(ValueError, match="same timestamps"):
96
+ mag_l2(mag_test_l2_data[0], mag_test_l2_data[1], dataset)
97
+
98
+ dataset = mag_l1a_dataset_generator(3505)
99
+ with pytest.raises(ValueError, match="same timestamps"):
100
+ mag_l2(mag_test_l2_data[0], mag_test_l2_data[1], dataset)
101
+
102
+
103
+ def test_full_calculation(norm_dataset, mag_test_l2_data):
104
+ # test matrix + offsets calculation
105
+ pass
106
+
107
+
108
+ def test_timestamp_truncation():
109
+ # Test that data is truncated to exactly 24 hours
110
+ pass
111
+
112
+
113
+ def test_fail_on_missing_offsets():
114
+ # Processing should fail if vectors do not have corresponding timestamps
115
+ pass
116
+
117
+
118
+ def test_magnitude():
119
+ # Test magnitude calculation
120
+ pass
121
+
122
+
123
+ def test_expected_output_norm():
124
+ # should return 4 files with correct attributes
125
+ pass
126
+
127
+
128
+ def test_expected_output_burst():
129
+ # should return 4 files with correct attributes
130
+ pass