imap-processing 0.7.0__py3-none-any.whl → 0.9.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 (172) hide show
  1. imap_processing/__init__.py +1 -1
  2. imap_processing/_version.py +2 -2
  3. imap_processing/ccsds/excel_to_xtce.py +36 -2
  4. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +1 -1
  5. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +145 -30
  6. imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +36 -36
  7. imap_processing/cdf/config/imap_hi_variable_attrs.yaml +136 -9
  8. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +14 -0
  9. imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +63 -1
  10. imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +9 -0
  11. imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +14 -7
  12. imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +577 -235
  13. imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +326 -0
  14. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +33 -23
  15. imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +24 -28
  16. imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +1 -0
  17. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +137 -79
  18. imap_processing/cdf/config/imap_variable_schema.yaml +13 -0
  19. imap_processing/cdf/imap_cdf_manager.py +31 -27
  20. imap_processing/cdf/utils.py +3 -5
  21. imap_processing/cli.py +25 -14
  22. imap_processing/codice/codice_l1a.py +153 -63
  23. imap_processing/codice/constants.py +10 -10
  24. imap_processing/codice/decompress.py +10 -11
  25. imap_processing/codice/utils.py +1 -0
  26. imap_processing/glows/l1a/glows_l1a.py +1 -2
  27. imap_processing/glows/l1b/glows_l1b.py +3 -3
  28. imap_processing/glows/l1b/glows_l1b_data.py +59 -37
  29. imap_processing/glows/l2/glows_l2_data.py +123 -0
  30. imap_processing/hi/l1a/hi_l1a.py +4 -4
  31. imap_processing/hi/l1a/histogram.py +107 -109
  32. imap_processing/hi/l1a/science_direct_event.py +92 -225
  33. imap_processing/hi/l1b/hi_l1b.py +85 -11
  34. imap_processing/hi/l1c/hi_l1c.py +23 -1
  35. imap_processing/hi/packet_definitions/TLM_HI_COMBINED_SCI.xml +3994 -0
  36. imap_processing/hi/utils.py +1 -1
  37. imap_processing/hit/hit_utils.py +221 -0
  38. imap_processing/hit/l0/constants.py +118 -0
  39. imap_processing/hit/l0/decom_hit.py +100 -156
  40. imap_processing/hit/l1a/hit_l1a.py +170 -184
  41. imap_processing/hit/l1b/hit_l1b.py +33 -153
  42. imap_processing/ialirt/l0/process_codicelo.py +153 -0
  43. imap_processing/ialirt/l0/process_hit.py +5 -5
  44. imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +281 -0
  45. imap_processing/ialirt/process_ephemeris.py +212 -0
  46. imap_processing/idex/idex_l1a.py +65 -84
  47. imap_processing/idex/idex_l1b.py +192 -0
  48. imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -0
  49. imap_processing/idex/packet_definitions/idex_packet_definition.xml +97 -595
  50. imap_processing/lo/l0/decompression_tables/decompression_tables.py +17 -1
  51. imap_processing/lo/l0/lo_science.py +45 -13
  52. imap_processing/lo/l1a/lo_l1a.py +76 -8
  53. imap_processing/lo/packet_definitions/lo_xtce.xml +8344 -1849
  54. imap_processing/mag/l0/decom_mag.py +4 -3
  55. imap_processing/mag/l1a/mag_l1a.py +12 -13
  56. imap_processing/mag/l1a/mag_l1a_data.py +1 -2
  57. imap_processing/mag/l1b/mag_l1b.py +90 -7
  58. imap_processing/spice/geometry.py +156 -16
  59. imap_processing/spice/time.py +144 -2
  60. imap_processing/swapi/l1/swapi_l1.py +4 -4
  61. imap_processing/swapi/l2/swapi_l2.py +1 -1
  62. imap_processing/swapi/packet_definitions/swapi_packet_definition.xml +1535 -446
  63. imap_processing/swe/l1b/swe_l1b_science.py +8 -8
  64. imap_processing/swe/l2/swe_l2.py +134 -17
  65. imap_processing/tests/ccsds/test_data/expected_output.xml +2 -1
  66. imap_processing/tests/ccsds/test_excel_to_xtce.py +4 -4
  67. imap_processing/tests/cdf/test_imap_cdf_manager.py +0 -10
  68. imap_processing/tests/codice/conftest.py +1 -17
  69. imap_processing/tests/codice/data/imap_codice_l0_raw_20241110_v001.pkts +0 -0
  70. imap_processing/tests/codice/test_codice_l0.py +8 -2
  71. imap_processing/tests/codice/test_codice_l1a.py +127 -107
  72. imap_processing/tests/codice/test_codice_l1b.py +1 -0
  73. imap_processing/tests/codice/test_decompress.py +7 -7
  74. imap_processing/tests/conftest.py +100 -58
  75. imap_processing/tests/glows/conftest.py +6 -0
  76. imap_processing/tests/glows/test_glows_l1b.py +9 -9
  77. imap_processing/tests/glows/test_glows_l1b_data.py +9 -9
  78. imap_processing/tests/hi/test_data/l0/H90_NHK_20241104.bin +0 -0
  79. imap_processing/tests/hi/test_data/l0/H90_sci_cnt_20241104.bin +0 -0
  80. imap_processing/tests/hi/test_data/l0/H90_sci_de_20241104.bin +0 -0
  81. imap_processing/tests/hi/test_data/l1a/imap_hi_l1a_45sensor-de_20250415_v000.cdf +0 -0
  82. imap_processing/tests/hi/test_hi_l1b.py +73 -3
  83. imap_processing/tests/hi/test_hi_l1c.py +10 -2
  84. imap_processing/tests/hi/test_l1a.py +31 -58
  85. imap_processing/tests/hi/test_science_direct_event.py +58 -0
  86. imap_processing/tests/hi/test_utils.py +4 -3
  87. imap_processing/tests/hit/test_data/sci_sample1.ccsds +0 -0
  88. imap_processing/tests/hit/{test_hit_decom.py → test_decom_hit.py} +95 -36
  89. imap_processing/tests/hit/test_hit_l1a.py +299 -179
  90. imap_processing/tests/hit/test_hit_l1b.py +231 -24
  91. imap_processing/tests/hit/test_hit_utils.py +218 -0
  92. imap_processing/tests/hit/validation_data/hskp_sample_eu.csv +89 -0
  93. imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +29 -0
  94. imap_processing/tests/ialirt/test_data/l0/apid01152.tlm +0 -0
  95. imap_processing/tests/ialirt/test_data/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
  96. imap_processing/tests/ialirt/unit/test_process_codicelo.py +106 -0
  97. imap_processing/tests/ialirt/unit/test_process_ephemeris.py +109 -0
  98. imap_processing/tests/ialirt/unit/test_process_hit.py +9 -6
  99. imap_processing/tests/idex/conftest.py +2 -2
  100. imap_processing/tests/idex/imap_idex_l0_raw_20231214_v001.pkts +0 -0
  101. imap_processing/tests/idex/impact_14_tof_high_data.txt +4444 -4444
  102. imap_processing/tests/idex/test_idex_l0.py +4 -4
  103. imap_processing/tests/idex/test_idex_l1a.py +8 -2
  104. imap_processing/tests/idex/test_idex_l1b.py +126 -0
  105. imap_processing/tests/lo/test_lo_l1a.py +7 -16
  106. imap_processing/tests/lo/test_lo_science.py +69 -5
  107. imap_processing/tests/lo/test_pkts/imap_lo_l0_raw_20240803_v002.pkts +0 -0
  108. imap_processing/tests/lo/validation_data/Instrument_FM1_T104_R129_20240803_ILO_SCI_DE_dec_DN_with_fills.csv +1999 -0
  109. imap_processing/tests/mag/imap_mag_l1a_norm-magi_20251017_v001.cdf +0 -0
  110. imap_processing/tests/mag/test_mag_l1b.py +97 -7
  111. imap_processing/tests/spice/test_data/imap_ena_sim_metakernel.template +3 -1
  112. imap_processing/tests/spice/test_geometry.py +115 -9
  113. imap_processing/tests/spice/test_time.py +135 -6
  114. imap_processing/tests/swapi/test_swapi_decom.py +75 -69
  115. imap_processing/tests/swapi/test_swapi_l1.py +4 -4
  116. imap_processing/tests/swe/conftest.py +33 -0
  117. imap_processing/tests/swe/l1_validation/swe_l0_unpacked-data_20240510_v001_VALIDATION_L1B_v3.dat +4332 -0
  118. imap_processing/tests/swe/test_swe_l1b.py +29 -8
  119. imap_processing/tests/swe/test_swe_l2.py +64 -8
  120. imap_processing/tests/test_utils.py +2 -2
  121. imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3314 -3314
  122. imap_processing/tests/ultra/test_data/l1/dps_exposure_helio_45_E12.cdf +0 -0
  123. imap_processing/tests/ultra/test_data/l1/dps_exposure_helio_45_E24.cdf +0 -0
  124. imap_processing/tests/ultra/unit/test_de.py +113 -0
  125. imap_processing/tests/ultra/unit/test_spatial_utils.py +125 -0
  126. imap_processing/tests/ultra/unit/test_ultra_l1b.py +27 -3
  127. imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +31 -10
  128. imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +55 -35
  129. imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +10 -68
  130. imap_processing/ultra/constants.py +12 -3
  131. imap_processing/ultra/l1b/de.py +168 -30
  132. imap_processing/ultra/l1b/ultra_l1b_annotated.py +24 -10
  133. imap_processing/ultra/l1b/ultra_l1b_extended.py +46 -80
  134. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +60 -144
  135. imap_processing/ultra/utils/spatial_utils.py +221 -0
  136. {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/METADATA +15 -14
  137. {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/RECORD +142 -139
  138. imap_processing/cdf/cdf_attribute_manager.py +0 -322
  139. imap_processing/cdf/config/shared/default_global_cdf_attrs_schema.yaml +0 -246
  140. imap_processing/cdf/config/shared/default_variable_cdf_attrs_schema.yaml +0 -466
  141. imap_processing/hi/l0/decom_hi.py +0 -24
  142. imap_processing/hi/packet_definitions/hi_packet_definition.xml +0 -482
  143. imap_processing/hit/l0/data_classes/housekeeping.py +0 -240
  144. imap_processing/hit/l0/data_classes/science_packet.py +0 -259
  145. imap_processing/hit/l0/utils/hit_base.py +0 -57
  146. imap_processing/tests/cdf/shared/default_global_cdf_attrs_schema.yaml +0 -246
  147. imap_processing/tests/cdf/shared/default_variable_cdf_attrs_schema.yaml +0 -466
  148. imap_processing/tests/cdf/test_cdf_attribute_manager.py +0 -353
  149. imap_processing/tests/codice/data/imap_codice_l0_hi-counters-aggregated_20240429_v001.pkts +0 -0
  150. imap_processing/tests/codice/data/imap_codice_l0_hi-counters-singles_20240429_v001.pkts +0 -0
  151. imap_processing/tests/codice/data/imap_codice_l0_hi-omni_20240429_v001.pkts +0 -0
  152. imap_processing/tests/codice/data/imap_codice_l0_hi-pha_20240429_v001.pkts +0 -0
  153. imap_processing/tests/codice/data/imap_codice_l0_hi-sectored_20240429_v001.pkts +0 -0
  154. imap_processing/tests/codice/data/imap_codice_l0_hskp_20100101_v001.pkts +0 -0
  155. imap_processing/tests/codice/data/imap_codice_l0_lo-counters-aggregated_20240429_v001.pkts +0 -0
  156. imap_processing/tests/codice/data/imap_codice_l0_lo-counters-singles_20240429_v001.pkts +0 -0
  157. imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-angular_20240429_v001.pkts +0 -0
  158. imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-priority_20240429_v001.pkts +0 -0
  159. imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-species_20240429_v001.pkts +0 -0
  160. imap_processing/tests/codice/data/imap_codice_l0_lo-pha_20240429_v001.pkts +0 -0
  161. imap_processing/tests/codice/data/imap_codice_l0_lo-sw-angular_20240429_v001.pkts +0 -0
  162. imap_processing/tests/codice/data/imap_codice_l0_lo-sw-priority_20240429_v001.pkts +0 -0
  163. imap_processing/tests/codice/data/imap_codice_l0_lo-sw-species_20240429_v001.pkts +0 -0
  164. imap_processing/tests/hi/test_decom.py +0 -55
  165. imap_processing/tests/hi/test_l1a_sci_de.py +0 -72
  166. imap_processing/tests/idex/imap_idex_l0_raw_20230725_v001.pkts +0 -0
  167. imap_processing/tests/mag/imap_mag_l1a_burst-magi_20231025_v001.cdf +0 -0
  168. /imap_processing/{hi/l0/__init__.py → tests/glows/test_glows_l2_data.py} +0 -0
  169. /imap_processing/tests/hit/test_data/{imap_hit_l0_hk_20100105_v001.pkts → imap_hit_l0_raw_20100105_v001.pkts} +0 -0
  170. {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/LICENSE +0 -0
  171. {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/WHEEL +0 -0
  172. {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/entry_points.txt +0 -0
@@ -95,7 +95,7 @@ def deadtime_correction(counts: np.ndarray, acq_duration: int) -> npt.NDArray:
95
95
  counts : numpy.ndarray
96
96
  Counts data before deadtime corrections.
97
97
  acq_duration : int
98
- This is ACQ_DURATION from science packet.
98
+ This is ACQ_DURATION from science packet. acq_duration is in microseconds.
99
99
 
100
100
  Returns
101
101
  -------
@@ -104,10 +104,10 @@ def deadtime_correction(counts: np.ndarray, acq_duration: int) -> npt.NDArray:
104
104
  """
105
105
  # deadtime is 360 ns
106
106
  deadtime = 360e-9
107
- correct = 1.0 - (deadtime * counts / (acq_duration / 1000.0))
107
+ correct = 1.0 - (deadtime * (counts / (acq_duration * 1e-6)))
108
108
  correct = np.maximum(0.1, correct)
109
109
  corrected_count = np.divide(counts, correct)
110
- return corrected_count
110
+ return corrected_count.astype(np.float64)
111
111
 
112
112
 
113
113
  def convert_counts_to_rate(data: np.ndarray, acq_duration: int) -> npt.NDArray:
@@ -121,17 +121,17 @@ def convert_counts_to_rate(data: np.ndarray, acq_duration: int) -> npt.NDArray:
121
121
  data : numpy.ndarray
122
122
  Counts data.
123
123
  acq_duration : int
124
- Acquisition duration. acq_duration is in millieseconds.
124
+ Acquisition duration. acq_duration is in microseconds.
125
125
 
126
126
  Returns
127
127
  -------
128
128
  numpy.ndarray
129
129
  Count rates array in seconds.
130
130
  """
131
- # convert milliseconds to seconds
132
- # Todo: check with SWE team about int or float types.
133
- acq_duration = int(acq_duration / 1000.0)
134
- return data / acq_duration
131
+ # convert microseconds to seconds
132
+ acq_duration_sec = acq_duration * 1e-6
133
+ count_rate = data / acq_duration_sec
134
+ return count_rate.astype(np.float64)
135
135
 
136
136
 
137
137
  def calculate_calibration_factor(time: int) -> None:
@@ -1,9 +1,14 @@
1
- """SWE L2 processing module."""
1
+ """
2
+ SWE L2 processing module.
3
+
4
+ This module contains functions to process L1B data to L2 data products.
5
+ """
2
6
 
3
7
  import numpy as np
4
8
  import numpy.typing as npt
5
9
  import xarray as xr
6
10
 
11
+ from imap_processing.spice.geometry import get_spacecraft_spin_phase
7
12
  from imap_processing.swe.utils.swe_utils import read_lookup_table
8
13
 
9
14
  # TODO: add these to instrument status summary
@@ -22,6 +27,9 @@ GEOMETRIC_FACTORS = np.array(
22
27
  )
23
28
  ELECTRON_MASS = 9.10938356e-31 # kg
24
29
 
30
+ # See doc string of calculate_phase_space_density() for more details.
31
+ VELOCITY_CONVERSION_FACTOR = 1.237e31
32
+
25
33
 
26
34
  def get_particle_energy() -> npt.NDArray:
27
35
  """
@@ -44,11 +52,11 @@ def get_particle_energy() -> npt.NDArray:
44
52
  return lookup_table
45
53
 
46
54
 
47
- def calculate_phase_space_density(l1b_dataset: xr.Dataset) -> npt.NDArray:
55
+ def calculate_phase_space_density(l1b_dataset: xr.Dataset) -> xr.Dataset:
48
56
  """
49
57
  Convert counts to phase space density.
50
58
 
51
- Calculate phase space density, fv, in units of s^3/cm^6
59
+ Calculate phase space density, fv, in units of s^3/ (cm^6 * ster).
52
60
  fv = 2 * (C/tau) / (G * v^4)
53
61
  where:
54
62
  C / tau = corrected count rate. L1B science data.
@@ -56,12 +64,26 @@ def calculate_phase_space_density(l1b_dataset: xr.Dataset) -> npt.NDArray:
56
64
  v = electron speed, computed from energy, in cm/s.
57
65
  We need to use this formula to convert energy to speed:
58
66
  E = 0.5 * m * v^2
59
- where E is electron energy, in eV
60
- (result from get_particle_energy() function),
61
- m is mass of electron (9.10938356e-31 kg),
62
- and v is what we want to calculate. Reorganizing above
63
- formula result in v = sqrt(2 * E / m). This will be used
64
- to calculate electron speed.
67
+ where E is electron energy, in eV
68
+ (result from get_particle_energy() function),
69
+ m is mass of electron (9.10938356e-31 kg),
70
+ and v is what we want to calculate. Reorganizing above
71
+ formula result in v = sqrt(2 * E / m). This will be used
72
+ to calculate electron speed, v.
73
+
74
+ Now to convert electron speed units to cm/s:
75
+ v = sqrt(2 * E / m)
76
+ = sqrt(2 * E(eV) * 1.60219e-19(J/eV) / 9.10938e-31 kg)
77
+ where J = kg * m^2 / s^2.
78
+ = sqrt(2 * 1.60219 * 10e−19 m^2/s^2 * E(eV) / 9.10938e-31)
79
+ = sqrt(2 * 1.60219 * 10e−19 * 10e4 cm^2/s^2 * E(eV) / 9.10938e-31)
80
+ = sqrt(3.20438 * 10e-15 * E(eV) / 9.10938e-31) cm/s
81
+ = sqrt( (3.20438 * 10e-15 / 9.10938e-31) * E(eV) ) cm/s
82
+ fv = 2 * (C/tau) / (G * v^4)
83
+ = 2 * (C/tau) / (G * (sqrt( (3.20438 * 10e-15 / 9.10938e-31) * E(eV) ))^4)
84
+ = 2 * (C/tau) / (G * (sqrt(3.5176e16)^4 * E(eV)^2)
85
+ = 2 * (C/tau) / (G * 1.237e31 * E(eV)^2)
86
+ Ruth Skoug also got the same result, 1.237e31.
65
87
 
66
88
  Parameters
67
89
  ----------
@@ -70,8 +92,9 @@ def calculate_phase_space_density(l1b_dataset: xr.Dataset) -> npt.NDArray:
70
92
 
71
93
  Returns
72
94
  -------
73
- density : numpy.ndarray
74
- Phase space density.
95
+ phase_space_density_dataset : xarray.Dataset
96
+ Phase space density. We need to call this phase space density because
97
+ there will be density in L3 processing.
75
98
  """
76
99
  # Get esa_table_num for each full sweep.
77
100
  esa_table_nums = l1b_dataset["esa_table_num"].values[:, 0]
@@ -87,13 +110,107 @@ def calculate_phase_space_density(l1b_dataset: xr.Dataset) -> npt.NDArray:
87
110
  )
88
111
  particle_energy_data = particle_energy_data.reshape(-1, 24, 30)
89
112
 
90
- # Calculate electron speed.
91
- electron_speed = np.sqrt(2 * particle_energy_data / ELECTRON_MASS)
92
-
93
- # Calculate phase space density.
113
+ # Calculate phase space density using formula:
114
+ # 2 * (C/tau) / (G * 1.237e31 * E(eV)^2)
115
+ # See doc string for more details.
94
116
  density = (2 * l1b_dataset["science_data"]) / (
95
117
  GEOMETRIC_FACTORS[np.newaxis, np.newaxis, np.newaxis, :]
96
- * electron_speed[:, :, :, np.newaxis] ** 4
118
+ * VELOCITY_CONVERSION_FACTOR
119
+ * particle_energy_data[:, :, :, np.newaxis] ** 2
120
+ )
121
+
122
+ # Return density as xr.dataset with phase space density and
123
+ # energy in eV value that flux calculation can use.
124
+ phase_space_density_dataset = xr.Dataset(
125
+ {
126
+ "phase_space_density": (["epoch", "energy", "angle", "cem"], density.data),
127
+ "energy_in_eV": (["epoch", "energy", "angle"], particle_energy_data),
128
+ },
129
+ coords=l1b_dataset.coords,
130
+ )
131
+
132
+ return phase_space_density_dataset
133
+
134
+
135
+ def calculate_flux(l1b_dataset: xr.Dataset) -> npt.NDArray:
136
+ """
137
+ Calculate flux.
138
+
139
+ To get flux, j = 2 * m * E * f
140
+ where:
141
+ f = calculate_phase_space_density() result
142
+ m - mass of electron
143
+ E - energy in joules. E(eV) * 1.60219e-19(J/eV)
144
+
145
+ To convert flux units:
146
+ j = 2 * m * E * f
147
+ = 2 * 9.10938356e-31 kg * E(eV) * 1.60219e-19(J/eV) * (s^3/ (cm^6 * ster)
148
+ = 2 * 9.10938356e-31 kg * E(eV) * 1.60219e-19 (kg * m^2 / s^2) *
149
+ (s^3 / (cm^6 * ster)
150
+ = 2 * 9.10938356e-31 * E(eV) * 1.60219e-19 kg^2 * ( 10^4 cm^2 / s^2) *
151
+ (s^3 / (cm^6 * ster)
152
+ = 2 * 9.10938356e-31 * E(eV) * 1.60219e-19 * 10^4 ((kg^2 * cm^2 * s^3) /
153
+ (s^2 * cm^6 * ster))
154
+ TODO: ask Ruth Skoug what units to use for flux and work out remaining units.
155
+
156
+ Parameters
157
+ ----------
158
+ l1b_dataset : xarray.Dataset
159
+ The L1B dataset to process.
160
+
161
+ Returns
162
+ -------
163
+ flux : numpy.ndarray
164
+ Flux values.
165
+ """
166
+ phase_space_density_ds = calculate_phase_space_density(l1b_dataset)
167
+ # TODO: update this once Ruth sends the correct conversion factors.
168
+ flux = (
169
+ 2
170
+ * ELECTRON_MASS
171
+ * phase_space_density_ds["energy_in_eV"].data[:, :, :, np.newaxis]
172
+ * 1.60219e-19
173
+ * 10e4
174
+ * phase_space_density_ds["phase_space_density"].data
97
175
  )
176
+ return flux
98
177
 
99
- return density
178
+
179
+ def swe_l2(l1b_dataset: xr.Dataset, data_version: str) -> xr.Dataset:
180
+ """
181
+ Will process data to L2.
182
+
183
+ Parameters
184
+ ----------
185
+ l1b_dataset : xarray.Dataset
186
+ The L1B dataset to process.
187
+ data_version : str
188
+ Version of the data product being created.
189
+
190
+ Returns
191
+ -------
192
+ data : xarray.Dataset
193
+ Processed data to L2.
194
+ """
195
+ flux = calculate_flux(l1b_dataset)
196
+
197
+ # Calculate spin phase using SWE sci_step_acq_time_sec calculated in l1b.
198
+ # L1B dataset stores it by (epoch, energy, angle, cem).
199
+ data_acq_time = l1b_dataset["sci_step_acq_time_sec"].data.flatten()
200
+
201
+ # calculate spin phase
202
+ spin_phase = get_spacecraft_spin_phase(
203
+ query_met_times=data_acq_time,
204
+ ).reshape(-1, 24, 30, 7)
205
+ # TODO: organize flux data by energy and spin_phase.
206
+ # My understanding from conversation with Ruth is that this is the hardest part
207
+ # and last part of the L2 processing.
208
+
209
+ # TODO: Correct return value. This is just a placeholder.
210
+ return xr.Dataset(
211
+ {
212
+ "flux": (["epoch", "energy", "spin_phase", "cem"], flux),
213
+ "spin_phase": (["epoch", "energy", "spin_phase", "cem"], spin_phase),
214
+ },
215
+ coords=l1b_dataset.coords,
216
+ )
@@ -1,6 +1,6 @@
1
1
  <?xml version='1.0' encoding='utf-8'?>
2
2
  <xtce:SpaceSystem xmlns:xtce="http://www.omg.org/space/xtce" name="Test Instrument">
3
- <xtce:Header date="2024-07-26 00:00:00" version="v1.2" author="IMAP SDC" />
3
+ <xtce:Header date="2024-07-26 00:00:00" version="v1.2" author="IMAP SDC" source_file="excel_to_xtce_test_file.xlsx" />
4
4
  <xtce:TelemetryMetaData>
5
5
  <xtce:ParameterTypeSet>
6
6
  <xtce:IntegerParameterType name="VERSION" signed="false">
@@ -64,6 +64,7 @@
64
64
  <xtce:EnumerationList>
65
65
  <xtce:Enumeration value="0" label="OFF" />
66
66
  <xtce:Enumeration value="1" label="ON" />
67
+ <xtce:Enumeration value="2" label="NONE" />
67
68
  </xtce:EnumerationList>
68
69
  </xtce:EnumeratedParameterType>
69
70
  <xtce:IntegerParameterType name="TEST_PACKET2.SHCOARSE" signed="false">
@@ -195,10 +195,10 @@ def xtce_excel_file(tmp_path):
195
195
  }
196
196
 
197
197
  states = {
198
- "packetName": ["TEST_PACKET"] * 2,
199
- "mnemonic": ["VAR_STATE"] * 2,
200
- "value": [0, 1],
201
- "state": ["OFF", "ON"],
198
+ "packetName": ["TEST_PACKET"] * 3,
199
+ "mnemonic": ["VAR_STATE"] * 3,
200
+ "value": [0, 1, "0x2"],
201
+ "state": ["OFF", "ON", "NONE"],
202
202
  }
203
203
 
204
204
  # Write the DataFrame to an excel file
@@ -1,5 +1,4 @@
1
1
  from pathlib import Path
2
- from unittest import mock
3
2
 
4
3
  # from imap_processing.cdf.cdf_attribute_manager import CdfAttributeManager
5
4
  from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
@@ -25,15 +24,6 @@ def test_add_instrument_global_attrs():
25
24
  assert instrument2_instrument["Project"] == "STP>Solar Terrestrial Probes"
26
25
 
27
26
 
28
- @mock.patch(
29
- "imap_processing.cdf.cdf_attribute_manager.CdfAttributeManager.load_variable_attributes"
30
- )
31
- def testing_source_dir(mock_load_variable_attributes):
32
- # Create an ImapCdfAttributes object
33
- imap_cdf_manager = ImapCdfAttributes(Path(__file__).parent.parent / "cdf")
34
- assert str(imap_cdf_manager.source_dir) == str(Path(__file__).parent.parent / "cdf")
35
-
36
-
37
27
  def test_add_instrument_variable_attrs():
38
28
  # Create an ImapCdfAttributes object
39
29
  imap_cdf_manager = ImapCdfAttributes()
@@ -2,23 +2,7 @@ from imap_processing import imap_module_directory
2
2
 
3
3
  TEST_DATA_PATH = imap_module_directory / "tests" / "codice" / "data"
4
4
 
5
- TEST_PACKETS = [
6
- TEST_DATA_PATH / "imap_codice_l0_hskp_20100101_v001.pkts",
7
- TEST_DATA_PATH / "imap_codice_l0_hi-counters-aggregated_20240429_v001.pkts",
8
- TEST_DATA_PATH / "imap_codice_l0_hi-counters-singles_20240429_v001.pkts",
9
- TEST_DATA_PATH / "imap_codice_l0_hi-omni_20240429_v001.pkts",
10
- TEST_DATA_PATH / "imap_codice_l0_hi-sectored_20240429_v001.pkts",
11
- TEST_DATA_PATH / "imap_codice_l0_hi-pha_20240429_v001.pkts",
12
- TEST_DATA_PATH / "imap_codice_l0_lo-counters-aggregated_20240429_v001.pkts",
13
- TEST_DATA_PATH / "imap_codice_l0_lo-counters-singles_20240429_v001.pkts",
14
- TEST_DATA_PATH / "imap_codice_l0_lo-sw-angular_20240429_v001.pkts",
15
- TEST_DATA_PATH / "imap_codice_l0_lo-nsw-angular_20240429_v001.pkts",
16
- TEST_DATA_PATH / "imap_codice_l0_lo-sw-priority_20240429_v001.pkts",
17
- TEST_DATA_PATH / "imap_codice_l0_lo-nsw-priority_20240429_v001.pkts",
18
- TEST_DATA_PATH / "imap_codice_l0_lo-sw-species_20240429_v001.pkts",
19
- TEST_DATA_PATH / "imap_codice_l0_lo-nsw-species_20240429_v001.pkts",
20
- TEST_DATA_PATH / "imap_codice_l0_lo-pha_20240429_v001.pkts",
21
- ]
5
+ TEST_L0_FILE = TEST_DATA_PATH / "imap_codice_l0_raw_20241110_v001.pkts"
22
6
 
23
7
  TEST_L1A_FILES = [
24
8
  TEST_DATA_PATH / "imap_codice_l1a_hskp_20100101_v001.pkts",
@@ -37,7 +37,7 @@ def decom_test_data() -> xr.Dataset:
37
37
 
38
38
  packet_file = Path(
39
39
  f"{imap_module_directory}/tests/codice/data/"
40
- f"imap_codice_l0_hskp_20100101_v001.pkts"
40
+ f"imap_codice_l0_raw_20241110_v001.pkts"
41
41
  )
42
42
 
43
43
  packet = codice_l0.decom_packets(packet_file)[1136]
@@ -69,6 +69,9 @@ def validation_data() -> pd.core.frame.DataFrame:
69
69
  return validation_data
70
70
 
71
71
 
72
+ @pytest.mark.xfail(
73
+ reason="Need to update to validate against new validation CDFs. See issue #1154."
74
+ )
72
75
  def test_eu_hskp_data(
73
76
  decom_test_data: xr.Dataset,
74
77
  validation_data: pd.core.frame.DataFrame,
@@ -106,6 +109,9 @@ def test_eu_hskp_data(
106
109
  assert round(eu_val, 5) == round(validation_val, 5)
107
110
 
108
111
 
112
+ @pytest.mark.xfail(
113
+ reason="Need to update to validate against new validation CDFs. See issue #1154."
114
+ )
109
115
  def test_raw_hskp_data(
110
116
  decom_test_data: xr.Dataset,
111
117
  validation_data: pd.core.frame.DataFrame,
@@ -140,5 +146,5 @@ def test_total_packets_in_data_file(decom_test_data: xr.Dataset):
140
146
  The decommutated housekeeping packet
141
147
  """
142
148
 
143
- total_packets = 99
149
+ total_packets = 31778
144
150
  assert len(decom_test_data.epoch) == total_packets