imap-processing 0.17.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/ccsds/excel_to_xtce.py +12 -0
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +6 -6
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +312 -274
- imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +39 -28
- imap_processing/cdf/config/imap_codice_l2_variable_attrs.yaml +1048 -183
- 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_hit_l1a_variable_attrs.yaml +163 -100
- imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +4 -4
- imap_processing/cdf/config/imap_ialirt_l1_variable_attrs.yaml +97 -54
- imap_processing/cdf/config/imap_idex_l2a_variable_attrs.yaml +33 -4
- imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml +44 -44
- imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml +77 -61
- imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +30 -0
- 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 +99 -2
- imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +24 -1
- imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +60 -0
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +99 -11
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +50 -7
- imap_processing/cli.py +121 -44
- imap_processing/codice/codice_l1a.py +165 -77
- imap_processing/codice/codice_l1b.py +1 -1
- imap_processing/codice/codice_l2.py +118 -19
- imap_processing/codice/constants.py +1217 -1089
- 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 +5 -8
- imap_processing/hit/l1a/hit_l1a.py +375 -45
- imap_processing/hit/l1b/constants.py +5 -0
- imap_processing/hit/l1b/hit_l1b.py +61 -131
- imap_processing/hit/l2/constants.py +1 -1
- imap_processing/hit/l2/hit_l2.py +10 -11
- imap_processing/ialirt/calculate_ingest.py +219 -0
- imap_processing/ialirt/constants.py +32 -1
- imap_processing/ialirt/generate_coverage.py +201 -0
- imap_processing/ialirt/l0/ialirt_spice.py +5 -2
- imap_processing/ialirt/l0/parse_mag.py +337 -29
- imap_processing/ialirt/l0/process_hit.py +5 -3
- imap_processing/ialirt/l0/process_swapi.py +41 -25
- imap_processing/ialirt/l0/process_swe.py +23 -7
- imap_processing/ialirt/process_ephemeris.py +70 -14
- imap_processing/ialirt/utils/constants.py +22 -16
- imap_processing/ialirt/utils/create_xarray.py +42 -19
- imap_processing/idex/idex_constants.py +1 -5
- 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 +313 -119
- imap_processing/idex/idex_utils.py +1 -3
- imap_processing/lo/l0/lo_apid.py +1 -0
- imap_processing/lo/l0/lo_science.py +25 -24
- imap_processing/lo/l1a/lo_l1a.py +44 -0
- 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/lo/packet_definitions/lo_xtce.xml +5359 -106
- imap_processing/mag/constants.py +1 -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/__init__.py +0 -0
- imap_processing/mag/l1d/mag_l1d.py +176 -0
- imap_processing/mag/l1d/mag_l1d_data.py +725 -0
- imap_processing/mag/l2/__init__.py +0 -0
- imap_processing/mag/l2/mag_l2.py +25 -20
- imap_processing/mag/l2/mag_l2_data.py +199 -130
- imap_processing/quality_flags.py +28 -2
- imap_processing/spice/geometry.py +101 -36
- imap_processing/spice/pointing_frame.py +1 -7
- imap_processing/spice/repoint.py +29 -2
- imap_processing/spice/spin.py +32 -8
- imap_processing/spice/time.py +60 -19
- imap_processing/swapi/l1/swapi_l1.py +10 -4
- imap_processing/swapi/l2/swapi_l2.py +66 -24
- imap_processing/swapi/swapi_utils.py +1 -1
- imap_processing/swe/l1b/swe_l1b.py +3 -6
- imap_processing/ultra/constants.py +28 -3
- imap_processing/ultra/l0/decom_tools.py +15 -8
- imap_processing/ultra/l0/decom_ultra.py +35 -11
- imap_processing/ultra/l0/ultra_utils.py +102 -12
- imap_processing/ultra/l1a/ultra_l1a.py +26 -6
- imap_processing/ultra/l1b/cullingmask.py +6 -3
- imap_processing/ultra/l1b/de.py +122 -26
- imap_processing/ultra/l1b/extendedspin.py +29 -2
- imap_processing/ultra/l1b/lookup_utils.py +424 -50
- imap_processing/ultra/l1b/quality_flag_filters.py +23 -0
- imap_processing/ultra/l1b/ultra_l1b_culling.py +356 -5
- imap_processing/ultra/l1b/ultra_l1b_extended.py +534 -90
- imap_processing/ultra/l1c/helio_pset.py +127 -7
- imap_processing/ultra/l1c/l1c_lookup_utils.py +256 -0
- imap_processing/ultra/l1c/spacecraft_pset.py +90 -15
- imap_processing/ultra/l1c/ultra_l1c.py +6 -0
- imap_processing/ultra/l1c/ultra_l1c_culling.py +85 -0
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +446 -341
- imap_processing/ultra/l2/ultra_l2.py +0 -1
- imap_processing/ultra/utils/ultra_l1_utils.py +40 -3
- imap_processing/utils.py +3 -4
- {imap_processing-0.17.0.dist-info → imap_processing-0.19.0.dist-info}/METADATA +3 -3
- {imap_processing-0.17.0.dist-info → imap_processing-0.19.0.dist-info}/RECORD +126 -126
- imap_processing/idex/idex_l2c.py +0 -250
- imap_processing/spice/kernels.py +0 -187
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +0 -526
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +0 -526
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +0 -526
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +0 -524
- imap_processing/ultra/lookup_tables/EgyNorm.mem.csv +0 -32769
- imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +0 -2
- imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +0 -2
- imap_processing/ultra/lookup_tables/dps_grid45_compressed.cdf +0 -0
- imap_processing/ultra/lookup_tables/ultra45_back-pos-luts.csv +0 -4097
- imap_processing/ultra/lookup_tables/ultra45_tdc_norm.csv +0 -2050
- imap_processing/ultra/lookup_tables/ultra90_back-pos-luts.csv +0 -4097
- imap_processing/ultra/lookup_tables/ultra90_tdc_norm.csv +0 -2050
- imap_processing/ultra/lookup_tables/yadjust.csv +0 -257
- {imap_processing-0.17.0.dist-info → imap_processing-0.19.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.17.0.dist-info → imap_processing-0.19.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.17.0.dist-info → imap_processing-0.19.0.dist-info}/entry_points.txt +0 -0
imap_processing/hi/utils.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"""IMAP-Hi utils functions."""
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
|
-
from collections.abc import Sequence
|
|
4
|
+
from collections.abc import Iterable, Sequence
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
from enum import IntEnum
|
|
7
|
-
from typing import Optional, Union
|
|
8
7
|
|
|
9
8
|
import numpy as np
|
|
9
|
+
import pandas as pd
|
|
10
10
|
import xarray as xr
|
|
11
11
|
|
|
12
12
|
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
@@ -15,11 +15,13 @@ from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
|
15
15
|
class HIAPID(IntEnum):
|
|
16
16
|
"""Create ENUM for apid."""
|
|
17
17
|
|
|
18
|
+
H45_MEMDMP = 740
|
|
18
19
|
H45_APP_NHK = 754
|
|
19
20
|
H45_SCI_CNT = 769
|
|
20
21
|
H45_SCI_DE = 770
|
|
21
22
|
H45_DIAG_FEE = 772
|
|
22
23
|
|
|
24
|
+
H90_MEMDMP = 804
|
|
23
25
|
H90_APP_NHK = 818
|
|
24
26
|
H90_SCI_CNT = 833
|
|
25
27
|
H90_SCI_DE = 834
|
|
@@ -100,9 +102,9 @@ def parse_sensor_number(full_string: str) -> int:
|
|
|
100
102
|
def full_dataarray(
|
|
101
103
|
name: str,
|
|
102
104
|
attrs: dict,
|
|
103
|
-
coords:
|
|
104
|
-
shape:
|
|
105
|
-
fill_value:
|
|
105
|
+
coords: dict[str, xr.DataArray] | None = None,
|
|
106
|
+
shape: int | Sequence[int] | None = None,
|
|
107
|
+
fill_value: float | None = None,
|
|
106
108
|
) -> xr.DataArray:
|
|
107
109
|
"""
|
|
108
110
|
Generate an empty xarray.DataArray with appropriate attributes.
|
|
@@ -158,9 +160,9 @@ def full_dataarray(
|
|
|
158
160
|
|
|
159
161
|
def create_dataset_variables(
|
|
160
162
|
variable_names: list[str],
|
|
161
|
-
variable_shape:
|
|
162
|
-
coords:
|
|
163
|
-
fill_value:
|
|
163
|
+
variable_shape: int | Sequence[int] | None = None,
|
|
164
|
+
coords: dict[str, xr.DataArray] | None = None,
|
|
165
|
+
fill_value: float | None = None,
|
|
164
166
|
att_manager_lookup_str: str = "{0}",
|
|
165
167
|
) -> dict[str, xr.DataArray]:
|
|
166
168
|
"""
|
|
@@ -247,3 +249,146 @@ class CoincidenceBitmap(IntEnum):
|
|
|
247
249
|
matches = re.findall(pattern, detector_hit_str)
|
|
248
250
|
# Sum the integer value assigned to the detector name for each match
|
|
249
251
|
return sum(CoincidenceBitmap[m] for m in matches)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class EsaEnergyStepLookupTable:
|
|
255
|
+
"""Class for holding a esa_step to esa_energy lookup table."""
|
|
256
|
+
|
|
257
|
+
def __init__(self) -> None:
|
|
258
|
+
self.df = pd.DataFrame(
|
|
259
|
+
columns=["start_met", "end_met", "esa_step", "esa_energy_step"]
|
|
260
|
+
)
|
|
261
|
+
self._indexed = False
|
|
262
|
+
|
|
263
|
+
# Get the FILLVAL from the CDF attribute manager that will be returned
|
|
264
|
+
# for queries without matches
|
|
265
|
+
attr_mgr = ImapCdfAttributes()
|
|
266
|
+
attr_mgr.add_instrument_global_attrs("hi")
|
|
267
|
+
attr_mgr.add_instrument_variable_attrs(instrument="hi", level=None)
|
|
268
|
+
var_attrs = attr_mgr.get_variable_attributes(
|
|
269
|
+
"hi_de_esa_energy_step", check_schema=False
|
|
270
|
+
)
|
|
271
|
+
self._fillval = var_attrs["FILLVAL"]
|
|
272
|
+
self._esa_energy_step_dtype = var_attrs["dtype"]
|
|
273
|
+
|
|
274
|
+
def add_entry(
|
|
275
|
+
self, start_met: float, end_met: float, esa_step: int, esa_energy_step: int
|
|
276
|
+
) -> None:
|
|
277
|
+
"""
|
|
278
|
+
Add a single entry to the lookup table.
|
|
279
|
+
|
|
280
|
+
Parameters
|
|
281
|
+
----------
|
|
282
|
+
start_met : float
|
|
283
|
+
Start mission elapsed time of the time range.
|
|
284
|
+
end_met : float
|
|
285
|
+
End mission elapsed time of the time range.
|
|
286
|
+
esa_step : int
|
|
287
|
+
ESA step value.
|
|
288
|
+
esa_energy_step : int
|
|
289
|
+
ESA energy step value to be stored.
|
|
290
|
+
"""
|
|
291
|
+
new_row = pd.DataFrame(
|
|
292
|
+
{
|
|
293
|
+
"start_met": [start_met],
|
|
294
|
+
"end_met": [end_met],
|
|
295
|
+
"esa_step": [esa_step],
|
|
296
|
+
"esa_energy_step": [esa_energy_step],
|
|
297
|
+
}
|
|
298
|
+
)
|
|
299
|
+
self.df = pd.concat([self.df, new_row], ignore_index=True)
|
|
300
|
+
self._indexed = False
|
|
301
|
+
|
|
302
|
+
def _ensure_indexed(self) -> None:
|
|
303
|
+
"""
|
|
304
|
+
Create index for faster queries if not already done.
|
|
305
|
+
|
|
306
|
+
Notes
|
|
307
|
+
-----
|
|
308
|
+
This method sorts the internal DataFrame by start_met and esa_step
|
|
309
|
+
for improved query performance.
|
|
310
|
+
"""
|
|
311
|
+
if not self._indexed:
|
|
312
|
+
# Sort by start_met and esa_step for better query performance
|
|
313
|
+
self.df = self.df.sort_values(["start_met", "esa_step"]).reset_index(
|
|
314
|
+
drop=True
|
|
315
|
+
)
|
|
316
|
+
self._indexed = True
|
|
317
|
+
|
|
318
|
+
def query(
|
|
319
|
+
self,
|
|
320
|
+
query_met: float | Iterable[float],
|
|
321
|
+
esa_step: int | Iterable[float],
|
|
322
|
+
) -> float | np.ndarray:
|
|
323
|
+
"""
|
|
324
|
+
Query MET(s) and esa_step(s) to retrieve esa_energy_step(s).
|
|
325
|
+
|
|
326
|
+
Parameters
|
|
327
|
+
----------
|
|
328
|
+
query_met : float or array_like
|
|
329
|
+
Mission elapsed time value(s) to query.
|
|
330
|
+
Can be a single float or array-like of floats.
|
|
331
|
+
esa_step : int or array_like
|
|
332
|
+
ESA step value(s) to match. Can be a single int or array-like of ints.
|
|
333
|
+
Must be same type (scalar or array-like) as query_met.
|
|
334
|
+
|
|
335
|
+
Returns
|
|
336
|
+
-------
|
|
337
|
+
float or numpy.ndarray
|
|
338
|
+
- If inputs are scalars: returns float (esa_energy_step)
|
|
339
|
+
- If inputs are array-like: returns numpy array of esa_energy_steps
|
|
340
|
+
with same length as inputs.
|
|
341
|
+
Contains FILLVAL for queries with no matches.
|
|
342
|
+
|
|
343
|
+
Raises
|
|
344
|
+
------
|
|
345
|
+
ValueError
|
|
346
|
+
If one input is scalar and the other is array-like, or if both are
|
|
347
|
+
array-like but have different lengths.
|
|
348
|
+
|
|
349
|
+
Notes
|
|
350
|
+
-----
|
|
351
|
+
If multiple entries match a query, returns the first match found.
|
|
352
|
+
"""
|
|
353
|
+
self._ensure_indexed()
|
|
354
|
+
|
|
355
|
+
# Check if inputs are scalars
|
|
356
|
+
is_scalar_met = np.isscalar(query_met)
|
|
357
|
+
is_scalar_step = np.isscalar(esa_step)
|
|
358
|
+
|
|
359
|
+
# Check for mismatched input types
|
|
360
|
+
if is_scalar_met != is_scalar_step:
|
|
361
|
+
raise ValueError(
|
|
362
|
+
"query_met and esa_step must both be scalars or both be array-like"
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
# Convert to arrays for uniform processing
|
|
366
|
+
query_mets = np.atleast_1d(query_met)
|
|
367
|
+
esa_steps = np.atleast_1d(esa_step)
|
|
368
|
+
|
|
369
|
+
# Ensure both arrays have the same shape
|
|
370
|
+
if query_mets.shape != esa_steps.shape:
|
|
371
|
+
raise ValueError(
|
|
372
|
+
"query_met and esa_step must have the same "
|
|
373
|
+
"length when both are array-like"
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
results = np.full_like(query_mets, self._fillval)
|
|
377
|
+
|
|
378
|
+
# Lookup esa_energy_steps for queries
|
|
379
|
+
for i, (qm, es) in enumerate(zip(query_mets, esa_steps, strict=False)):
|
|
380
|
+
mask = (
|
|
381
|
+
(self.df["start_met"] <= qm)
|
|
382
|
+
& (self.df["end_met"] >= qm)
|
|
383
|
+
& (self.df["esa_step"] == es)
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
matches = self.df[mask]
|
|
387
|
+
if not matches.empty:
|
|
388
|
+
results[i] = matches["esa_energy_step"].iloc[0]
|
|
389
|
+
|
|
390
|
+
# Return scalar for scalar inputs, array for array inputs
|
|
391
|
+
if is_scalar_met and is_scalar_step:
|
|
392
|
+
return results.astype(self._esa_energy_step_dtype)[0]
|
|
393
|
+
else:
|
|
394
|
+
return results.astype(self._esa_energy_step_dtype)
|
|
@@ -114,6 +114,9 @@ FLAG_PATTERN = np.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
114
114
|
# Define size of science frame (num of packets)
|
|
115
115
|
FRAME_SIZE = len(FLAG_PATTERN)
|
|
116
116
|
|
|
117
|
+
# Mod 10 pattern
|
|
118
|
+
MOD_10_PATTERN = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
|
|
119
|
+
|
|
117
120
|
# Define the number of bits in the mantissa and exponent for
|
|
118
121
|
# decompressing data
|
|
119
122
|
MANTISSA_BITS = 12
|
|
@@ -124,9 +124,9 @@ def parse_count_rates(sci_dataset: xr.Dataset) -> None:
|
|
|
124
124
|
for dim in dims:
|
|
125
125
|
if dim not in sci_dataset.coords:
|
|
126
126
|
sci_dataset.coords[dim] = xr.DataArray(
|
|
127
|
-
np.arange(sci_dataset.sizes[dim], dtype=np.
|
|
127
|
+
np.arange(sci_dataset.sizes[dim], dtype=np.uint16)
|
|
128
128
|
if dim == "gain"
|
|
129
|
-
else np.arange(sci_dataset.sizes[dim], dtype=np.
|
|
129
|
+
else np.arange(sci_dataset.sizes[dim], dtype=np.uint32),
|
|
130
130
|
dims=[dim],
|
|
131
131
|
name=dim,
|
|
132
132
|
)
|
|
@@ -260,12 +260,9 @@ def assemble_science_frames(sci_dataset: xr.Dataset) -> xr.Dataset:
|
|
|
260
260
|
height event data per valid science frame added as new
|
|
261
261
|
data variables.
|
|
262
262
|
"""
|
|
263
|
-
# TODO:
|
|
264
|
-
#
|
|
265
|
-
#
|
|
266
|
-
# from the previous file. Only discard incomplete science frames
|
|
267
|
-
# in the middle of the CCSDS file. The code currently skips all
|
|
268
|
-
# incomplete science frames.
|
|
263
|
+
# TODO: The code currently skips all incomplete science frames.
|
|
264
|
+
# Only discard incomplete science frames in the middle of the CCSDS file or
|
|
265
|
+
# use fill values?
|
|
269
266
|
|
|
270
267
|
# Convert sequence flags and counters to NumPy arrays for vectorized operations
|
|
271
268
|
seq_flgs = sci_dataset.seq_flgs.values
|