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
@@ -1,4 +1,5 @@
1
1
  from collections import namedtuple
2
+ from unittest.mock import patch
2
3
 
3
4
  import numpy as np
4
5
  import pytest
@@ -8,17 +9,29 @@ from imap_processing import imap_module_directory
8
9
  from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
9
10
  from imap_processing.cdf.utils import load_cdf
10
11
  from imap_processing.lo.l1b.lo_l1b import (
12
+ calculate_tof1_for_golden_triples,
11
13
  convert_start_end_acq_times,
14
+ convert_tofs_to_eu,
12
15
  create_datasets,
13
16
  get_avg_spin_durations,
14
17
  get_spin_angle,
18
+ get_spin_start_times,
19
+ identify_species,
15
20
  initialize_l1b_de,
16
21
  lo_l1b,
22
+ set_bad_times,
23
+ set_coincidence_type,
24
+ set_each_event_epoch,
25
+ set_event_met,
26
+ set_pointing_bin,
27
+ set_pointing_direction,
17
28
  set_spin_bin,
29
+ set_spin_cycle,
18
30
  )
31
+ from imap_processing.spice.time import met_to_ttj2000ns
19
32
 
20
33
 
21
- @pytest.fixture()
34
+ @pytest.fixture
22
35
  def dependencies():
23
36
  return {
24
37
  "imap_lo_l1a_de": load_cdf(
@@ -32,16 +45,24 @@ def dependencies():
32
45
  }
33
46
 
34
47
 
35
- @pytest.fixture()
48
+ @pytest.fixture
36
49
  def attr_mgr_l1b():
37
50
  attr_mgr_l1b = ImapCdfAttributes()
38
51
  attr_mgr_l1b.add_instrument_global_attrs(instrument="lo")
39
52
  attr_mgr_l1b.add_instrument_variable_attrs(instrument="lo", level="l1b")
40
- attr_mgr_l1b.add_global_attribute("Data_version", "000")
41
53
  return attr_mgr_l1b
42
54
 
43
55
 
44
- def test_lo_l1b():
56
+ @pytest.fixture
57
+ def attr_mgr_l1a():
58
+ attr_mgr = ImapCdfAttributes()
59
+ attr_mgr.add_instrument_global_attrs(instrument="lo")
60
+ attr_mgr.add_instrument_variable_attrs(instrument="lo", level="l1a")
61
+ return attr_mgr
62
+
63
+
64
+ @patch("imap_processing.lo.l1b.lo_l1b.instrument_pointing")
65
+ def test_lo_l1b(mock_instrument_pointing):
45
66
  # Arrange
46
67
  de_file = (
47
68
  imap_module_directory / "tests/lo/test_cdfs/imap_lo_l1a_de_20241022_v002.cdf"
@@ -55,13 +76,16 @@ def test_lo_l1b():
55
76
  data[dataset.attrs["Logical_source"]] = dataset
56
77
 
57
78
  expected_logical_source = "imap_lo_l1b_de"
79
+ mock_instrument_pointing.return_value = np.zeros((2000, 2))
58
80
  # Act
59
- output_file = lo_l1b(data, "001")
81
+ output_file = lo_l1b(data)
60
82
 
61
83
  # Assert
62
84
  assert expected_logical_source == output_file[0].attrs["Logical_source"]
63
85
 
64
86
 
87
+ # @pytest.mark.external_kernel
88
+ # @pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
65
89
  def test_create_datasets():
66
90
  attr_mgr = ImapCdfAttributes()
67
91
  attr_mgr.add_instrument_global_attrs(instrument="lo")
@@ -201,7 +225,6 @@ def test_get_spin_angle():
201
225
  spin_angle,
202
226
  spin_angle_expected,
203
227
  atol=1e-2,
204
- err_msg=f"Spin angle: {spin_angle} vs {spin_angle_expected}",
205
228
  )
206
229
 
207
230
 
@@ -216,3 +239,345 @@ def test_spin_bin():
216
239
 
217
240
  # Assert
218
241
  np.testing.assert_array_equal(l1b_de["spin_bin"], expected_spin_bins)
242
+
243
+
244
+ def test_spin_cycle():
245
+ # Arrange
246
+ de = xr.Dataset(
247
+ {
248
+ "de_count": ("epoch", [2, 3]),
249
+ "esa_step": ("direct_event", [1, 2, 3, 4, 5]),
250
+ },
251
+ coords={"epoch": [0, 1], "direct_event": [1, 2, 3, 4, 5]},
252
+ )
253
+
254
+ # spin_cycle = spin_start + 7 + (esa_step - 1) * 2
255
+ # where spin start is the spin number for the first spin
256
+ # in an Aggregated Science Cycle (first spin number of an epoch)
257
+ # and esa_step is the esa_step for a direct event
258
+ spin_cycle_expected = np.array([7, 9, 39, 41, 43])
259
+ spin_cycle_data = xr.Dataset()
260
+
261
+ # Act
262
+ spin_cycle_data = set_spin_cycle(de, spin_cycle_data)
263
+
264
+ # Assert
265
+ np.testing.assert_array_equal(spin_cycle_data["spin_cycle"], spin_cycle_expected)
266
+
267
+
268
+ def test_get_spin_start_times():
269
+ # Arrange
270
+ l1b_de = xr.Dataset(
271
+ {
272
+ "spin_cycle": ("epoch", [0, 1, 2, 3, 4]),
273
+ },
274
+ coords={
275
+ "epoch": [
276
+ 0,
277
+ 1,
278
+ 2,
279
+ 3,
280
+ 4,
281
+ ]
282
+ },
283
+ )
284
+ l1a_de = xr.Dataset(
285
+ {
286
+ "de_count": ("epoch", [2, 3]),
287
+ "met": ("direct_event", [0, 1, 2, 3, 4]),
288
+ "de_time": ("direct_event", [0000, 1000, 2000, 3000, 4000]),
289
+ },
290
+ coords={"epoch": [0, 1], "direct_event": [0, 1, 2, 3, 4]},
291
+ )
292
+ spin = xr.Dataset(
293
+ {
294
+ "start_sec_spin": (
295
+ ["epoch", "spin"],
296
+ [[20, 25, 30, 35, 40], [45, 50, 55, 60, 65]],
297
+ ),
298
+ "start_subsec_spin": (
299
+ ["epoch", "spin"],
300
+ [[2000, 3000, 4000, 5000, 6000], [1000, 1500, 2000, 3000, 4000]],
301
+ ),
302
+ }
303
+ )
304
+
305
+ end_acq = xr.DataArray([0, 1], dims="epoch")
306
+ spin_start_times_expected = np.array([20.002, 50.0015, 55.002, 60.003, 65.004])
307
+ spin_start_times = get_spin_start_times(l1a_de, l1b_de, spin, end_acq)
308
+
309
+ np.testing.assert_allclose(
310
+ spin_start_times,
311
+ spin_start_times_expected,
312
+ atol=1e-4,
313
+ )
314
+
315
+
316
+ def test_set_event_met():
317
+ # Arrange
318
+ l1b_de = xr.Dataset()
319
+ l1a_de = xr.Dataset(
320
+ {
321
+ "de_count": ("epoch", [2, 3]),
322
+ "de_time": ("direct_event", [0000, 1000, 2000, 3000, 4000]),
323
+ },
324
+ coords={
325
+ "epoch": [0, 1],
326
+ "direct_event": [
327
+ 0,
328
+ 1,
329
+ 2,
330
+ 3,
331
+ 4,
332
+ ],
333
+ },
334
+ )
335
+ avg_spin_durations = xr.DataArray([5, 10])
336
+ spin_start_times = xr.DataArray([10, 20, 30, 40, 50])
337
+ expected_event_met = np.array([10, 21.2207, 34.8828, 47.3242, 59.7656])
338
+
339
+ # Act
340
+ l1b_de = set_event_met(l1a_de, l1b_de, spin_start_times, avg_spin_durations)
341
+
342
+ # Assert
343
+ np.testing.assert_allclose(
344
+ l1b_de["event_met"].values,
345
+ expected_event_met,
346
+ atol=1e-4,
347
+ )
348
+
349
+ def test_set_each_event_epoch():
350
+ l1b_de = xr.Dataset(
351
+ {
352
+ "event_met": ("epoch", [10, 20, 30, 40, 50]),
353
+ },
354
+ coords={
355
+ "epoch": [0, 1, 2, 3, 4],
356
+ },
357
+ )
358
+ epoch_expected = met_to_ttj2000ns(np.array([10, 20, 30, 40, 50]))
359
+
360
+ l1b_de = set_each_event_epoch(l1b_de)
361
+
362
+ np.testing.assert_allclose(
363
+ l1b_de["epoch"].values,
364
+ epoch_expected,
365
+ atol=1e-4,
366
+ )
367
+
368
+
369
+ def test_calculate_tof1_for_golden_triples():
370
+ # Arrange
371
+ l1a_de = xr.Dataset(
372
+ {
373
+ "coincidence_type": ("epoch", [0, 0, 0]),
374
+ "mode": ("epoch", [0, 0, 1]),
375
+ "tof0": ("epoch", [2, 4, 2]),
376
+ "tof1": ("epoch", [0, 0, 0]),
377
+ "tof2": ("epoch", [2, 6, 2]),
378
+ "tof3": ("epoch", [2, 8, 2]),
379
+ "cksm": ("epoch", [2, 12, 2]),
380
+ }
381
+ )
382
+
383
+ l1a_de_expected = xr.Dataset(
384
+ {
385
+ "coincidence_type": ("epoch", [0, 0, 0]),
386
+ "mode": ("epoch", [0, 0, 1]),
387
+ "tof0": ("epoch", [2, 4, 2]),
388
+ "tof1": ("epoch", [42, 36, 0]),
389
+ "tof2": ("epoch", [2, 6, 2]),
390
+ "tof3": ("epoch", [2, 8, 2]),
391
+ "cksm": ("epoch", [2, 12, 2]),
392
+ }
393
+ )
394
+
395
+ # Act
396
+ l1a_de = calculate_tof1_for_golden_triples(l1a_de)
397
+
398
+ # Assert
399
+ assert l1a_de_expected.equals(l1a_de)
400
+
401
+
402
+ def test_set_coincidence_type(attr_mgr_l1a):
403
+ # Arrange
404
+ l1b_de = xr.Dataset()
405
+ tof_fill = attr_mgr_l1a.get_variable_attributes("tof0")["FILLVAL"]
406
+ ckm_fill = attr_mgr_l1a.get_variable_attributes("cksm")["FILLVAL"]
407
+ l1a_de = xr.Dataset(
408
+ {
409
+ "de_count": ("epoch", [3]),
410
+ "coincidence_type": ("direct_events", [0, 0, 4]),
411
+ "mode": ("direct_events", [1, 0, 1]),
412
+ "tof0": ("direct_events", [5, 2, 10]),
413
+ "tof1": ("direct_events", [10, 4, tof_fill]),
414
+ "tof2": ("direct_events", [15, 6, 20]),
415
+ "tof3": ("direct_events", [20, 8, 30]),
416
+ "cksm": ("direct_events", [25, ckm_fill, ckm_fill]),
417
+ },
418
+ coords={
419
+ "epoch": [0],
420
+ "direct_events": [0, 1, 2],
421
+ },
422
+ )
423
+
424
+ coincidence_type_expected = np.array(["111111", "111100", "101101"])
425
+
426
+ # Act
427
+ l1b_de = set_coincidence_type(l1a_de, l1b_de, attr_mgr_l1a)
428
+
429
+ # Assert
430
+ np.testing.assert_array_equal(
431
+ l1b_de["coincidence_type"].values,
432
+ coincidence_type_expected,
433
+ )
434
+
435
+
436
+ def test_convert_tofs_to_eu(attr_mgr_l1b, attr_mgr_l1a):
437
+ l1b_de = xr.Dataset()
438
+ tof_fill_l1a = attr_mgr_l1a.get_variable_attributes("tof0")["FILLVAL"]
439
+ tof_fill_l1b = attr_mgr_l1b.get_variable_attributes("tof1")["FILLVAL"]
440
+ l1a_de = xr.Dataset(
441
+ {
442
+ "de_count": ("epoch", [2]),
443
+ "coincidence_type": ("direct_events", [0, 4]),
444
+ "mode": ("direct_events", [1, 0]),
445
+ "tof0": ("direct_events", [5, 2]),
446
+ "tof1": ("direct_events", [10, tof_fill_l1a]),
447
+ "tof2": ("direct_events", [15, 6]),
448
+ "tof3": ("direct_events", [20, 8]),
449
+ },
450
+ coords={
451
+ "epoch": [0],
452
+ "direct_events": [0, 1],
453
+ },
454
+ )
455
+
456
+ tof0_expected = np.array([1.394394, 0.889272])
457
+ tof1_expected = np.array([0.931059, tof_fill_l1b])
458
+ tof2_expected = np.array([2.870557, 1.372876])
459
+ tof3_expected = np.array([3.88245, 1.818162])
460
+
461
+ # Act
462
+ l1b_de = convert_tofs_to_eu(l1a_de, l1b_de, attr_mgr_l1a, attr_mgr_l1b)
463
+
464
+ tof_checks = [
465
+ ("tof0", tof0_expected),
466
+ ("tof1", tof1_expected),
467
+ ("tof2", tof2_expected),
468
+ ("tof3", tof3_expected),
469
+ ]
470
+ # Assert
471
+ for tof, expected_tof in tof_checks:
472
+ np.testing.assert_allclose(
473
+ l1b_de[tof].values,
474
+ expected_tof,
475
+ atol=1e-6,
476
+ )
477
+
478
+
479
+ def test_identify_species(attr_mgr_l1b):
480
+ # Arrange
481
+ fill_val = attr_mgr_l1b.get_variable_attributes("tof2")["FILLVAL"]
482
+ l1b_de = xr.Dataset(
483
+ {
484
+ "tof2": ("epoch", [1, 14, 50, 80, 500, fill_val]),
485
+ }
486
+ )
487
+
488
+ expected_species = np.array(["U", "H", "U", "O", "U", "U"])
489
+
490
+ # Act
491
+ l1b_de = identify_species(l1b_de)
492
+
493
+ # Assert
494
+ np.testing.assert_array_equal(l1b_de["species"], expected_species)
495
+
496
+
497
+ def test_set_bad_times():
498
+ # Arrange
499
+ l1b_de = xr.Dataset(
500
+ {},
501
+ coords={
502
+ "epoch": [0, 1, 2],
503
+ },
504
+ )
505
+
506
+ expected_bad_times = np.array([0, 0, 0])
507
+
508
+ # Act
509
+ l1b_de = set_bad_times(l1b_de)
510
+
511
+ # Assert
512
+ np.testing.assert_array_equal(l1b_de["badtimes"], expected_bad_times)
513
+
514
+
515
+ @pytest.mark.external_kernel
516
+ @pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
517
+ def test_set_direction():
518
+ # Arrange
519
+ l1b_de = xr.Dataset(
520
+ {},
521
+ coords={
522
+ "epoch": [
523
+ 7.9794907254e17,
524
+ # + 1 second. Should be 24deg diff from
525
+ # previous epoch
526
+ 7.9794907254e17 + 1e9,
527
+ # + 7.5 seconds. Should be 180deg diff from
528
+ # first epoch
529
+ 7.9794907254e17 + 7.5e9,
530
+ # + 15 seconds. Should be 360deg diff from
531
+ # previous epoch
532
+ 7.9794907254e17 + 15e9,
533
+ ],
534
+ },
535
+ )
536
+ # latitudes are -90 to 90
537
+ expected_direction_lat = np.array([0, 0, 0, 0])
538
+ # longitude are -180 to 180
539
+ expected_direction_lon = np.array([140.5, 164.5, -39.5, 140.5])
540
+
541
+ # Act
542
+ l1b_de = set_pointing_direction(l1b_de)
543
+
544
+ # Assert
545
+ np.testing.assert_allclose(
546
+ l1b_de["direction_lat"].values,
547
+ expected_direction_lat,
548
+ atol=1e-1,
549
+ )
550
+ np.testing.assert_allclose(
551
+ l1b_de["direction_lon"].values,
552
+ expected_direction_lon,
553
+ atol=1e-1,
554
+ )
555
+
556
+
557
+ def test_pointing_bins():
558
+ # Arrange
559
+ l1b_de = xr.Dataset(
560
+ {
561
+ "direction_lat": ("epoch", [0, 0, 0, 0, 0]),
562
+ "direction_lon": ("epoch", [-180, 91.3, 116.3, 140.5, 180]),
563
+ },
564
+ coords={
565
+ "epoch": [
566
+ 7.9794907049e17,
567
+ 7.9794907153e17,
568
+ 7.9794907254e17,
569
+ 7.9794907354e17,
570
+ 7.9794907454e17,
571
+ ],
572
+ },
573
+ )
574
+
575
+ expected_pointing_lats = np.array([20, 20, 20, 20, 20])
576
+ expected_pointing_lons = np.array([0, 2712, 2962, 3205, 3600])
577
+
578
+ # Act
579
+ l1b_de = set_pointing_bin(l1b_de)
580
+
581
+ # Assert
582
+ np.testing.assert_array_equal(l1b_de["pointing_bin_lat"], expected_pointing_lats)
583
+ np.testing.assert_array_equal(l1b_de["pointing_bin_lon"], expected_pointing_lons)
@@ -19,7 +19,7 @@ def test_lo_l1c():
19
19
 
20
20
  expected_logical_source = "imap_lo_l1c_pset"
21
21
  # Act
22
- output_dataset = lo_l1c(data, "001")
22
+ output_dataset = lo_l1c(data)
23
23
 
24
24
  # Assert
25
25
  assert expected_logical_source == output_dataset.attrs["Logical_source"]
@@ -17,7 +17,7 @@ from imap_processing.lo.l0.lo_science import (
17
17
  from imap_processing.utils import convert_to_binary_string, packet_file_to_datasets
18
18
 
19
19
 
20
- @pytest.fixture()
20
+ @pytest.fixture
21
21
  def fake_de_dataset():
22
22
  # binary packet fields
23
23
  count = "0000000000000010" # 2
@@ -72,7 +72,7 @@ def fake_de_dataset():
72
72
  return dataset
73
73
 
74
74
 
75
- @pytest.fixture()
75
+ @pytest.fixture
76
76
  def sample_data():
77
77
  xtce_file = imap_module_directory / "lo/packet_definitions/lo_xtce.xml"
78
78
  dependency = (
@@ -86,7 +86,7 @@ def sample_data():
86
86
  return datasets_by_apid
87
87
 
88
88
 
89
- @pytest.fixture()
89
+ @pytest.fixture
90
90
  def segmented_pkts_fake_data():
91
91
  dataset = xr.Dataset(
92
92
  data_vars=dict(
@@ -116,7 +116,7 @@ def segmented_pkts_fake_data():
116
116
  return dataset
117
117
 
118
118
 
119
- @pytest.fixture()
119
+ @pytest.fixture
120
120
  def fake_spin_data():
121
121
  dataset = xr.Dataset(
122
122
  data_vars=dict(
@@ -148,16 +148,15 @@ def fake_spin_data():
148
148
  return dataset
149
149
 
150
150
 
151
- @pytest.fixture()
151
+ @pytest.fixture
152
152
  def attr_mgr():
153
153
  attr_mgr = ImapCdfAttributes()
154
154
  attr_mgr.add_instrument_global_attrs(instrument="lo")
155
155
  attr_mgr.add_instrument_variable_attrs(instrument="lo", level="l1a")
156
- attr_mgr.add_global_attribute("Data_version", "v000")
157
156
  return attr_mgr
158
157
 
159
158
 
160
- @pytest.fixture()
159
+ @pytest.fixture
161
160
  def initialized_dataset(fake_de_dataset, attr_mgr):
162
161
  fake_de_dataset.attrs["bit_pos"] = 0
163
162
  de_fields = [
@@ -6,7 +6,7 @@ from imap_processing.ccsds.ccsds_data import CcsdsData
6
6
  from imap_processing.lo.l0.data_classes.star_sensor import StarSensor
7
7
 
8
8
 
9
- @pytest.fixture()
9
+ @pytest.fixture
10
10
  def star_sensor():
11
11
  fake_data_field = namedtuple("fake_packet", ["raw_value", "derived_value"])
12
12
  star_sensor = StarSensor.__new__(StarSensor)
@@ -7,15 +7,17 @@ import pytest
7
7
  import xarray as xr
8
8
 
9
9
  from imap_processing.cdf.utils import load_cdf
10
+ from imap_processing.mag.constants import VecSec
10
11
  from imap_processing.mag.l1a.mag_l1a import mag_l1a
12
+ from imap_processing.spice.time import TTJ2000_EPOCH
11
13
 
12
14
 
13
- @pytest.fixture()
15
+ @pytest.fixture
14
16
  def validation_l1a():
15
17
  current_directory = Path(__file__).parent
16
18
  test_file = current_directory / "validation" / "mag_l1_test_data.pkts"
17
19
  # Test file contains only normal packets
18
- l1a = mag_l1a(test_file, "v000")
20
+ l1a = mag_l1a(test_file)
19
21
  return l1a
20
22
 
21
23
 
@@ -57,27 +59,74 @@ def mag_l1a_dataset_generator(length):
57
59
  return output_dataset
58
60
 
59
61
 
60
- @pytest.fixture()
61
- def mag_test_calibration_data():
62
+ @pytest.fixture
63
+ def mag_test_l1b_calibration_data():
62
64
  imap_dir = Path(__file__).parent
63
- cal_file = imap_dir / "validation" / "imap_calibration_mag_20240229_v01.cdf"
65
+ cal_file = (
66
+ imap_dir
67
+ / "validation"
68
+ / "calibration"
69
+ / "imap_mag_l1b-calibration_20240229_v001.cdf"
70
+ )
64
71
  calibration_data = load_cdf(cal_file)
65
72
  return calibration_data
66
73
 
67
74
 
68
- def generate_test_epoch(end, vectors_per_second, starting_point=0, gaps=None):
69
- spacing = 1 / vectors_per_second[0]
75
+ @pytest.fixture
76
+ def mag_test_l2_data():
77
+ imap_dir = Path(__file__).parent
78
+ cal_file = (
79
+ imap_dir
80
+ / "validation"
81
+ / "calibration"
82
+ / "imap_mag_l2-calibration-matrices_20251017_v004.cdf"
83
+ )
84
+ calibration_data = load_cdf(cal_file)
85
+
86
+ offsets_data = load_cdf(
87
+ imap_dir
88
+ / "validation"
89
+ / "calibration"
90
+ / "imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf"
91
+ )
92
+
93
+ return calibration_data, offsets_data
94
+
95
+
96
+ def mag_generate_l1b_from_csv(df, logical_source):
97
+ length = len(df.index)
98
+ dataset = mag_l1a_dataset_generator(length)
99
+
100
+ dataset["vectors"].data = np.array(df[["x", "y", "z", "range"]])
101
+ dataset["compression_flags"].data = np.array(
102
+ df[["compression", "compression_width"]]
103
+ )
104
+
105
+ epoch = [np.datetime64(t) - np.datetime64(TTJ2000_EPOCH) for t in df["t"]]
106
+ epoch_ns = [(e / np.timedelta64(1, "ns")).astype(np.int64) for e in epoch]
107
+ dataset.coords["epoch"] = xr.DataArray(epoch_ns, name="epoch", dims=["epoch"])
108
+
109
+ dataset.attrs["Logical_source"] = logical_source
110
+ dataset.attrs["vectors_per_second"] = f"{epoch_ns[0]}:2"
111
+
112
+ return dataset
113
+
114
+
115
+ def generate_test_epoch(
116
+ end, vectors_per_second: list[VecSec], starting_point=0, gaps=None
117
+ ):
118
+ spacing = 1 / vectors_per_second[0].value
70
119
  output = np.array([])
71
120
  prev = starting_point
72
121
  if gaps:
73
122
  for index, gap in enumerate(gaps):
74
123
  if len(vectors_per_second) != 1:
75
- spacing = 1 / vectors_per_second[index]
124
+ spacing = 1 / vectors_per_second[index].value
76
125
  output = np.concatenate(
77
126
  (output, np.arange(prev, gap[0] + spacing, step=spacing) * 1e9)
78
127
  )
79
128
  prev = gap[1]
80
- spacing = 1 / vectors_per_second[-1]
129
+ spacing = 1 / vectors_per_second[-1].value
81
130
  output = np.concatenate(
82
131
  (output, np.arange(prev, end + spacing, step=spacing) * 1e9)
83
132
  )
@@ -9,11 +9,12 @@ from imap_processing.mag.constants import DataMode
9
9
  from imap_processing.mag.l0.decom_mag import decom_packets, generate_dataset
10
10
 
11
11
 
12
- @pytest.fixture()
12
+ @pytest.fixture
13
13
  def cdf_attrs():
14
14
  test_attrs = ImapCdfAttributes()
15
15
  test_attrs.add_instrument_global_attrs("mag")
16
16
  test_attrs.add_instrument_variable_attrs("mag", "l1a")
17
+ # Default v001 expected when writing to file and re-loading
17
18
  test_attrs.add_global_attribute("Data_version", "v001")
18
19
  return test_attrs
19
20
 
@@ -75,7 +76,7 @@ def test_mag_raw_xarray(cdf_attrs):
75
76
  [
76
77
  item is not None
77
78
  for key, item in norm_data.attrs.items()
78
- if key != "Logical_file_id"
79
+ if key not in ("Logical_file_id", "Data_version")
79
80
  ]
80
81
  )
81
82
 
@@ -83,7 +84,7 @@ def test_mag_raw_xarray(cdf_attrs):
83
84
  [
84
85
  item is not None
85
86
  for key, item in burst_data.attrs.items()
86
- if key != "Logical_file_id"
87
+ if key not in ("Logical_file_id", "Data_version")
87
88
  ]
88
89
  )
89
90
 
@@ -15,7 +15,7 @@ from imap_processing.mag.l1a.mag_l1a_data import (
15
15
  from imap_processing.spice.time import met_to_ttj2000ns
16
16
 
17
17
 
18
- @pytest.fixture()
18
+ @pytest.fixture
19
19
  def uncompressed_vector_bytearray():
20
20
  input_data = np.array(
21
21
  [
@@ -225,7 +225,7 @@ def uncompressed_vector_bytearray():
225
225
  return input_data
226
226
 
227
227
 
228
- @pytest.fixture()
228
+ @pytest.fixture
229
229
  def expected_vectors():
230
230
  primary_expected = np.array(
231
231
  [
@@ -272,7 +272,7 @@ def expected_vectors():
272
272
  return (primary_expected, secondary_expected)
273
273
 
274
274
 
275
- @pytest.fixture()
275
+ @pytest.fixture
276
276
  def raw_compressed_vectors():
277
277
  # compressed vectors, without the first starting uncompressed vector.
278
278
  # 15 primary vectors and 15 secondary vectors, corresponding to most of
@@ -883,7 +883,7 @@ def test_mag_l1a():
883
883
  current_directory = Path(__file__).parent
884
884
  test_file = current_directory / "validation" / "mag_l1_test_data.pkts"
885
885
 
886
- output_data = mag_l1a(test_file, "v001")
886
+ output_data = mag_l1a(test_file)
887
887
 
888
888
  # Test data is one day's worth of NORM data, so it should return one raw, one MAGO
889
889
  # and one MAGI dataset
@@ -897,9 +897,6 @@ def test_mag_l1a():
897
897
  for data_type in [data.attrs["Logical_source"] for data in output_data]:
898
898
  assert data_type in expected_logical_source
899
899
 
900
- for data in output_data:
901
- assert data.attrs["Data_version"] == "v001"
902
-
903
900
  assert "vectors" in output_data[-1].variables.keys()
904
901
  assert "compression_flags" in output_data[-1].variables.keys()
905
902
 
@@ -910,6 +907,15 @@ def test_mag_l1a():
910
907
  == output_data[-1]["compression_flags"].data.shape[0]
911
908
  )
912
909
 
910
+ assert (
911
+ str(output_data[-1]["epoch"].data[0])
912
+ in output_data[-1].attrs["vectors_per_second"]
913
+ )
914
+ assert (
915
+ str(output_data[-2]["epoch"].data[0])
916
+ in output_data[-2].attrs["vectors_per_second"]
917
+ )
918
+
913
919
 
914
920
  def test_mag_packet_properties():
915
921
  # equal to 01001011