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,24 +1,21 @@
1
1
  """Tests the L2a processing for IDEX data"""
2
2
 
3
- from unittest import mock
4
-
5
3
  import numpy as np
6
- import pytest
7
4
  import xarray as xr
8
5
  from scipy.stats import exponnorm
9
6
 
10
7
  from imap_processing.idex import idex_constants
11
- from imap_processing.idex.idex_l1b import idex_l1b
12
8
  from imap_processing.idex.idex_l2a import (
13
9
  BaselineNoiseTime,
14
10
  analyze_peaks,
15
11
  butter_lowpass_filter,
16
12
  calculate_kappa,
17
13
  calculate_snr,
14
+ chi_square,
18
15
  estimate_dust_mass,
19
16
  fit_impact,
20
- idex_l2a,
21
17
  remove_signal_noise,
18
+ sine_fit,
22
19
  time_to_mass,
23
20
  )
24
21
 
@@ -29,30 +26,14 @@ def mock_microphonics_noise(time: np.ndarray) -> np.ndarray:
29
26
  phase_shift = 45
30
27
  amp = 10
31
28
  # Create a sine wave signal
32
- sine_signal = amp * np.sin(2 * np.pi * noise_frequency * time + phase_shift)
29
+ sine_signal = sine_fit(time, amp, noise_frequency, phase_shift)
33
30
  # Combine the sine wave signals with a linear signal to create noise
34
31
  combined_sig = sine_signal + (time * 5)
35
32
 
36
33
  return combined_sig
37
34
 
38
35
 
39
- @pytest.fixture(scope="module")
40
- def l2a_dataset(decom_test_data: xr.Dataset) -> xr.Dataset:
41
- """Return a ``xarray`` dataset containing test data.
42
-
43
- Returns
44
- -------
45
- dataset : xr.Dataset
46
- A ``xarray`` dataset containing the test data
47
- """
48
- with mock.patch("imap_processing.idex.idex_l1b.get_spice_data", return_value={}):
49
- dataset = idex_l2a(
50
- idex_l1b(decom_test_data, data_version="001"), data_version="001"
51
- )
52
- return dataset
53
-
54
-
55
- def test_l2a_cdf_filenames(l2a_dataset: xr.Dataset):
36
+ def test_l2a_logical_source(l2a_dataset: xr.Dataset):
56
37
  """Tests that the ``idex_l2a`` function generates datasets
57
38
  with the expected logical source.
58
39
 
@@ -75,25 +56,31 @@ def test_l2a_cdf_variables(l2a_dataset: xr.Dataset):
75
56
  A ``xarray`` dataset containing the test data
76
57
  """
77
58
  expected_vars = [
78
- "mass",
79
59
  "target_low_fit_parameters",
80
- "target_low_fit_imapct_charge",
81
- "target_low_fit_imapct_mass_estimate",
60
+ "target_low_fit_impact_charge",
61
+ "target_low_fit_impact_mass_estimate",
82
62
  "target_low_chi_squared",
83
63
  "target_low_reduced_chi_squared",
84
64
  "target_low_fit_results",
85
65
  "target_high_fit_parameters",
86
- "target_high_fit_imapct_charge",
87
- "target_high_fit_imapct_mass_estimate",
66
+ "target_high_fit_impact_charge",
67
+ "target_high_fit_impact_mass_estimate",
88
68
  "target_high_chi_squared",
89
69
  "target_high_reduced_chi_squared",
90
70
  "target_high_fit_results",
91
71
  "ion_grid_fit_parameters",
92
- "ion_grid_fit_imapct_charge",
93
- "ion_grid_fit_imapct_mass_estimate",
72
+ "ion_grid_fit_impact_charge",
73
+ "ion_grid_fit_impact_mass_estimate",
94
74
  "ion_grid_chi_squared",
95
75
  "ion_grid_reduced_chi_squared",
96
76
  "ion_grid_fit_results",
77
+ "tof_peak_fit_parameters",
78
+ "tof_peak_area_under_fit",
79
+ "tof_peak_chi_square",
80
+ "tof_peak_reduced_chi_square",
81
+ "tof_peak_kappa",
82
+ "tof_snr",
83
+ "mass",
97
84
  ]
98
85
 
99
86
  cdf_vars = l2a_dataset.variables
@@ -235,7 +222,9 @@ def test_analyze_peaks_warning(caplog):
235
222
  tof = np.ones_like(time)
236
223
  mass_scale = np.ones_like(time)
237
224
  with caplog.at_level("WARNING"):
238
- fit_params, area_under_curve = analyze_peaks(tof, time, mass_scale, 0, peaks)
225
+ fit_params, area_under_curve, chisqr, redchi = analyze_peaks(
226
+ tof, time, mass_scale, 0, peaks
227
+ )
239
228
  assert any(
240
229
  "Failed to fit EMG curve" in message for message in caplog.text.splitlines()
241
230
  )
@@ -243,6 +232,9 @@ def test_analyze_peaks_warning(caplog):
243
232
  # The fit_params and area_under_curve arrays should be zero
244
233
  assert np.all(fit_params == 0)
245
234
  assert np.all(area_under_curve == 0)
235
+ # chi-square and reduced chi-square values should all be np.nan
236
+ np.testing.assert_array_equal(chisqr, np.nan)
237
+ np.testing.assert_array_equal(chisqr, np.nan)
246
238
 
247
239
 
248
240
  def test_analyze_peaks_perfect_fits():
@@ -269,7 +261,9 @@ def test_analyze_peaks_perfect_fits():
269
261
  gauss = exponnorm.pdf(time.data, k, mu, sigma)
270
262
  tof[peak - 5 : peak + 6] = gauss[peak - 5 : peak + 6]
271
263
 
272
- fit_params, area_under_curve = analyze_peaks(tof, time, mass_scale, event, peaks)
264
+ fit_params, area_under_curve, chisqr, redchi = analyze_peaks(
265
+ tof, time, mass_scale, event, peaks
266
+ )
273
267
 
274
268
  for peak in peaks[event]:
275
269
  mu = peak - 0.4
@@ -278,6 +272,9 @@ def test_analyze_peaks_perfect_fits():
278
272
  assert np.allclose(fit_params[mass], np.asarray([mu, sigma, lam]), rtol=1e-12)
279
273
  # Test that there is a value greater than zero at this index
280
274
  assert area_under_curve[mass] > 0
275
+ # Test the goodness of fit
276
+ assert chisqr < 1e-20
277
+ assert redchi < 1e-20
281
278
 
282
279
 
283
280
  def test_estimate_dust_mass_no_noise_removal():
@@ -381,3 +378,22 @@ def test_remove_signal_noise_no_sine_wave(caplog):
381
378
  filtered_sig = remove_signal_noise(time, signal, mask)
382
379
  # Test that the filtered signal is close to zero
383
380
  assert np.allclose(filtered_sig, np.zeros_like(filtered_sig), rtol=1e-24)
381
+
382
+
383
+ def test_chi_square():
384
+ """
385
+ Test that chi_square() function calculates the expected values for an array of given
386
+ residuals.
387
+ """
388
+ residual = 3
389
+ nparams = 2
390
+ exp = np.array([16, 18, 16, 14, 12, 12])
391
+ obs = exp + residual
392
+
393
+ expected_chi_square = np.square(residual) * len(exp)
394
+ expected_red_chi_square = expected_chi_square / (len(exp) - nparams)
395
+
396
+ chisqr, redchi = chi_square(obs, exp, nparams)
397
+
398
+ assert chisqr == expected_chi_square
399
+ assert redchi == expected_red_chi_square
@@ -0,0 +1,93 @@
1
+ """Tests the L2b processing for IDEX data"""
2
+
3
+ import numpy as np
4
+ import pytest
5
+ import xarray as xr
6
+ from numpy.testing import assert_array_equal
7
+
8
+ from imap_processing.idex.idex_l2b import idex_l2b, round_spin_phases
9
+
10
+
11
+ @pytest.fixture
12
+ def l2b_dataset(l2a_dataset: xr.Dataset) -> xr.Dataset:
13
+ """Return a ``xarray`` dataset containing test data.
14
+
15
+ Returns
16
+ -------
17
+ dataset : xr.Dataset
18
+ A ``xarray`` dataset containing the test data
19
+ """
20
+ dataset = idex_l2b(l2a_dataset)
21
+ return dataset
22
+
23
+
24
+ def test_l2b_logical_source(l2b_dataset: xr.Dataset):
25
+ """Tests that the ``idex_l2b`` function generates datasets
26
+ with the expected logical source.
27
+
28
+ Parameters
29
+ ----------
30
+ l2b_dataset : xr.Dataset
31
+ A ``xarray`` dataset containing the test data
32
+ """
33
+ expected_src = "imap_idex_l2b_sci"
34
+ assert l2b_dataset.attrs["Logical_source"] == expected_src
35
+
36
+
37
+ def test_l2a_cdf_variables(l2b_dataset: xr.Dataset):
38
+ """Tests that the ``idex_l2a`` function generates datasets
39
+ with the expected variables.
40
+
41
+ Parameters
42
+ ----------
43
+ l2b_dataset : xr.Dataset
44
+ A ``xarray`` dataset containing the test data
45
+ """
46
+ expected_vars = [
47
+ "epoch",
48
+ "impact_day_of_year",
49
+ "spin_phase_quadrants",
50
+ "target_low_fit_impact_charge",
51
+ "target_low_fit_impact_mass_estimate",
52
+ "target_high_fit_impact_charge",
53
+ "target_high_fit_impact_mass_estimate",
54
+ "ion_grid_fit_impact_charge",
55
+ "ion_grid_fit_impact_mass_estimate",
56
+ ]
57
+
58
+ cdf_vars = l2b_dataset.variables
59
+ for var in expected_vars:
60
+ assert var in cdf_vars
61
+
62
+
63
+ def test_round_spin_phases():
64
+ """Tests that round_spin_phases() produces expected results."""
65
+ spin_phase_angles = xr.DataArray([90, 1, 10, 200, 359, 179, 100])
66
+ expected_quadrants = [90, 0, 0, 180, 0, 180, 90]
67
+
68
+ spin_quadrants = round_spin_phases(spin_phase_angles)
69
+ assert_array_equal(spin_quadrants, expected_quadrants)
70
+
71
+ # Test with a larger number of random values
72
+ spin_phase_angles = np.random.randint(0, 360, 1000)
73
+ spin_quadrants = round_spin_phases(spin_phase_angles)
74
+ unique_quadrants = np.unique(spin_quadrants)
75
+ assert set(unique_quadrants) == {0, 90, 180, 270}
76
+
77
+ # Test values that are exactly halfway between quadrants
78
+ spin_quadrants = round_spin_phases(np.array([45, 135, 225, 315]))
79
+ assert_array_equal(spin_quadrants, [90, 180, 270, 0])
80
+
81
+
82
+ def test_round_spin_phases_warning(caplog):
83
+ """Tests that round_spin_phases() logs expected out of range warning."""
84
+ # The last value in the array should trigger a warning since it is >=360.
85
+ spin_phase_angles = xr.DataArray([90, 1, 10, 200, 360])
86
+
87
+ with caplog.at_level("WARNING"):
88
+ round_spin_phases(spin_phase_angles)
89
+
90
+ assert (
91
+ f"Spin phase angles, {spin_phase_angles.data} "
92
+ f"are outside of the expected spin phase angle range, [0, 360)."
93
+ ) in caplog.text
@@ -15,7 +15,7 @@ def test_lo_l1a():
15
15
  "imap_lo_l1a_histogram",
16
16
  "imap_lo_l1a_de",
17
17
  ]
18
- output_dataset = lo_l1a(dependency, "001")
18
+ output_dataset = lo_l1a(dependency)
19
19
 
20
20
  # Assert
21
21
  for dataset, logical_source in zip(output_dataset, expected_logical_source):
@@ -56,7 +56,7 @@ def test_lo_l1a_dataset():
56
56
  hist_fields_lower = [field.lower() for field in histogram_fields]
57
57
 
58
58
  # Act
59
- output_datasets = lo_l1a(dependency, "001")
59
+ output_datasets = lo_l1a(dependency)
60
60
 
61
61
  # Assert
62
62
  np.testing.assert_array_equal(hist_fields_lower, output_datasets[1].data_vars)
@@ -108,7 +108,7 @@ def test_validate_spin_data():
108
108
  validation_data = validation_data.drop(matching_columns, axis=1)
109
109
 
110
110
  # Act
111
- output_dataset = lo_l1a(dependency, "001")
111
+ output_dataset = lo_l1a(dependency)
112
112
 
113
113
  # Assert
114
114
  for field in spin_fields: