imap-processing 0.18.0__py3-none-any.whl → 0.19.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.
- imap_processing/_version.py +2 -2
- imap_processing/ancillary/ancillary_dataset_combiner.py +161 -1
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +301 -274
- imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +28 -28
- imap_processing/cdf/config/imap_codice_l2_variable_attrs.yaml +1044 -203
- imap_processing/cdf/config/imap_constant_attrs.yaml +4 -2
- imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +12 -0
- imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +5 -0
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +10 -4
- imap_processing/cdf/config/imap_idex_l2a_variable_attrs.yaml +33 -4
- imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml +8 -91
- imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml +106 -16
- imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +4 -15
- imap_processing/cdf/config/imap_lo_l1c_variable_attrs.yaml +189 -98
- imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +85 -2
- imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +24 -1
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +12 -4
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +50 -7
- imap_processing/cli.py +95 -41
- imap_processing/codice/codice_l1a.py +131 -31
- imap_processing/codice/codice_l2.py +118 -10
- imap_processing/codice/constants.py +740 -595
- imap_processing/decom.py +1 -4
- imap_processing/ena_maps/ena_maps.py +32 -25
- imap_processing/ena_maps/utils/naming.py +8 -2
- imap_processing/glows/ancillary/imap_glows_exclusions-by-instr-team_20250923_v002.dat +10 -0
- imap_processing/glows/ancillary/imap_glows_map-of-excluded-regions_20250923_v002.dat +393 -0
- imap_processing/glows/ancillary/imap_glows_map-of-uv-sources_20250923_v002.dat +593 -0
- imap_processing/glows/ancillary/imap_glows_pipeline_settings_20250923_v002.json +54 -0
- imap_processing/glows/ancillary/imap_glows_suspected-transients_20250923_v002.dat +10 -0
- imap_processing/glows/l1b/glows_l1b.py +99 -9
- imap_processing/glows/l1b/glows_l1b_data.py +350 -38
- imap_processing/glows/l2/glows_l2.py +11 -0
- imap_processing/hi/hi_l1a.py +124 -3
- imap_processing/hi/hi_l1b.py +154 -71
- imap_processing/hi/hi_l2.py +84 -51
- imap_processing/hi/utils.py +153 -8
- imap_processing/hit/l0/constants.py +3 -0
- imap_processing/hit/l0/decom_hit.py +3 -6
- imap_processing/hit/l1a/hit_l1a.py +311 -21
- imap_processing/hit/l1b/hit_l1b.py +54 -126
- imap_processing/hit/l2/hit_l2.py +6 -6
- imap_processing/ialirt/calculate_ingest.py +219 -0
- imap_processing/ialirt/constants.py +12 -2
- imap_processing/ialirt/generate_coverage.py +15 -2
- imap_processing/ialirt/l0/ialirt_spice.py +5 -2
- imap_processing/ialirt/l0/parse_mag.py +293 -42
- imap_processing/ialirt/l0/process_hit.py +5 -3
- imap_processing/ialirt/l0/process_swapi.py +41 -25
- imap_processing/ialirt/process_ephemeris.py +70 -14
- imap_processing/idex/idex_l0.py +2 -2
- imap_processing/idex/idex_l1a.py +2 -3
- imap_processing/idex/idex_l1b.py +2 -3
- imap_processing/idex/idex_l2a.py +130 -4
- imap_processing/idex/idex_l2b.py +158 -143
- imap_processing/idex/idex_utils.py +1 -3
- imap_processing/lo/l0/lo_science.py +25 -24
- imap_processing/lo/l1b/lo_l1b.py +3 -3
- imap_processing/lo/l1c/lo_l1c.py +116 -50
- imap_processing/lo/l2/lo_l2.py +29 -29
- imap_processing/lo/lo_ancillary.py +55 -0
- imap_processing/mag/l1a/mag_l1a.py +1 -0
- imap_processing/mag/l1a/mag_l1a_data.py +26 -0
- imap_processing/mag/l1b/mag_l1b.py +3 -2
- imap_processing/mag/l1c/interpolation_methods.py +14 -15
- imap_processing/mag/l1c/mag_l1c.py +23 -6
- imap_processing/mag/l1d/mag_l1d.py +57 -14
- imap_processing/mag/l1d/mag_l1d_data.py +167 -30
- imap_processing/mag/l2/mag_l2_data.py +10 -2
- imap_processing/quality_flags.py +9 -1
- imap_processing/spice/geometry.py +76 -33
- imap_processing/spice/pointing_frame.py +0 -6
- imap_processing/spice/repoint.py +29 -2
- imap_processing/spice/spin.py +28 -8
- imap_processing/spice/time.py +12 -22
- imap_processing/swapi/l1/swapi_l1.py +10 -4
- imap_processing/swapi/l2/swapi_l2.py +15 -17
- imap_processing/swe/l1b/swe_l1b.py +1 -2
- imap_processing/ultra/constants.py +1 -24
- imap_processing/ultra/l0/ultra_utils.py +9 -11
- imap_processing/ultra/l1a/ultra_l1a.py +1 -2
- imap_processing/ultra/l1b/cullingmask.py +6 -3
- imap_processing/ultra/l1b/de.py +81 -23
- imap_processing/ultra/l1b/extendedspin.py +13 -10
- imap_processing/ultra/l1b/lookup_utils.py +281 -28
- imap_processing/ultra/l1b/quality_flag_filters.py +10 -1
- imap_processing/ultra/l1b/ultra_l1b_culling.py +161 -3
- imap_processing/ultra/l1b/ultra_l1b_extended.py +253 -47
- imap_processing/ultra/l1c/helio_pset.py +97 -24
- imap_processing/ultra/l1c/l1c_lookup_utils.py +256 -0
- imap_processing/ultra/l1c/spacecraft_pset.py +83 -16
- imap_processing/ultra/l1c/ultra_l1c.py +6 -2
- imap_processing/ultra/l1c/ultra_l1c_culling.py +85 -0
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +385 -277
- imap_processing/ultra/l2/ultra_l2.py +0 -1
- imap_processing/ultra/utils/ultra_l1_utils.py +28 -3
- imap_processing/utils.py +3 -4
- {imap_processing-0.18.0.dist-info → imap_processing-0.19.0.dist-info}/METADATA +2 -2
- {imap_processing-0.18.0.dist-info → imap_processing-0.19.0.dist-info}/RECORD +102 -95
- imap_processing/idex/idex_l2c.py +0 -84
- imap_processing/spice/kernels.py +0 -187
- {imap_processing-0.18.0.dist-info → imap_processing-0.19.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.18.0.dist-info → imap_processing-0.19.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.18.0.dist-info → imap_processing-0.19.0.dist-info}/entry_points.txt +0 -0
imap_processing/idex/idex_l2b.py
CHANGED
|
@@ -17,8 +17,9 @@ Examples
|
|
|
17
17
|
l1a_data, l1a_evt_data, l1b_evt_data = PacketParser(l0_file)
|
|
18
18
|
l1b_data = idex_l1b(l1a_data)
|
|
19
19
|
l1a_data = idex_l2a(l1b_data)
|
|
20
|
-
|
|
21
|
-
write_cdf(
|
|
20
|
+
l2b_and_l2c_datasets = idex_l2b(l2a_data, [evt_data])
|
|
21
|
+
write_cdf(l2b_and_l2c_datasets[0])
|
|
22
|
+
write_cdf(l2b_and_l2c_datasets[1])
|
|
22
23
|
"""
|
|
23
24
|
|
|
24
25
|
import collections
|
|
@@ -29,9 +30,11 @@ from datetime import datetime, timedelta
|
|
|
29
30
|
import numpy as np
|
|
30
31
|
import xarray as xr
|
|
31
32
|
|
|
33
|
+
from imap_processing.ena_maps.ena_maps import SkyTilingType
|
|
32
34
|
from imap_processing.ena_maps.utils.spatial_utils import AzElSkyGrid
|
|
33
35
|
from imap_processing.idex.idex_constants import (
|
|
34
36
|
FG_TO_KG,
|
|
37
|
+
IDEX_EVENT_REFERENCE_FRAME,
|
|
35
38
|
IDEX_SPACING_DEG,
|
|
36
39
|
SECONDS_IN_DAY,
|
|
37
40
|
IDEXEvtAcquireCodes,
|
|
@@ -81,9 +84,12 @@ LAT_BINS_EDGES = SKY_GRID.el_bin_edges
|
|
|
81
84
|
|
|
82
85
|
def idex_l2b(
|
|
83
86
|
l2a_datasets: list[xr.Dataset], evt_datasets: list[xr.Dataset]
|
|
84
|
-
) -> xr.Dataset:
|
|
87
|
+
) -> list[xr.Dataset]:
|
|
85
88
|
"""
|
|
86
|
-
Will process IDEX l2a data to create l2b data products.
|
|
89
|
+
Will process IDEX l2a data to create l2b and l2c data products.
|
|
90
|
+
|
|
91
|
+
IDEX L2B processing creates L2b and L2c at the same time because L2c needs no
|
|
92
|
+
additional dependencies and is a natural extension of L2b processing.
|
|
87
93
|
|
|
88
94
|
Parameters
|
|
89
95
|
----------
|
|
@@ -94,16 +100,18 @@ def idex_l2b(
|
|
|
94
100
|
|
|
95
101
|
Returns
|
|
96
102
|
-------
|
|
97
|
-
|
|
98
|
-
The``xarray``
|
|
103
|
+
list[xarray.Dataset]
|
|
104
|
+
The``xarray`` datasets containing the l2b and l2c science data and supporting
|
|
105
|
+
metadata.
|
|
99
106
|
"""
|
|
100
107
|
logger.info(
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
"Running IDEX L2B and L2C processing on L2a datasets. NOTE: L2C datasets are "
|
|
109
|
+
"processed at the same time as L2B datasets because L2C needs no additional "
|
|
110
|
+
"dependencies."
|
|
103
111
|
)
|
|
104
|
-
|
|
105
112
|
# create the attribute manager for this data level
|
|
106
|
-
|
|
113
|
+
idex_l2b_attrs = get_idex_attrs("l2b")
|
|
114
|
+
idex_l2c_attrs = get_idex_attrs("l2c")
|
|
107
115
|
evt_dataset = xr.concat(evt_datasets, dim="epoch")
|
|
108
116
|
|
|
109
117
|
# Concat all the l2a datasets together
|
|
@@ -133,125 +141,138 @@ def idex_l2b(
|
|
|
133
141
|
daily_on_percentage,
|
|
134
142
|
)
|
|
135
143
|
# Create l2b Dataset
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
144
|
+
charge_bin_means = np.sqrt(CHARGE_BIN_EDGES[:-1] * CHARGE_BIN_EDGES[1:])
|
|
145
|
+
mass_bin_means = np.sqrt(MASS_BIN_EDGES[:-1] * MASS_BIN_EDGES[1:])
|
|
146
|
+
spin_phase_means = (SPIN_PHASE_BIN_EDGES[:-1] + SPIN_PHASE_BIN_EDGES[1:]) / 2
|
|
147
|
+
|
|
148
|
+
# Define xarrays that are shared between l2b and l2c
|
|
139
149
|
epoch = xr.DataArray(
|
|
140
150
|
name="epoch",
|
|
141
151
|
data=daily_epoch,
|
|
142
152
|
dims="epoch",
|
|
143
|
-
attrs=
|
|
153
|
+
attrs=idex_l2b_attrs.get_variable_attributes("epoch", check_schema=False),
|
|
144
154
|
)
|
|
145
|
-
|
|
155
|
+
|
|
156
|
+
common_vars = {
|
|
146
157
|
"impact_day_of_year": xr.DataArray(
|
|
147
158
|
name="impact_day_of_year",
|
|
148
159
|
data=epoch_doy_unique,
|
|
149
160
|
dims="epoch",
|
|
150
|
-
attrs=
|
|
151
|
-
),
|
|
152
|
-
"rate_calculation_quality_flags": xr.DataArray(
|
|
153
|
-
name="rate_calculation_quality_flags",
|
|
154
|
-
data=rate_quality_flags,
|
|
155
|
-
dims="epoch",
|
|
156
|
-
attrs=idex_attrs.get_variable_attributes("rate_calculation_quality_flags"),
|
|
161
|
+
attrs=idex_l2b_attrs.get_variable_attributes("impact_day_of_year"),
|
|
157
162
|
),
|
|
158
163
|
"charge_labels": xr.DataArray(
|
|
159
164
|
name="impact_charge_labels",
|
|
160
|
-
data=
|
|
165
|
+
data=charge_bin_means.astype(str),
|
|
161
166
|
dims="impact_charge",
|
|
162
|
-
attrs=
|
|
167
|
+
attrs=idex_l2b_attrs.get_variable_attributes(
|
|
163
168
|
"charge_labels", check_schema=False
|
|
164
169
|
),
|
|
165
170
|
),
|
|
166
|
-
"spin_phase_labels": xr.DataArray(
|
|
167
|
-
name="spin_phase_labels",
|
|
168
|
-
data=spin_phase_bins.astype(str),
|
|
169
|
-
dims="spin_phase",
|
|
170
|
-
attrs=idex_attrs.get_variable_attributes(
|
|
171
|
-
"spin_phase_labels", check_schema=False
|
|
172
|
-
),
|
|
173
|
-
),
|
|
174
171
|
"mass_labels": xr.DataArray(
|
|
175
172
|
name="mass_labels",
|
|
176
|
-
data=
|
|
173
|
+
data=mass_bin_means.astype(str),
|
|
177
174
|
dims="mass",
|
|
178
|
-
attrs=
|
|
179
|
-
|
|
180
|
-
"rectangular_lon_pixel_label": xr.DataArray(
|
|
181
|
-
name="rectangular_lon_pixel_label",
|
|
182
|
-
data=SKY_GRID.az_bin_midpoints.astype(str),
|
|
183
|
-
dims="rectangular_lon_pixel",
|
|
184
|
-
attrs=idex_attrs.get_variable_attributes(
|
|
185
|
-
"rectangular_lon_pixel_label", check_schema=False
|
|
186
|
-
),
|
|
187
|
-
),
|
|
188
|
-
"rectangular_lat_pixel_label": xr.DataArray(
|
|
189
|
-
name="rectangular_lat_pixel_label",
|
|
190
|
-
data=SKY_GRID.el_bin_midpoints.astype(str),
|
|
191
|
-
dims="rectangular_lat_pixel",
|
|
192
|
-
attrs=idex_attrs.get_variable_attributes(
|
|
193
|
-
"rectangular_lat_pixel_label", check_schema=False
|
|
175
|
+
attrs=idex_l2b_attrs.get_variable_attributes(
|
|
176
|
+
"mass_labels", check_schema=False
|
|
194
177
|
),
|
|
195
178
|
),
|
|
196
179
|
"impact_charge": xr.DataArray(
|
|
197
180
|
name="impact_charge",
|
|
198
|
-
data=
|
|
181
|
+
data=charge_bin_means,
|
|
199
182
|
dims="impact_charge",
|
|
200
|
-
attrs=
|
|
183
|
+
attrs=idex_l2b_attrs.get_variable_attributes(
|
|
201
184
|
"impact_charge", check_schema=False
|
|
202
185
|
),
|
|
203
186
|
),
|
|
204
187
|
"mass": xr.DataArray(
|
|
205
188
|
name="mass",
|
|
206
|
-
data=
|
|
189
|
+
data=mass_bin_means,
|
|
207
190
|
dims="mass",
|
|
208
|
-
attrs=
|
|
191
|
+
attrs=idex_l2b_attrs.get_variable_attributes("mass", check_schema=False),
|
|
209
192
|
),
|
|
193
|
+
}
|
|
194
|
+
l2b_vars = common_vars | {
|
|
210
195
|
"spin_phase": xr.DataArray(
|
|
211
196
|
name="spin_phase",
|
|
212
|
-
data=
|
|
197
|
+
data=spin_phase_means,
|
|
213
198
|
dims="spin_phase",
|
|
214
|
-
attrs=
|
|
199
|
+
attrs=idex_l2b_attrs.get_variable_attributes(
|
|
200
|
+
"spin_phase", check_schema=False
|
|
201
|
+
),
|
|
215
202
|
),
|
|
216
|
-
"
|
|
217
|
-
name="
|
|
218
|
-
data=
|
|
219
|
-
dims="
|
|
220
|
-
attrs=
|
|
221
|
-
"
|
|
203
|
+
"spin_phase_labels": xr.DataArray(
|
|
204
|
+
name="spin_phase_labels",
|
|
205
|
+
data=spin_phase_means.astype(str),
|
|
206
|
+
dims="spin_phase",
|
|
207
|
+
attrs=idex_l2b_attrs.get_variable_attributes(
|
|
208
|
+
"spin_phase_labels", check_schema=False
|
|
222
209
|
),
|
|
223
210
|
),
|
|
224
|
-
"
|
|
225
|
-
name="
|
|
226
|
-
data=
|
|
227
|
-
dims="
|
|
228
|
-
attrs=
|
|
229
|
-
"
|
|
211
|
+
"rate_calculation_quality_flags": xr.DataArray(
|
|
212
|
+
name="rate_calculation_quality_flags",
|
|
213
|
+
data=rate_quality_flags,
|
|
214
|
+
dims="epoch",
|
|
215
|
+
attrs=idex_l2b_attrs.get_variable_attributes(
|
|
216
|
+
"rate_calculation_quality_flags"
|
|
230
217
|
),
|
|
231
218
|
),
|
|
232
219
|
"counts_by_charge": xr.DataArray(
|
|
233
220
|
name="counts_by_charge",
|
|
234
221
|
data=counts_by_charge.astype(np.int64),
|
|
235
222
|
dims=("epoch", "impact_charge", "spin_phase"),
|
|
236
|
-
attrs=
|
|
223
|
+
attrs=idex_l2b_attrs.get_variable_attributes("counts_by_charge"),
|
|
237
224
|
),
|
|
238
225
|
"counts_by_mass": xr.DataArray(
|
|
239
226
|
name="counts_by_mass",
|
|
240
227
|
data=counts_by_mass.astype(np.int64),
|
|
241
228
|
dims=("epoch", "mass", "spin_phase"),
|
|
242
|
-
attrs=
|
|
229
|
+
attrs=idex_l2b_attrs.get_variable_attributes("counts_by_mass"),
|
|
243
230
|
),
|
|
244
231
|
"rate_by_charge": xr.DataArray(
|
|
245
232
|
name="rate_by_charge",
|
|
246
233
|
data=rate_by_charge,
|
|
247
234
|
dims=("epoch", "impact_charge", "spin_phase"),
|
|
248
|
-
attrs=
|
|
235
|
+
attrs=idex_l2b_attrs.get_variable_attributes("rate_by_charge"),
|
|
249
236
|
),
|
|
250
237
|
"rate_by_mass": xr.DataArray(
|
|
251
238
|
name="rate_by_mass",
|
|
252
239
|
data=rate_by_mass,
|
|
253
240
|
dims=("epoch", "mass", "spin_phase"),
|
|
254
|
-
attrs=
|
|
241
|
+
attrs=idex_l2b_attrs.get_variable_attributes("rate_by_mass"),
|
|
242
|
+
),
|
|
243
|
+
}
|
|
244
|
+
l2c_vars = common_vars | {
|
|
245
|
+
"rectangular_lon_pixel_label": xr.DataArray(
|
|
246
|
+
name="rectangular_lon_pixel_label",
|
|
247
|
+
data=SKY_GRID.az_bin_midpoints.astype(str),
|
|
248
|
+
dims="rectangular_lon_pixel",
|
|
249
|
+
attrs=idex_l2c_attrs.get_variable_attributes(
|
|
250
|
+
"rectangular_lon_pixel_label", check_schema=False
|
|
251
|
+
),
|
|
252
|
+
),
|
|
253
|
+
"rectangular_lat_pixel_label": xr.DataArray(
|
|
254
|
+
name="rectangular_lat_pixel_label",
|
|
255
|
+
data=SKY_GRID.el_bin_midpoints.astype(str),
|
|
256
|
+
dims="rectangular_lat_pixel",
|
|
257
|
+
attrs=idex_l2c_attrs.get_variable_attributes(
|
|
258
|
+
"rectangular_lat_pixel_label", check_schema=False
|
|
259
|
+
),
|
|
260
|
+
),
|
|
261
|
+
"rectangular_lon_pixel": xr.DataArray(
|
|
262
|
+
name="rectangular_lon_pixel",
|
|
263
|
+
data=SKY_GRID.az_bin_midpoints,
|
|
264
|
+
dims="rectangular_lon_pixel",
|
|
265
|
+
attrs=idex_l2c_attrs.get_variable_attributes(
|
|
266
|
+
"rectangular_lon_pixel", check_schema=False
|
|
267
|
+
),
|
|
268
|
+
),
|
|
269
|
+
"rectangular_lat_pixel": xr.DataArray(
|
|
270
|
+
name="rectangular_lat_pixel",
|
|
271
|
+
data=SKY_GRID.el_bin_midpoints,
|
|
272
|
+
dims="rectangular_lat_pixel",
|
|
273
|
+
attrs=idex_l2c_attrs.get_variable_attributes(
|
|
274
|
+
"rectangular_lat_pixel", check_schema=False
|
|
275
|
+
),
|
|
255
276
|
),
|
|
256
277
|
"counts_by_charge_map": xr.DataArray(
|
|
257
278
|
name="counts_by_charge_map",
|
|
@@ -262,7 +283,7 @@ def idex_l2b(
|
|
|
262
283
|
"rectangular_lon_pixel",
|
|
263
284
|
"rectangular_lat_pixel",
|
|
264
285
|
),
|
|
265
|
-
attrs=
|
|
286
|
+
attrs=idex_l2c_attrs.get_variable_attributes("counts_by_charge_map"),
|
|
266
287
|
),
|
|
267
288
|
"counts_by_mass_map": xr.DataArray(
|
|
268
289
|
name="counts_by_mass_map",
|
|
@@ -273,7 +294,7 @@ def idex_l2b(
|
|
|
273
294
|
"rectangular_lon_pixel",
|
|
274
295
|
"rectangular_lat_pixel",
|
|
275
296
|
),
|
|
276
|
-
attrs=
|
|
297
|
+
attrs=idex_l2c_attrs.get_variable_attributes("counts_by_mass_map"),
|
|
277
298
|
),
|
|
278
299
|
"rate_by_charge_map": xr.DataArray(
|
|
279
300
|
name="rate_by_charge_map",
|
|
@@ -284,7 +305,7 @@ def idex_l2b(
|
|
|
284
305
|
"rectangular_lon_pixel",
|
|
285
306
|
"rectangular_lat_pixel",
|
|
286
307
|
),
|
|
287
|
-
attrs=
|
|
308
|
+
attrs=idex_l2c_attrs.get_variable_attributes("rate_by_charge_map"),
|
|
288
309
|
),
|
|
289
310
|
"rate_by_mass_map": xr.DataArray(
|
|
290
311
|
name="rate_by_mass_map",
|
|
@@ -295,18 +316,31 @@ def idex_l2b(
|
|
|
295
316
|
"rectangular_lon_pixel",
|
|
296
317
|
"rectangular_lat_pixel",
|
|
297
318
|
),
|
|
298
|
-
attrs=
|
|
319
|
+
attrs=idex_l2c_attrs.get_variable_attributes("rate_by_mass_map"),
|
|
299
320
|
),
|
|
300
321
|
}
|
|
322
|
+
|
|
301
323
|
l2b_dataset = xr.Dataset(
|
|
302
324
|
coords={"epoch": epoch},
|
|
303
|
-
data_vars=
|
|
304
|
-
attrs=
|
|
325
|
+
data_vars=l2b_vars,
|
|
326
|
+
attrs=idex_l2b_attrs.get_global_attributes("imap_idex_l2b_sci"),
|
|
327
|
+
)
|
|
328
|
+
l2c_dataset = xr.Dataset(
|
|
329
|
+
coords={"epoch": epoch},
|
|
330
|
+
data_vars=l2c_vars,
|
|
305
331
|
)
|
|
332
|
+
# Add map attributes
|
|
333
|
+
map_attrs = {
|
|
334
|
+
"sky_tiling_type": SkyTilingType.RECTANGULAR.value,
|
|
335
|
+
"Spacing_degrees": str(IDEX_SPACING_DEG),
|
|
336
|
+
"Spice_reference_frame": IDEX_EVENT_REFERENCE_FRAME.name,
|
|
337
|
+
} | idex_l2c_attrs.get_global_attributes("imap_idex_l2c_sci-rectangular")
|
|
306
338
|
|
|
307
|
-
|
|
339
|
+
l2c_dataset.attrs.update(map_attrs)
|
|
308
340
|
|
|
309
|
-
|
|
341
|
+
logger.info("IDEX L2B and L2C science data processing completed.")
|
|
342
|
+
|
|
343
|
+
return [l2b_dataset, l2c_dataset]
|
|
310
344
|
|
|
311
345
|
|
|
312
346
|
def compute_counts_by_charge_and_mass(
|
|
@@ -329,37 +363,11 @@ def compute_counts_by_charge_and_mass(
|
|
|
329
363
|
dataset, Two 4D arrays containing counts by charge or mass, and by lon and lat
|
|
330
364
|
for each dataset, and a 1D array of daily epoch values.
|
|
331
365
|
"""
|
|
332
|
-
# Initialize
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
len(epoch_doy_unique),
|
|
338
|
-
len(CHARGE_BIN_EDGES) - 1,
|
|
339
|
-
len(SPIN_PHASE_BIN_EDGES) - 1,
|
|
340
|
-
),
|
|
341
|
-
)
|
|
342
|
-
counts_by_mass = np.zeros(
|
|
343
|
-
(len(epoch_doy_unique), len(MASS_BIN_EDGES) - 1, len(SPIN_PHASE_BIN_EDGES) - 1),
|
|
344
|
-
)
|
|
345
|
-
# Initialize arrays to hold count maps. Each map is a 3 or 4D array with shape
|
|
346
|
-
# (epoch, 10 [charge or mass], 60 [longitude bins], 30 [latitude bins]).
|
|
347
|
-
counts_by_charge_map = np.zeros(
|
|
348
|
-
(
|
|
349
|
-
len(epoch_doy_unique),
|
|
350
|
-
len(CHARGE_BIN_EDGES) - 1,
|
|
351
|
-
len(LON_BINS_EDGES) - 1,
|
|
352
|
-
len(LAT_BINS_EDGES) - 1,
|
|
353
|
-
),
|
|
354
|
-
)
|
|
355
|
-
counts_by_mass_map = np.zeros(
|
|
356
|
-
(
|
|
357
|
-
len(epoch_doy_unique),
|
|
358
|
-
len(MASS_BIN_EDGES) - 1,
|
|
359
|
-
len(LON_BINS_EDGES) - 1,
|
|
360
|
-
len(LAT_BINS_EDGES) - 1,
|
|
361
|
-
),
|
|
362
|
-
)
|
|
366
|
+
# Initialize lists to hold counts.
|
|
367
|
+
counts_by_charge = []
|
|
368
|
+
counts_by_mass = []
|
|
369
|
+
counts_by_charge_map = []
|
|
370
|
+
counts_by_mass_map = []
|
|
363
371
|
daily_epoch = np.zeros(len(epoch_doy_unique), dtype=np.float64)
|
|
364
372
|
for i in range(len(epoch_doy_unique)):
|
|
365
373
|
doy = epoch_doy_unique[i]
|
|
@@ -379,43 +387,44 @@ def compute_counts_by_charge_and_mass(
|
|
|
379
387
|
latitude = l2a_dataset["latitude"].data[current_day_indices]
|
|
380
388
|
# Convert units
|
|
381
389
|
mass_vals = FG_TO_KG * np.atleast_1d(mass_vals)
|
|
382
|
-
# Bin masses
|
|
383
|
-
binned_mass = np.asarray(np.digitize(mass_vals, bins=MASS_BIN_EDGES))
|
|
384
|
-
# Bin charges
|
|
385
|
-
binned_charge = np.asarray(np.digitize(charge_vals, bins=CHARGE_BIN_EDGES))
|
|
386
390
|
# Bin spin phases
|
|
387
391
|
binned_spin_phase = bin_spin_phases(spin_phase_angles)
|
|
388
|
-
#
|
|
389
|
-
binned_longitude = np.asarray(np.digitize(longitude, bins=LON_BINS_EDGES))
|
|
392
|
+
# Clip arrays to ensure that the values are within the valid range of bins.
|
|
390
393
|
# Latitude should be binned with the right edge included. 90 is a valid latitude
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
394
|
+
latitude = np.clip(latitude, -90, 90)
|
|
395
|
+
mass_vals = np.clip(mass_vals, MASS_BIN_EDGES[0], MASS_BIN_EDGES[-1])
|
|
396
|
+
charge_vals = np.clip(charge_vals, CHARGE_BIN_EDGES[0], CHARGE_BIN_EDGES[-1])
|
|
397
|
+
|
|
398
|
+
counts_by_mass.append(
|
|
399
|
+
np.histogramdd(
|
|
400
|
+
np.column_stack([mass_vals, binned_spin_phase]),
|
|
401
|
+
bins=[MASS_BIN_EDGES, np.arange(5)],
|
|
402
|
+
)[0]
|
|
403
|
+
)
|
|
404
|
+
counts_by_charge.append(
|
|
405
|
+
np.histogramdd(
|
|
406
|
+
np.column_stack([charge_vals, binned_spin_phase]),
|
|
407
|
+
bins=[CHARGE_BIN_EDGES, np.arange(5)],
|
|
408
|
+
)[0]
|
|
409
|
+
)
|
|
410
|
+
counts_by_mass_map.append(
|
|
411
|
+
np.histogramdd(
|
|
412
|
+
np.column_stack([mass_vals, longitude, latitude]),
|
|
413
|
+
bins=[MASS_BIN_EDGES, LON_BINS_EDGES, LAT_BINS_EDGES],
|
|
414
|
+
)[0]
|
|
415
|
+
)
|
|
416
|
+
counts_by_charge_map.append(
|
|
417
|
+
np.histogramdd(
|
|
418
|
+
np.column_stack([charge_vals, longitude, latitude]),
|
|
419
|
+
bins=[CHARGE_BIN_EDGES, LON_BINS_EDGES, LAT_BINS_EDGES],
|
|
420
|
+
)[0]
|
|
421
|
+
)
|
|
413
422
|
|
|
414
423
|
return (
|
|
415
|
-
counts_by_charge,
|
|
416
|
-
counts_by_mass,
|
|
417
|
-
counts_by_charge_map,
|
|
418
|
-
counts_by_mass_map,
|
|
424
|
+
np.stack(counts_by_charge),
|
|
425
|
+
np.stack(counts_by_mass),
|
|
426
|
+
np.stack(counts_by_charge_map),
|
|
427
|
+
np.stack(counts_by_mass_map),
|
|
419
428
|
daily_epoch,
|
|
420
429
|
)
|
|
421
430
|
|
|
@@ -598,7 +607,7 @@ def get_science_acquisition_timestamps(
|
|
|
598
607
|
epochs = evt_dataset["epoch"][sc_indices].data
|
|
599
608
|
# Now the state change values and check if it is either a science
|
|
600
609
|
# acquisition start or science acquisition stop event.
|
|
601
|
-
for v1, v2, epoch in zip(val1, val2, epochs):
|
|
610
|
+
for v1, v2, epoch in zip(val1, val2, epochs, strict=False):
|
|
602
611
|
# An "acquire" start will have val1=ACQSETUP and val2=ACQ
|
|
603
612
|
# An "acquire" stop will have val1=ACQ and val2=CHILL
|
|
604
613
|
if (v1, v2) == (IDEXEvtAcquireCodes.ACQSETUP, IDEXEvtAcquireCodes.ACQ):
|
|
@@ -637,6 +646,12 @@ def get_science_acquisition_on_percentage(evt_dataset: xr.Dataset) -> dict:
|
|
|
637
646
|
"""
|
|
638
647
|
# Get science acquisition start and stop times
|
|
639
648
|
evt_logs, evt_time, evt_values = get_science_acquisition_timestamps(evt_dataset)
|
|
649
|
+
if len(evt_time) == 0:
|
|
650
|
+
logger.warning(
|
|
651
|
+
"No science acquisition events found in event dataset. Returning empty "
|
|
652
|
+
"uptime percentages. All rate variables will be set to -1."
|
|
653
|
+
)
|
|
654
|
+
return {}
|
|
640
655
|
# Track total and 'on' durations per day
|
|
641
656
|
daily_totals: collections.defaultdict = defaultdict(timedelta)
|
|
642
657
|
daily_on: collections.defaultdict = defaultdict(timedelta)
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"""Contains helper functions to support IDEX processing."""
|
|
2
2
|
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
3
|
import xarray as xr
|
|
6
4
|
|
|
7
5
|
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
@@ -31,7 +29,7 @@ def setup_dataset(
|
|
|
31
29
|
dataset: xr.Dataset,
|
|
32
30
|
match_strings: list,
|
|
33
31
|
idex_attrs: ImapCdfAttributes,
|
|
34
|
-
data_vars:
|
|
32
|
+
data_vars: dict | None = None,
|
|
35
33
|
) -> xr.Dataset:
|
|
36
34
|
"""
|
|
37
35
|
Initialize a dataset and copy over any dataArrays.
|
|
@@ -37,28 +37,28 @@ HistPacking = namedtuple(
|
|
|
37
37
|
|
|
38
38
|
HIST_DATA_META = {
|
|
39
39
|
# field: bit_length, section_length, shape
|
|
40
|
-
"start_a": HistPacking(12, 504, (
|
|
41
|
-
"start_c": HistPacking(12, 504, (
|
|
42
|
-
"stop_b0": HistPacking(12, 504, (
|
|
43
|
-
"stop_b3": HistPacking(12, 504, (
|
|
44
|
-
"tof0_count": HistPacking(8, 336, (
|
|
45
|
-
"tof1_count": HistPacking(8, 336, (
|
|
46
|
-
"tof2_count": HistPacking(8, 336, (
|
|
47
|
-
"tof3_count": HistPacking(8, 336, (
|
|
48
|
-
"tof0_tof1": HistPacking(8, 3360, (
|
|
49
|
-
"tof0_tof2": HistPacking(8, 3360, (
|
|
50
|
-
"tof1_tof2": HistPacking(8, 3360, (
|
|
51
|
-
"silver": HistPacking(8, 3360, (
|
|
52
|
-
"disc_tof0": HistPacking(8, 336, (
|
|
53
|
-
"disc_tof1": HistPacking(8, 336, (
|
|
54
|
-
"disc_tof2": HistPacking(8, 336, (
|
|
55
|
-
"disc_tof3": HistPacking(8, 336, (
|
|
56
|
-
"pos0": HistPacking(12, 504, (
|
|
57
|
-
"pos1": HistPacking(12, 504, (
|
|
58
|
-
"pos2": HistPacking(12, 504, (
|
|
59
|
-
"pos3": HistPacking(12, 504, (
|
|
60
|
-
"hydrogen": HistPacking(8, 3360, (
|
|
61
|
-
"oxygen": HistPacking(8, 3360, (
|
|
40
|
+
"start_a": HistPacking(12, 504, (7, 6)),
|
|
41
|
+
"start_c": HistPacking(12, 504, (7, 6)),
|
|
42
|
+
"stop_b0": HistPacking(12, 504, (7, 6)),
|
|
43
|
+
"stop_b3": HistPacking(12, 504, (7, 6)),
|
|
44
|
+
"tof0_count": HistPacking(8, 336, (7, 6)),
|
|
45
|
+
"tof1_count": HistPacking(8, 336, (7, 6)),
|
|
46
|
+
"tof2_count": HistPacking(8, 336, (7, 6)),
|
|
47
|
+
"tof3_count": HistPacking(8, 336, (7, 6)),
|
|
48
|
+
"tof0_tof1": HistPacking(8, 3360, (7, 60)),
|
|
49
|
+
"tof0_tof2": HistPacking(8, 3360, (7, 60)),
|
|
50
|
+
"tof1_tof2": HistPacking(8, 3360, (7, 60)),
|
|
51
|
+
"silver": HistPacking(8, 3360, (7, 60)),
|
|
52
|
+
"disc_tof0": HistPacking(8, 336, (7, 6)),
|
|
53
|
+
"disc_tof1": HistPacking(8, 336, (7, 6)),
|
|
54
|
+
"disc_tof2": HistPacking(8, 336, (7, 6)),
|
|
55
|
+
"disc_tof3": HistPacking(8, 336, (7, 6)),
|
|
56
|
+
"pos0": HistPacking(12, 504, (7, 6)),
|
|
57
|
+
"pos1": HistPacking(12, 504, (7, 6)),
|
|
58
|
+
"pos2": HistPacking(12, 504, (7, 6)),
|
|
59
|
+
"pos3": HistPacking(12, 504, (7, 6)),
|
|
60
|
+
"hydrogen": HistPacking(8, 3360, (7, 60)),
|
|
61
|
+
"oxygen": HistPacking(8, 3360, (7, 60)),
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
|
|
@@ -399,7 +399,7 @@ def combine_segmented_packets(dataset: xr.Dataset) -> xr.Dataset:
|
|
|
399
399
|
# Combine the segmented packets into a single binary string
|
|
400
400
|
dataset["events"] = [
|
|
401
401
|
"".join(dataset["data"].values[start : end + 1])
|
|
402
|
-
for start, end in zip(seg_starts, seg_ends)
|
|
402
|
+
for start, end in zip(seg_starts, seg_ends, strict=False)
|
|
403
403
|
]
|
|
404
404
|
|
|
405
405
|
# drop any group of segmented packets that aren't sequential
|
|
@@ -441,7 +441,8 @@ def find_valid_groups(
|
|
|
441
441
|
"""
|
|
442
442
|
# Check if the sequence counters from the CCSDS header are sequential
|
|
443
443
|
grouped_seq_ctrs = [
|
|
444
|
-
np.array(seq_ctrs[start : end + 1])
|
|
444
|
+
np.array(seq_ctrs[start : end + 1])
|
|
445
|
+
for start, end in zip(seg_starts, seg_ends, strict=False)
|
|
445
446
|
]
|
|
446
447
|
valid_groups = [is_sequential(seq_ctrs) for seq_ctrs in grouped_seq_ctrs]
|
|
447
448
|
return valid_groups
|
imap_processing/lo/l1b/lo_l1b.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
from dataclasses import Field
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
import xarray as xr
|
|
@@ -204,7 +204,7 @@ def get_avg_spin_durations_per_cycle(
|
|
|
204
204
|
return avg_spin_durations_per_cycle
|
|
205
205
|
|
|
206
206
|
|
|
207
|
-
def get_spin_angle(l1a_de: xr.Dataset) ->
|
|
207
|
+
def get_spin_angle(l1a_de: xr.Dataset) -> np.ndarray[np.float64] | Any:
|
|
208
208
|
"""
|
|
209
209
|
Get the spin angle (0 - 360 degrees) for each DE.
|
|
210
210
|
|
|
@@ -587,7 +587,7 @@ def convert_tofs_to_eu(
|
|
|
587
587
|
tof_conversions = [TOF0_CONV, TOF1_CONV, TOF2_CONV, TOF3_CONV]
|
|
588
588
|
|
|
589
589
|
# Loop through the TOF fields and convert them to engineering units
|
|
590
|
-
for tof, conv in zip(tof_fields, tof_conversions):
|
|
590
|
+
for tof, conv in zip(tof_fields, tof_conversions, strict=False):
|
|
591
591
|
# Get the fill value for the L1A and L1B TOF
|
|
592
592
|
fillval_1a = attr_mgr_l1a.get_variable_attributes(tof)["FILLVAL"]
|
|
593
593
|
fillval_1b = attr_mgr_l1b.get_variable_attributes(tof)["FILLVAL"]
|