imap-processing 0.11.0__py3-none-any.whl → 0.13.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (415) hide show
  1. imap_processing/__init__.py +11 -11
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/ccsds_data.py +1 -2
  4. imap_processing/ccsds/excel_to_xtce.py +66 -18
  5. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +24 -40
  6. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +934 -42
  7. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
  8. imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +0 -5
  9. imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +10 -11
  10. imap_processing/cdf/config/imap_hi_variable_attrs.yaml +17 -19
  11. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +27 -14
  12. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +106 -116
  13. imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +120 -145
  14. imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +14 -0
  15. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +25 -9
  16. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +6 -4
  17. imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +3 -3
  18. imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +0 -12
  19. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +1 -1
  20. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +23 -20
  21. imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml +361 -0
  22. imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml +160 -0
  23. imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +160 -0
  24. imap_processing/cdf/config/imap_spacecraft_global_cdf_attrs.yaml +18 -0
  25. imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml +40 -0
  26. imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +1 -5
  27. imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
  28. imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +12 -4
  29. imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +16 -2
  30. imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +64 -52
  31. imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +71 -47
  32. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +180 -19
  33. imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
  34. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +80 -17
  35. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +32 -57
  36. imap_processing/cdf/utils.py +52 -38
  37. imap_processing/cli.py +477 -233
  38. imap_processing/codice/codice_l1a.py +466 -131
  39. imap_processing/codice/codice_l1b.py +51 -152
  40. imap_processing/codice/constants.py +1360 -569
  41. imap_processing/codice/decompress.py +2 -6
  42. imap_processing/ena_maps/ena_maps.py +1103 -146
  43. imap_processing/ena_maps/utils/coordinates.py +19 -0
  44. imap_processing/ena_maps/utils/map_utils.py +14 -17
  45. imap_processing/ena_maps/utils/spatial_utils.py +55 -52
  46. imap_processing/glows/l1a/glows_l1a.py +28 -99
  47. imap_processing/glows/l1a/glows_l1a_data.py +2 -2
  48. imap_processing/glows/l1b/glows_l1b.py +1 -4
  49. imap_processing/glows/l1b/glows_l1b_data.py +1 -3
  50. imap_processing/glows/l2/glows_l2.py +2 -5
  51. imap_processing/hi/l1a/hi_l1a.py +54 -29
  52. imap_processing/hi/l1a/histogram.py +0 -1
  53. imap_processing/hi/l1a/science_direct_event.py +6 -8
  54. imap_processing/hi/l1b/hi_l1b.py +111 -82
  55. imap_processing/hi/l1c/hi_l1c.py +416 -32
  56. imap_processing/hi/utils.py +58 -12
  57. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
  58. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt0-factors_20250219_v002.csv +205 -0
  59. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt1-factors_20250219_v002.csv +205 -0
  60. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt2-factors_20250219_v002.csv +205 -0
  61. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt3-factors_20250219_v002.csv +205 -0
  62. imap_processing/hit/ancillary/imap_hit_l1b-to-l2-summed-dt0-factors_20250219_v002.csv +68 -0
  63. imap_processing/hit/hit_utils.py +235 -5
  64. imap_processing/hit/l0/constants.py +20 -11
  65. imap_processing/hit/l0/decom_hit.py +21 -5
  66. imap_processing/hit/l1a/hit_l1a.py +71 -75
  67. imap_processing/hit/l1b/constants.py +321 -0
  68. imap_processing/hit/l1b/hit_l1b.py +377 -67
  69. imap_processing/hit/l2/constants.py +318 -0
  70. imap_processing/hit/l2/hit_l2.py +723 -0
  71. imap_processing/hit/packet_definitions/hit_packet_definitions.xml +1323 -71
  72. imap_processing/ialirt/l0/mag_l0_ialirt_data.py +155 -0
  73. imap_processing/ialirt/l0/parse_mag.py +374 -0
  74. imap_processing/ialirt/l0/process_swapi.py +69 -0
  75. imap_processing/ialirt/l0/process_swe.py +548 -0
  76. imap_processing/ialirt/packet_definitions/ialirt.xml +216 -208
  77. imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +1 -1
  78. imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +1 -1
  79. imap_processing/ialirt/packet_definitions/ialirt_mag.xml +115 -0
  80. imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
  81. imap_processing/ialirt/utils/grouping.py +114 -0
  82. imap_processing/ialirt/utils/time.py +29 -0
  83. imap_processing/idex/atomic_masses.csv +22 -0
  84. imap_processing/idex/decode.py +2 -2
  85. imap_processing/idex/idex_constants.py +33 -0
  86. imap_processing/idex/idex_l0.py +22 -8
  87. imap_processing/idex/idex_l1a.py +81 -51
  88. imap_processing/idex/idex_l1b.py +13 -39
  89. imap_processing/idex/idex_l2a.py +823 -0
  90. imap_processing/idex/idex_l2b.py +120 -0
  91. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +11 -11
  92. imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
  93. imap_processing/lo/l0/lo_science.py +7 -2
  94. imap_processing/lo/l1a/lo_l1a.py +1 -5
  95. imap_processing/lo/l1b/lo_l1b.py +702 -29
  96. imap_processing/lo/l1b/tof_conversions.py +11 -0
  97. imap_processing/lo/l1c/lo_l1c.py +1 -4
  98. imap_processing/mag/constants.py +51 -0
  99. imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
  100. imap_processing/mag/l0/decom_mag.py +10 -3
  101. imap_processing/mag/l1a/mag_l1a.py +23 -19
  102. imap_processing/mag/l1a/mag_l1a_data.py +35 -10
  103. imap_processing/mag/l1b/mag_l1b.py +259 -50
  104. imap_processing/mag/l1c/interpolation_methods.py +388 -0
  105. imap_processing/mag/l1c/mag_l1c.py +621 -17
  106. imap_processing/mag/l2/mag_l2.py +140 -0
  107. imap_processing/mag/l2/mag_l2_data.py +288 -0
  108. imap_processing/quality_flags.py +1 -0
  109. imap_processing/spacecraft/packet_definitions/scid_x252.xml +538 -0
  110. imap_processing/spacecraft/quaternions.py +121 -0
  111. imap_processing/spice/geometry.py +19 -22
  112. imap_processing/spice/kernels.py +0 -276
  113. imap_processing/spice/pointing_frame.py +257 -0
  114. imap_processing/spice/repoint.py +149 -0
  115. imap_processing/spice/spin.py +38 -33
  116. imap_processing/spice/time.py +24 -0
  117. imap_processing/swapi/l1/swapi_l1.py +20 -12
  118. imap_processing/swapi/l2/swapi_l2.py +116 -5
  119. imap_processing/swapi/swapi_utils.py +32 -0
  120. imap_processing/swe/l1a/swe_l1a.py +44 -12
  121. imap_processing/swe/l1a/swe_science.py +13 -13
  122. imap_processing/swe/l1b/swe_l1b.py +898 -23
  123. imap_processing/swe/l2/swe_l2.py +75 -136
  124. imap_processing/swe/packet_definitions/swe_packet_definition.xml +1121 -1
  125. imap_processing/swe/utils/swe_constants.py +64 -0
  126. imap_processing/swe/utils/swe_utils.py +85 -28
  127. imap_processing/tests/ccsds/test_data/expected_output.xml +40 -1
  128. imap_processing/tests/ccsds/test_excel_to_xtce.py +24 -21
  129. imap_processing/tests/cdf/test_data/imap_instrument2_global_cdf_attrs.yaml +0 -2
  130. imap_processing/tests/cdf/test_utils.py +14 -16
  131. imap_processing/tests/codice/conftest.py +44 -33
  132. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  133. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  134. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-ialirt_20241110193700_v0.0.0.cdf +0 -0
  135. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-omni_20241110193700_v0.0.0.cdf +0 -0
  136. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
  137. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-priorities_20241110193700_v0.0.0.cdf +0 -0
  138. imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-sectored_20241110193700_v0.0.0.cdf +0 -0
  139. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
  140. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-singles_20241110193700_v0.0.0.cdf +0 -0
  141. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  142. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-angular_20241110193700_v0.0.0.cdf +0 -0
  143. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-priority_20241110193700_v0.0.0.cdf +0 -0
  144. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-species_20241110193700_v0.0.0.cdf +0 -0
  145. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
  146. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-angular_20241110193700_v0.0.0.cdf +0 -0
  147. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-priority_20241110193700_v0.0.0.cdf +0 -0
  148. imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-species_20241110193700_v0.0.0.cdf +0 -0
  149. imap_processing/tests/codice/test_codice_l1a.py +126 -53
  150. imap_processing/tests/codice/test_codice_l1b.py +6 -7
  151. imap_processing/tests/codice/test_decompress.py +4 -4
  152. imap_processing/tests/conftest.py +239 -27
  153. imap_processing/tests/ena_maps/conftest.py +51 -0
  154. imap_processing/tests/ena_maps/test_ena_maps.py +1068 -110
  155. imap_processing/tests/ena_maps/test_map_utils.py +66 -43
  156. imap_processing/tests/ena_maps/test_spatial_utils.py +17 -21
  157. imap_processing/tests/glows/conftest.py +10 -14
  158. imap_processing/tests/glows/test_glows_decom.py +4 -4
  159. imap_processing/tests/glows/test_glows_l1a_cdf.py +6 -27
  160. imap_processing/tests/glows/test_glows_l1a_data.py +6 -8
  161. imap_processing/tests/glows/test_glows_l1b.py +11 -11
  162. imap_processing/tests/glows/test_glows_l1b_data.py +5 -5
  163. imap_processing/tests/glows/test_glows_l2.py +2 -8
  164. imap_processing/tests/hi/conftest.py +1 -1
  165. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208.bin +0 -0
  166. imap_processing/tests/hi/data/l0/H45_diag_fee_20250208_verify.csv +205 -0
  167. imap_processing/tests/hi/test_hi_l1b.py +22 -27
  168. imap_processing/tests/hi/test_hi_l1c.py +249 -18
  169. imap_processing/tests/hi/test_l1a.py +35 -7
  170. imap_processing/tests/hi/test_science_direct_event.py +3 -3
  171. imap_processing/tests/hi/test_utils.py +24 -2
  172. imap_processing/tests/hit/helpers/l1_validation.py +74 -73
  173. imap_processing/tests/hit/test_data/hskp_sample.ccsds +0 -0
  174. imap_processing/tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts +0 -0
  175. imap_processing/tests/hit/test_decom_hit.py +5 -1
  176. imap_processing/tests/hit/test_hit_l1a.py +32 -36
  177. imap_processing/tests/hit/test_hit_l1b.py +300 -81
  178. imap_processing/tests/hit/test_hit_l2.py +716 -0
  179. imap_processing/tests/hit/test_hit_utils.py +184 -7
  180. imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
  181. imap_processing/tests/hit/validation_data/hskp_sample_eu_3_6_2025.csv +89 -0
  182. imap_processing/tests/hit/validation_data/hskp_sample_raw.csv +89 -88
  183. imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
  184. imap_processing/tests/ialirt/data/l0/461971383-404.bin +0 -0
  185. imap_processing/tests/ialirt/data/l0/461971384-405.bin +0 -0
  186. imap_processing/tests/ialirt/data/l0/461971385-406.bin +0 -0
  187. imap_processing/tests/ialirt/data/l0/461971386-407.bin +0 -0
  188. imap_processing/tests/ialirt/data/l0/461971387-408.bin +0 -0
  189. imap_processing/tests/ialirt/data/l0/461971388-409.bin +0 -0
  190. imap_processing/tests/ialirt/data/l0/461971389-410.bin +0 -0
  191. imap_processing/tests/ialirt/data/l0/461971390-411.bin +0 -0
  192. imap_processing/tests/ialirt/data/l0/461971391-412.bin +0 -0
  193. imap_processing/tests/ialirt/data/l0/sample_decoded_i-alirt_data.csv +383 -0
  194. imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
  195. imap_processing/tests/ialirt/unit/test_grouping.py +81 -0
  196. imap_processing/tests/ialirt/unit/test_parse_mag.py +223 -0
  197. imap_processing/tests/ialirt/unit/test_process_codicehi.py +3 -3
  198. imap_processing/tests/ialirt/unit/test_process_codicelo.py +3 -10
  199. imap_processing/tests/ialirt/unit/test_process_ephemeris.py +4 -4
  200. imap_processing/tests/ialirt/unit/test_process_hit.py +3 -3
  201. imap_processing/tests/ialirt/unit/test_process_swapi.py +24 -16
  202. imap_processing/tests/ialirt/unit/test_process_swe.py +319 -6
  203. imap_processing/tests/ialirt/unit/test_time.py +16 -0
  204. imap_processing/tests/idex/conftest.py +127 -6
  205. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231218_v001.pkts +0 -0
  206. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20241206_v001.pkts +0 -0
  207. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20250108_v001.pkts +0 -0
  208. imap_processing/tests/idex/test_data/impact_14_tof_high_data.txt +4508 -4508
  209. imap_processing/tests/idex/test_idex_l0.py +33 -11
  210. imap_processing/tests/idex/test_idex_l1a.py +92 -21
  211. imap_processing/tests/idex/test_idex_l1b.py +106 -27
  212. imap_processing/tests/idex/test_idex_l2a.py +399 -0
  213. imap_processing/tests/idex/test_idex_l2b.py +93 -0
  214. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20241022_v002.cdf +0 -0
  215. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20241022_v002.cdf +0 -0
  216. imap_processing/tests/lo/test_lo_l1a.py +3 -3
  217. imap_processing/tests/lo/test_lo_l1b.py +515 -6
  218. imap_processing/tests/lo/test_lo_l1c.py +1 -1
  219. imap_processing/tests/lo/test_lo_science.py +7 -7
  220. imap_processing/tests/lo/test_star_sensor.py +1 -1
  221. imap_processing/tests/mag/conftest.py +120 -2
  222. imap_processing/tests/mag/test_mag_decom.py +5 -4
  223. imap_processing/tests/mag/test_mag_l1a.py +51 -7
  224. imap_processing/tests/mag/test_mag_l1b.py +40 -59
  225. imap_processing/tests/mag/test_mag_l1c.py +354 -19
  226. imap_processing/tests/mag/test_mag_l2.py +130 -0
  227. imap_processing/tests/mag/test_mag_validation.py +247 -26
  228. imap_processing/tests/mag/validation/L1b/T009/MAGScience-normal-(2,2)-8s-20250204-16h39.csv +17 -0
  229. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-magi-out.csv +16 -16
  230. imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-mago-out.csv +16 -16
  231. imap_processing/tests/mag/validation/L1b/T010/MAGScience-normal-(2,2)-8s-20250206-12h05.csv +17 -0
  232. imap_processing/tests/mag/validation/L1b/T011/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  233. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-magi-out.csv +16 -16
  234. imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-mago-out.csv +16 -16
  235. imap_processing/tests/mag/validation/L1b/T012/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
  236. imap_processing/tests/mag/validation/L1b/T012/data.bin +0 -0
  237. imap_processing/tests/mag/validation/L1b/T012/field_like_all_ranges.txt +19200 -0
  238. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-cal.cdf +0 -0
  239. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-in.csv +17 -0
  240. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-magi-out.csv +17 -0
  241. imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-mago-out.csv +17 -0
  242. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-in.csv +1217 -0
  243. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-out.csv +1857 -0
  244. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-in.csv +1217 -0
  245. imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-out.csv +1857 -0
  246. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-in.csv +1217 -0
  247. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-out.csv +1793 -0
  248. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-in.csv +1217 -0
  249. imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-out.csv +1793 -0
  250. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-burst-in.csv +2561 -0
  251. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-in.csv +961 -0
  252. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-out.csv +1539 -0
  253. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-in.csv +1921 -0
  254. imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-out.csv +2499 -0
  255. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-in.csv +865 -0
  256. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv +1196 -0
  257. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-in.csv +1729 -0
  258. imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv +3053 -0
  259. imap_processing/tests/mag/validation/L2/imap_mag_l1b_norm-mago_20251017_v002.cdf +0 -0
  260. imap_processing/tests/mag/validation/calibration/imap_mag_l1b-calibration_20240229_v001.cdf +0 -0
  261. imap_processing/tests/mag/validation/calibration/imap_mag_l2-calibration-matrices_20251017_v004.cdf +0 -0
  262. imap_processing/tests/mag/validation/calibration/imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf +0 -0
  263. imap_processing/tests/spacecraft/data/SSR_2024_190_20_08_12_0483851794_2_DA_apid0594_1packet.pkts +0 -0
  264. imap_processing/tests/spacecraft/test_quaternions.py +71 -0
  265. imap_processing/tests/spice/test_data/fake_repoint_data.csv +5 -0
  266. imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
  267. imap_processing/tests/spice/test_geometry.py +9 -12
  268. imap_processing/tests/spice/test_kernels.py +1 -200
  269. imap_processing/tests/spice/test_pointing_frame.py +185 -0
  270. imap_processing/tests/spice/test_repoint.py +121 -0
  271. imap_processing/tests/spice/test_spin.py +50 -9
  272. imap_processing/tests/spice/test_time.py +14 -0
  273. imap_processing/tests/swapi/lut/imap_swapi_esa-unit-conversion_20250211_v000.csv +73 -0
  274. imap_processing/tests/swapi/lut/imap_swapi_lut-notes_20250211_v000.csv +1025 -0
  275. imap_processing/tests/swapi/test_swapi_l1.py +13 -11
  276. imap_processing/tests/swapi/test_swapi_l2.py +180 -8
  277. imap_processing/tests/swe/l0_data/2024051010_SWE_HK_packet.bin +0 -0
  278. imap_processing/tests/swe/l0_data/2024051011_SWE_CEM_RAW_packet.bin +0 -0
  279. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_APP_HK_20240510_092742.csv +49 -0
  280. imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_CEM_RAW_20240510_092742.csv +593 -0
  281. imap_processing/tests/swe/lut/checker-board-indices.csv +24 -0
  282. imap_processing/tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv +385 -0
  283. imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv +3 -0
  284. imap_processing/tests/swe/test_swe_l1a.py +20 -2
  285. imap_processing/tests/swe/test_swe_l1a_cem_raw.py +52 -0
  286. imap_processing/tests/swe/test_swe_l1a_hk.py +68 -0
  287. imap_processing/tests/swe/test_swe_l1a_science.py +3 -3
  288. imap_processing/tests/swe/test_swe_l1b.py +162 -24
  289. imap_processing/tests/swe/test_swe_l2.py +153 -91
  290. imap_processing/tests/test_cli.py +171 -88
  291. imap_processing/tests/test_utils.py +140 -17
  292. imap_processing/tests/ultra/data/l0/FM45_UltraFM45_Functional_2024-01-22T0105_20240122T010548.CCSDS +0 -0
  293. imap_processing/tests/ultra/data/l0/ultra45_raw_sc_ultraimgrates_20220530_00.csv +164 -0
  294. imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3243 -3243
  295. imap_processing/tests/ultra/data/mock_data.py +369 -0
  296. imap_processing/tests/ultra/unit/conftest.py +115 -89
  297. imap_processing/tests/ultra/unit/test_badtimes.py +4 -4
  298. imap_processing/tests/ultra/unit/test_cullingmask.py +8 -6
  299. imap_processing/tests/ultra/unit/test_de.py +14 -13
  300. imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
  301. imap_processing/tests/ultra/unit/test_decom_apid_881.py +54 -11
  302. imap_processing/tests/ultra/unit/test_decom_apid_883.py +12 -10
  303. imap_processing/tests/ultra/unit/test_decom_apid_896.py +202 -55
  304. imap_processing/tests/ultra/unit/test_lookup_utils.py +23 -1
  305. imap_processing/tests/ultra/unit/test_spacecraft_pset.py +77 -0
  306. imap_processing/tests/ultra/unit/test_ultra_l1a.py +98 -305
  307. imap_processing/tests/ultra/unit/test_ultra_l1b.py +60 -14
  308. imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
  309. imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +26 -27
  310. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +239 -70
  311. imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
  312. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +114 -83
  313. imap_processing/tests/ultra/unit/test_ultra_l2.py +230 -0
  314. imap_processing/ultra/constants.py +1 -1
  315. imap_processing/ultra/l0/decom_tools.py +27 -39
  316. imap_processing/ultra/l0/decom_ultra.py +168 -204
  317. imap_processing/ultra/l0/ultra_utils.py +152 -136
  318. imap_processing/ultra/l1a/ultra_l1a.py +55 -271
  319. imap_processing/ultra/l1b/badtimes.py +1 -4
  320. imap_processing/ultra/l1b/cullingmask.py +2 -6
  321. imap_processing/ultra/l1b/de.py +116 -57
  322. imap_processing/ultra/l1b/extendedspin.py +20 -18
  323. imap_processing/ultra/l1b/lookup_utils.py +72 -9
  324. imap_processing/ultra/l1b/ultra_l1b.py +36 -16
  325. imap_processing/ultra/l1b/ultra_l1b_culling.py +66 -30
  326. imap_processing/ultra/l1b/ultra_l1b_extended.py +297 -94
  327. imap_processing/ultra/l1c/histogram.py +2 -6
  328. imap_processing/ultra/l1c/spacecraft_pset.py +84 -0
  329. imap_processing/ultra/l1c/ultra_l1c.py +8 -9
  330. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +206 -108
  331. imap_processing/ultra/l2/ultra_l2.py +299 -0
  332. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +526 -0
  333. imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +526 -0
  334. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +526 -0
  335. imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +526 -0
  336. imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -2
  337. imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
  338. imap_processing/ultra/packet_definitions/README.md +38 -0
  339. imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +15302 -482
  340. imap_processing/ultra/utils/ultra_l1_utils.py +31 -12
  341. imap_processing/utils.py +69 -29
  342. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +10 -6
  343. imap_processing-0.13.0.dist-info/RECORD +578 -0
  344. imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +0 -237
  345. imap_processing/hi/l1a/housekeeping.py +0 -27
  346. imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
  347. imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
  348. imap_processing/swe/l1b/swe_l1b_science.py +0 -652
  349. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-aggregated_20240429_v001.cdf +0 -0
  350. imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-singles_20240429_v001.cdf +0 -0
  351. imap_processing/tests/codice/data/imap_codice_l1a_hi-omni_20240429_v001.cdf +0 -0
  352. imap_processing/tests/codice/data/imap_codice_l1a_hi-sectored_20240429_v001.cdf +0 -0
  353. imap_processing/tests/codice/data/imap_codice_l1a_hskp_20100101_v001.cdf +0 -0
  354. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-aggregated_20240429_v001.cdf +0 -0
  355. imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-singles_20240429_v001.cdf +0 -0
  356. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-angular_20240429_v001.cdf +0 -0
  357. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-priority_20240429_v001.cdf +0 -0
  358. imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-species_20240429_v001.cdf +0 -0
  359. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-angular_20240429_v001.cdf +0 -0
  360. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-priority_20240429_v001.cdf +0 -0
  361. imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-species_20240429_v001.cdf +0 -0
  362. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-aggregated_20240429_v001.cdf +0 -0
  363. imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-singles_20240429_v001.cdf +0 -0
  364. imap_processing/tests/codice/data/imap_codice_l1b_hi-omni_20240429_v001.cdf +0 -0
  365. imap_processing/tests/codice/data/imap_codice_l1b_hi-sectored_20240429_v001.cdf +0 -0
  366. imap_processing/tests/codice/data/imap_codice_l1b_hskp_20100101_v001.cdf +0 -0
  367. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-aggregated_20240429_v001.cdf +0 -0
  368. imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-singles_20240429_v001.cdf +0 -0
  369. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-angular_20240429_v001.cdf +0 -0
  370. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-priority_20240429_v001.cdf +0 -0
  371. imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-species_20240429_v001.cdf +0 -0
  372. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-angular_20240429_v001.cdf +0 -0
  373. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-priority_20240429_v001.cdf +0 -0
  374. imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-species_20240429_v001.cdf +0 -0
  375. imap_processing/tests/hi/data/l1/imap_hi_l1b_45sensor-de_20250415_v999.cdf +0 -0
  376. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1251.pkts +0 -0
  377. imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1252.pkts +0 -0
  378. imap_processing/tests/hit/validation_data/hskp_sample_eu.csv +0 -89
  379. imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +0 -29
  380. imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231214_v001.pkts +0 -0
  381. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20100101_v001.cdf +0 -0
  382. imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20100101_v001.cdf +0 -0
  383. imap_processing/tests/swe/test_swe_l1b_science.py +0 -84
  384. imap_processing/tests/ultra/test_data/mock_data.py +0 -161
  385. imap_processing/ultra/l1c/pset.py +0 -40
  386. imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
  387. imap_processing-0.11.0.dist-info/RECORD +0 -488
  388. /imap_processing/idex/packet_definitions/{idex_packet_definition.xml → idex_science_packet_definition.xml} +0 -0
  389. /imap_processing/tests/ialirt/{test_data → data}/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
  390. /imap_processing/tests/ialirt/{test_data → data}/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
  391. /imap_processing/tests/ialirt/{test_data → data}/l0/IALiRT Raw Packet Telemetry.txt +0 -0
  392. /imap_processing/tests/ialirt/{test_data → data}/l0/apid01152.tlm +0 -0
  393. /imap_processing/tests/ialirt/{test_data → data}/l0/eu_SWP_IAL_20240826_152033.csv +0 -0
  394. /imap_processing/tests/ialirt/{test_data → data}/l0/hi_fsw_view_1_ccsds.bin +0 -0
  395. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.ccsds +0 -0
  396. /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.csv +0 -0
  397. /imap_processing/tests/ialirt/{test_data → data}/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +0 -0
  398. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
  399. /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  400. /imap_processing/{mag/l1b → tests/spacecraft}/__init__.py +0 -0
  401. /imap_processing/{swe/l1b/engineering_unit_convert_table.csv → tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv} +0 -0
  402. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00_20240207T102740.CCSDS +0 -0
  403. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_7P_Phi0.0_BeamCal_LinearScan_phi0.04_theta-0.01_20230821T121304.CCSDS +0 -0
  404. /imap_processing/tests/ultra/{test_data → data}/l0/FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.CCSDS +0 -0
  405. /imap_processing/tests/ultra/{test_data → data}/l0/Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.CCSDS +0 -0
  406. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_auxdata_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  407. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_enaphxtofhangimg_FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.csv +0 -0
  408. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultraimgrates_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
  409. /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimgevent_FM45_7P_Phi00_BeamCal_LinearScan_phi004_theta-001_20230821T121304.csv +0 -0
  410. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E1.cdf +0 -0
  411. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E12.cdf +0 -0
  412. /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E24.cdf +0 -0
  413. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
  414. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
  415. {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
@@ -3,18 +3,22 @@
3
3
  import numpy as np
4
4
  import pytest
5
5
 
6
+ from imap_processing import imap_module_directory
6
7
  from imap_processing.quality_flags import ImapAttitudeUltraFlags, ImapRatesUltraFlags
7
8
  from imap_processing.ultra.constants import UltraConstants
8
9
  from imap_processing.ultra.l1b.ultra_l1b_culling import (
10
+ compare_aux_univ_spin_table,
9
11
  flag_attitude,
10
12
  flag_spin,
11
13
  get_energy_histogram,
12
14
  get_n_sigma,
13
- get_spin,
15
+ get_spin_data,
14
16
  )
15
17
 
18
+ TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1"
16
19
 
17
- @pytest.fixture()
20
+
21
+ @pytest.fixture
18
22
  def test_data(use_fake_spin_data_for_time):
19
23
  """Fixture to compute and return test data."""
20
24
 
@@ -37,28 +41,13 @@ def test_data(use_fake_spin_data_for_time):
37
41
  )
38
42
  expected_counts[energy_idx, spin_idx] = count
39
43
 
40
- return time, spin_number, energy, expected_counts
41
-
42
-
43
- def test_get_spin(use_fake_spin_data_for_time):
44
- """Tests get_spin function."""
45
-
46
- nspins = 5
47
- spin_period = 15
48
- start = 0
49
- stop = start + (nspins + 1) * spin_period
50
- use_fake_spin_data_for_time(start, stop)
51
- spin_number = get_spin(np.linspace(start, stop, num=20))
52
-
53
- assert len(spin_number) == len(np.linspace(start, stop, num=20))
54
- expected_num_spins = np.ceil((stop - start) / 15) + 1
55
- assert np.array_equal(len(np.unique(spin_number)), expected_num_spins)
44
+ return spin_number, energy, expected_counts
56
45
 
57
46
 
58
47
  def test_get_energy_histogram(test_data):
59
48
  """Tests get_energy_histogram function."""
60
49
 
61
- _, spin_number, energy, expected_counts = test_data
50
+ spin_number, energy, expected_counts = test_data
62
51
 
63
52
  hist, _, counts, duration = get_energy_histogram(spin_number, energy)
64
53
 
@@ -67,19 +56,17 @@ def test_get_energy_histogram(test_data):
67
56
  assert duration == 15
68
57
 
69
58
 
70
- def test_flag_attitude(use_fake_spin_data_for_time):
59
+ def test_flag_attitude(use_fake_spin_data_for_time, faux_aux_dataset):
71
60
  """Tests flag_attitude function."""
72
61
 
73
- start = 4.45015658e08
74
- stop = 4.45015873e08
75
- use_fake_spin_data_for_time(start, stop)
62
+ use_fake_spin_data_for_time(0, 15 * 147)
76
63
  quality_flags, spin_rates, spin_period, spin_start_time = flag_attitude(
77
- np.linspace(start, stop, num=20)
64
+ faux_aux_dataset["SPINNUMBER"].values, faux_aux_dataset
78
65
  )
79
66
 
80
67
  flag = ImapAttitudeUltraFlags(quality_flags[0])
81
68
  assert flag.name == "NONE"
82
- assert np.all(quality_flags == ImapAttitudeUltraFlags.NONE.value)
69
+ assert quality_flags[-1] == ImapAttitudeUltraFlags.AUXMISMATCH.value
83
70
  assert np.all(spin_rates == 60 / spin_period)
84
71
  assert np.all(np.diff(spin_start_time) == 15)
85
72
 
@@ -102,8 +89,8 @@ def test_get_n_sigma():
102
89
  def test_flag_spin(test_data):
103
90
  """Tests flag_spin function."""
104
91
 
105
- time, _, energy, expected_counts = test_data
106
- quality_flags, spin, energy, _ = flag_spin(time, energy, 1)
92
+ spin_number, energy, expected_counts = test_data
93
+ quality_flags, spin, energy, _ = flag_spin(spin_number, energy, 1)
107
94
  threshold = get_n_sigma(expected_counts / 15, 15, 1)
108
95
 
109
96
  # At the first energy level were the rates > threshold and the counts > threshold?
@@ -112,3 +99,15 @@ def test_flag_spin(test_data):
112
99
  )
113
100
  high_rates_flag = quality_flags[expected_counts / 15 > threshold[:, np.newaxis]]
114
101
  assert np.all(high_rates_flag == ImapRatesUltraFlags.HIGHRATES.value)
102
+
103
+
104
+ def test_compare_aux_univ_spin_table(use_fake_spin_data_for_time, faux_aux_dataset):
105
+ """Tests compare_aux_univ_spin_table function."""
106
+ use_fake_spin_data_for_time(0, 15 * 147)
107
+ spins = faux_aux_dataset["SPINNUMBER"].values
108
+ spin_df = get_spin_data()
109
+
110
+ result = compare_aux_univ_spin_table(faux_aux_dataset, spins, spin_df)
111
+ expected = np.array([False] * 14 + [True])
112
+
113
+ assert np.all(result == expected)
@@ -4,7 +4,10 @@ import numpy as np
4
4
  import pandas as pd
5
5
  import pytest
6
6
 
7
+ from imap_processing import imap_module_directory
8
+ from imap_processing.spice.spin import get_spin_data
7
9
  from imap_processing.ultra.constants import UltraConstants
10
+ from imap_processing.ultra.l1b.lookup_utils import get_angular_profiles
8
11
  from imap_processing.ultra.l1b.ultra_l1b_extended import (
9
12
  CoinType,
10
13
  StartType,
@@ -13,61 +16,70 @@ from imap_processing.ultra.l1b.ultra_l1b_extended import (
13
16
  determine_species,
14
17
  get_coincidence_positions,
15
18
  get_ctof,
16
- get_de_az_el,
17
19
  get_de_energy_kev,
18
20
  get_de_velocity,
21
+ get_efficiency,
19
22
  get_energy_pulse_height,
20
23
  get_energy_ssd,
24
+ get_eventtimes,
21
25
  get_front_x_position,
22
26
  get_front_y_position,
27
+ get_fwhm,
23
28
  get_path_length,
24
29
  get_ph_tof_and_back_positions,
30
+ get_phi_theta,
25
31
  get_ssd_back_position_and_tof_offset,
26
32
  get_ssd_tof,
33
+ interpolate_fwhm,
27
34
  )
28
35
 
36
+ TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1"
29
37
 
30
- @pytest.fixture()
31
- def yf_fixture(de_dataset, events_fsw_comparison_theta_0):
38
+
39
+ @pytest.fixture
40
+ def test_fixture(de_dataset, events_fsw_comparison_theta_0):
32
41
  """Fixture to compute and return yf and related data."""
42
+ # Remove start_type with fill values
43
+ de_dataset = de_dataset.where(de_dataset["start_type"] != 255, drop=True)
44
+
33
45
  df = pd.read_csv(events_fsw_comparison_theta_0)
34
46
  df_filt = df[df["StartType"] != -1]
35
47
 
36
48
  d, yf = get_front_y_position(
37
- de_dataset["START_TYPE"].data, df_filt.Yb.values.astype("float")
49
+ de_dataset["start_type"].data, df_filt.Yb.values.astype("float")
38
50
  )
39
51
 
40
- return df_filt, d, yf
52
+ return df_filt, d, yf, de_dataset
41
53
 
42
54
 
43
55
  def test_get_front_x_position(
44
- de_dataset,
45
- yf_fixture,
56
+ test_fixture,
46
57
  ):
47
58
  """Tests get_front_x_position function."""
48
59
 
49
- df_filt, _, _ = yf_fixture
60
+ df_filt, _, _, de_dataset = test_fixture
50
61
 
51
62
  xf = get_front_x_position(
52
- de_dataset["START_TYPE"].data,
53
- de_dataset["START_POS_TDC"].data,
63
+ de_dataset["start_type"].data,
64
+ de_dataset["start_pos_tdc"].data,
65
+ "ultra45",
54
66
  )
55
67
 
56
68
  assert xf == pytest.approx(df_filt["Xf"].astype("float"), 1e-5)
57
69
 
58
70
 
59
- def test_get_front_y_position(yf_fixture):
71
+ def test_get_front_y_position(test_fixture):
60
72
  """Tests get_front_y_position function."""
61
- df_filt, d, yf = yf_fixture
73
+ df_filt, d, yf, _ = test_fixture
62
74
 
63
75
  assert yf == pytest.approx(df_filt["Yf"].astype("float"), abs=1e-5)
64
76
  assert d == pytest.approx(df_filt["d"].astype("float"), abs=1e-5)
65
77
 
66
78
 
67
- def test_get_path_length(de_dataset, yf_fixture):
79
+ def test_get_path_length(test_fixture):
68
80
  """Tests get_path_length function."""
69
81
 
70
- df_filt, d, yf = yf_fixture
82
+ df_filt, d, yf, _ = test_fixture
71
83
 
72
84
  test_xf = df_filt["Xf"].astype("float").values
73
85
  test_yf = df_filt["Yf"].astype("float").values
@@ -79,19 +91,18 @@ def test_get_path_length(de_dataset, yf_fixture):
79
91
 
80
92
 
81
93
  def test_get_ph_tof_and_back_positions(
82
- de_dataset,
83
- yf_fixture,
94
+ test_fixture,
84
95
  ):
85
96
  """Tests get_ph_tof_and_back_positions function."""
86
97
 
87
- df_filt, _, _ = yf_fixture
98
+ df_filt, _, _, de_dataset = test_fixture
88
99
 
89
100
  ph_tof, _, ph_xb, ph_yb = get_ph_tof_and_back_positions(
90
101
  de_dataset, df_filt.Xf.astype("float").values, "ultra45"
91
102
  )
92
103
 
93
104
  ph_indices = np.nonzero(
94
- np.isin(de_dataset["STOP_TYPE"], [StopType.Top.value, StopType.Bottom.value])
105
+ np.isin(de_dataset["stop_type"], [StopType.Top.value, StopType.Bottom.value])
95
106
  )[0]
96
107
 
97
108
  selected_rows = df_filt.iloc[ph_indices]
@@ -104,11 +115,14 @@ def test_get_ph_tof_and_back_positions(
104
115
 
105
116
 
106
117
  def test_get_ssd_back_position_and_tof_offset(
107
- de_dataset,
118
+ test_fixture,
108
119
  events_fsw_comparison_theta_0,
109
120
  ):
110
121
  """Tests get_ssd_back_position function."""
111
- yb, tof_offset, ssd_number = get_ssd_back_position_and_tof_offset(de_dataset)
122
+ _, _, _, de_dataset = test_fixture
123
+ yb, tof_offset, ssd_number = get_ssd_back_position_and_tof_offset(
124
+ de_dataset, "ultra45"
125
+ )
112
126
 
113
127
  df = pd.read_csv(events_fsw_comparison_theta_0)
114
128
  df_filt = df[(df["StartType"] != -1) & (df["StopType"] >= 8)]
@@ -143,9 +157,9 @@ def test_get_ssd_back_position_and_tof_offset(
143
157
  assert np.all(ssd_number_rt <= 7), "Values in ssd_number_rt out of range."
144
158
 
145
159
 
146
- def test_get_coincidence_positions(de_dataset, yf_fixture):
160
+ def test_get_coincidence_positions(test_fixture):
147
161
  """Tests get_coincidence_positions function."""
148
- df_filt, _, _ = yf_fixture
162
+ df_filt, _, _, de_dataset = test_fixture
149
163
  # Get particle tof (t2).
150
164
  _, t2, _, _ = get_ph_tof_and_back_positions(
151
165
  de_dataset, df_filt.Xf.astype("float").values, "ultra45"
@@ -153,7 +167,7 @@ def test_get_coincidence_positions(de_dataset, yf_fixture):
153
167
 
154
168
  # Filter for stop type.
155
169
  indices = np.nonzero(
156
- np.isin(de_dataset["STOP_TYPE"], [StopType.Top.value, StopType.Bottom.value])
170
+ np.isin(de_dataset["stop_type"], [StopType.Top.value, StopType.Bottom.value])
157
171
  )[0]
158
172
  de_filtered = de_dataset.isel(epoch=indices)
159
173
  rows = df_filt.iloc[indices]
@@ -167,26 +181,26 @@ def test_get_coincidence_positions(de_dataset, yf_fixture):
167
181
  )
168
182
 
169
183
 
170
- def test_calculate_etof_xc(de_dataset, yf_fixture):
184
+ def test_calculate_etof_xc(test_fixture):
171
185
  """Tests calculate_etof_xc function."""
172
- df_filt, _, _ = yf_fixture
186
+ df_filt, _, _, de_dataset = test_fixture
173
187
  # Get particle tof (t2).
174
188
  _, t2, _, _ = get_ph_tof_and_back_positions(
175
189
  de_dataset, df_filt.Xf.astype("float").values, "ultra45"
176
190
  )
177
191
  # Filter based on STOP_TYPE.
178
192
  indices = np.nonzero(
179
- np.isin(de_dataset["STOP_TYPE"], [StopType.Top.value, StopType.Bottom.value])
193
+ np.isin(de_dataset["stop_type"], [StopType.Top.value, StopType.Bottom.value])
180
194
  )[0]
181
195
  de_filtered = de_dataset.isel(epoch=indices)
182
196
  df_filtered = df_filt.iloc[indices]
183
197
 
184
198
  # Filter for COIN_TYPE Top and Bottom.
185
- index_top = np.nonzero(np.isin(de_filtered["COIN_TYPE"], CoinType.Top.value))[0]
199
+ index_top = np.nonzero(np.isin(de_filtered["coin_type"], CoinType.Top.value))[0]
186
200
  de_top = de_filtered.isel(epoch=index_top)
187
201
  df_top = df_filtered.iloc[index_top]
188
202
 
189
- index_bottom = np.nonzero(np.isin(de_filtered["COIN_TYPE"], CoinType.Bottom.value))[
203
+ index_bottom = np.nonzero(np.isin(de_filtered["coin_type"], CoinType.Bottom.value))[
190
204
  0
191
205
  ]
192
206
  de_bottom = de_filtered.isel(epoch=index_bottom)
@@ -215,9 +229,9 @@ def test_calculate_etof_xc(de_dataset, yf_fixture):
215
229
  )
216
230
 
217
231
 
218
- def test_get_de_velocity(de_dataset, yf_fixture):
232
+ def test_get_de_velocity(test_fixture):
219
233
  """Tests get_de_velocity function."""
220
- df_filt, _, _ = yf_fixture
234
+ df_filt, _, _, _ = test_fixture
221
235
  df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])]
222
236
 
223
237
  test_xf, test_yf, test_xb, test_yb, test_d, test_tof = (
@@ -225,7 +239,7 @@ def test_get_de_velocity(de_dataset, yf_fixture):
225
239
  for col in ["Xf", "Yf", "Xb", "Yb", "d", "TOF"]
226
240
  )
227
241
 
228
- v = get_de_velocity(
242
+ v, vhat, r = get_de_velocity(
229
243
  (test_xf, test_yf),
230
244
  (test_xb, test_yb),
231
245
  test_d,
@@ -252,24 +266,60 @@ def test_get_de_velocity(de_dataset, yf_fixture):
252
266
  atol=1e-01,
253
267
  rtol=0,
254
268
  )
269
+ np.testing.assert_allclose(
270
+ vhat[test_tof > 0][:, 0],
271
+ df_ph["vhatX"].astype("float").values[test_tof > 0],
272
+ atol=1e-01,
273
+ rtol=0,
274
+ )
275
+ np.testing.assert_allclose(
276
+ vhat[test_tof > 0][:, 1],
277
+ df_ph["vhatY"].astype("float").values[test_tof > 0],
278
+ atol=1e-01,
279
+ rtol=0,
280
+ )
281
+ np.testing.assert_allclose(
282
+ vhat[test_tof > 0][:, 2],
283
+ df_ph["vhatZ"].astype("float").values[test_tof > 0],
284
+ atol=1e-01,
285
+ rtol=0,
286
+ )
287
+ np.testing.assert_allclose(
288
+ r[test_tof > 0][:, 0],
289
+ -df_ph["vhatX"].astype("float").values[test_tof > 0],
290
+ atol=1e-01,
291
+ rtol=0,
292
+ )
293
+ np.testing.assert_allclose(
294
+ r[test_tof > 0][:, 1],
295
+ -df_ph["vhatY"].astype("float").values[test_tof > 0],
296
+ atol=1e-01,
297
+ rtol=0,
298
+ )
299
+ np.testing.assert_allclose(
300
+ r[test_tof > 0][:, 2],
301
+ -df_ph["vhatZ"].astype("float").values[test_tof > 0],
302
+ atol=1e-01,
303
+ rtol=0,
304
+ )
255
305
 
256
306
 
257
- def test_get_ssd_tof(de_dataset, yf_fixture):
307
+ def test_get_ssd_tof(test_fixture):
258
308
  """Tests get_ssd_tof function."""
259
- df_filt, _, _ = yf_fixture
309
+ df_filt, _, _, de_dataset = test_fixture
260
310
  df_ssd = df_filt[np.isin(df_filt["StopType"], [StopType.SSD.value])]
261
311
  test_xf = df_filt["Xf"].astype("float").values
262
312
 
263
- ssd_tof = get_ssd_tof(de_dataset, test_xf)
313
+ ssd_tof = get_ssd_tof(de_dataset, test_xf, "ultra45")
264
314
 
265
315
  np.testing.assert_allclose(
266
316
  ssd_tof, df_ssd["TOF"].astype("float"), atol=1e-05, rtol=0
267
317
  )
268
318
 
269
319
 
270
- def test_get_de_energy_kev(de_dataset, yf_fixture):
320
+ def test_get_de_energy_kev(test_fixture):
271
321
  """Tests get_de_energy_kev function."""
272
- df_filt, _, _ = yf_fixture
322
+ df_filt, _, _, _ = test_fixture
273
323
  df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])]
274
324
  df_ph = df_ph[df_ph["energy_revised"].astype("str") != "FILL"]
275
325
 
@@ -283,7 +333,7 @@ def test_get_de_energy_kev(de_dataset, yf_fixture):
283
333
  for col in ["Xf", "Yf", "Xb", "Yb", "d", "TOF"]
284
334
  )
285
335
 
286
- v = get_de_velocity(
336
+ v, v_hat, r_hat = get_de_velocity(
287
337
  (test_xf, test_yf),
288
338
  (test_xb, test_yb),
289
339
  test_d,
@@ -291,46 +341,50 @@ def test_get_de_energy_kev(de_dataset, yf_fixture):
291
341
  )
292
342
 
293
343
  energy = get_de_energy_kev(v, species_bin_ph)
294
- index_hydrogen = np.where(species_bin_ph == "H")
344
+ index_hydrogen = np.where(species_bin_ph == 1)
295
345
  actual_energy = energy[index_hydrogen[0]]
296
346
  expected_energy = df_ph["energy_revised"].astype("float")
297
347
 
298
348
  np.testing.assert_allclose(actual_energy, expected_energy, atol=1e-01, rtol=0)
299
349
 
300
350
 
301
- def test_get_energy_ssd(de_dataset, yf_fixture):
351
+ def test_get_energy_ssd(test_fixture):
302
352
  """Tests get_energy_ssd function."""
303
- df_filt, _, _ = yf_fixture
353
+ df_filt, _, _, de_dataset = test_fixture
304
354
  df_ssd = df_filt[np.isin(df_filt["StopType"], [StopType.SSD.value])]
305
- _, _, ssd_number = get_ssd_back_position_and_tof_offset(de_dataset)
355
+ _, _, ssd_number = get_ssd_back_position_and_tof_offset(de_dataset, "ultra45")
306
356
  energy = get_energy_ssd(de_dataset, ssd_number)
307
357
  test_energy = df_ssd["Energy"].astype("float")
308
358
 
309
359
  assert np.array_equal(test_energy, energy)
310
360
 
311
361
 
312
- def test_get_energy_pulse_height(de_dataset, yf_fixture):
362
+ def test_get_energy_pulse_height(test_fixture):
313
363
  """Tests get_energy_ssd function."""
314
- df_filt, _, _ = yf_fixture
364
+ df_filt, _, _, de_dataset = test_fixture
315
365
  df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])]
316
366
  ph_indices = np.nonzero(
317
- np.isin(de_dataset["STOP_TYPE"], [StopType.Top.value, StopType.Bottom.value])
367
+ np.isin(de_dataset["stop_type"], [StopType.Top.value, StopType.Bottom.value])
318
368
  )[0]
319
369
 
320
370
  test_xb = df_filt["Xb"].astype("float").values
321
371
  test_yb = df_filt["Yb"].astype("float").values
322
372
 
323
373
  energy = get_energy_pulse_height(
324
- de_dataset["STOP_TYPE"].data, de_dataset["ENERGY_PH"].data, test_xb, test_yb
374
+ de_dataset["stop_type"].data,
375
+ de_dataset["energy_ph"].data,
376
+ test_xb,
377
+ test_yb,
378
+ "ultra45",
325
379
  )
326
380
  test_energy = df_ph["Energy"].astype("float")
327
381
 
328
382
  assert np.array_equal(test_energy, energy[ph_indices])
329
383
 
330
384
 
331
- def test_get_ctof(yf_fixture):
385
+ def test_get_ctof(test_fixture):
332
386
  """Tests get_ctof function."""
333
- df_filt, _, _ = yf_fixture
387
+ df_filt, _, _, _ = test_fixture
334
388
  df_filt = df_filt[df_filt["eTOF"].astype("str") != "FILL"]
335
389
  df_filt = df_filt[df_filt["cTOF"].astype("float") > 0]
336
390
 
@@ -363,9 +417,9 @@ def test_get_ctof(yf_fixture):
363
417
  )
364
418
 
365
419
 
366
- def test_determine_species(yf_fixture):
420
+ def test_determine_species(test_fixture):
367
421
  """Tests determine_species function."""
368
- df_filt, _, _ = yf_fixture
422
+ df_filt, _, _, _ = test_fixture
369
423
  df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])]
370
424
  df_ssd = df_filt[np.isin(df_filt["StopType"], [StopType.SSD.value])]
371
425
 
@@ -380,13 +434,13 @@ def test_determine_species(yf_fixture):
380
434
  "SSD",
381
435
  )
382
436
 
383
- h_indices_ph = np.where(species_bin_ph == "H")[0]
437
+ h_indices_ph = np.where(species_bin_ph == 1)[0]
384
438
  ctof_indices_ph = np.where(
385
439
  (df_ph["cTOF"].astype("float") > UltraConstants.CTOF_SPECIES_MIN)
386
440
  & (df_ph["cTOF"].astype("float") < UltraConstants.CTOF_SPECIES_MAX)
387
441
  )[0]
388
442
 
389
- h_indices_ssd = np.where(species_bin_ssd == "H")[0]
443
+ h_indices_ssd = np.where(species_bin_ssd == 1)[0]
390
444
  ctof_indices_ssd = np.where(
391
445
  (df_ssd["cTOF"].astype("float") > UltraConstants.CTOF_SPECIES_MIN)
392
446
  & (df_ssd["cTOF"].astype("float") < UltraConstants.CTOF_SPECIES_MAX)
@@ -396,27 +450,142 @@ def test_determine_species(yf_fixture):
396
450
  np.testing.assert_array_equal(h_indices_ssd, ctof_indices_ssd)
397
451
 
398
452
 
399
- def test_get_de_az_el(de_dataset, yf_fixture):
400
- """Tests get_de_az_el function."""
401
- df_filt, _, _ = yf_fixture
402
- df_filt = df_filt[
403
- (df_filt["event_theta"].astype("str") != "FILL")
404
- & (df_filt["TOF"].astype("float") >= 0)
405
- ]
406
- df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])]
453
+ def test_get_phi_theta(test_fixture):
454
+ """Tests get_phi_theta function."""
455
+ df_filt, d, _, _ = test_fixture
407
456
 
408
- test_xf, test_yf, test_xb, test_yb, test_d, test_tof = (
409
- df_ph[col].astype("float").values
410
- for col in ["Xf", "Yf", "Xb", "Yb", "d", "TOF"]
457
+ test_xf = df_filt["Xf"].astype("float").values
458
+ test_yf = df_filt["Yf"].astype("float").values
459
+
460
+ test_xb = df_filt["Xb"].astype("float").values
461
+ test_yb = df_filt["Yb"].astype("float").values
462
+
463
+ phi, theta = get_phi_theta((test_xf, test_yf), (test_xb, test_yb), d)
464
+ expected_phi = df_filt["phi"].astype("float")
465
+ expected_theta = df_filt["theta"].astype("float")
466
+
467
+ np.testing.assert_allclose(phi, expected_phi, atol=1e-03, rtol=0)
468
+ np.testing.assert_allclose(theta, expected_theta, atol=1e-03, rtol=0)
469
+
470
+
471
+ def test_get_eventtimes(test_fixture, use_fake_spin_data_for_time):
472
+ """Tests get_eventtimes function."""
473
+ df_filt, _, _, de_dataset = test_fixture
474
+ # Create a spin table that cover spin 0-141
475
+ use_fake_spin_data_for_time(0, 141 * 15)
476
+
477
+ event_times, spin_starts, spin_period_sec = get_eventtimes(
478
+ de_dataset["spin"].values, de_dataset["phase_angle"].values
411
479
  )
412
480
 
413
- v = get_de_velocity(
414
- (test_xf, test_yf),
415
- (test_xb, test_yb),
416
- test_d,
417
- test_tof,
481
+ spin_df = get_spin_data()
482
+ expected_min_df = spin_df[spin_df["spin_number"] == de_dataset["spin"].values.min()]
483
+ expected_max_df = spin_df[spin_df["spin_number"] == de_dataset["spin"].values.max()]
484
+ spin_period_sec_min = expected_min_df["spin_period_sec"].values[0]
485
+ spin_period_sec_max = expected_max_df["spin_period_sec"].values[0]
486
+
487
+ spin_start_min = (
488
+ expected_min_df["spin_start_sec_sclk"]
489
+ + expected_min_df["spin_start_subsec_sclk"] / 1e6
490
+ )
491
+ spin_start_max = (
492
+ expected_max_df["spin_start_sec_sclk"]
493
+ + expected_max_df["spin_start_subsec_sclk"] / 1e6
494
+ )
495
+
496
+ assert spin_start_min.values[0] == spin_starts.min()
497
+ assert spin_start_max.values[0] == spin_starts.max()
498
+
499
+ event_times_min = spin_start_min.values[0] + spin_period_sec_min * (
500
+ de_dataset["phase_angle"][0] / 720
501
+ )
502
+ event_times_max = spin_start_max.values[0] + spin_period_sec_max * (
503
+ de_dataset["phase_angle"][-1] / 720
504
+ )
505
+
506
+ assert event_times_min == event_times.min()
507
+ assert event_times_max == event_times.max()
508
+
509
+
510
+ def test_interpolate_fwhm():
511
+ """Tests interpolate_fwhm function."""
512
+
513
+ # Test interpolation of FWHM values
514
+ test_phi = np.linspace(1, 53, 40)
515
+ test_theta = np.linspace(-44, 43, 40)
516
+ test_energy = np.full(test_theta.shape, 10)
517
+ lt_table = get_angular_profiles("left", "ultra45")
518
+
519
+ phi_interp, theta_interp = interpolate_fwhm(
520
+ lt_table, test_energy, test_phi, test_theta
521
+ )
522
+
523
+ lt_table_e10 = lt_table[lt_table.Energy == 10]
524
+ lt_table_test = lt_table_e10.sort_values("phi_degrees")
525
+ phi_fwhm_expected = np.interp(
526
+ test_phi, lt_table_test.phi_degrees, lt_table_test.phi_fwhm
527
+ )
528
+
529
+ np.testing.assert_allclose(phi_fwhm_expected, phi_interp, atol=1e-03, rtol=0)
530
+
531
+ # Test empty input
532
+ phi_interp, theta_interp = interpolate_fwhm(
533
+ lt_table, np.array([]), np.array([]), np.array([])
534
+ )
535
+
536
+ assert phi_interp.size == 0
537
+ assert theta_interp.size == 0
538
+
539
+
540
+ def test_get_fwhm():
541
+ """Tests get_fwhm function."""
542
+
543
+ test_phi = np.linspace(1, 53, 40)
544
+ test_theta = np.linspace(-44, 43, 40)
545
+ test_energy = np.full(test_phi.shape, 10)
546
+ test_start_type = np.empty(test_theta.shape, dtype=int)
547
+ test_start_type[:20] = 1 # First half -> Left
548
+ test_start_type[20:] = 2 # Second half -> Right
549
+
550
+ phi_interp, theta_interp = get_fwhm(
551
+ start_type=test_start_type,
552
+ sensor="ultra45",
553
+ energy=test_energy,
554
+ phi_inst=test_phi,
555
+ theta_inst=test_theta,
556
+ )
557
+
558
+ idx_left = test_start_type == StartType.Left.value
559
+ test_phi_left = test_phi[idx_left]
560
+
561
+ lt_table = get_angular_profiles("left", "ultra45")
562
+ lt_table_e10 = lt_table[lt_table.Energy == 10]
563
+ lt_table_sorted = lt_table_e10.sort_values("phi_degrees")
564
+
565
+ phi_expected_left = np.interp(
566
+ test_phi_left,
567
+ lt_table_sorted.phi_degrees.values,
568
+ lt_table_sorted.phi_fwhm.values,
569
+ )
570
+
571
+ np.testing.assert_allclose(
572
+ phi_interp[idx_left], phi_expected_left, atol=1e-3, rtol=0
418
573
  )
419
- az, _ = get_de_az_el(v)
420
- expected_phi = df_ph["event_phi"].astype("float")
421
574
 
422
- np.testing.assert_allclose(az, expected_phi % (2 * np.pi), atol=1e-03, rtol=0)
575
+ assert phi_interp.shape == test_phi.shape
576
+ assert theta_interp.shape == test_theta.shape
577
+
578
+
579
+ @pytest.mark.external_test_data
580
+ def test_get_efficiency():
581
+ """Tests get_efficiency function."""
582
+
583
+ # spot check
584
+ theta = np.array([-52.7, 52.7, -52.7, -52.7])
585
+ phi = np.array([-60, 60, -60, -50])
586
+ energy = np.array([3, 80, 39.75, 7])
587
+
588
+ efficiency = get_efficiency(energy, phi, theta)
589
+ expected_efficiency = np.array([0.0593281, 0.21803386, 0.0593281, 0.0628940])
590
+
591
+ np.testing.assert_allclose(efficiency, expected_efficiency, atol=1e-03, rtol=0)
@@ -6,7 +6,7 @@ from imap_processing.ultra.l1c.ultra_l1c import ultra_l1c
6
6
  from imap_processing.ultra.utils.ultra_l1_utils import create_dataset
7
7
 
8
8
 
9
- @pytest.fixture()
9
+ @pytest.fixture
10
10
  def mock_data_l1b_dict():
11
11
  # Create sample data for the xarray Dataset
12
12
  epoch = np.arange(
@@ -55,7 +55,7 @@ def mock_data_l1b_dict():
55
55
  return data_dict
56
56
 
57
57
 
58
- @pytest.fixture()
58
+ @pytest.fixture
59
59
  def mock_data_l1c_dict():
60
60
  epoch = np.array(
61
61
  [760591786368000000, 760591787368000000, 760591788368000000],
@@ -68,7 +68,7 @@ def mock_data_l1c_dict():
68
68
  def test_create_dataset(mock_data_l1c_dict):
69
69
  """Tests that dataset is created as expected."""
70
70
  dataset = create_dataset(
71
- mock_data_l1c_dict, "imap_ultra_l1c_45sensor-histogram", "l1c", "001"
71
+ mock_data_l1c_dict, "imap_ultra_l1c_45sensor-histogram", "l1c"
72
72
  )
73
73
 
74
74
  assert "epoch" in dataset.coords
@@ -80,7 +80,7 @@ def test_create_dataset(mock_data_l1c_dict):
80
80
 
81
81
  def test_ultra_l1c(mock_data_l1b_dict):
82
82
  """Tests that L1c data is created."""
83
- output_datasets = ultra_l1c(mock_data_l1b_dict, data_version="001")
83
+ output_datasets = ultra_l1c(mock_data_l1b_dict)
84
84
 
85
85
  assert len(output_datasets) == 1
86
86
  assert (
@@ -101,4 +101,4 @@ def test_ultra_l1c_error(mock_data_l1b_dict):
101
101
  with pytest.raises(
102
102
  ValueError, match="Data dictionary does not contain the expected keys."
103
103
  ):
104
- ultra_l1c(mock_data_l1b_dict, data_version="001")
104
+ ultra_l1c(mock_data_l1b_dict)