imap-processing 1.0.1__py3-none-any.whl → 1.0.3__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.
- imap_processing/_version.py +2 -2
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +18 -0
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +101 -258
- imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml +1 -1
- imap_processing/cdf/config/imap_hi_variable_attrs.yaml +12 -2
- imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +1 -8
- imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +16 -5
- imap_processing/cdf/config/imap_idex_l2a_variable_attrs.yaml +27 -25
- imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml +16 -16
- imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml +2 -2
- imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +2 -13
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +12 -0
- imap_processing/cdf/utils.py +2 -2
- imap_processing/cli.py +4 -16
- imap_processing/codice/codice_l1a_lo_angular.py +362 -0
- imap_processing/codice/codice_l1a_lo_species.py +282 -0
- imap_processing/codice/codice_l1b.py +80 -97
- imap_processing/codice/codice_l2.py +270 -103
- imap_processing/codice/codice_new_l1a.py +64 -0
- imap_processing/codice/constants.py +37 -2
- imap_processing/codice/utils.py +270 -0
- imap_processing/ena_maps/ena_maps.py +51 -39
- imap_processing/ena_maps/utils/corrections.py +196 -14
- imap_processing/ena_maps/utils/naming.py +3 -1
- imap_processing/hi/hi_l1c.py +57 -19
- imap_processing/hi/hi_l2.py +89 -36
- imap_processing/ialirt/calculate_ingest.py +19 -1
- imap_processing/ialirt/constants.py +12 -6
- imap_processing/ialirt/generate_coverage.py +6 -1
- imap_processing/ialirt/l0/parse_mag.py +1 -0
- imap_processing/ialirt/l0/process_hit.py +1 -0
- imap_processing/ialirt/l0/process_swapi.py +1 -0
- imap_processing/ialirt/l0/process_swe.py +2 -0
- imap_processing/ialirt/process_ephemeris.py +6 -2
- imap_processing/ialirt/utils/create_xarray.py +3 -2
- imap_processing/lo/l1b/lo_l1b.py +12 -2
- imap_processing/lo/l1c/lo_l1c.py +4 -4
- imap_processing/lo/l2/lo_l2.py +101 -8
- imap_processing/quality_flags.py +1 -0
- imap_processing/swapi/constants.py +4 -0
- imap_processing/swapi/l1/swapi_l1.py +47 -20
- imap_processing/swapi/l2/swapi_l2.py +17 -3
- imap_processing/ultra/l1a/ultra_l1a.py +121 -72
- imap_processing/ultra/l1b/de.py +57 -1
- imap_processing/ultra/l1b/ultra_l1b_annotated.py +0 -1
- imap_processing/ultra/l1b/ultra_l1b_extended.py +24 -11
- imap_processing/ultra/l1c/helio_pset.py +34 -8
- imap_processing/ultra/l1c/l1c_lookup_utils.py +4 -2
- imap_processing/ultra/l1c/spacecraft_pset.py +13 -7
- imap_processing/ultra/l1c/ultra_l1c.py +6 -6
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +79 -20
- imap_processing/ultra/l2/ultra_l2.py +2 -2
- imap_processing/ultra/utils/ultra_l1_utils.py +6 -0
- {imap_processing-1.0.1.dist-info → imap_processing-1.0.3.dist-info}/METADATA +1 -1
- {imap_processing-1.0.1.dist-info → imap_processing-1.0.3.dist-info}/RECORD +58 -54
- {imap_processing-1.0.1.dist-info → imap_processing-1.0.3.dist-info}/LICENSE +0 -0
- {imap_processing-1.0.1.dist-info → imap_processing-1.0.3.dist-info}/WHEEL +0 -0
- {imap_processing-1.0.1.dist-info → imap_processing-1.0.3.dist-info}/entry_points.txt +0 -0
|
@@ -15,20 +15,15 @@ from pathlib import Path
|
|
|
15
15
|
import numpy as np
|
|
16
16
|
import xarray as xr
|
|
17
17
|
|
|
18
|
-
from imap_processing import imap_module_directory
|
|
19
18
|
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
20
19
|
from imap_processing.cdf.utils import load_cdf
|
|
21
20
|
from imap_processing.codice import constants
|
|
22
|
-
from imap_processing.codice.utils import CODICEAPID
|
|
23
|
-
from imap_processing.utils import packet_file_to_datasets
|
|
24
21
|
|
|
25
22
|
logger = logging.getLogger(__name__)
|
|
26
23
|
logger.setLevel(logging.INFO)
|
|
27
24
|
|
|
28
25
|
|
|
29
|
-
def convert_to_rates(
|
|
30
|
-
dataset: xr.Dataset, descriptor: str, variable_name: str
|
|
31
|
-
) -> np.ndarray:
|
|
26
|
+
def convert_to_rates(dataset: xr.Dataset, descriptor: str) -> np.ndarray:
|
|
32
27
|
"""
|
|
33
28
|
Apply a conversion from counts to rates.
|
|
34
29
|
|
|
@@ -41,14 +36,34 @@ def convert_to_rates(
|
|
|
41
36
|
The L1b dataset containing the data to convert.
|
|
42
37
|
descriptor : str
|
|
43
38
|
The descriptor of the data product of interest.
|
|
44
|
-
variable_name : str
|
|
45
|
-
The variable name to apply the conversion to.
|
|
46
39
|
|
|
47
40
|
Returns
|
|
48
41
|
-------
|
|
49
42
|
rates_data : np.ndarray
|
|
50
43
|
The converted data array.
|
|
51
44
|
"""
|
|
45
|
+
# Variables to convert based on descriptor
|
|
46
|
+
variables_to_convert = getattr(
|
|
47
|
+
constants, f"{descriptor.upper().replace('-', '_')}_VARIABLE_NAMES"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if descriptor.startswith("lo-"):
|
|
51
|
+
# Calculate energy_table using voltage_table and k_factor
|
|
52
|
+
energy_attrs = dataset["voltage_table"].attrs | {
|
|
53
|
+
"UNITS": "keV/e",
|
|
54
|
+
"LABLAXIS": "E/q",
|
|
55
|
+
"CATDESC": "Energy per charge",
|
|
56
|
+
"FIELDNAM": "Energy per charge",
|
|
57
|
+
}
|
|
58
|
+
# 1e3 is to convert eV to keV
|
|
59
|
+
dataset["energy_table"] = xr.DataArray(
|
|
60
|
+
dataset["voltage_table"].values * dataset["k_factor"].values * 1e-3,
|
|
61
|
+
dims=[
|
|
62
|
+
"esa_step",
|
|
63
|
+
],
|
|
64
|
+
attrs=energy_attrs,
|
|
65
|
+
)
|
|
66
|
+
|
|
52
67
|
if descriptor in [
|
|
53
68
|
"lo-counters-aggregated",
|
|
54
69
|
"lo-counters-singles",
|
|
@@ -58,41 +73,50 @@ def convert_to_rates(
|
|
|
58
73
|
"lo-sw-priority",
|
|
59
74
|
"lo-ialirt",
|
|
60
75
|
]:
|
|
61
|
-
#
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# time data array to match the data variable shape
|
|
65
|
-
dims = [1] * dataset[variable_name].data.ndim
|
|
66
|
-
dims[1] = 128
|
|
67
|
-
acq_times = dataset.acquisition_time_per_step.data.reshape(dims) # (128)
|
|
68
|
-
# Now perform the calculation
|
|
69
|
-
rates_data = dataset[variable_name].data / (
|
|
70
|
-
acq_times
|
|
71
|
-
* 1e-3 # Converting from milliseconds to seconds
|
|
76
|
+
# Denominator to convert counts to rates
|
|
77
|
+
denominator = (
|
|
78
|
+
dataset.acquisition_time_per_step
|
|
72
79
|
* constants.L1B_DATA_PRODUCT_CONFIGURATIONS[descriptor]["num_spin_sectors"]
|
|
73
80
|
)
|
|
81
|
+
|
|
82
|
+
# Do not carry these variable attributes from L1a to L1b for above products
|
|
83
|
+
drop_variables = [
|
|
84
|
+
"k_factor",
|
|
85
|
+
"nso_half_spin",
|
|
86
|
+
"sw_bias_gain_mode",
|
|
87
|
+
"st_bias_gain_mode",
|
|
88
|
+
"spin_period",
|
|
89
|
+
"voltage_table",
|
|
90
|
+
"acquisition_time_per_step",
|
|
91
|
+
]
|
|
92
|
+
dataset = dataset.drop_vars(drop_variables)
|
|
74
93
|
elif descriptor in [
|
|
75
94
|
"lo-nsw-species",
|
|
76
95
|
"lo-sw-species",
|
|
77
96
|
]:
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
# time data array to match the data variable shape (epoch, esa_step, sector)
|
|
82
|
-
dims = [1] * dataset[variable_name].data.ndim
|
|
83
|
-
dims[1] = 128
|
|
84
|
-
acq_times = dataset.acquisition_time_per_step.data.reshape(dims) # (128)
|
|
85
|
-
# acquisition time have an array of shape (128,). We match n_sector to that.
|
|
97
|
+
# Create n_sector with 'esa_step' dimension. This is done by xr.full_like
|
|
98
|
+
# with input dataset.acquisition_time_per_step. This ensures that the resulting
|
|
99
|
+
# n_sector has the same dimensions as acquisition_time_per_step.
|
|
86
100
|
# Per CoDICE, fill first 127 with default value of 12. Then fill last with 11.
|
|
87
|
-
n_sector =
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
# Now perform the calculation
|
|
91
|
-
rates_data = dataset[variable_name].data / (
|
|
92
|
-
acq_times
|
|
93
|
-
* 1e-3 # Converting from milliseconds to seconds
|
|
94
|
-
* n_sector[:, np.newaxis] # Spin sectors
|
|
101
|
+
n_sector = xr.full_like(
|
|
102
|
+
dataset.acquisition_time_per_step, 12.0, dtype=np.float64
|
|
95
103
|
)
|
|
104
|
+
n_sector[-1] = 11.0
|
|
105
|
+
|
|
106
|
+
# Denominator to convert counts to rates
|
|
107
|
+
denominator = dataset.acquisition_time_per_step * n_sector
|
|
108
|
+
# Do not carry these variable attributes from L1a to L1b for above products
|
|
109
|
+
drop_variables = [
|
|
110
|
+
"k_factor",
|
|
111
|
+
"nso_half_spin",
|
|
112
|
+
"sw_bias_gain_mode",
|
|
113
|
+
"st_bias_gain_mode",
|
|
114
|
+
"spin_period",
|
|
115
|
+
"voltage_table",
|
|
116
|
+
"acquisition_time_per_step",
|
|
117
|
+
]
|
|
118
|
+
dataset = dataset.drop_vars(drop_variables)
|
|
119
|
+
|
|
96
120
|
elif descriptor in [
|
|
97
121
|
"hi-counters-aggregated",
|
|
98
122
|
"hi-counters-singles",
|
|
@@ -101,15 +125,27 @@ def convert_to_rates(
|
|
|
101
125
|
"hi-sectored",
|
|
102
126
|
"hi-ialirt",
|
|
103
127
|
]:
|
|
104
|
-
#
|
|
105
|
-
|
|
106
|
-
rates_data = dataset[variable_name].data / (
|
|
128
|
+
# Denominator to convert counts to rates
|
|
129
|
+
denominator = (
|
|
107
130
|
constants.L1B_DATA_PRODUCT_CONFIGURATIONS[descriptor]["num_spin_sectors"]
|
|
108
131
|
* constants.L1B_DATA_PRODUCT_CONFIGURATIONS[descriptor]["num_spins"]
|
|
109
132
|
* constants.HI_ACQUISITION_TIME
|
|
110
133
|
)
|
|
111
134
|
|
|
112
|
-
|
|
135
|
+
# For each variable, convert counts and uncertainty to rates
|
|
136
|
+
for variable in variables_to_convert:
|
|
137
|
+
dataset[variable].data = dataset[variable].astype(np.float64) / denominator
|
|
138
|
+
# Carry over attrs and update as needed
|
|
139
|
+
dataset[variable].attrs["UNITS"] = "counts/s"
|
|
140
|
+
|
|
141
|
+
# Uncertainty calculation
|
|
142
|
+
unc_variable = f"unc_{variable}"
|
|
143
|
+
dataset[unc_variable].data = (
|
|
144
|
+
dataset[unc_variable].astype(np.float64) / denominator
|
|
145
|
+
)
|
|
146
|
+
dataset[unc_variable].attrs["UNITS"] = "1/s"
|
|
147
|
+
|
|
148
|
+
return dataset
|
|
113
149
|
|
|
114
150
|
|
|
115
151
|
def process_codice_l1b(file_path: Path) -> xr.Dataset:
|
|
@@ -136,70 +172,17 @@ def process_codice_l1b(file_path: Path) -> xr.Dataset:
|
|
|
136
172
|
dataset_name = l1a_dataset.attrs["Logical_source"].replace("_l1a_", "_l1b_")
|
|
137
173
|
descriptor = dataset_name.removeprefix("imap_codice_l1b_")
|
|
138
174
|
|
|
139
|
-
# Direct event data products do not have a level L1B
|
|
140
|
-
if descriptor in ["lo-direct-events", "hi-direct-events"]:
|
|
141
|
-
logger.warning("Encountered direct event data product. Skipping L1b processing")
|
|
142
|
-
return None
|
|
143
|
-
|
|
144
175
|
# Get the L1b CDF attributes
|
|
145
176
|
cdf_attrs = ImapCdfAttributes()
|
|
146
177
|
cdf_attrs.add_instrument_global_attrs("codice")
|
|
147
178
|
cdf_attrs.add_instrument_variable_attrs("codice", "l1b")
|
|
148
179
|
|
|
149
180
|
# Use the L1a data product as a starting point for L1b
|
|
150
|
-
l1b_dataset = l1a_dataset.copy()
|
|
181
|
+
l1b_dataset = l1a_dataset.copy(deep=True)
|
|
151
182
|
|
|
152
183
|
# Update the global attributes
|
|
153
184
|
l1b_dataset.attrs = cdf_attrs.get_global_attributes(dataset_name)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
xtce_packet_definition = Path(
|
|
159
|
-
f"{imap_module_directory}/codice/packet_definitions/{xtce_filename}"
|
|
160
|
-
)
|
|
161
|
-
packet_file = (
|
|
162
|
-
imap_module_directory
|
|
163
|
-
/ "tests"
|
|
164
|
-
/ "codice"
|
|
165
|
-
/ "data"
|
|
166
|
-
/ "imap_codice_l0_raw_20241110_v001.pkts"
|
|
167
|
-
)
|
|
168
|
-
datasets: dict[int, xr.Dataset] = packet_file_to_datasets(
|
|
169
|
-
packet_file, xtce_packet_definition, use_derived_value=True
|
|
170
|
-
)
|
|
171
|
-
l1b_dataset = datasets[CODICEAPID.COD_NHK]
|
|
172
|
-
|
|
173
|
-
# TODO: Drop the same variables as we do in L1a? (see line 1103 in
|
|
174
|
-
# codice_l1a.py
|
|
175
|
-
|
|
176
|
-
else:
|
|
177
|
-
variables_to_convert = getattr(
|
|
178
|
-
constants, f"{descriptor.upper().replace('-', '_')}_VARIABLE_NAMES"
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
# Apply the conversion to rates
|
|
182
|
-
for variable_name in variables_to_convert:
|
|
183
|
-
l1b_dataset[variable_name].data = convert_to_rates(
|
|
184
|
-
l1b_dataset, descriptor, variable_name
|
|
185
|
-
)
|
|
186
|
-
# Set the variable attributes
|
|
187
|
-
cdf_attrs_key = f"{descriptor}-{variable_name}"
|
|
188
|
-
l1b_dataset[variable_name].attrs = cdf_attrs.get_variable_attributes(
|
|
189
|
-
cdf_attrs_key, check_schema=False
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
if descriptor in ["lo-sw-species", "lo-nsw-species"]:
|
|
193
|
-
# Do not carry these variable attributes from L1a to L1b
|
|
194
|
-
drop_variables = [
|
|
195
|
-
"k_factor",
|
|
196
|
-
"nso_half_spin",
|
|
197
|
-
"sw_bias_gain_mode",
|
|
198
|
-
"st_bias_gain_mode",
|
|
199
|
-
"spin_period",
|
|
200
|
-
]
|
|
201
|
-
l1b_dataset = l1b_dataset.drop_vars(drop_variables)
|
|
202
|
-
|
|
203
|
-
logger.info(f"\nFinal data product:\n{l1b_dataset}\n")
|
|
204
|
-
|
|
205
|
-
return l1b_dataset
|
|
185
|
+
return convert_to_rates(
|
|
186
|
+
l1b_dataset,
|
|
187
|
+
descriptor,
|
|
188
|
+
)
|