imap-processing 0.17.0__py3-none-any.whl → 0.18.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/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 +11 -0
- imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +11 -0
- imap_processing/cdf/config/imap_codice_l2_variable_attrs.yaml +24 -0
- 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_l2b_variable_attrs.yaml +119 -36
- imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml +16 -90
- imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +30 -0
- imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +15 -1
- imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +60 -0
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +91 -11
- imap_processing/cli.py +28 -5
- imap_processing/codice/codice_l1a.py +36 -48
- imap_processing/codice/codice_l1b.py +1 -1
- imap_processing/codice/codice_l2.py +0 -9
- imap_processing/codice/constants.py +481 -498
- imap_processing/hit/l0/decom_hit.py +2 -2
- imap_processing/hit/l1a/hit_l1a.py +64 -24
- imap_processing/hit/l1b/constants.py +5 -0
- imap_processing/hit/l1b/hit_l1b.py +18 -16
- imap_processing/hit/l2/constants.py +1 -1
- imap_processing/hit/l2/hit_l2.py +4 -5
- imap_processing/ialirt/constants.py +21 -0
- imap_processing/ialirt/generate_coverage.py +188 -0
- imap_processing/ialirt/l0/parse_mag.py +62 -5
- imap_processing/ialirt/l0/process_swapi.py +1 -1
- imap_processing/ialirt/l0/process_swe.py +23 -7
- 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_l2b.py +246 -67
- imap_processing/idex/idex_l2c.py +30 -196
- imap_processing/lo/l0/lo_apid.py +1 -0
- imap_processing/lo/l1a/lo_l1a.py +44 -0
- imap_processing/lo/packet_definitions/lo_xtce.xml +5359 -106
- imap_processing/mag/constants.py +1 -0
- imap_processing/mag/l1d/__init__.py +0 -0
- imap_processing/mag/l1d/mag_l1d.py +133 -0
- imap_processing/mag/l1d/mag_l1d_data.py +588 -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 +191 -130
- imap_processing/quality_flags.py +20 -2
- imap_processing/spice/geometry.py +25 -3
- imap_processing/spice/pointing_frame.py +1 -1
- imap_processing/spice/spin.py +4 -0
- imap_processing/spice/time.py +51 -0
- imap_processing/swapi/l2/swapi_l2.py +52 -8
- imap_processing/swapi/swapi_utils.py +1 -1
- imap_processing/swe/l1b/swe_l1b.py +2 -4
- imap_processing/ultra/constants.py +49 -1
- 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 +97 -5
- imap_processing/ultra/l1a/ultra_l1a.py +25 -4
- imap_processing/ultra/l1b/cullingmask.py +3 -3
- imap_processing/ultra/l1b/de.py +53 -15
- imap_processing/ultra/l1b/extendedspin.py +26 -2
- imap_processing/ultra/l1b/lookup_utils.py +171 -50
- imap_processing/ultra/l1b/quality_flag_filters.py +14 -0
- imap_processing/ultra/l1b/ultra_l1b_culling.py +198 -5
- imap_processing/ultra/l1b/ultra_l1b_extended.py +304 -66
- imap_processing/ultra/l1c/helio_pset.py +54 -7
- imap_processing/ultra/l1c/spacecraft_pset.py +9 -1
- imap_processing/ultra/l1c/ultra_l1c.py +2 -0
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +106 -109
- imap_processing/ultra/utils/ultra_l1_utils.py +13 -1
- {imap_processing-0.17.0.dist-info → imap_processing-0.18.0.dist-info}/METADATA +2 -2
- {imap_processing-0.17.0.dist-info → imap_processing-0.18.0.dist-info}/RECORD +76 -83
- 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.18.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.17.0.dist-info → imap_processing-0.18.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.17.0.dist-info → imap_processing-0.18.0.dist-info}/entry_points.txt +0 -0
|
@@ -767,10 +767,8 @@ def swe_l1b_science(dependencies: ProcessingInputCollection) -> xr.Dataset:
|
|
|
767
767
|
|
|
768
768
|
# Store ESA energies of full cycle for L2 purposes.
|
|
769
769
|
esa_energies = get_esa_energy_pattern(esa_lut_files[0])
|
|
770
|
-
# Repeat
|
|
771
|
-
esa_energies = np.repeat(esa_energies, total_packets // 4)
|
|
772
|
-
-1, swe_constants.N_ESA_STEPS, swe_constants.N_ANGLE_SECTORS
|
|
773
|
-
)
|
|
770
|
+
# Repeat the (24, 30) energy pattern n_cycles times along a new first axis
|
|
771
|
+
esa_energies = np.repeat(esa_energies[np.newaxis, :, :], total_packets // 4, axis=0)
|
|
774
772
|
# Convert voltage to electron energy in eV by apply conversion factor
|
|
775
773
|
esa_energies = esa_energies * swe_constants.ENERGY_CONVERSION_FACTOR
|
|
776
774
|
# ------------------------------------------------------------------
|
|
@@ -80,4 +80,52 @@ class UltraConstants:
|
|
|
80
80
|
CULLING_RPM_MAX = 6.0
|
|
81
81
|
|
|
82
82
|
# Thresholds for culling based on counts.
|
|
83
|
-
CULLING_ENERGY_BIN_EDGES: ClassVar[list] = [
|
|
83
|
+
CULLING_ENERGY_BIN_EDGES: ClassVar[list] = [
|
|
84
|
+
3.385,
|
|
85
|
+
4.13722222222222,
|
|
86
|
+
4.13722222222222,
|
|
87
|
+
5.05660493827161,
|
|
88
|
+
5.05660493827161,
|
|
89
|
+
6.18029492455419,
|
|
90
|
+
6.18029492455419,
|
|
91
|
+
7.55369379667734,
|
|
92
|
+
7.55369379667734,
|
|
93
|
+
9.23229241816119,
|
|
94
|
+
9.23229241816119,
|
|
95
|
+
11.2839129555303,
|
|
96
|
+
11.2839129555303,
|
|
97
|
+
13.7914491678704,
|
|
98
|
+
13.7914491678704,
|
|
99
|
+
16.8562156496194,
|
|
100
|
+
16.8562156496194,
|
|
101
|
+
20.6020413495348,
|
|
102
|
+
20.6020413495348,
|
|
103
|
+
25.1802727605426,
|
|
104
|
+
25.1802727605426,
|
|
105
|
+
30.775888929552,
|
|
106
|
+
30.775888929552,
|
|
107
|
+
37.6149753583414,
|
|
108
|
+
37.6149753583414,
|
|
109
|
+
45.9738587713061,
|
|
110
|
+
45.9738587713061,
|
|
111
|
+
56.1902718315964,
|
|
112
|
+
56.1902718315964,
|
|
113
|
+
68.6769989052845,
|
|
114
|
+
68.6769989052845,
|
|
115
|
+
83.93855421757,
|
|
116
|
+
83.93855421757,
|
|
117
|
+
102.591566265919,
|
|
118
|
+
102.591566265919,
|
|
119
|
+
125.38969210279,
|
|
120
|
+
125.38969210279,
|
|
121
|
+
153.254068125632,
|
|
122
|
+
153.254068125632,
|
|
123
|
+
187.310527709106,
|
|
124
|
+
187.310527709106,
|
|
125
|
+
228.93508942224,
|
|
126
|
+
228.93508942224,
|
|
127
|
+
279.809553738294,
|
|
128
|
+
279.809553738294,
|
|
129
|
+
341.989454569026,
|
|
130
|
+
1e5,
|
|
131
|
+
]
|
|
@@ -4,6 +4,7 @@ import numpy as np
|
|
|
4
4
|
from numpy.typing import NDArray
|
|
5
5
|
|
|
6
6
|
from imap_processing.ultra.l0.ultra_utils import (
|
|
7
|
+
PacketProperties,
|
|
7
8
|
parse_event,
|
|
8
9
|
)
|
|
9
10
|
from imap_processing.utils import convert_to_binary_string
|
|
@@ -155,8 +156,7 @@ def decompress_binary(
|
|
|
155
156
|
def decompress_image(
|
|
156
157
|
pixel0: int,
|
|
157
158
|
binary_data: str,
|
|
158
|
-
|
|
159
|
-
mantissa_bit_length: int,
|
|
159
|
+
packet_props: PacketProperties,
|
|
160
160
|
) -> NDArray:
|
|
161
161
|
"""
|
|
162
162
|
Will decompress a binary string representing an image into a matrix of pixel values.
|
|
@@ -171,10 +171,9 @@ def decompress_image(
|
|
|
171
171
|
The first, unmodified pixel p0,0.
|
|
172
172
|
binary_data : str
|
|
173
173
|
Binary string.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
The bit length of the mantissa.
|
|
174
|
+
packet_props : PacketProperties
|
|
175
|
+
Properties of the packet, including width bit, mantissa bit length and pixel
|
|
176
|
+
window dimensions.
|
|
178
177
|
|
|
179
178
|
Returns
|
|
180
179
|
-------
|
|
@@ -187,10 +186,18 @@ def decompress_image(
|
|
|
187
186
|
This process is described starting on page 168 in IMAP-Ultra Flight
|
|
188
187
|
Software Specification document.
|
|
189
188
|
"""
|
|
190
|
-
rows =
|
|
191
|
-
cols =
|
|
189
|
+
rows = packet_props.pixel_window_rows
|
|
190
|
+
cols = packet_props.pixel_window_columns
|
|
191
|
+
width_bit = packet_props.width
|
|
192
|
+
mantissa_bit_length = packet_props.mantissa_bit_length
|
|
192
193
|
pixels_per_block = 15
|
|
193
194
|
|
|
195
|
+
if width_bit is None or rows is None or cols is None or mantissa_bit_length is None:
|
|
196
|
+
raise ValueError(
|
|
197
|
+
"Packet properties must specify pixel window dimensions, "
|
|
198
|
+
"width bit, and mantissa bit length for this packet type."
|
|
199
|
+
)
|
|
200
|
+
|
|
194
201
|
blocks_per_row = cols // pixels_per_block
|
|
195
202
|
|
|
196
203
|
# Compressed pixel matrix
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Decommutates Ultra CCSDS packets."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import math
|
|
4
5
|
from collections import defaultdict
|
|
5
6
|
from typing import cast
|
|
6
7
|
|
|
@@ -29,7 +30,7 @@ from imap_processing.ultra.l0.ultra_utils import (
|
|
|
29
30
|
ULTRA_PRI_3_EVENTS,
|
|
30
31
|
ULTRA_PRI_4_EVENTS,
|
|
31
32
|
ULTRA_RATES,
|
|
32
|
-
|
|
33
|
+
PacketProperties,
|
|
33
34
|
)
|
|
34
35
|
from imap_processing.utils import convert_to_binary_string
|
|
35
36
|
|
|
@@ -37,7 +38,7 @@ logging.basicConfig(level=logging.INFO)
|
|
|
37
38
|
logger = logging.getLogger(__name__)
|
|
38
39
|
|
|
39
40
|
|
|
40
|
-
def process_ultra_tof(ds: xr.Dataset) -> xr.Dataset:
|
|
41
|
+
def process_ultra_tof(ds: xr.Dataset, packet_props: PacketProperties) -> xr.Dataset:
|
|
41
42
|
"""
|
|
42
43
|
Unpack and decode Ultra TOF packets.
|
|
43
44
|
|
|
@@ -45,6 +46,9 @@ def process_ultra_tof(ds: xr.Dataset) -> xr.Dataset:
|
|
|
45
46
|
----------
|
|
46
47
|
ds : xarray.Dataset
|
|
47
48
|
TOF dataset.
|
|
49
|
+
packet_props : PacketProperties
|
|
50
|
+
Information that defines properties of the packet including the pixel window
|
|
51
|
+
dimensions of images and number of image panes.
|
|
48
52
|
|
|
49
53
|
Returns
|
|
50
54
|
-------
|
|
@@ -53,14 +57,35 @@ def process_ultra_tof(ds: xr.Dataset) -> xr.Dataset:
|
|
|
53
57
|
"""
|
|
54
58
|
scalar_keys = [key for key in ds.data_vars if key not in ("packetdata", "sid")]
|
|
55
59
|
|
|
60
|
+
image_planes = packet_props.image_planes
|
|
61
|
+
rows = packet_props.pixel_window_rows
|
|
62
|
+
cols = packet_props.pixel_window_columns
|
|
63
|
+
planes_per_packet = packet_props.image_planes_per_packet
|
|
64
|
+
|
|
65
|
+
if (
|
|
66
|
+
image_planes is None
|
|
67
|
+
or rows is None
|
|
68
|
+
or cols is None
|
|
69
|
+
or planes_per_packet is None
|
|
70
|
+
):
|
|
71
|
+
raise ValueError(
|
|
72
|
+
"Packet properties must specify pixel window dimensions, "
|
|
73
|
+
"width bit, image planes, and image planes per packet for this packet type."
|
|
74
|
+
)
|
|
75
|
+
# Calculate the number of image packets based on the number of image panes and
|
|
76
|
+
# planes per packet.
|
|
77
|
+
# There may be cases where the last packet has fewer planes than the
|
|
78
|
+
# planes_per_packet, to account for this, we use ceiling division.
|
|
79
|
+
num_image_packets = math.ceil(image_planes / planes_per_packet)
|
|
80
|
+
|
|
56
81
|
decom_data: defaultdict[str, list[np.ndarray]] = defaultdict(list)
|
|
57
82
|
decom_data["packetdata"] = []
|
|
58
83
|
valid_epoch = []
|
|
59
|
-
width = cast(int, ULTRA_TOF.width)
|
|
60
|
-
mantissa_bit_length = cast(int, ULTRA_TOF.mantissa_bit_length)
|
|
61
84
|
|
|
62
85
|
for val, group in ds.groupby("epoch"):
|
|
63
|
-
if set(group["sid"].values) >= set(
|
|
86
|
+
if set(group["sid"].values) >= set(
|
|
87
|
+
np.arange(0, image_planes, planes_per_packet)
|
|
88
|
+
):
|
|
64
89
|
valid_epoch.append(val)
|
|
65
90
|
group.sortby("sid")
|
|
66
91
|
|
|
@@ -68,13 +93,12 @@ def process_ultra_tof(ds: xr.Dataset) -> xr.Dataset:
|
|
|
68
93
|
decom_data[key].append(group[key].values)
|
|
69
94
|
|
|
70
95
|
image = []
|
|
71
|
-
for i in range(
|
|
96
|
+
for i in range(num_image_packets):
|
|
72
97
|
binary = convert_to_binary_string(group["packetdata"].values[i])
|
|
73
98
|
decompressed = decompress_image(
|
|
74
99
|
group["p00"].values[i],
|
|
75
100
|
binary,
|
|
76
|
-
|
|
77
|
-
mantissa_bit_length,
|
|
101
|
+
packet_props,
|
|
78
102
|
)
|
|
79
103
|
image.append(decompressed)
|
|
80
104
|
|
|
@@ -87,9 +111,9 @@ def process_ultra_tof(ds: xr.Dataset) -> xr.Dataset:
|
|
|
87
111
|
|
|
88
112
|
coords = {
|
|
89
113
|
"epoch": np.array(valid_epoch, dtype=np.uint64),
|
|
90
|
-
"sid": xr.DataArray(np.arange(
|
|
91
|
-
"row": xr.DataArray(np.arange(
|
|
92
|
-
"column": xr.DataArray(np.arange(
|
|
114
|
+
"sid": xr.DataArray(np.arange(num_image_packets), dims=["sid"], name="sid"),
|
|
115
|
+
"row": xr.DataArray(np.arange(rows), dims=["row"], name="row"),
|
|
116
|
+
"column": xr.DataArray(np.arange(cols), dims=["column"], name="column"),
|
|
93
117
|
}
|
|
94
118
|
|
|
95
119
|
dataset = xr.Dataset(coords=coords)
|
|
@@ -10,15 +10,23 @@ class PacketProperties(NamedTuple):
|
|
|
10
10
|
logical_source: list # List of logical sources
|
|
11
11
|
addition_to_logical_desc: str # Description of the logical source
|
|
12
12
|
width: Union[int, None] # Width of binary data (could be None).
|
|
13
|
+
# Block, image_planes, pixel_window_rows, and pixel_window_columns are important for
|
|
14
|
+
# decompressing the images and a description is available on page 171 of IMAP-Ultra
|
|
15
|
+
# Flight Software Specification document (7523-9009_Rev_-.pdf).
|
|
13
16
|
block: Union[int, None] # Number of values in each block (could be None).
|
|
14
|
-
# This is important for decompressing the images and
|
|
15
|
-
# a description is available on page 171 of IMAP-Ultra Flight
|
|
16
|
-
# Software Specification document (7523-9009_Rev_-.pdf).
|
|
17
17
|
len_array: Union[
|
|
18
18
|
int, None
|
|
19
19
|
] # Length of the array to be decompressed (could be None).
|
|
20
20
|
mantissa_bit_length: Union[int, None] # used to determine the level of
|
|
21
21
|
# precision that can be recovered from compressed data (could be None).
|
|
22
|
+
image_planes: Union[int, None] = None
|
|
23
|
+
# number of images. See table 11 in the FSSD.
|
|
24
|
+
pixel_window_rows: Union[int, None] = None
|
|
25
|
+
# number of rows in each image. See table 49 in the FSSD.
|
|
26
|
+
pixel_window_columns: Union[int, None] = None
|
|
27
|
+
# number of columns in each image. See table 49 in the FSSD.
|
|
28
|
+
image_planes_per_packet: Union[int, None] = None
|
|
29
|
+
# number of image planes in each packet. See table 52 in the FSSD.
|
|
22
30
|
|
|
23
31
|
|
|
24
32
|
# Define PacketProperties instances directly in the module namespace
|
|
@@ -64,15 +72,99 @@ ULTRA_ENERGY_SPECTRA = PacketProperties(
|
|
|
64
72
|
len_array=1,
|
|
65
73
|
mantissa_bit_length=5,
|
|
66
74
|
)
|
|
67
|
-
|
|
75
|
+
ULTRA_PHXTOF_HIGH_ANGULAR = PacketProperties(
|
|
68
76
|
apid=[883, 947],
|
|
69
77
|
logical_source=[
|
|
70
78
|
"imap_ultra_l1a_45sensor-histogram-ena-phxtof-hi-ang",
|
|
71
79
|
"imap_ultra_l1a_90sensor-histogram-ena-phxtof-hi-ang",
|
|
72
80
|
],
|
|
73
|
-
addition_to_logical_desc="Time of Flight Images",
|
|
81
|
+
addition_to_logical_desc="Pulse Height Time of Flight High Angular Images",
|
|
74
82
|
width=4,
|
|
75
83
|
block=15,
|
|
84
|
+
image_planes=8,
|
|
85
|
+
pixel_window_rows=54,
|
|
86
|
+
pixel_window_columns=180,
|
|
87
|
+
image_planes_per_packet=1,
|
|
88
|
+
len_array=None,
|
|
89
|
+
mantissa_bit_length=4,
|
|
90
|
+
)
|
|
91
|
+
ULTRA_PHXTOF_HIGH_ENERGY = PacketProperties(
|
|
92
|
+
apid=[884, 948],
|
|
93
|
+
logical_source=[
|
|
94
|
+
"imap_ultra_l1a_45sensor-histogram-ena-phxtof-hi-nrg",
|
|
95
|
+
"imap_ultra_l1a_90sensor-histogram-ena-phxtof-hi-nrg",
|
|
96
|
+
],
|
|
97
|
+
addition_to_logical_desc="Pulse Height By Time of Flight High Energy Images",
|
|
98
|
+
width=4,
|
|
99
|
+
block=15,
|
|
100
|
+
image_planes=28,
|
|
101
|
+
pixel_window_rows=27,
|
|
102
|
+
pixel_window_columns=90,
|
|
103
|
+
image_planes_per_packet=1,
|
|
104
|
+
len_array=None,
|
|
105
|
+
mantissa_bit_length=4,
|
|
106
|
+
)
|
|
107
|
+
ULTRA_PHXTOF_HIGH_TIME = PacketProperties(
|
|
108
|
+
apid=[885, 949],
|
|
109
|
+
logical_source=[
|
|
110
|
+
"imap_ultra_l1a_45sensor-histogram-ena-phxtof-hi-time",
|
|
111
|
+
"imap_ultra_l1a_90sensor-histogram-ena-phxtof-hi-time",
|
|
112
|
+
],
|
|
113
|
+
addition_to_logical_desc="Time of Flight High Time Images",
|
|
114
|
+
width=4,
|
|
115
|
+
block=15,
|
|
116
|
+
image_planes=8,
|
|
117
|
+
pixel_window_rows=18,
|
|
118
|
+
pixel_window_columns=60,
|
|
119
|
+
image_planes_per_packet=2,
|
|
120
|
+
len_array=None,
|
|
121
|
+
mantissa_bit_length=4,
|
|
122
|
+
)
|
|
123
|
+
ULTRA_EXTOF_HIGH_ANGULAR = PacketProperties(
|
|
124
|
+
apid=[886, 950],
|
|
125
|
+
logical_source=[
|
|
126
|
+
"imap_ultra_l1a_45sensor-histogram-ena-extof-hi-ang",
|
|
127
|
+
"imap_ultra_l1a_90sensor-histogram-ena-extof-hi-ang",
|
|
128
|
+
],
|
|
129
|
+
addition_to_logical_desc="Energy By Time of Flight High Angular Images",
|
|
130
|
+
width=4,
|
|
131
|
+
block=15,
|
|
132
|
+
image_planes=12,
|
|
133
|
+
pixel_window_rows=18,
|
|
134
|
+
pixel_window_columns=60,
|
|
135
|
+
image_planes_per_packet=2,
|
|
136
|
+
len_array=None,
|
|
137
|
+
mantissa_bit_length=4,
|
|
138
|
+
)
|
|
139
|
+
ULTRA_EXTOF_HIGH_TIME = PacketProperties(
|
|
140
|
+
apid=[888, 952],
|
|
141
|
+
logical_source=[
|
|
142
|
+
"imap_ultra_l1a_45sensor-histogram-ena-extof-hi-time",
|
|
143
|
+
"imap_ultra_l1a_90sensor-histogram-ena-extof-hi-time",
|
|
144
|
+
],
|
|
145
|
+
addition_to_logical_desc="Energy By Time of Flight High Time Images",
|
|
146
|
+
width=4,
|
|
147
|
+
block=15,
|
|
148
|
+
image_planes=4,
|
|
149
|
+
pixel_window_rows=9,
|
|
150
|
+
pixel_window_columns=30,
|
|
151
|
+
image_planes_per_packet=8,
|
|
152
|
+
len_array=None,
|
|
153
|
+
mantissa_bit_length=4,
|
|
154
|
+
)
|
|
155
|
+
ULTRA_EXTOF_HIGH_ENERGY = PacketProperties(
|
|
156
|
+
apid=[887, 951],
|
|
157
|
+
logical_source=[
|
|
158
|
+
"imap_ultra_l1a_45sensor-histogram-ena-extof-hi-nrg",
|
|
159
|
+
"imap_ultra_l1a_90sensor-histogram-ena-extof-hi-nrg",
|
|
160
|
+
],
|
|
161
|
+
addition_to_logical_desc="Energy By Time of Flight High Energy Images",
|
|
162
|
+
width=4,
|
|
163
|
+
block=15,
|
|
164
|
+
image_planes=44,
|
|
165
|
+
pixel_window_rows=9,
|
|
166
|
+
pixel_window_columns=30,
|
|
167
|
+
image_planes_per_packet=8,
|
|
76
168
|
len_array=None,
|
|
77
169
|
mantissa_bit_length=4,
|
|
78
170
|
)
|
|
@@ -24,14 +24,19 @@ from imap_processing.ultra.l0.ultra_utils import (
|
|
|
24
24
|
ULTRA_ENERGY_RATES,
|
|
25
25
|
ULTRA_ENERGY_SPECTRA,
|
|
26
26
|
ULTRA_EVENTS,
|
|
27
|
+
ULTRA_EXTOF_HIGH_ANGULAR,
|
|
28
|
+
ULTRA_EXTOF_HIGH_ENERGY,
|
|
29
|
+
ULTRA_EXTOF_HIGH_TIME,
|
|
27
30
|
ULTRA_HK,
|
|
28
31
|
ULTRA_MACROS_CHECKSUM,
|
|
32
|
+
ULTRA_PHXTOF_HIGH_ANGULAR,
|
|
33
|
+
ULTRA_PHXTOF_HIGH_ENERGY,
|
|
34
|
+
ULTRA_PHXTOF_HIGH_TIME,
|
|
29
35
|
ULTRA_PRI_1_EVENTS,
|
|
30
36
|
ULTRA_PRI_2_EVENTS,
|
|
31
37
|
ULTRA_PRI_3_EVENTS,
|
|
32
38
|
ULTRA_PRI_4_EVENTS,
|
|
33
39
|
ULTRA_RATES,
|
|
34
|
-
ULTRA_TOF,
|
|
35
40
|
)
|
|
36
41
|
from imap_processing.utils import packet_file_to_datasets
|
|
37
42
|
|
|
@@ -87,6 +92,19 @@ def ultra_l1a( # noqa: PLR0912
|
|
|
87
92
|
for i, apid in enumerate(group.apid)
|
|
88
93
|
}
|
|
89
94
|
|
|
95
|
+
all_l1a_image_apids = {
|
|
96
|
+
apid: group
|
|
97
|
+
for group in [
|
|
98
|
+
ULTRA_PHXTOF_HIGH_ANGULAR,
|
|
99
|
+
ULTRA_PHXTOF_HIGH_ENERGY,
|
|
100
|
+
ULTRA_PHXTOF_HIGH_TIME,
|
|
101
|
+
ULTRA_EXTOF_HIGH_ANGULAR,
|
|
102
|
+
ULTRA_EXTOF_HIGH_TIME,
|
|
103
|
+
ULTRA_EXTOF_HIGH_ENERGY,
|
|
104
|
+
]
|
|
105
|
+
for apid in group.apid
|
|
106
|
+
}
|
|
107
|
+
|
|
90
108
|
# Update dataset global attributes
|
|
91
109
|
attr_mgr = ImapCdfAttributes()
|
|
92
110
|
attr_mgr.add_instrument_global_attrs("ultra")
|
|
@@ -96,9 +114,12 @@ def ultra_l1a( # noqa: PLR0912
|
|
|
96
114
|
if apid in ULTRA_AUX.apid:
|
|
97
115
|
decom_ultra_dataset = datasets_by_apid[apid]
|
|
98
116
|
gattr_key = ULTRA_AUX.logical_source[ULTRA_AUX.apid.index(apid)]
|
|
99
|
-
elif apid in
|
|
100
|
-
|
|
101
|
-
|
|
117
|
+
elif apid in all_l1a_image_apids:
|
|
118
|
+
packet_props = all_l1a_image_apids[apid]
|
|
119
|
+
decom_ultra_dataset = process_ultra_tof(
|
|
120
|
+
datasets_by_apid[apid], packet_props
|
|
121
|
+
)
|
|
122
|
+
gattr_key = packet_props.logical_source[packet_props.apid.index(apid)]
|
|
102
123
|
elif apid in ULTRA_RATES.apid:
|
|
103
124
|
decom_ultra_dataset = process_ultra_rates(datasets_by_apid[apid])
|
|
104
125
|
decom_ultra_dataset = decom_ultra_dataset.drop_vars("fastdata_00")
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import xarray as xr
|
|
5
5
|
|
|
6
|
-
from imap_processing.
|
|
6
|
+
from imap_processing.ultra.l1b.quality_flag_filters import QUALITY_FLAG_FILTERS
|
|
7
7
|
from imap_processing.ultra.utils.ultra_l1_utils import create_dataset, extract_data_dict
|
|
8
8
|
|
|
9
9
|
FILLVAL_UINT16 = 65535
|
|
@@ -32,14 +32,14 @@ def calculate_cullingmask(extendedspin_dataset: xr.Dataset, name: str) -> xr.Dat
|
|
|
32
32
|
good_mask = (
|
|
33
33
|
(
|
|
34
34
|
extendedspin_dataset["quality_attitude"]
|
|
35
|
-
&
|
|
35
|
+
& sum(flag.value for flag in QUALITY_FLAG_FILTERS["quality_attitude"])
|
|
36
36
|
)
|
|
37
37
|
== 0
|
|
38
38
|
) & (
|
|
39
39
|
(
|
|
40
40
|
(
|
|
41
41
|
extendedspin_dataset["quality_ena_rates"]
|
|
42
|
-
&
|
|
42
|
+
& sum(flag.value for flag in QUALITY_FLAG_FILTERS["quality_ena_rates"])
|
|
43
43
|
)
|
|
44
44
|
== 0
|
|
45
45
|
).all(dim="energy_bin_geometric_mean")
|
imap_processing/ultra/l1b/de.py
CHANGED
|
@@ -4,12 +4,16 @@ import numpy as np
|
|
|
4
4
|
import xarray as xr
|
|
5
5
|
|
|
6
6
|
from imap_processing.cdf.utils import parse_filename_like
|
|
7
|
+
from imap_processing.quality_flags import ImapDEUltraFlags
|
|
7
8
|
from imap_processing.spice.geometry import SpiceFrame
|
|
9
|
+
from imap_processing.ultra.l1b.lookup_utils import get_geometric_factor
|
|
8
10
|
from imap_processing.ultra.l1b.ultra_l1b_annotated import (
|
|
9
11
|
get_annotated_particle_velocity,
|
|
10
12
|
)
|
|
11
13
|
from imap_processing.ultra.l1b.ultra_l1b_extended import (
|
|
12
14
|
StopType,
|
|
15
|
+
determine_ebin_pulse_height,
|
|
16
|
+
determine_ebin_ssd,
|
|
13
17
|
determine_species,
|
|
14
18
|
get_coincidence_positions,
|
|
15
19
|
get_ctof,
|
|
@@ -25,6 +29,7 @@ from imap_processing.ultra.l1b.ultra_l1b_extended import (
|
|
|
25
29
|
get_path_length,
|
|
26
30
|
get_ph_tof_and_back_positions,
|
|
27
31
|
get_phi_theta,
|
|
32
|
+
get_spin_number,
|
|
28
33
|
get_ssd_back_position_and_tof_offset,
|
|
29
34
|
get_ssd_tof,
|
|
30
35
|
)
|
|
@@ -59,7 +64,10 @@ def calculate_de(
|
|
|
59
64
|
|
|
60
65
|
# Define epoch and spin.
|
|
61
66
|
de_dict["epoch"] = de_dataset["epoch"].data
|
|
62
|
-
|
|
67
|
+
spin_number = get_spin_number(
|
|
68
|
+
de_dataset["shcoarse"].values, de_dataset["spin"].values
|
|
69
|
+
)
|
|
70
|
+
de_dict["spin"] = spin_number
|
|
63
71
|
|
|
64
72
|
# Add already populated fields.
|
|
65
73
|
keys = [
|
|
@@ -108,6 +116,7 @@ def calculate_de(
|
|
|
108
116
|
ctof = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
|
|
109
117
|
magnitude_v = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
|
|
110
118
|
energy = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
|
|
119
|
+
e_bin = np.full(len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8)
|
|
111
120
|
species_bin = np.full(len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8)
|
|
112
121
|
t2 = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
|
|
113
122
|
event_times = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32)
|
|
@@ -116,40 +125,44 @@ def calculate_de(
|
|
|
116
125
|
sc_dps_velocity = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32)
|
|
117
126
|
helio_velocity = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32)
|
|
118
127
|
spin_starts = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float64)
|
|
119
|
-
|
|
120
|
-
len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float64
|
|
121
|
-
)
|
|
128
|
+
|
|
122
129
|
start_type = np.full(len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8)
|
|
130
|
+
quality_flags = np.full(
|
|
131
|
+
de_dataset["epoch"].shape, ImapDEUltraFlags.NONE.value, dtype=np.uint16
|
|
132
|
+
)
|
|
123
133
|
|
|
124
134
|
xf[valid_indices] = get_front_x_position(
|
|
125
135
|
de_dataset["start_type"].data[valid_indices],
|
|
126
136
|
de_dataset["start_pos_tdc"].data[valid_indices],
|
|
127
137
|
f"ultra{sensor}",
|
|
138
|
+
ancillary_files,
|
|
128
139
|
)
|
|
129
140
|
start_type[valid_indices] = de_dataset["start_type"].data[valid_indices]
|
|
130
141
|
|
|
131
142
|
(
|
|
132
143
|
event_times[valid_indices],
|
|
133
144
|
spin_starts[valid_indices],
|
|
134
|
-
|
|
145
|
+
_,
|
|
135
146
|
) = get_eventtimes(
|
|
136
|
-
|
|
147
|
+
de_dict["spin"][valid_indices],
|
|
137
148
|
de_dataset["phase_angle"].data[valid_indices],
|
|
138
149
|
)
|
|
139
150
|
|
|
140
151
|
# Pulse height
|
|
141
152
|
tof[ph_indices], t2[ph_indices], xb[ph_indices], yb[ph_indices] = (
|
|
142
|
-
get_ph_tof_and_back_positions(de_dataset, xf, f"ultra{sensor}")
|
|
153
|
+
get_ph_tof_and_back_positions(de_dataset, xf, f"ultra{sensor}", ancillary_files)
|
|
143
154
|
)
|
|
144
155
|
d[ph_indices], yf[ph_indices] = get_front_y_position(
|
|
145
|
-
de_dataset["start_type"].data[ph_indices], yb[ph_indices]
|
|
156
|
+
de_dataset["start_type"].data[ph_indices], yb[ph_indices], ancillary_files
|
|
146
157
|
)
|
|
147
|
-
energy[ph_indices] = get_energy_pulse_height(
|
|
158
|
+
energy[ph_indices], _ = get_energy_pulse_height(
|
|
148
159
|
de_dataset["stop_type"].data[ph_indices],
|
|
149
160
|
de_dataset["energy_ph"].data[ph_indices],
|
|
150
161
|
xb[ph_indices],
|
|
151
162
|
yb[ph_indices],
|
|
152
163
|
f"ultra{sensor}",
|
|
164
|
+
ancillary_files,
|
|
165
|
+
quality_flags[ph_indices],
|
|
153
166
|
)
|
|
154
167
|
r[ph_indices] = get_path_length(
|
|
155
168
|
(xf[ph_indices], yf[ph_indices]),
|
|
@@ -161,26 +174,32 @@ def calculate_de(
|
|
|
161
174
|
(xb[ph_indices], yb[ph_indices]),
|
|
162
175
|
d[ph_indices],
|
|
163
176
|
)
|
|
177
|
+
e_bin[ph_indices] = determine_ebin_pulse_height(
|
|
178
|
+
energy[ph_indices], tof[ph_indices], r[ph_indices]
|
|
179
|
+
)
|
|
164
180
|
species_bin[ph_indices] = determine_species(tof[ph_indices], r[ph_indices], "PH")
|
|
165
181
|
etof[ph_indices], xc[ph_indices] = get_coincidence_positions(
|
|
166
|
-
de_dataset.isel(epoch=ph_indices),
|
|
182
|
+
de_dataset.isel(epoch=ph_indices),
|
|
183
|
+
t2[ph_indices],
|
|
184
|
+
f"ultra{sensor}",
|
|
185
|
+
ancillary_files,
|
|
167
186
|
)
|
|
168
187
|
ctof[ph_indices], magnitude_v[ph_indices] = get_ctof(
|
|
169
188
|
tof[ph_indices], r[ph_indices], "PH"
|
|
170
189
|
)
|
|
171
190
|
|
|
172
191
|
# SSD
|
|
173
|
-
tof[ssd_indices] = get_ssd_tof(de_dataset, xf, f"ultra{sensor}")
|
|
192
|
+
tof[ssd_indices] = get_ssd_tof(de_dataset, xf, f"ultra{sensor}", ancillary_files)
|
|
174
193
|
yb[ssd_indices], _, ssd_number = get_ssd_back_position_and_tof_offset(
|
|
175
|
-
de_dataset, f"ultra{sensor}"
|
|
194
|
+
de_dataset, f"ultra{sensor}", ancillary_files
|
|
176
195
|
)
|
|
177
196
|
xc[ssd_indices] = np.zeros(len(ssd_indices))
|
|
178
197
|
xb[ssd_indices] = np.zeros(len(ssd_indices))
|
|
179
198
|
etof[ssd_indices] = np.zeros(len(ssd_indices))
|
|
180
199
|
d[ssd_indices], yf[ssd_indices] = get_front_y_position(
|
|
181
|
-
de_dataset["start_type"].data[ssd_indices], yb[ssd_indices]
|
|
200
|
+
de_dataset["start_type"].data[ssd_indices], yb[ssd_indices], ancillary_files
|
|
182
201
|
)
|
|
183
|
-
energy[ssd_indices] = get_energy_ssd(de_dataset, ssd_number)
|
|
202
|
+
energy[ssd_indices] = get_energy_ssd(de_dataset, ssd_number, ancillary_files)
|
|
184
203
|
r[ssd_indices] = get_path_length(
|
|
185
204
|
(xf[ssd_indices], yf[ssd_indices]),
|
|
186
205
|
(xb[ssd_indices], yb[ssd_indices]),
|
|
@@ -191,6 +210,9 @@ def calculate_de(
|
|
|
191
210
|
(xb[ssd_indices], yb[ssd_indices]),
|
|
192
211
|
d[ssd_indices],
|
|
193
212
|
)
|
|
213
|
+
e_bin[ssd_indices] = determine_ebin_ssd(
|
|
214
|
+
energy[ssd_indices], tof[ssd_indices], r[ssd_indices]
|
|
215
|
+
)
|
|
194
216
|
species_bin[ssd_indices] = determine_species(
|
|
195
217
|
tof[ssd_indices], r[ssd_indices], "SSD"
|
|
196
218
|
)
|
|
@@ -202,7 +224,6 @@ def calculate_de(
|
|
|
202
224
|
de_dict["x_front"] = xf.astype(np.float32)
|
|
203
225
|
de_dict["event_times"] = event_times
|
|
204
226
|
de_dict["spin_starts"] = spin_starts
|
|
205
|
-
de_dict["spin_period"] = spin_period_sec
|
|
206
227
|
de_dict["y_front"] = yf
|
|
207
228
|
de_dict["x_back"] = xb
|
|
208
229
|
de_dict["y_back"] = yb
|
|
@@ -228,6 +249,7 @@ def calculate_de(
|
|
|
228
249
|
|
|
229
250
|
de_dict["tof_energy"] = get_de_energy_kev(v, species_bin)
|
|
230
251
|
de_dict["energy"] = energy
|
|
252
|
+
de_dict["ebin"] = e_bin
|
|
231
253
|
de_dict["species"] = species_bin
|
|
232
254
|
|
|
233
255
|
# Annotated Events.
|
|
@@ -261,10 +283,26 @@ def calculate_de(
|
|
|
261
283
|
de_dict["tof_energy"],
|
|
262
284
|
de_dict["phi"],
|
|
263
285
|
de_dict["theta"],
|
|
286
|
+
ancillary_files,
|
|
264
287
|
)
|
|
265
288
|
de_dict["event_efficiency"] = get_efficiency(
|
|
266
289
|
de_dict["tof_energy"], de_dict["phi"], de_dict["theta"], ancillary_files
|
|
267
290
|
)
|
|
291
|
+
de_dict["geometric_factor_blades"] = get_geometric_factor(
|
|
292
|
+
ancillary_files,
|
|
293
|
+
"l1b-sensor-gf-blades",
|
|
294
|
+
de_dict["phi"],
|
|
295
|
+
de_dict["theta"],
|
|
296
|
+
quality_flags,
|
|
297
|
+
)
|
|
298
|
+
de_dict["geometric_factor_noblades"] = get_geometric_factor(
|
|
299
|
+
ancillary_files,
|
|
300
|
+
"l1b-sensor-gf-noblades",
|
|
301
|
+
de_dict["phi"],
|
|
302
|
+
de_dict["theta"],
|
|
303
|
+
quality_flags,
|
|
304
|
+
)
|
|
305
|
+
de_dict["quality_fov"] = quality_flags
|
|
268
306
|
|
|
269
307
|
dataset = create_dataset(de_dict, name, "l1b")
|
|
270
308
|
|