imap-processing 0.18.0__py3-none-any.whl → 0.19.2__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 (122) hide show
  1. imap_processing/_version.py +2 -2
  2. imap_processing/ancillary/ancillary_dataset_combiner.py +161 -1
  3. imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +6 -0
  4. imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +221 -1057
  5. imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +307 -283
  6. imap_processing/cdf/config/imap_codice_l2_variable_attrs.yaml +1044 -203
  7. imap_processing/cdf/config/imap_constant_attrs.yaml +4 -2
  8. imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml +11 -0
  9. imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +15 -1
  10. imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +5 -0
  11. imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +10 -4
  12. imap_processing/cdf/config/imap_idex_l2a_variable_attrs.yaml +33 -4
  13. imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml +8 -91
  14. imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml +106 -16
  15. imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +5 -4
  16. imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +4 -15
  17. imap_processing/cdf/config/imap_lo_l1c_variable_attrs.yaml +189 -98
  18. imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +85 -2
  19. imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +24 -1
  20. imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +20 -8
  21. imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +45 -35
  22. imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +110 -7
  23. imap_processing/cli.py +138 -93
  24. imap_processing/codice/codice_l0.py +2 -1
  25. imap_processing/codice/codice_l1a.py +167 -69
  26. imap_processing/codice/codice_l1b.py +42 -32
  27. imap_processing/codice/codice_l2.py +215 -9
  28. imap_processing/codice/constants.py +790 -603
  29. imap_processing/codice/data/lo_stepping_values.csv +1 -1
  30. imap_processing/decom.py +1 -4
  31. imap_processing/ena_maps/ena_maps.py +71 -43
  32. imap_processing/ena_maps/utils/corrections.py +291 -0
  33. imap_processing/ena_maps/utils/map_utils.py +20 -4
  34. imap_processing/ena_maps/utils/naming.py +8 -2
  35. imap_processing/glows/ancillary/imap_glows_exclusions-by-instr-team_20250923_v002.dat +10 -0
  36. imap_processing/glows/ancillary/imap_glows_map-of-excluded-regions_20250923_v002.dat +393 -0
  37. imap_processing/glows/ancillary/imap_glows_map-of-uv-sources_20250923_v002.dat +593 -0
  38. imap_processing/glows/ancillary/imap_glows_pipeline-settings_20250923_v002.json +54 -0
  39. imap_processing/glows/ancillary/imap_glows_suspected-transients_20250923_v002.dat +10 -0
  40. imap_processing/glows/l1b/glows_l1b.py +123 -18
  41. imap_processing/glows/l1b/glows_l1b_data.py +358 -47
  42. imap_processing/glows/l2/glows_l2.py +11 -0
  43. imap_processing/hi/hi_l1a.py +124 -3
  44. imap_processing/hi/hi_l1b.py +154 -71
  45. imap_processing/hi/hi_l1c.py +4 -109
  46. imap_processing/hi/hi_l2.py +104 -60
  47. imap_processing/hi/utils.py +262 -8
  48. imap_processing/hit/l0/constants.py +3 -0
  49. imap_processing/hit/l0/decom_hit.py +3 -6
  50. imap_processing/hit/l1a/hit_l1a.py +311 -21
  51. imap_processing/hit/l1b/hit_l1b.py +54 -126
  52. imap_processing/hit/l2/hit_l2.py +6 -6
  53. imap_processing/ialirt/calculate_ingest.py +219 -0
  54. imap_processing/ialirt/constants.py +12 -2
  55. imap_processing/ialirt/generate_coverage.py +15 -2
  56. imap_processing/ialirt/l0/ialirt_spice.py +6 -2
  57. imap_processing/ialirt/l0/parse_mag.py +293 -42
  58. imap_processing/ialirt/l0/process_hit.py +5 -3
  59. imap_processing/ialirt/l0/process_swapi.py +41 -25
  60. imap_processing/ialirt/process_ephemeris.py +70 -14
  61. imap_processing/ialirt/utils/create_xarray.py +1 -1
  62. imap_processing/idex/idex_l0.py +2 -2
  63. imap_processing/idex/idex_l1a.py +2 -3
  64. imap_processing/idex/idex_l1b.py +2 -3
  65. imap_processing/idex/idex_l2a.py +130 -4
  66. imap_processing/idex/idex_l2b.py +158 -143
  67. imap_processing/idex/idex_utils.py +1 -3
  68. imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv +75 -0
  69. imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv +75 -0
  70. imap_processing/lo/l0/lo_science.py +25 -24
  71. imap_processing/lo/l1b/lo_l1b.py +93 -19
  72. imap_processing/lo/l1c/lo_l1c.py +273 -93
  73. imap_processing/lo/l2/lo_l2.py +949 -135
  74. imap_processing/lo/lo_ancillary.py +55 -0
  75. imap_processing/mag/l1a/mag_l1a.py +1 -0
  76. imap_processing/mag/l1a/mag_l1a_data.py +26 -0
  77. imap_processing/mag/l1b/mag_l1b.py +3 -2
  78. imap_processing/mag/l1c/interpolation_methods.py +14 -15
  79. imap_processing/mag/l1c/mag_l1c.py +23 -6
  80. imap_processing/mag/l1d/mag_l1d.py +57 -14
  81. imap_processing/mag/l1d/mag_l1d_data.py +202 -32
  82. imap_processing/mag/l2/mag_l2.py +2 -0
  83. imap_processing/mag/l2/mag_l2_data.py +14 -5
  84. imap_processing/quality_flags.py +23 -1
  85. imap_processing/spice/geometry.py +89 -39
  86. imap_processing/spice/pointing_frame.py +4 -8
  87. imap_processing/spice/repoint.py +78 -2
  88. imap_processing/spice/spin.py +28 -8
  89. imap_processing/spice/time.py +12 -22
  90. imap_processing/swapi/l1/swapi_l1.py +10 -4
  91. imap_processing/swapi/l2/swapi_l2.py +15 -17
  92. imap_processing/swe/l1b/swe_l1b.py +1 -2
  93. imap_processing/ultra/constants.py +30 -24
  94. imap_processing/ultra/l0/ultra_utils.py +9 -11
  95. imap_processing/ultra/l1a/ultra_l1a.py +1 -2
  96. imap_processing/ultra/l1b/badtimes.py +35 -11
  97. imap_processing/ultra/l1b/de.py +95 -31
  98. imap_processing/ultra/l1b/extendedspin.py +31 -16
  99. imap_processing/ultra/l1b/goodtimes.py +112 -0
  100. imap_processing/ultra/l1b/lookup_utils.py +281 -28
  101. imap_processing/ultra/l1b/quality_flag_filters.py +10 -1
  102. imap_processing/ultra/l1b/ultra_l1b.py +7 -7
  103. imap_processing/ultra/l1b/ultra_l1b_culling.py +169 -7
  104. imap_processing/ultra/l1b/ultra_l1b_extended.py +311 -69
  105. imap_processing/ultra/l1c/helio_pset.py +139 -37
  106. imap_processing/ultra/l1c/l1c_lookup_utils.py +289 -0
  107. imap_processing/ultra/l1c/spacecraft_pset.py +140 -29
  108. imap_processing/ultra/l1c/ultra_l1c.py +33 -24
  109. imap_processing/ultra/l1c/ultra_l1c_culling.py +92 -0
  110. imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +400 -292
  111. imap_processing/ultra/l2/ultra_l2.py +54 -11
  112. imap_processing/ultra/utils/ultra_l1_utils.py +37 -7
  113. imap_processing/utils.py +3 -4
  114. {imap_processing-0.18.0.dist-info → imap_processing-0.19.2.dist-info}/METADATA +2 -2
  115. {imap_processing-0.18.0.dist-info → imap_processing-0.19.2.dist-info}/RECORD +118 -109
  116. imap_processing/idex/idex_l2c.py +0 -84
  117. imap_processing/spice/kernels.py +0 -187
  118. imap_processing/ultra/l1b/cullingmask.py +0 -87
  119. imap_processing/ultra/l1c/histogram.py +0 -36
  120. {imap_processing-0.18.0.dist-info → imap_processing-0.19.2.dist-info}/LICENSE +0 -0
  121. {imap_processing-0.18.0.dist-info → imap_processing-0.19.2.dist-info}/WHEEL +0 -0
  122. {imap_processing-0.18.0.dist-info → imap_processing-0.19.2.dist-info}/entry_points.txt +0 -0
@@ -12,10 +12,12 @@ dataset = process_codice_l2(l1_filename)
12
12
  import logging
13
13
  from pathlib import Path
14
14
 
15
+ import numpy as np
15
16
  import xarray as xr
16
17
 
17
18
  from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
18
19
  from imap_processing.cdf.utils import load_cdf
20
+ from imap_processing.codice.constants import HALF_SPIN_LUT
19
21
 
20
22
  logger = logging.getLogger(__name__)
21
23
  logger.setLevel(logging.INFO)
@@ -52,21 +54,225 @@ def process_codice_l2(file_path: Path) -> xr.Dataset:
52
54
 
53
55
  # Get the L2 CDF attributes
54
56
  cdf_attrs = ImapCdfAttributes()
57
+ l2_dataset = add_dataset_attributes(l2_dataset, dataset_name, cdf_attrs)
58
+
59
+ # TODO: update list of datasets that need geometric factors (if needed)
60
+ # Compute geometric factors needed for intensity calculations
61
+ if dataset_name in [
62
+ "imap_codice_l2_lo-sw-species",
63
+ "imap_codice_l2_lo-nsw-species",
64
+ ]:
65
+ geometric_factors = compute_geometric_factors(l2_dataset)
66
+
67
+ if dataset_name in [
68
+ "imap_codice_l2_hi-counters-singles",
69
+ "imap_codice_l2_hi-counters-aggregated",
70
+ "imap_codice_l2_lo-counters-singles",
71
+ "imap_codice_l2_lo-counters-aggregated",
72
+ "imap_codice_l2_lo-sw-priority",
73
+ "imap_codice_l2_lo-nsw-priority",
74
+ ]:
75
+ # No changes needed. Just save to an L2 CDF file.
76
+ # TODO: May not even need L2 files for these products
77
+ pass
78
+
79
+ elif dataset_name == "imap_codice_l2_hi-direct-events":
80
+ # Convert the following data variables to physical units using
81
+ # calibration data:
82
+ # - ssd_energy
83
+ # - tof
84
+ # - elevation_angle
85
+ # - spin_angle
86
+ # These converted variables are *in addition* to the existing L1 variables
87
+ # The other data variables require no changes
88
+ # See section 11.1.2 of algorithm document
89
+ pass
90
+
91
+ elif dataset_name == "imap_codice_l2_hi-sectored":
92
+ # Convert the sectored count rates using equation described in section
93
+ # 11.1.3 of algorithm document.
94
+ pass
95
+
96
+ elif dataset_name == "imap_codice_l2_hi-omni":
97
+ # Calculate the omni-directional intensity for each species using
98
+ # equation described in section 11.1.4 of algorithm document
99
+ # hopefully this can also apply to hi-ialirt
100
+ pass
101
+
102
+ elif dataset_name == "imap_codice_l2_lo-direct-events":
103
+ # Convert the following data variables to physical units using
104
+ # calibration data:
105
+ # - apd_energy
106
+ # - elevation_angle
107
+ # - tof
108
+ # - spin_sector
109
+ # - esa_step
110
+ # These converted variables are *in addition* to the existing L1 variables
111
+ # The other data variables require no changes
112
+ # See section 11.1.2 of algorithm document
113
+ pass
114
+
115
+ elif dataset_name == "imap_codice_l2_lo-sw-angular":
116
+ # Calculate the sunward angular intensities using equation described in
117
+ # section 11.2.3 of algorithm document.
118
+ pass
119
+
120
+ elif dataset_name == "imap_codice_l2_lo-nsw-angular":
121
+ # Calculate the non-sunward angular intensities using equation described
122
+ # in section 11.2.3 of algorithm document.
123
+ pass
124
+
125
+ elif dataset_name == "imap_codice_l2_lo-sw-species":
126
+ # Calculate the sunward solar wind species intensities using equation
127
+ # described in section 11.2.4 of algorithm document.
128
+ # Calculate the pickup ion sunward solar wind intensities using equation
129
+ # described in section 11.2.4 of algorithm document.
130
+ # Hopefully this can also apply to lo-ialirt
131
+ # TODO: WIP - needs to be completed
132
+ l2_dataset = process_lo_sw_species(l2_dataset, geometric_factors)
133
+ pass
134
+
135
+ elif dataset_name == "imap_codice_l2_lo-nsw-species":
136
+ # Calculate the non-sunward solar wind species intensities using
137
+ # equation described in section 11.2.4 of algorithm document.
138
+ # Calculate the pickup ion non-sunward solar wind intensities using
139
+ # equation described in section 11.2.4 of algorithm document.
140
+ pass
141
+
142
+ logger.info(f"\nFinal data product:\n{l2_dataset}\n")
143
+
144
+ return l2_dataset
145
+
146
+
147
+ def add_dataset_attributes(
148
+ dataset: xr.Dataset, dataset_name: str, cdf_attrs: ImapCdfAttributes
149
+ ) -> xr.Dataset:
150
+ """
151
+ Add the global and variable attributes to the dataset.
152
+
153
+ Parameters
154
+ ----------
155
+ dataset : xarray.Dataset
156
+ The dataset to update.
157
+ dataset_name : str
158
+ The name of the dataset.
159
+ cdf_attrs : ImapCdfAttributes
160
+ The attribute manager for CDF attributes.
161
+
162
+ Returns
163
+ -------
164
+ xarray.Dataset
165
+ The updated dataset.
166
+ """
55
167
  cdf_attrs.add_instrument_global_attrs("codice")
56
168
  cdf_attrs.add_instrument_variable_attrs("codice", "l2")
57
169
 
58
170
  # Update the global attributes
59
- l2_dataset.attrs = cdf_attrs.get_global_attributes(dataset_name)
171
+ dataset.attrs = cdf_attrs.get_global_attributes(dataset_name)
60
172
 
61
173
  # Set the variable attributes
62
- for variable_name in l2_dataset:
63
- l2_dataset[variable_name].attrs = cdf_attrs.get_variable_attributes(
64
- variable_name, check_schema=False
65
- )
174
+ for variable_name in dataset.data_vars.keys():
175
+ try:
176
+ dataset[variable_name].attrs = cdf_attrs.get_variable_attributes(
177
+ variable_name, check_schema=False
178
+ )
179
+ except KeyError:
180
+ # Some variables may have a product descriptor prefix in the
181
+ # cdf attributes key if they are common to multiple products.
182
+ descriptor = dataset_name.split("imap_codice_l2_")[-1]
183
+ cdf_attrs_key = f"{descriptor}-{variable_name}"
184
+ try:
185
+ dataset[variable_name].attrs = cdf_attrs.get_variable_attributes(
186
+ f"{cdf_attrs_key}", check_schema=False
187
+ )
188
+ except KeyError:
189
+ logger.error(
190
+ f"Field '{variable_name}' and '{cdf_attrs_key}' not found in "
191
+ f"attribute manager."
192
+ )
193
+ return dataset
66
194
 
67
- # TODO: Add L2-specific algorithms/functionality here. For SIT-4, we can
68
- # just keep the data as-is.
69
195
 
70
- logger.info(f"\nFinal data product:\n{l2_dataset}\n")
196
+ def compute_geometric_factors(dataset: xr.Dataset) -> np.ndarray:
197
+ """
198
+ Calculate geometric factors needed for intensity calculations.
71
199
 
72
- return l2_dataset
200
+ Geometric factors are determined by comparing the half-spin values per
201
+ esa_step in the HALF_SPIN_LUT to the rgfo_half_spin values in the provided
202
+ L2 dataset.
203
+
204
+ If the half-spin value is less than the corresponding rgfo_half_spin value,
205
+ the geometric factor is set to 0.75 (full mode); otherwise, it is set to 0.5
206
+ (reduced mode).
207
+
208
+ NOTE: Half spin values are associated with ESA steps which corresponds to the
209
+ index of the energy_per_charge dimension that is between 0 and 127.
210
+
211
+ Parameters
212
+ ----------
213
+ dataset : xarray.Dataset
214
+ The L2 dataset containing rgfo_half_spin data variable.
215
+
216
+ Returns
217
+ -------
218
+ geometric_factors : np.ndarray
219
+ A 2D array of geometric factors with shape (epoch, esa_steps).
220
+ """
221
+ # Convert the HALF_SPIN_LUT to a reverse mapping of esa_step to half_spin
222
+ esa_step_to_half_spin_map = {
223
+ val: key for key, vals in HALF_SPIN_LUT.items() for val in vals
224
+ }
225
+
226
+ # Create a list of half_spin values corresponding to ESA steps (0 to 127)
227
+ half_spin_values = np.array(
228
+ [esa_step_to_half_spin_map[step] for step in range(128)]
229
+ )
230
+
231
+ # Expand dimensions to compare each rgfo_half_spin value against
232
+ # all half_spin_values
233
+ rgfo_half_spin = dataset.rgfo_half_spin.data[:, np.newaxis] # Shape: (epoch, 1)
234
+
235
+ # Perform the comparison and calculate geometric factors
236
+ geometric_factors = np.where(half_spin_values < rgfo_half_spin, 0.75, 0.5)
237
+
238
+ return geometric_factors
239
+
240
+
241
+ def process_lo_sw_species(
242
+ dataset: xr.Dataset, geometric_factors: np.ndarray
243
+ ) -> xr.Dataset:
244
+ """
245
+ Process the lo-sw-species L2 dataset to calculate species intensities.
246
+
247
+ Parameters
248
+ ----------
249
+ dataset : xarray.Dataset
250
+ The L2 dataset to process.
251
+ geometric_factors : np.ndarray
252
+ The geometric factors array with shape (epoch, esa_steps).
253
+
254
+ Returns
255
+ -------
256
+ xarray.Dataset
257
+ The updated L2 dataset with species intensities calculated.
258
+ """
259
+ # TODO: WIP - implement intensity calculations
260
+ # valid_solar_wind_vars = [
261
+ # "hplus",
262
+ # "heplusplus",
263
+ # "cplus4",
264
+ # "cplus5",
265
+ # "cplus6",
266
+ # "oplus5",
267
+ # "oplus6",
268
+ # "oplus7",
269
+ # "oplus8",
270
+ # "ne",
271
+ # "mg",
272
+ # "si",
273
+ # "fe_loq",
274
+ # "fe_hiq",
275
+ # ]
276
+ # valid_pick_up_ion_vars = ["heplus", "cnoplus"]
277
+
278
+ return dataset