imap-processing 0.8.0__py3-none-any.whl → 0.9.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 +2 -0
- imap_processing/cdf/config/imap_hi_variable_attrs.yaml +100 -1
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +14 -0
- imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +63 -1
- imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +7 -0
- imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +574 -231
- imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +326 -0
- imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +33 -23
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +7 -4
- imap_processing/cdf/utils.py +3 -5
- imap_processing/cli.py +13 -4
- imap_processing/codice/codice_l1a.py +5 -5
- imap_processing/codice/constants.py +9 -9
- imap_processing/codice/decompress.py +6 -2
- imap_processing/glows/l1a/glows_l1a.py +1 -2
- imap_processing/hi/l1a/hi_l1a.py +4 -4
- imap_processing/hi/l1a/histogram.py +106 -108
- imap_processing/hi/l1a/science_direct_event.py +91 -224
- imap_processing/hi/packet_definitions/TLM_HI_COMBINED_SCI.xml +3994 -0
- imap_processing/hit/l0/constants.py +2 -2
- imap_processing/hit/l0/decom_hit.py +12 -101
- imap_processing/hit/l1a/hit_l1a.py +164 -23
- imap_processing/ialirt/l0/process_codicelo.py +153 -0
- imap_processing/ialirt/l0/process_hit.py +5 -5
- imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +281 -0
- imap_processing/ialirt/process_ephemeris.py +212 -0
- imap_processing/idex/idex_l1a.py +55 -75
- imap_processing/idex/idex_l1b.py +192 -0
- imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -0
- imap_processing/idex/packet_definitions/idex_packet_definition.xml +97 -595
- imap_processing/lo/l0/decompression_tables/decompression_tables.py +16 -0
- imap_processing/lo/l0/lo_science.py +44 -12
- imap_processing/lo/l1a/lo_l1a.py +76 -8
- imap_processing/lo/packet_definitions/lo_xtce.xml +9877 -87
- imap_processing/mag/l1a/mag_l1a.py +1 -2
- imap_processing/mag/l1a/mag_l1a_data.py +1 -2
- imap_processing/mag/l1b/mag_l1b.py +2 -1
- imap_processing/spice/geometry.py +37 -19
- imap_processing/spice/time.py +144 -2
- imap_processing/swapi/l1/swapi_l1.py +3 -3
- imap_processing/swapi/packet_definitions/swapi_packet_definition.xml +1535 -446
- imap_processing/swe/l2/swe_l2.py +134 -17
- imap_processing/tests/ccsds/test_data/expected_output.xml +1 -1
- imap_processing/tests/codice/test_codice_l1a.py +8 -8
- imap_processing/tests/codice/test_decompress.py +4 -4
- imap_processing/tests/conftest.py +46 -43
- imap_processing/tests/hi/test_data/l0/H90_NHK_20241104.bin +0 -0
- imap_processing/tests/hi/test_data/l0/H90_sci_cnt_20241104.bin +0 -0
- imap_processing/tests/hi/test_data/l0/H90_sci_de_20241104.bin +0 -0
- imap_processing/tests/hi/test_hi_l1b.py +2 -2
- imap_processing/tests/hi/test_l1a.py +31 -58
- imap_processing/tests/hi/test_science_direct_event.py +58 -0
- imap_processing/tests/hit/test_data/sci_sample1.ccsds +0 -0
- imap_processing/tests/hit/test_decom_hit.py +60 -50
- imap_processing/tests/hit/test_hit_l1a.py +327 -12
- imap_processing/tests/hit/test_hit_l1b.py +76 -0
- imap_processing/tests/hit/validation_data/hskp_sample_eu.csv +89 -0
- imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +29 -0
- imap_processing/tests/ialirt/test_data/l0/apid01152.tlm +0 -0
- imap_processing/tests/ialirt/test_data/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/ialirt/unit/test_process_codicelo.py +106 -0
- imap_processing/tests/ialirt/unit/test_process_ephemeris.py +109 -0
- imap_processing/tests/ialirt/unit/test_process_hit.py +9 -6
- imap_processing/tests/idex/conftest.py +1 -1
- imap_processing/tests/idex/test_idex_l0.py +1 -1
- imap_processing/tests/idex/test_idex_l1a.py +7 -1
- imap_processing/tests/idex/test_idex_l1b.py +126 -0
- imap_processing/tests/lo/test_lo_l1a.py +7 -16
- imap_processing/tests/lo/test_lo_science.py +67 -3
- imap_processing/tests/lo/test_pkts/imap_lo_l0_raw_20240803_v002.pkts +0 -0
- imap_processing/tests/lo/validation_data/Instrument_FM1_T104_R129_20240803_ILO_SCI_DE_dec_DN_with_fills.csv +1999 -0
- imap_processing/tests/mag/test_mag_l1b.py +39 -5
- imap_processing/tests/spice/test_geometry.py +32 -6
- imap_processing/tests/spice/test_time.py +135 -6
- imap_processing/tests/swapi/test_swapi_decom.py +75 -69
- imap_processing/tests/swapi/test_swapi_l1.py +4 -4
- imap_processing/tests/swe/test_swe_l2.py +64 -8
- imap_processing/tests/test_utils.py +1 -1
- imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3314 -3314
- imap_processing/tests/ultra/unit/test_de.py +8 -3
- imap_processing/tests/ultra/unit/test_spatial_utils.py +125 -0
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +39 -29
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +2 -25
- imap_processing/ultra/constants.py +4 -0
- imap_processing/ultra/l1b/de.py +8 -14
- imap_processing/ultra/l1b/ultra_l1b_extended.py +29 -70
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +1 -36
- imap_processing/ultra/utils/spatial_utils.py +221 -0
- {imap_processing-0.8.0.dist-info → imap_processing-0.9.0.dist-info}/METADATA +1 -1
- {imap_processing-0.8.0.dist-info → imap_processing-0.9.0.dist-info}/RECORD +94 -76
- imap_processing/hi/l0/__init__.py +0 -0
- imap_processing/hi/l0/decom_hi.py +0 -24
- imap_processing/hi/packet_definitions/hi_packet_definition.xml +0 -482
- imap_processing/tests/hi/test_decom.py +0 -55
- imap_processing/tests/hi/test_l1a_sci_de.py +0 -72
- {imap_processing-0.8.0.dist-info → imap_processing-0.9.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.8.0.dist-info → imap_processing-0.9.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.8.0.dist-info → imap_processing-0.9.0.dist-info}/entry_points.txt +0 -0
|
@@ -184,7 +184,7 @@ DATA_PRODUCT_CONFIGURATIONS = {
|
|
|
184
184
|
"energy_label",
|
|
185
185
|
], # TODO: These will likely change
|
|
186
186
|
"dataset_name": "imap_codice_l1a_lo-counters-aggregated",
|
|
187
|
-
"dims": ["epoch", "
|
|
187
|
+
"dims": ["epoch", "esa_step", "inst_az", "spin_sector"],
|
|
188
188
|
"instrument": "lo",
|
|
189
189
|
"num_counters": 1,
|
|
190
190
|
"num_energy_steps": 128,
|
|
@@ -205,7 +205,7 @@ DATA_PRODUCT_CONFIGURATIONS = {
|
|
|
205
205
|
"energy_label",
|
|
206
206
|
], # TODO: These will likely change
|
|
207
207
|
"dataset_name": "imap_codice_l1a_lo-counters-singles",
|
|
208
|
-
"dims": ["epoch", "
|
|
208
|
+
"dims": ["epoch", "esa_step", "inst_az", "spin_sector"],
|
|
209
209
|
"instrument": "lo",
|
|
210
210
|
"num_counters": 1,
|
|
211
211
|
"num_energy_steps": 128,
|
|
@@ -225,9 +225,9 @@ DATA_PRODUCT_CONFIGURATIONS = {
|
|
|
225
225
|
"variable_names": LO_INST_COUNTS_SINGLES_VARIABLE_NAMES,
|
|
226
226
|
},
|
|
227
227
|
CODICEAPID.COD_LO_SW_ANGULAR_COUNTS: {
|
|
228
|
-
"coords": ["epoch", "
|
|
228
|
+
"coords": ["epoch", "energy_label", "esa_step", "inst_az", "spin_sector"],
|
|
229
229
|
"dataset_name": "imap_codice_l1a_lo-sw-angular",
|
|
230
|
-
"dims": ["epoch", "
|
|
230
|
+
"dims": ["epoch", "esa_step", "inst_az", "spin_sector"],
|
|
231
231
|
"instrument": "lo",
|
|
232
232
|
"num_counters": 4,
|
|
233
233
|
"num_energy_steps": 128,
|
|
@@ -248,7 +248,7 @@ DATA_PRODUCT_CONFIGURATIONS = {
|
|
|
248
248
|
CODICEAPID.COD_LO_NSW_ANGULAR_COUNTS: {
|
|
249
249
|
"coords": ["epoch", "inst_az", "spin_sector", "esa_step", "energy_label"],
|
|
250
250
|
"dataset_name": "imap_codice_l1a_lo-nsw-angular",
|
|
251
|
-
"dims": ["epoch", "
|
|
251
|
+
"dims": ["epoch", "esa_step", "inst_az", "spin_sector"],
|
|
252
252
|
"instrument": "lo",
|
|
253
253
|
"num_counters": 1,
|
|
254
254
|
"num_energy_steps": 128,
|
|
@@ -269,7 +269,7 @@ DATA_PRODUCT_CONFIGURATIONS = {
|
|
|
269
269
|
CODICEAPID.COD_LO_SW_PRIORITY_COUNTS: {
|
|
270
270
|
"coords": ["epoch", "inst_az", "spin_sector", "esa_step", "energy_label"],
|
|
271
271
|
"dataset_name": "imap_codice_l1a_lo-sw-priority",
|
|
272
|
-
"dims": ["epoch", "
|
|
272
|
+
"dims": ["epoch", "esa_step", "inst_az", "spin_sector"],
|
|
273
273
|
"instrument": "lo",
|
|
274
274
|
"num_counters": 5,
|
|
275
275
|
"num_energy_steps": 128,
|
|
@@ -290,7 +290,7 @@ DATA_PRODUCT_CONFIGURATIONS = {
|
|
|
290
290
|
CODICEAPID.COD_LO_NSW_PRIORITY_COUNTS: {
|
|
291
291
|
"coords": ["epoch", "inst_az", "spin_sector", "esa_step", "energy_label"],
|
|
292
292
|
"dataset_name": "imap_codice_l1a_lo-nsw-priority",
|
|
293
|
-
"dims": ["epoch", "
|
|
293
|
+
"dims": ["epoch", "esa_step", "inst_az", "spin_sector"],
|
|
294
294
|
"instrument": "lo",
|
|
295
295
|
"num_counters": 2,
|
|
296
296
|
"num_energy_steps": 128,
|
|
@@ -311,7 +311,7 @@ DATA_PRODUCT_CONFIGURATIONS = {
|
|
|
311
311
|
CODICEAPID.COD_LO_SW_SPECIES_COUNTS: {
|
|
312
312
|
"coords": ["epoch", "inst_az", "spin_sector", "esa_step", "energy_label"],
|
|
313
313
|
"dataset_name": "imap_codice_l1a_lo-sw-species",
|
|
314
|
-
"dims": ["epoch", "
|
|
314
|
+
"dims": ["epoch", "esa_step", "inst_az", "spin_sector"],
|
|
315
315
|
"instrument": "lo",
|
|
316
316
|
"num_counters": 16,
|
|
317
317
|
"num_energy_steps": 128,
|
|
@@ -332,7 +332,7 @@ DATA_PRODUCT_CONFIGURATIONS = {
|
|
|
332
332
|
CODICEAPID.COD_LO_NSW_SPECIES_COUNTS: {
|
|
333
333
|
"coords": ["epoch", "inst_az", "spin_sector", "esa_step", "energy_label"],
|
|
334
334
|
"dataset_name": "imap_codice_l1a_lo-nsw-species",
|
|
335
|
-
"dims": ["epoch", "
|
|
335
|
+
"dims": ["epoch", "esa_step", "inst_az", "spin_sector"],
|
|
336
336
|
"instrument": "lo",
|
|
337
337
|
"num_counters": 8,
|
|
338
338
|
"num_energy_steps": 128,
|
|
@@ -50,7 +50,9 @@ def _apply_lossy_a(compressed_bytes: bytes) -> list[int]:
|
|
|
50
50
|
The 24- or 32-bit decompressed values.
|
|
51
51
|
"""
|
|
52
52
|
compressed_values = list(compressed_bytes)
|
|
53
|
-
decompressed_values = [
|
|
53
|
+
decompressed_values = [
|
|
54
|
+
LOSSY_A_TABLE[item - 1] if item > 0 else 0 for item in compressed_values
|
|
55
|
+
]
|
|
54
56
|
return decompressed_values
|
|
55
57
|
|
|
56
58
|
|
|
@@ -71,7 +73,9 @@ def _apply_lossy_b(compressed_bytes: bytes) -> list[int]:
|
|
|
71
73
|
The 24- or 32-bit decompressed values.
|
|
72
74
|
"""
|
|
73
75
|
compressed_values = list(compressed_bytes)
|
|
74
|
-
decompressed_values = [
|
|
76
|
+
decompressed_values = [
|
|
77
|
+
LOSSY_B_TABLE[item - 1] if item > 0 else 0 for item in compressed_values
|
|
78
|
+
]
|
|
75
79
|
return decompressed_values
|
|
76
80
|
|
|
77
81
|
|
|
@@ -7,11 +7,10 @@ import numpy as np
|
|
|
7
7
|
import xarray as xr
|
|
8
8
|
|
|
9
9
|
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
10
|
-
from imap_processing.cdf.utils import J2000_EPOCH
|
|
11
10
|
from imap_processing.glows.l0.decom_glows import decom_packets
|
|
12
11
|
from imap_processing.glows.l0.glows_l0_data import DirectEventL0
|
|
13
12
|
from imap_processing.glows.l1a.glows_l1a_data import DirectEventL1A, HistogramL1A
|
|
14
|
-
from imap_processing.spice.time import met_to_j2000ns
|
|
13
|
+
from imap_processing.spice.time import J2000_EPOCH, met_to_j2000ns
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
def create_glows_attr_obj(data_version: str) -> ImapCdfAttributes:
|
imap_processing/hi/l1a/hi_l1a.py
CHANGED
|
@@ -33,7 +33,7 @@ def hi_l1a(packet_file_path: Union[str, Path], data_version: str) -> list[xr.Dat
|
|
|
33
33
|
List of processed xarray dataset.
|
|
34
34
|
"""
|
|
35
35
|
packet_def_file = (
|
|
36
|
-
imap_module_directory / "hi/packet_definitions/
|
|
36
|
+
imap_module_directory / "hi/packet_definitions/TLM_HI_COMBINED_SCI.xml"
|
|
37
37
|
)
|
|
38
38
|
datasets_by_apid = packet_file_to_datasets(
|
|
39
39
|
packet_file=packet_file_path, xtce_packet_definition=packet_def_file
|
|
@@ -42,18 +42,18 @@ def hi_l1a(packet_file_path: Union[str, Path], data_version: str) -> list[xr.Dat
|
|
|
42
42
|
# Process science to l1a.
|
|
43
43
|
processed_data = []
|
|
44
44
|
for apid in datasets_by_apid:
|
|
45
|
-
if apid
|
|
45
|
+
if apid in [HIAPID.H45_SCI_CNT, HIAPID.H90_SCI_CNT]:
|
|
46
46
|
logger.info(
|
|
47
47
|
"Processing histogram data for [%s] packets", HIAPID.H45_SCI_CNT.name
|
|
48
48
|
)
|
|
49
49
|
data = hist_create_dataset(datasets_by_apid[apid])
|
|
50
|
-
elif apid
|
|
50
|
+
elif apid in [HIAPID.H45_SCI_DE, HIAPID.H90_SCI_DE]:
|
|
51
51
|
logger.info(
|
|
52
52
|
"Processing direct event data for [%s] packets", HIAPID.H45_SCI_DE.name
|
|
53
53
|
)
|
|
54
54
|
|
|
55
55
|
data = science_direct_event(datasets_by_apid[apid])
|
|
56
|
-
elif apid
|
|
56
|
+
elif apid in [HIAPID.H45_APP_NHK, HIAPID.H90_APP_NHK]:
|
|
57
57
|
logger.info(
|
|
58
58
|
"Processing housekeeping data for [%s] packets", HIAPID.H45_APP_NHK.name
|
|
59
59
|
)
|
|
@@ -2,36 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import xarray as xr
|
|
5
|
+
from numpy._typing import NDArray
|
|
5
6
|
|
|
6
7
|
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
7
|
-
from imap_processing.utils import convert_to_binary_string
|
|
8
8
|
|
|
9
9
|
# define the names of the 24 counter arrays
|
|
10
10
|
# contained in the histogram packet
|
|
11
11
|
QUALIFIED_COUNTERS = (
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
12
|
+
"ab_qualified",
|
|
13
|
+
"c1c2_qualified",
|
|
14
|
+
"ac1_qualified",
|
|
15
|
+
"bc1_qualified",
|
|
16
|
+
"abc1_qualified",
|
|
17
|
+
"ac1c2_qualified",
|
|
18
|
+
"bc1c2_qualified",
|
|
19
|
+
"abc1c2_qualified",
|
|
20
20
|
)
|
|
21
21
|
LONG_COUNTERS = (
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
22
|
+
"a_first_only",
|
|
23
|
+
"b_first_only",
|
|
24
|
+
"c_first_only",
|
|
25
|
+
"ab_long",
|
|
26
|
+
"c1c2_long",
|
|
27
|
+
"ac1_long",
|
|
28
|
+
"bc1_long",
|
|
29
|
+
"abc1_long",
|
|
30
|
+
"ac1c2_long",
|
|
31
|
+
"bc1c2_long",
|
|
32
|
+
"abc1c2_long",
|
|
33
33
|
)
|
|
34
|
-
TOTAL_COUNTERS = ("
|
|
34
|
+
TOTAL_COUNTERS = ("a_total", "b_total", "c_total", "fee_de_recd", "fee_de_sent")
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
def create_dataset(input_ds: xr.Dataset) -> xr.Dataset:
|
|
@@ -41,99 +41,56 @@ def create_dataset(input_ds: xr.Dataset) -> xr.Dataset:
|
|
|
41
41
|
Parameters
|
|
42
42
|
----------
|
|
43
43
|
input_ds : xarray.Dataset
|
|
44
|
-
Dataset of packets
|
|
44
|
+
Dataset of packets generated using the
|
|
45
|
+
`imap_processing.utils.packet_file_to_datasets` function.
|
|
45
46
|
|
|
46
47
|
Returns
|
|
47
48
|
-------
|
|
48
49
|
dataset : xarray.Dataset
|
|
49
50
|
Dataset with all metadata field data in xr.DataArray.
|
|
50
51
|
"""
|
|
51
|
-
dataset = allocate_histogram_dataset(len(input_ds.epoch))
|
|
52
|
-
|
|
53
|
-
# TODO: Move into the allocate dataset function?
|
|
54
|
-
dataset["epoch"].data[:] = input_ds["epoch"].data
|
|
55
|
-
dataset["ccsds_met"].data = input_ds["ccsds_met"].data
|
|
56
|
-
dataset["esa_stepping_num"].data = input_ds["esa_step"].data
|
|
57
|
-
|
|
58
|
-
# unpack the packets data into the Dataset
|
|
59
|
-
# (npackets, 24 * 90 * 12)
|
|
60
|
-
# TODO: Look into avoiding the for-loops below
|
|
61
|
-
# It seems like we could try to reshape the arrays and do some numpy
|
|
62
|
-
# broadcasting rather than for-loops directly here
|
|
63
|
-
for i_epoch, counters_bytes_data in enumerate(input_ds["counters"].data):
|
|
64
|
-
binary_str_val = convert_to_binary_string(counters_bytes_data)
|
|
65
|
-
# unpack 24 arrays of 90 12-bit unsigned integers
|
|
66
|
-
counter_ints = [
|
|
67
|
-
int(binary_str_val[i * 12 : (i + 1) * 12], 2) for i in range(90 * 24)
|
|
68
|
-
]
|
|
69
|
-
# populate the dataset with the unpacked integers
|
|
70
|
-
for i_counter, counter in enumerate(
|
|
71
|
-
(*QUALIFIED_COUNTERS, *LONG_COUNTERS, *TOTAL_COUNTERS)
|
|
72
|
-
):
|
|
73
|
-
dataset[counter][i_epoch] = counter_ints[
|
|
74
|
-
i_counter * 90 : (i_counter + 1) * 90
|
|
75
|
-
]
|
|
76
|
-
|
|
77
|
-
return dataset
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def allocate_histogram_dataset(num_packets: int) -> xr.Dataset:
|
|
81
|
-
"""
|
|
82
|
-
Allocate empty xarray.Dataset for specified number of Hi Histogram packets.
|
|
83
|
-
|
|
84
|
-
Parameters
|
|
85
|
-
----------
|
|
86
|
-
num_packets : int
|
|
87
|
-
The number of Hi Histogram packets to allocate space for
|
|
88
|
-
in the xarray.Dataset.
|
|
89
|
-
|
|
90
|
-
Returns
|
|
91
|
-
-------
|
|
92
|
-
dataset : xarray.Dataset
|
|
93
|
-
Empty xarray.Dataset ready to be filled with packet data.
|
|
94
|
-
"""
|
|
95
52
|
attr_mgr = ImapCdfAttributes()
|
|
96
53
|
attr_mgr.add_instrument_global_attrs(instrument="hi")
|
|
97
54
|
attr_mgr.add_instrument_variable_attrs(instrument="hi", level=None)
|
|
98
|
-
# preallocate the xr.DataArrays for all CDF attributes based on number of packets
|
|
99
|
-
coords = dict()
|
|
100
|
-
coords["epoch"] = xr.DataArray(
|
|
101
|
-
np.empty(num_packets, dtype="datetime64[ns]"),
|
|
102
|
-
name="epoch",
|
|
103
|
-
dims=["epoch"],
|
|
104
|
-
attrs=attr_mgr.get_variable_attributes("epoch"),
|
|
105
|
-
)
|
|
106
|
-
# Histogram data is binned in 90, 4-degree bins
|
|
107
|
-
coords["angle"] = xr.DataArray(
|
|
108
|
-
np.arange(2, 360, 4),
|
|
109
|
-
name="angle",
|
|
110
|
-
dims=["angle"],
|
|
111
|
-
attrs=attr_mgr.get_variable_attributes("hi_hist_angle"),
|
|
112
|
-
)
|
|
113
55
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
dims=["angle"],
|
|
120
|
-
attrs=attr_mgr.get_variable_attributes(
|
|
121
|
-
"hi_hist_angle_label", check_schema=False
|
|
122
|
-
),
|
|
123
|
-
)
|
|
124
|
-
# Other data variables
|
|
125
|
-
data_vars["ccsds_met"] = xr.DataArray(
|
|
126
|
-
np.empty(num_packets, dtype=np.uint32),
|
|
127
|
-
dims=["epoch"],
|
|
128
|
-
attrs=attr_mgr.get_variable_attributes("hi_hist_ccsds_met"),
|
|
56
|
+
# Rename shcoarse variable (do this first since it copies the input_ds)
|
|
57
|
+
dataset = input_ds.rename_vars({"shcoarse": "ccsds_met"})
|
|
58
|
+
|
|
59
|
+
dataset.epoch.attrs.update(
|
|
60
|
+
attr_mgr.get_variable_attributes("epoch"),
|
|
129
61
|
)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
62
|
+
# Add the hist_angle coordinate
|
|
63
|
+
# Histogram data is binned in 90, 4-degree bins
|
|
64
|
+
attrs = attr_mgr.get_variable_attributes("hi_hist_angle")
|
|
65
|
+
dataset.coords.update(
|
|
66
|
+
{
|
|
67
|
+
"angle": xr.DataArray(
|
|
68
|
+
np.arange(2, 360, 4),
|
|
69
|
+
name="angle",
|
|
70
|
+
dims=["angle"],
|
|
71
|
+
attrs=attrs,
|
|
72
|
+
)
|
|
73
|
+
}
|
|
134
74
|
)
|
|
135
|
-
|
|
136
|
-
|
|
75
|
+
# Update existing variable attributes
|
|
76
|
+
for var_name in [
|
|
77
|
+
"version",
|
|
78
|
+
"type",
|
|
79
|
+
"sec_hdr_flg",
|
|
80
|
+
"pkt_apid",
|
|
81
|
+
"seq_flgs",
|
|
82
|
+
"src_seq_ctr",
|
|
83
|
+
"pkt_len",
|
|
84
|
+
"ccsds_met",
|
|
85
|
+
"esa_step",
|
|
86
|
+
"num_of_spins",
|
|
87
|
+
"cksum",
|
|
88
|
+
]:
|
|
89
|
+
attrs = attr_mgr.get_variable_attributes(f"hi_hist_{var_name}")
|
|
90
|
+
dataset.data_vars[var_name].attrs.update(attrs)
|
|
91
|
+
|
|
92
|
+
new_vars = dict()
|
|
93
|
+
# Populate 90-element histogram counters
|
|
137
94
|
default_counter_attrs = attr_mgr.get_variable_attributes("hi_hist_counters")
|
|
138
95
|
for counter_name in (*QUALIFIED_COUNTERS, *LONG_COUNTERS, *TOTAL_COUNTERS):
|
|
139
96
|
# Inject counter name into generic counter attributes
|
|
@@ -141,15 +98,56 @@ def allocate_histogram_dataset(num_packets: int) -> xr.Dataset:
|
|
|
141
98
|
for key, val in counter_attrs.items():
|
|
142
99
|
if isinstance(val, str) and "{counter_name}" in val:
|
|
143
100
|
counter_attrs[key] = val.format(counter_name=counter_name)
|
|
144
|
-
|
|
145
|
-
|
|
101
|
+
# Instantiate the counter DataArray
|
|
102
|
+
new_vars[counter_name] = xr.DataArray(
|
|
103
|
+
data=unpack_hist_counter(input_ds[counter_name].data.sum()),
|
|
146
104
|
dims=["epoch", "angle"],
|
|
147
105
|
attrs=counter_attrs,
|
|
148
106
|
)
|
|
149
107
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
coords
|
|
153
|
-
|
|
108
|
+
# Generate label variable for angle coordinate
|
|
109
|
+
new_vars["angle_label"] = xr.DataArray(
|
|
110
|
+
dataset.coords["angle"].values.astype(str),
|
|
111
|
+
name="angle_label",
|
|
112
|
+
dims=["angle"],
|
|
113
|
+
attrs=attr_mgr.get_variable_attributes(
|
|
114
|
+
"hi_hist_angle_label", check_schema=False
|
|
115
|
+
),
|
|
154
116
|
)
|
|
117
|
+
|
|
118
|
+
dataset.update(new_vars)
|
|
119
|
+
dataset.attrs.update(attr_mgr.get_global_attributes("imap_hi_l1a_hist_attrs"))
|
|
120
|
+
|
|
155
121
|
return dataset
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def unpack_hist_counter(counter_bytes: bytes) -> NDArray[np.uint16]:
|
|
125
|
+
"""
|
|
126
|
+
Unpack Hi SCI_CNT counter data for a single counter.
|
|
127
|
+
|
|
128
|
+
Parameters
|
|
129
|
+
----------
|
|
130
|
+
counter_bytes : bytes
|
|
131
|
+
Sum individual bytes for all epochs of a Hi SCI_CNT counter.
|
|
132
|
+
|
|
133
|
+
Returns
|
|
134
|
+
-------
|
|
135
|
+
output_array : numpy.ndarray[numpy.uint16]
|
|
136
|
+
The unpacked 12-bit unsigned integers for the input bytes. The
|
|
137
|
+
output array has a shape of (n, 90) where n is the number of SCI_CNT
|
|
138
|
+
packets in the input dataset.
|
|
139
|
+
"""
|
|
140
|
+
# Interpret bytes for all epochs of current counter as uint8 array
|
|
141
|
+
counter_uint8 = np.frombuffer(counter_bytes, dtype=np.uint8)
|
|
142
|
+
# Split into triplets of upper-byte, split-byte and lower-byte arrays
|
|
143
|
+
upper_uint8, split_unit8, lower_uint8 = np.reshape(
|
|
144
|
+
counter_uint8, (3, -1), order="F"
|
|
145
|
+
).astype(np.uint16)
|
|
146
|
+
# Compute even indexed uint12 values from upper-byte and first 4-bits of
|
|
147
|
+
# split-byte
|
|
148
|
+
even_uint12 = (upper_uint8 << 4) + (split_unit8 >> 4)
|
|
149
|
+
# Compute odd indexed uint12 values from lower 4-bits of split-byte and
|
|
150
|
+
# lower-byte
|
|
151
|
+
odd_uint12 = ((split_unit8 & (2**4 - 1)) << 8) + lower_uint8
|
|
152
|
+
output_array = np.column_stack((even_uint12, odd_uint12)).reshape(-1, 90)
|
|
153
|
+
return output_array
|