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/idex/idex_l2c.py
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Perform IDEX L2c Processing.
|
|
3
|
-
|
|
4
|
-
Examples
|
|
5
|
-
--------
|
|
6
|
-
.. code-block:: python
|
|
7
|
-
from imap_processing.idex.idex_l1a import PacketParser
|
|
8
|
-
from imap_processing.idex.idex_l1b import idex_l1b
|
|
9
|
-
from imap_processing.idex.idex_l2a import idex_l2a
|
|
10
|
-
from imap_processing.idex.idex_l2b import idex_l2b
|
|
11
|
-
from imap_processing.cdf.utils import write_cdf
|
|
12
|
-
|
|
13
|
-
l0_file = "imap_processing/tests/idex/imap_idex_l0_sci_20231214_v001.pkts"
|
|
14
|
-
l1a_data = PacketParser(l0_file)
|
|
15
|
-
l1b_data = idex_l1b(l1a_data)
|
|
16
|
-
l2a_data = idex_l2a(l1b_data)
|
|
17
|
-
l2b_data = idex_l2b(l2a_data)
|
|
18
|
-
write_cdf(l2b_data)
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
import logging
|
|
22
|
-
|
|
23
|
-
import astropy_healpix.healpy as hp
|
|
24
|
-
import numpy as np
|
|
25
|
-
import xarray as xr
|
|
26
|
-
|
|
27
|
-
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
28
|
-
from imap_processing.ena_maps.ena_maps import SkyTilingType
|
|
29
|
-
from imap_processing.ena_maps.utils.coordinates import CoordNames
|
|
30
|
-
from imap_processing.ena_maps.utils.spatial_utils import AzElSkyGrid
|
|
31
|
-
from imap_processing.idex.idex_constants import (
|
|
32
|
-
IDEX_EVENT_REFERENCE_FRAME,
|
|
33
|
-
IDEX_HEALPIX_NESTED,
|
|
34
|
-
IDEX_HEALPIX_NSIDE,
|
|
35
|
-
IDEX_SPACING_DEG,
|
|
36
|
-
)
|
|
37
|
-
from imap_processing.idex.idex_utils import get_idex_attrs
|
|
38
|
-
|
|
39
|
-
logger = logging.getLogger(__name__)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def idex_l2c(l2b_dataset: xr.Dataset) -> list[xr.Dataset]:
|
|
43
|
-
"""
|
|
44
|
-
Will process IDEX l2b data to create l2c data products.
|
|
45
|
-
|
|
46
|
-
Parameters
|
|
47
|
-
----------
|
|
48
|
-
l2b_dataset : xarray.Dataset
|
|
49
|
-
IDEX L2b dataset.
|
|
50
|
-
|
|
51
|
-
Returns
|
|
52
|
-
-------
|
|
53
|
-
l2b_dataset : list[xarray.Dataset]
|
|
54
|
-
The``xarray`` dataset containing the science data and supporting metadata.
|
|
55
|
-
"""
|
|
56
|
-
logger.info(
|
|
57
|
-
f"Running IDEX L2C processing on datasets: "
|
|
58
|
-
f"{l2b_dataset.attrs['Logical_source']}"
|
|
59
|
-
)
|
|
60
|
-
# create the attribute manager for this data level
|
|
61
|
-
idex_attrs = get_idex_attrs("l2c")
|
|
62
|
-
# Epoch should be the start of the collection period.
|
|
63
|
-
# TODO should epoch be start of sci acquisition?
|
|
64
|
-
epoch = xr.DataArray(
|
|
65
|
-
l2b_dataset["epoch"].data[0:1].astype(np.int64),
|
|
66
|
-
name="epoch",
|
|
67
|
-
dims=["epoch"],
|
|
68
|
-
attrs=idex_attrs.get_variable_attributes(
|
|
69
|
-
"epoch_collection_set", check_schema=False
|
|
70
|
-
),
|
|
71
|
-
)
|
|
72
|
-
l2c_healpix_dataset = idex_healpix_map(l2b_dataset, epoch, idex_attrs)
|
|
73
|
-
l2c_rectangular_dataset = idex_rectangular_map(l2b_dataset, epoch, idex_attrs)
|
|
74
|
-
|
|
75
|
-
# TODO exposure time
|
|
76
|
-
logger.info("IDEX L2C science data processing completed.")
|
|
77
|
-
return [l2c_healpix_dataset, l2c_rectangular_dataset]
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def idex_healpix_map(
|
|
81
|
-
l1b_dataset: xr.Dataset,
|
|
82
|
-
epoch_da: xr.DataArray,
|
|
83
|
-
idex_attrs: ImapCdfAttributes,
|
|
84
|
-
nside: int = IDEX_HEALPIX_NSIDE,
|
|
85
|
-
nested: bool = IDEX_HEALPIX_NESTED,
|
|
86
|
-
) -> xr.Dataset:
|
|
87
|
-
"""
|
|
88
|
-
Create a healpix map out of a l1b dataset.
|
|
89
|
-
|
|
90
|
-
Parameters
|
|
91
|
-
----------
|
|
92
|
-
l1b_dataset : xarray.Dataset
|
|
93
|
-
IDEX L2b dataset.
|
|
94
|
-
epoch_da : xarray.DataArray
|
|
95
|
-
Epoch data array of the collection. Size: (1,).
|
|
96
|
-
idex_attrs : ImapCdfAttributes
|
|
97
|
-
The attribute manager for this data level.
|
|
98
|
-
nside : int
|
|
99
|
-
Healpix nside parameter.
|
|
100
|
-
nested : bool
|
|
101
|
-
Healpix nested parameter.
|
|
102
|
-
|
|
103
|
-
Returns
|
|
104
|
-
-------
|
|
105
|
-
map : xarray.Dataset
|
|
106
|
-
Spatially binned dust counts in a healpix map format.
|
|
107
|
-
"""
|
|
108
|
-
longitude = l1b_dataset["longitude"]
|
|
109
|
-
latitude = l1b_dataset["latitude"]
|
|
110
|
-
|
|
111
|
-
# Get the healpix indices
|
|
112
|
-
hpix_idx = hp.ang2pix(
|
|
113
|
-
nside, nest=nested, lonlat=True, theta=longitude, phi=latitude
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
n_pix = hp.nside2npix(nside)
|
|
117
|
-
healpix = xr.DataArray(
|
|
118
|
-
np.arange(n_pix),
|
|
119
|
-
name=CoordNames.HEALPIX_INDEX.value,
|
|
120
|
-
dims=CoordNames.HEALPIX_INDEX.value,
|
|
121
|
-
attrs=idex_attrs.get_variable_attributes("pixel_index", check_schema=False),
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
# Create a histogram of the raw dust event counts for each pixel
|
|
125
|
-
counts = np.histogram(hpix_idx, bins=n_pix, range=(0, n_pix))[0]
|
|
126
|
-
# Add epoch dimension
|
|
127
|
-
counts_da = xr.DataArray(
|
|
128
|
-
counts[np.newaxis, :].astype(np.int64),
|
|
129
|
-
name="counts",
|
|
130
|
-
dims=("epoch", CoordNames.HEALPIX_INDEX.value),
|
|
131
|
-
attrs=idex_attrs.get_variable_attributes("healpix_counts"),
|
|
132
|
-
)
|
|
133
|
-
pixel_label = xr.DataArray(
|
|
134
|
-
healpix.astype(str),
|
|
135
|
-
name="pixel_label",
|
|
136
|
-
dims="pixel_index",
|
|
137
|
-
attrs=idex_attrs.get_variable_attributes("pixel_label", check_schema=False),
|
|
138
|
-
)
|
|
139
|
-
l2c_dataset = xr.Dataset(
|
|
140
|
-
coords={CoordNames.HEALPIX_INDEX.value: healpix, "epoch": epoch_da},
|
|
141
|
-
data_vars={
|
|
142
|
-
"counts": counts_da,
|
|
143
|
-
"longitude": longitude,
|
|
144
|
-
"latitude": latitude,
|
|
145
|
-
"pixel_label": pixel_label,
|
|
146
|
-
},
|
|
147
|
-
)
|
|
148
|
-
map_attrs = {
|
|
149
|
-
"Sky_tiling_type": SkyTilingType.HEALPIX.value,
|
|
150
|
-
"HEALPix_nside": str(nside),
|
|
151
|
-
"HEALPix_nest": str(nested),
|
|
152
|
-
"Spice_reference_frame": IDEX_EVENT_REFERENCE_FRAME.name,
|
|
153
|
-
"num_points": str(n_pix),
|
|
154
|
-
} | idex_attrs.get_global_attributes("imap_idex_l2c_sci-healpix")
|
|
155
|
-
l2c_dataset.attrs.update(map_attrs)
|
|
156
|
-
|
|
157
|
-
return l2c_dataset
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
def idex_rectangular_map(
|
|
161
|
-
l1b_dataset: xr.Dataset,
|
|
162
|
-
epoch_da: xr.DataArray,
|
|
163
|
-
idex_attrs: ImapCdfAttributes,
|
|
164
|
-
spacing_deg: int = IDEX_SPACING_DEG,
|
|
165
|
-
) -> xr.Dataset:
|
|
166
|
-
"""
|
|
167
|
-
Create a rectangular map out of a l1b dataset.
|
|
168
|
-
|
|
169
|
-
Parameters
|
|
170
|
-
----------
|
|
171
|
-
l1b_dataset : xarray.Dataset
|
|
172
|
-
IDEX L2b dataset.
|
|
173
|
-
epoch_da : xarray.DataArray
|
|
174
|
-
Epoch data array of the collection. Size: (1,).
|
|
175
|
-
idex_attrs : ImapCdfAttributes
|
|
176
|
-
The attribute manager for this data level.
|
|
177
|
-
spacing_deg : int
|
|
178
|
-
The spacing in degrees for the rectangular grid.
|
|
179
|
-
|
|
180
|
-
Returns
|
|
181
|
-
-------
|
|
182
|
-
map : xarray.Dataset
|
|
183
|
-
Spatially binned dust counts in a rectangular map format.
|
|
184
|
-
"""
|
|
185
|
-
# Get the rectangular grid with the specified spacing
|
|
186
|
-
grid = AzElSkyGrid(spacing_deg)
|
|
187
|
-
# Make sure longitude values are in the range [0, 360)
|
|
188
|
-
longitude_wrapped = np.mod(l1b_dataset["longitude"], 360)
|
|
189
|
-
latitude = l1b_dataset["latitude"]
|
|
190
|
-
# Create a 2d histogram of the raw dust event counts for each pixel using the grid
|
|
191
|
-
# bin edges
|
|
192
|
-
counts, _, _ = np.histogram2d(
|
|
193
|
-
longitude_wrapped, latitude, bins=[grid.az_bin_edges, grid.el_bin_edges]
|
|
194
|
-
)
|
|
195
|
-
counts_da = xr.DataArray(
|
|
196
|
-
counts[np.newaxis, :, :].astype(np.int64),
|
|
197
|
-
name="counts",
|
|
198
|
-
dims=("epoch", "rectangular_lon_pixel", "rectangular_lat_pixel"),
|
|
199
|
-
attrs=idex_attrs.get_variable_attributes("rectangular_counts"),
|
|
200
|
-
)
|
|
201
|
-
rec_lon_pixels = xr.DataArray(
|
|
202
|
-
name="rectangular_lon_pixel",
|
|
203
|
-
data=grid.az_bin_midpoints,
|
|
204
|
-
dims="rectangular_lon_pixel",
|
|
205
|
-
attrs=idex_attrs.get_variable_attributes(
|
|
206
|
-
"rectangular_lon_pixel", check_schema=False
|
|
207
|
-
),
|
|
208
|
-
)
|
|
209
|
-
rec_lat_pixels = xr.DataArray(
|
|
210
|
-
name="rectangular_lat_pixel",
|
|
211
|
-
data=grid.el_bin_midpoints,
|
|
212
|
-
dims="rectangular_lat_pixel",
|
|
213
|
-
attrs=idex_attrs.get_variable_attributes(
|
|
214
|
-
"rectangular_lat_pixel", check_schema=False
|
|
215
|
-
),
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
l2c_dataset = xr.Dataset(
|
|
219
|
-
coords={
|
|
220
|
-
"epoch": epoch_da,
|
|
221
|
-
"rectangular_lon_pixel": rec_lon_pixels,
|
|
222
|
-
"rectangular_lat_pixel": rec_lat_pixels,
|
|
223
|
-
},
|
|
224
|
-
data_vars={
|
|
225
|
-
"counts": counts_da,
|
|
226
|
-
"longitude": longitude_wrapped,
|
|
227
|
-
"latitude": latitude,
|
|
228
|
-
"rectangular_lon_pixel_label": rec_lon_pixels.astype(str),
|
|
229
|
-
"rectangular_lat_pixel_label": rec_lat_pixels.astype(str),
|
|
230
|
-
},
|
|
231
|
-
)
|
|
232
|
-
l2c_dataset[
|
|
233
|
-
"rectangular_lon_pixel_label"
|
|
234
|
-
].attrs = idex_attrs.get_variable_attributes(
|
|
235
|
-
"rectangular_lon_pixel_label", check_schema=False
|
|
236
|
-
)
|
|
237
|
-
l2c_dataset[
|
|
238
|
-
"rectangular_lat_pixel_label"
|
|
239
|
-
].attrs = idex_attrs.get_variable_attributes(
|
|
240
|
-
"rectangular_lat_pixel_label", check_schema=False
|
|
241
|
-
)
|
|
242
|
-
map_attrs = {
|
|
243
|
-
"sky_tiling_type": SkyTilingType.RECTANGULAR.value,
|
|
244
|
-
"Spacing_degrees": str(spacing_deg),
|
|
245
|
-
"Spice_reference_frame": IDEX_EVENT_REFERENCE_FRAME.name,
|
|
246
|
-
"num_points": str(counts.size),
|
|
247
|
-
} | idex_attrs.get_global_attributes("imap_idex_l2c_sci-rectangular")
|
|
248
|
-
|
|
249
|
-
l2c_dataset.attrs.update(map_attrs)
|
|
250
|
-
return l2c_dataset
|
imap_processing/spice/kernels.py
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
"""Functions that generate, furnish, and retrieve metadata from SPICE kernels."""
|
|
2
|
-
|
|
3
|
-
import functools
|
|
4
|
-
import logging
|
|
5
|
-
import os
|
|
6
|
-
from typing import Any, Callable, Optional, Union, overload
|
|
7
|
-
|
|
8
|
-
import spiceypy
|
|
9
|
-
from spiceypy.utils.exceptions import SpiceyError
|
|
10
|
-
|
|
11
|
-
from imap_processing import imap_module_directory
|
|
12
|
-
|
|
13
|
-
logger = logging.getLogger(__name__)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# Declarations to help with typing. Taken from mypy documentation on
|
|
17
|
-
# decorator-factories:
|
|
18
|
-
# https://mypy.readthedocs.io/en/stable/generics.html#decorator-factories
|
|
19
|
-
# Bare decorator usage
|
|
20
|
-
@overload
|
|
21
|
-
def ensure_spice(
|
|
22
|
-
__func: Callable[..., Any],
|
|
23
|
-
) -> Callable[..., Any]: ... # numpydoc ignore=GL08
|
|
24
|
-
# Decorator with arguments
|
|
25
|
-
@overload
|
|
26
|
-
def ensure_spice(
|
|
27
|
-
*, time_kernels_only: bool = False
|
|
28
|
-
) -> Callable[[Callable[..., Any]], Callable[..., Any]]: ... # numpydoc ignore=GL08
|
|
29
|
-
# Implementation
|
|
30
|
-
def ensure_spice(
|
|
31
|
-
__func: Optional[Callable[..., Any]] = None, *, time_kernels_only: bool = False
|
|
32
|
-
) -> Union[Callable[..., Any], Callable[[Callable[..., Any]], Callable[..., Any]]]:
|
|
33
|
-
"""
|
|
34
|
-
Decorator/wrapper that automatically furnishes SPICE kernels.
|
|
35
|
-
|
|
36
|
-
Parameters
|
|
37
|
-
----------
|
|
38
|
-
__func : Callable
|
|
39
|
-
The function requiring SPICE that we are going to wrap if being used
|
|
40
|
-
explicitly, otherwise None, in which case ensure_spice is being used,
|
|
41
|
-
not as a function wrapper (see l2a_processing.py) but as a true
|
|
42
|
-
decorator without an explicit function argument.
|
|
43
|
-
time_kernels_only : bool
|
|
44
|
-
Specify that we only need to furnish time kernels (if SPICE_METAKERNEL
|
|
45
|
-
is set, we still just furnish that metakernel and assume the time
|
|
46
|
-
kernels are included.
|
|
47
|
-
|
|
48
|
-
Returns
|
|
49
|
-
-------
|
|
50
|
-
Callable
|
|
51
|
-
Decorated function, with spice error handling.
|
|
52
|
-
|
|
53
|
-
Notes
|
|
54
|
-
-----
|
|
55
|
-
Before trying to understand this piece of code, read this:
|
|
56
|
-
https://stackoverflow.com/questions/5929107/decorators-with-parameters/60832711#60832711
|
|
57
|
-
|
|
58
|
-
**Control flow overview:**
|
|
59
|
-
|
|
60
|
-
1. Try simply calling the wrapped function naively.
|
|
61
|
-
* SUCCESS? Great! We're done.
|
|
62
|
-
* SpiceyError? Go to step 2.
|
|
63
|
-
|
|
64
|
-
2. Furnish metakernel at SPICE_METAKERNEL
|
|
65
|
-
* SUCCESS? Great, return the original function again (so it can be
|
|
66
|
-
re-run).
|
|
67
|
-
* KeyError? Seems like SPICE_METAKERNEL isn't set, no problem. Go to
|
|
68
|
-
step 3.
|
|
69
|
-
|
|
70
|
-
3. Did we get the parameter time_kernels_only=True?
|
|
71
|
-
* YES? We only need LSK and SCLK kernels to run this function. Go fetch
|
|
72
|
-
those and furnish and return the original function (so it can be re-run).
|
|
73
|
-
* NO? Dang. This is sort of the end of the line. Re-raise the error
|
|
74
|
-
generated from the failed spiceypy function call but add a better
|
|
75
|
-
message to it.
|
|
76
|
-
|
|
77
|
-
Examples
|
|
78
|
-
--------
|
|
79
|
-
There are three ways to use this object
|
|
80
|
-
|
|
81
|
-
1. A decorator with no arguments
|
|
82
|
-
|
|
83
|
-
>>> @ensure_spice
|
|
84
|
-
... def my_spicey_func(a, b):
|
|
85
|
-
... pass
|
|
86
|
-
|
|
87
|
-
2. A decorator with parameters. This is useful
|
|
88
|
-
if we only need the latest SCLK and LSK kernels for the function involved.
|
|
89
|
-
|
|
90
|
-
>>> @ensure_spice(time_kernels_only=True)
|
|
91
|
-
... def my_spicey_time_func(a, b):
|
|
92
|
-
... pass
|
|
93
|
-
|
|
94
|
-
3. An explicit wrapper function, providing a dynamically set value for
|
|
95
|
-
parameters, e.g. time_kernels_only
|
|
96
|
-
|
|
97
|
-
>>> wrapped = ensure_spice(spicey_func, time_kernels_only=True)
|
|
98
|
-
... result = wrapped(args, kwargs)
|
|
99
|
-
"""
|
|
100
|
-
|
|
101
|
-
def _decorator(func: Callable[..., Callable]) -> Callable:
|
|
102
|
-
"""
|
|
103
|
-
Decorate or wrap input function depending on how ensure_spice is used.
|
|
104
|
-
|
|
105
|
-
Parameters
|
|
106
|
-
----------
|
|
107
|
-
func : Callable
|
|
108
|
-
The function to be decorated/wrapped.
|
|
109
|
-
|
|
110
|
-
Returns
|
|
111
|
-
-------
|
|
112
|
-
Callable
|
|
113
|
-
If used as a function wrapper, the decorated function is returned.
|
|
114
|
-
"""
|
|
115
|
-
|
|
116
|
-
@functools.wraps(func)
|
|
117
|
-
def wrapper_ensure_spice(*args: Any, **kwargs: Any) -> Any:
|
|
118
|
-
"""
|
|
119
|
-
Wrap the function that ensure_spice is used on.
|
|
120
|
-
|
|
121
|
-
Parameters
|
|
122
|
-
----------
|
|
123
|
-
*args : list
|
|
124
|
-
The positional arguments passed to the decorated function.
|
|
125
|
-
**kwargs
|
|
126
|
-
The keyword arguments passed to the decorated function.
|
|
127
|
-
|
|
128
|
-
Returns
|
|
129
|
-
-------
|
|
130
|
-
Object
|
|
131
|
-
Output from wrapped function.
|
|
132
|
-
"""
|
|
133
|
-
try:
|
|
134
|
-
# Step 1.
|
|
135
|
-
return func(
|
|
136
|
-
*args, **kwargs
|
|
137
|
-
) # Naive first try. Maybe SPICE is already furnished.
|
|
138
|
-
except SpiceyError as spicey_err:
|
|
139
|
-
try:
|
|
140
|
-
# Step 2.
|
|
141
|
-
if os.getenv("SPICE_METAKERNEL"):
|
|
142
|
-
metakernel_path = os.getenv("SPICE_METAKERNEL")
|
|
143
|
-
spiceypy.furnsh(metakernel_path)
|
|
144
|
-
else:
|
|
145
|
-
furnish_time_kernel()
|
|
146
|
-
except KeyError:
|
|
147
|
-
# TODO: An additional step that was used on EMUS was to get
|
|
148
|
-
# a custom metakernel from the SDC API based on an input
|
|
149
|
-
# time range.
|
|
150
|
-
if time_kernels_only:
|
|
151
|
-
# Step 3.
|
|
152
|
-
# TODO: Decide if this is useful for IMAP. Possible
|
|
153
|
-
# implementation could include downloading
|
|
154
|
-
# the most recent leapsecond kernel from NAIF (see:
|
|
155
|
-
# https://lasp.colorado.edu/nucleus/projects/LIBSDC/repos/libera_utils/browse/libera_utils/spice_utils.py
|
|
156
|
-
# for LIBERA implementation of downloading and caching
|
|
157
|
-
# kernels) and finding the most recent IMAP clock
|
|
158
|
-
# kernel in EFS.
|
|
159
|
-
raise NotImplementedError from spicey_err
|
|
160
|
-
else:
|
|
161
|
-
raise SpiceyError(
|
|
162
|
-
"When calling a function requiring SPICE, we failed "
|
|
163
|
-
"to load a metakernel. SPICE_METAKERNEL is not set,"
|
|
164
|
-
"and time_kernels_only is not set to True"
|
|
165
|
-
) from spicey_err
|
|
166
|
-
return func(*args, **kwargs)
|
|
167
|
-
|
|
168
|
-
return wrapper_ensure_spice
|
|
169
|
-
|
|
170
|
-
# Note: This return was originally implemented as a ternary operator, but
|
|
171
|
-
# this caused mypy to fail due to this bug:
|
|
172
|
-
# https://github.com/python/mypy/issues/4134
|
|
173
|
-
if callable(__func):
|
|
174
|
-
return _decorator(__func)
|
|
175
|
-
else:
|
|
176
|
-
return _decorator
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
def furnish_time_kernel() -> None:
|
|
180
|
-
"""Furnish the time kernels."""
|
|
181
|
-
spice_test_data_path = imap_module_directory / "tests/spice/test_data"
|
|
182
|
-
|
|
183
|
-
# TODO: we need to load these kernels from EFS volumen that is
|
|
184
|
-
# mounted to batch volume and extend this to generate metakernell
|
|
185
|
-
# which is TBD.
|
|
186
|
-
spiceypy.furnsh(str(spice_test_data_path / "imap_sclk_0000.tsc"))
|
|
187
|
-
spiceypy.furnsh(str(spice_test_data_path / "naif0012.tls"))
|