imap-processing 0.7.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/__init__.py +1 -1
- imap_processing/_version.py +2 -2
- imap_processing/ccsds/excel_to_xtce.py +36 -2
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +1 -1
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +145 -30
- imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +36 -36
- imap_processing/cdf/config/imap_hi_variable_attrs.yaml +136 -9
- 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_hit_l1b_variable_attrs.yaml +9 -0
- imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +14 -7
- imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +577 -235
- 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_mag_l1_variable_attrs.yaml +24 -28
- imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +1 -0
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +137 -79
- imap_processing/cdf/config/imap_variable_schema.yaml +13 -0
- imap_processing/cdf/imap_cdf_manager.py +31 -27
- imap_processing/cdf/utils.py +3 -5
- imap_processing/cli.py +25 -14
- imap_processing/codice/codice_l1a.py +153 -63
- imap_processing/codice/constants.py +10 -10
- imap_processing/codice/decompress.py +10 -11
- imap_processing/codice/utils.py +1 -0
- imap_processing/glows/l1a/glows_l1a.py +1 -2
- imap_processing/glows/l1b/glows_l1b.py +3 -3
- imap_processing/glows/l1b/glows_l1b_data.py +59 -37
- imap_processing/glows/l2/glows_l2_data.py +123 -0
- imap_processing/hi/l1a/hi_l1a.py +4 -4
- imap_processing/hi/l1a/histogram.py +107 -109
- imap_processing/hi/l1a/science_direct_event.py +92 -225
- imap_processing/hi/l1b/hi_l1b.py +85 -11
- imap_processing/hi/l1c/hi_l1c.py +23 -1
- imap_processing/hi/packet_definitions/TLM_HI_COMBINED_SCI.xml +3994 -0
- imap_processing/hi/utils.py +1 -1
- imap_processing/hit/hit_utils.py +221 -0
- imap_processing/hit/l0/constants.py +118 -0
- imap_processing/hit/l0/decom_hit.py +100 -156
- imap_processing/hit/l1a/hit_l1a.py +170 -184
- imap_processing/hit/l1b/hit_l1b.py +33 -153
- 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 +65 -84
- 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 +17 -1
- imap_processing/lo/l0/lo_science.py +45 -13
- imap_processing/lo/l1a/lo_l1a.py +76 -8
- imap_processing/lo/packet_definitions/lo_xtce.xml +8344 -1849
- imap_processing/mag/l0/decom_mag.py +4 -3
- imap_processing/mag/l1a/mag_l1a.py +12 -13
- imap_processing/mag/l1a/mag_l1a_data.py +1 -2
- imap_processing/mag/l1b/mag_l1b.py +90 -7
- imap_processing/spice/geometry.py +156 -16
- imap_processing/spice/time.py +144 -2
- imap_processing/swapi/l1/swapi_l1.py +4 -4
- imap_processing/swapi/l2/swapi_l2.py +1 -1
- imap_processing/swapi/packet_definitions/swapi_packet_definition.xml +1535 -446
- imap_processing/swe/l1b/swe_l1b_science.py +8 -8
- imap_processing/swe/l2/swe_l2.py +134 -17
- imap_processing/tests/ccsds/test_data/expected_output.xml +2 -1
- imap_processing/tests/ccsds/test_excel_to_xtce.py +4 -4
- imap_processing/tests/cdf/test_imap_cdf_manager.py +0 -10
- imap_processing/tests/codice/conftest.py +1 -17
- imap_processing/tests/codice/data/imap_codice_l0_raw_20241110_v001.pkts +0 -0
- imap_processing/tests/codice/test_codice_l0.py +8 -2
- imap_processing/tests/codice/test_codice_l1a.py +127 -107
- imap_processing/tests/codice/test_codice_l1b.py +1 -0
- imap_processing/tests/codice/test_decompress.py +7 -7
- imap_processing/tests/conftest.py +100 -58
- imap_processing/tests/glows/conftest.py +6 -0
- imap_processing/tests/glows/test_glows_l1b.py +9 -9
- imap_processing/tests/glows/test_glows_l1b_data.py +9 -9
- 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_data/l1a/imap_hi_l1a_45sensor-de_20250415_v000.cdf +0 -0
- imap_processing/tests/hi/test_hi_l1b.py +73 -3
- imap_processing/tests/hi/test_hi_l1c.py +10 -2
- imap_processing/tests/hi/test_l1a.py +31 -58
- imap_processing/tests/hi/test_science_direct_event.py +58 -0
- imap_processing/tests/hi/test_utils.py +4 -3
- imap_processing/tests/hit/test_data/sci_sample1.ccsds +0 -0
- imap_processing/tests/hit/{test_hit_decom.py → test_decom_hit.py} +95 -36
- imap_processing/tests/hit/test_hit_l1a.py +299 -179
- imap_processing/tests/hit/test_hit_l1b.py +231 -24
- imap_processing/tests/hit/test_hit_utils.py +218 -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 +2 -2
- imap_processing/tests/idex/imap_idex_l0_raw_20231214_v001.pkts +0 -0
- imap_processing/tests/idex/impact_14_tof_high_data.txt +4444 -4444
- imap_processing/tests/idex/test_idex_l0.py +4 -4
- imap_processing/tests/idex/test_idex_l1a.py +8 -2
- 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 +69 -5
- 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/imap_mag_l1a_norm-magi_20251017_v001.cdf +0 -0
- imap_processing/tests/mag/test_mag_l1b.py +97 -7
- imap_processing/tests/spice/test_data/imap_ena_sim_metakernel.template +3 -1
- imap_processing/tests/spice/test_geometry.py +115 -9
- 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/conftest.py +33 -0
- imap_processing/tests/swe/l1_validation/swe_l0_unpacked-data_20240510_v001_VALIDATION_L1B_v3.dat +4332 -0
- imap_processing/tests/swe/test_swe_l1b.py +29 -8
- imap_processing/tests/swe/test_swe_l2.py +64 -8
- imap_processing/tests/test_utils.py +2 -2
- 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/test_data/l1/dps_exposure_helio_45_E12.cdf +0 -0
- imap_processing/tests/ultra/test_data/l1/dps_exposure_helio_45_E24.cdf +0 -0
- imap_processing/tests/ultra/unit/test_de.py +113 -0
- imap_processing/tests/ultra/unit/test_spatial_utils.py +125 -0
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +27 -3
- imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +31 -10
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +55 -35
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +10 -68
- imap_processing/ultra/constants.py +12 -3
- imap_processing/ultra/l1b/de.py +168 -30
- imap_processing/ultra/l1b/ultra_l1b_annotated.py +24 -10
- imap_processing/ultra/l1b/ultra_l1b_extended.py +46 -80
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +60 -144
- imap_processing/ultra/utils/spatial_utils.py +221 -0
- {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/METADATA +15 -14
- {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/RECORD +142 -139
- imap_processing/cdf/cdf_attribute_manager.py +0 -322
- imap_processing/cdf/config/shared/default_global_cdf_attrs_schema.yaml +0 -246
- imap_processing/cdf/config/shared/default_variable_cdf_attrs_schema.yaml +0 -466
- imap_processing/hi/l0/decom_hi.py +0 -24
- imap_processing/hi/packet_definitions/hi_packet_definition.xml +0 -482
- imap_processing/hit/l0/data_classes/housekeeping.py +0 -240
- imap_processing/hit/l0/data_classes/science_packet.py +0 -259
- imap_processing/hit/l0/utils/hit_base.py +0 -57
- imap_processing/tests/cdf/shared/default_global_cdf_attrs_schema.yaml +0 -246
- imap_processing/tests/cdf/shared/default_variable_cdf_attrs_schema.yaml +0 -466
- imap_processing/tests/cdf/test_cdf_attribute_manager.py +0 -353
- imap_processing/tests/codice/data/imap_codice_l0_hi-counters-aggregated_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_hi-counters-singles_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_hi-omni_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_hi-pha_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_hi-sectored_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_hskp_20100101_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_lo-counters-aggregated_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_lo-counters-singles_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-angular_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-priority_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_lo-nsw-species_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_lo-pha_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_lo-sw-angular_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_lo-sw-priority_20240429_v001.pkts +0 -0
- imap_processing/tests/codice/data/imap_codice_l0_lo-sw-species_20240429_v001.pkts +0 -0
- imap_processing/tests/hi/test_decom.py +0 -55
- imap_processing/tests/hi/test_l1a_sci_de.py +0 -72
- imap_processing/tests/idex/imap_idex_l0_raw_20230725_v001.pkts +0 -0
- imap_processing/tests/mag/imap_mag_l1a_burst-magi_20231025_v001.cdf +0 -0
- /imap_processing/{hi/l0/__init__.py → tests/glows/test_glows_l2_data.py} +0 -0
- /imap_processing/tests/hit/test_data/{imap_hit_l0_hk_20100105_v001.pkts → imap_hit_l0_raw_20100105_v001.pkts} +0 -0
- {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.7.0.dist-info → imap_processing-0.9.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,109 +1,16 @@
|
|
|
1
1
|
"""Decommutate HIT CCSDS science data."""
|
|
2
2
|
|
|
3
|
-
from collections import namedtuple
|
|
4
|
-
|
|
5
3
|
import numpy as np
|
|
6
4
|
import xarray as xr
|
|
7
5
|
|
|
8
|
-
from imap_processing.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# binary data.
|
|
15
|
-
HITPacking = namedtuple(
|
|
16
|
-
"HITPacking",
|
|
17
|
-
[
|
|
18
|
-
"bit_length",
|
|
19
|
-
"section_length",
|
|
20
|
-
"shape",
|
|
21
|
-
],
|
|
6
|
+
from imap_processing.hit.l0.constants import (
|
|
7
|
+
COUNTS_DATA_STRUCTURE,
|
|
8
|
+
EXPONENT_BITS,
|
|
9
|
+
FLAG_PATTERN,
|
|
10
|
+
FRAME_SIZE,
|
|
11
|
+
MANTISSA_BITS,
|
|
22
12
|
)
|
|
23
|
-
|
|
24
|
-
# Define data structure for counts rates data
|
|
25
|
-
COUNTS_DATA_STRUCTURE = {
|
|
26
|
-
# field: bit_length, section_length, shape
|
|
27
|
-
# ------------------------------------------
|
|
28
|
-
# science frame header
|
|
29
|
-
"hdr_unit_num": HITPacking(2, 2, (1,)),
|
|
30
|
-
"hdr_frame_version": HITPacking(6, 6, (1,)),
|
|
31
|
-
"hdr_status_bits": HITPacking(8, 8, (1,)),
|
|
32
|
-
"hdr_minute_cnt": HITPacking(8, 8, (1,)),
|
|
33
|
-
# ------------------------------------------
|
|
34
|
-
# spare bits. Contains no data
|
|
35
|
-
"spare": HITPacking(24, 24, (1,)),
|
|
36
|
-
# ------------------------------------------
|
|
37
|
-
# erates - contains livetime counters
|
|
38
|
-
"livetime": HITPacking(16, 16, (1,)), # livetime counter
|
|
39
|
-
"num_trig": HITPacking(16, 16, (1,)), # number of triggers
|
|
40
|
-
"num_reject": HITPacking(16, 16, (1,)), # number of rejected events
|
|
41
|
-
"num_acc_w_pha": HITPacking(
|
|
42
|
-
16, 16, (1,)
|
|
43
|
-
), # number of accepted events with PHA data
|
|
44
|
-
"num_acc_no_pha": HITPacking(16, 16, (1,)), # number of events without PHA data
|
|
45
|
-
"num_haz_trig": HITPacking(16, 16, (1,)), # number of triggers with hazard flag
|
|
46
|
-
"num_haz_reject": HITPacking(
|
|
47
|
-
16, 16, (1,)
|
|
48
|
-
), # number of rejected events with hazard flag
|
|
49
|
-
"num_haz_acc_w_pha": HITPacking(
|
|
50
|
-
16, 16, (1,)
|
|
51
|
-
), # number of accepted hazard events with PHA data
|
|
52
|
-
"num_haz_acc_no_pha": HITPacking(
|
|
53
|
-
16, 16, (1,)
|
|
54
|
-
), # number of hazard events without PHA data
|
|
55
|
-
# -------------------------------------------
|
|
56
|
-
"sngrates": HITPacking(16, 1856, (2, 58)), # single rates
|
|
57
|
-
# -------------------------------------------
|
|
58
|
-
# evprates - contains event processing rates
|
|
59
|
-
"nread": HITPacking(16, 16, (1,)), # events read from event fifo
|
|
60
|
-
"nhazard": HITPacking(16, 16, (1,)), # events tagged with hazard flag
|
|
61
|
-
"nadcstim": HITPacking(16, 16, (1,)), # adc-stim events
|
|
62
|
-
"nodd": HITPacking(16, 16, (1,)), # odd events
|
|
63
|
-
"noddfix": HITPacking(16, 16, (1,)), # odd events that were fixed in sw
|
|
64
|
-
"nmulti": HITPacking(
|
|
65
|
-
16, 16, (1,)
|
|
66
|
-
), # events with multiple hits in a single detector
|
|
67
|
-
"nmultifix": HITPacking(16, 16, (1,)), # multi events that were fixed in sw
|
|
68
|
-
"nbadtraj": HITPacking(16, 16, (1,)), # bad trajectory
|
|
69
|
-
"nl2": HITPacking(16, 16, (1,)), # events sorted into L12 event category
|
|
70
|
-
"nl3": HITPacking(16, 16, (1,)), # events sorted into L123 event category
|
|
71
|
-
"nl4": HITPacking(16, 16, (1,)), # events sorted into L1423 event category
|
|
72
|
-
"npen": HITPacking(16, 16, (1,)), # events sorted into penetrating event category
|
|
73
|
-
"nformat": HITPacking(16, 16, (1,)), # nothing currently goes in this slot
|
|
74
|
-
"naside": HITPacking(16, 16, (1,)), # A-side events
|
|
75
|
-
"nbside": HITPacking(16, 16, (1,)), # B-side events
|
|
76
|
-
"nerror": HITPacking(16, 16, (1,)), # events that caused a processing error
|
|
77
|
-
"nbadtags": HITPacking(
|
|
78
|
-
16, 16, (1,)
|
|
79
|
-
), # events with inconsistent tags vs pulse heights
|
|
80
|
-
# -------------------------------------------
|
|
81
|
-
# other count rates
|
|
82
|
-
"coinrates": HITPacking(16, 416, (26,)), # coincidence rates
|
|
83
|
-
"bufrates": HITPacking(16, 512, (32,)), # priority buffer rates
|
|
84
|
-
"l2fgrates": HITPacking(16, 2112, (132,)), # range 2 foreground rates
|
|
85
|
-
"l2bgrates": HITPacking(16, 192, (12,)), # range 2 background rates
|
|
86
|
-
"l3fgrates": HITPacking(16, 2672, (167,)), # range 3 foreground rates
|
|
87
|
-
"l3bgrates": HITPacking(16, 192, (12,)), # range 3 background rates
|
|
88
|
-
"penfgrates": HITPacking(16, 528, (33,)), # range 4 foreground rates
|
|
89
|
-
"penbgrates": HITPacking(16, 240, (15,)), # range 4 background rates
|
|
90
|
-
"ialirtrates": HITPacking(16, 320, (20,)), # ialirt rates
|
|
91
|
-
"sectorates": HITPacking(16, 1920, (120,)), # sectored rates
|
|
92
|
-
"l4fgrates": HITPacking(16, 768, (48,)), # all range foreground rates
|
|
93
|
-
"l4bgrates": HITPacking(16, 384, (24,)), # all range foreground rates
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
# Define data structure for pulse height event data
|
|
97
|
-
PHA_DATA_STRUCTURE = {
|
|
98
|
-
# field: bit_length, section_length, shape
|
|
99
|
-
"pha_records": HITPacking(2, 29344, (917,)),
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
# Define the pattern of grouping flags in a complete science frame.
|
|
103
|
-
FLAG_PATTERN = np.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2])
|
|
104
|
-
|
|
105
|
-
# Define size of science frame (num of packets)
|
|
106
|
-
FRAME_SIZE = len(FLAG_PATTERN)
|
|
13
|
+
from imap_processing.utils import convert_to_binary_string
|
|
107
14
|
|
|
108
15
|
|
|
109
16
|
def parse_data(bin_str: str, bits_per_index: int, start: int, end: int) -> list:
|
|
@@ -138,13 +45,13 @@ def parse_count_rates(sci_dataset: xr.Dataset) -> None:
|
|
|
138
45
|
Parse binary count rates data and update dataset.
|
|
139
46
|
|
|
140
47
|
This function parses the binary count rates data,
|
|
141
|
-
stored as
|
|
48
|
+
stored as count_rates_raw in the dataset,
|
|
142
49
|
according to data structure details provided in
|
|
143
50
|
COUNTS_DATA_STRUCTURE. The parsed data, representing
|
|
144
51
|
integers, is added to the dataset as new data
|
|
145
52
|
fields.
|
|
146
53
|
|
|
147
|
-
Note:
|
|
54
|
+
Note: count_rates_raw is added to the dataset by
|
|
148
55
|
the assemble_science_frames function, which organizes
|
|
149
56
|
the binary science data packets by science frames.
|
|
150
57
|
|
|
@@ -154,7 +61,7 @@ def parse_count_rates(sci_dataset: xr.Dataset) -> None:
|
|
|
154
61
|
Xarray dataset containing HIT science packets
|
|
155
62
|
from a CCSDS file.
|
|
156
63
|
"""
|
|
157
|
-
counts_binary = sci_dataset.
|
|
64
|
+
counts_binary = sci_dataset.count_rates_raw
|
|
158
65
|
# initialize the starting bit for the sections of data
|
|
159
66
|
section_start = 0
|
|
160
67
|
# Decommutate binary data for each counts data field
|
|
@@ -176,23 +83,34 @@ def parse_count_rates(sci_dataset: xr.Dataset) -> None:
|
|
|
176
83
|
low_gain = data[1::2] # Items at odd indices 1, 3, 5, etc.
|
|
177
84
|
parsed_data[i] = [high_gain, low_gain]
|
|
178
85
|
|
|
179
|
-
#
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
# - decompress data
|
|
183
|
-
# - Follow up with HIT team about erates and evrates.
|
|
184
|
-
# (i.e.Should these be arrays containing all the sub fields
|
|
185
|
-
# or should each subfield be it's own data field/array)
|
|
86
|
+
# Decompress data where needed
|
|
87
|
+
if all(x not in field for x in ["hdr", "spare", "pha"]):
|
|
88
|
+
parsed_data = np.vectorize(decompress_rates_16_to_32)(parsed_data)
|
|
186
89
|
|
|
187
90
|
# Get dims for data variables (yaml file not created yet)
|
|
188
91
|
if len(field_meta.shape) > 1:
|
|
189
|
-
|
|
92
|
+
if "sectorates" in field:
|
|
93
|
+
# Reshape data to 8x15 for declination and azimuth look directions
|
|
94
|
+
parsed_data = np.array(parsed_data).reshape((-1, *field_meta.shape))
|
|
95
|
+
dims = ["epoch", "declination", "azimuth"]
|
|
96
|
+
elif "sngrates" in field:
|
|
97
|
+
dims = ["epoch", "gain", f"{field}_index"]
|
|
190
98
|
elif field_meta.shape[0] > 1:
|
|
191
99
|
dims = ["epoch", f"{field}_index"]
|
|
192
100
|
else:
|
|
193
101
|
dims = ["epoch"]
|
|
194
102
|
|
|
195
103
|
sci_dataset[field] = xr.DataArray(parsed_data, dims=dims, name=field)
|
|
104
|
+
# Add dimensions to coordinates
|
|
105
|
+
# TODO: confirm that dtype int16 is correct
|
|
106
|
+
for dim in dims:
|
|
107
|
+
if dim not in sci_dataset.coords:
|
|
108
|
+
sci_dataset.coords[dim] = xr.DataArray(
|
|
109
|
+
np.arange(sci_dataset.sizes[dim], dtype=np.int16),
|
|
110
|
+
dims=[dim],
|
|
111
|
+
name=dim,
|
|
112
|
+
)
|
|
113
|
+
|
|
196
114
|
# increment the start of the next section of data to parse
|
|
197
115
|
section_start += field_meta.section_length
|
|
198
116
|
|
|
@@ -214,7 +132,7 @@ def is_sequential(counters: np.ndarray) -> np.bool_:
|
|
|
214
132
|
return np.all(np.diff(counters) == 1)
|
|
215
133
|
|
|
216
134
|
|
|
217
|
-
def
|
|
135
|
+
def get_valid_starting_indices(flags: np.ndarray, counters: np.ndarray) -> np.ndarray:
|
|
218
136
|
"""
|
|
219
137
|
Find valid starting indices for science frames.
|
|
220
138
|
|
|
@@ -241,9 +159,6 @@ def find_valid_starting_indices(flags: np.ndarray, counters: np.ndarray) -> np.n
|
|
|
241
159
|
valid_indices : np.ndarray
|
|
242
160
|
Array of valid indices for science frames.
|
|
243
161
|
"""
|
|
244
|
-
# TODO: consider combining functions to get valid indices to reduce
|
|
245
|
-
# code tracing
|
|
246
|
-
|
|
247
162
|
# Use sliding windows to compare segments of the array (20 packets) with the
|
|
248
163
|
# pattern. This generates an array of overlapping sub-arrays, each of length
|
|
249
164
|
# 20, from the flags array and is used to slide the "window" across the array
|
|
@@ -254,40 +169,13 @@ def find_valid_starting_indices(flags: np.ndarray, counters: np.ndarray) -> np.n
|
|
|
254
169
|
# Get the starting indices of matches
|
|
255
170
|
match_indices = np.where(matches)[0]
|
|
256
171
|
# Filter for only indices from valid science frames with sequential counters
|
|
257
|
-
|
|
172
|
+
sequential_check = [
|
|
173
|
+
is_sequential(counters[idx : idx + FRAME_SIZE]) for idx in match_indices
|
|
174
|
+
]
|
|
175
|
+
valid_indices: np.ndarray = np.array(match_indices[sequential_check], dtype=int)
|
|
258
176
|
return valid_indices
|
|
259
177
|
|
|
260
178
|
|
|
261
|
-
def get_valid_indices(
|
|
262
|
-
indices: np.ndarray, counters: np.ndarray, size: int
|
|
263
|
-
) -> np.ndarray:
|
|
264
|
-
"""
|
|
265
|
-
Get valid indices for science frames.
|
|
266
|
-
|
|
267
|
-
Check if the packet sequence counters for the science frames
|
|
268
|
-
are sequential. If they are, the science frame is valid and
|
|
269
|
-
an updated array of valid indices is returned.
|
|
270
|
-
|
|
271
|
-
Parameters
|
|
272
|
-
----------
|
|
273
|
-
indices : np.ndarray
|
|
274
|
-
Array of indices where the packet grouping flags match the pattern.
|
|
275
|
-
counters : np.ndarray
|
|
276
|
-
Array of packet sequence counters.
|
|
277
|
-
size : int
|
|
278
|
-
Size of science frame. 20 packets per science frame.
|
|
279
|
-
|
|
280
|
-
Returns
|
|
281
|
-
-------
|
|
282
|
-
valid_indices : np.ndarray
|
|
283
|
-
Array of valid indices for science frames.
|
|
284
|
-
"""
|
|
285
|
-
# Check if the packet sequence counters are sequential by getting an array
|
|
286
|
-
# of boolean values where True indicates the counters are sequential.
|
|
287
|
-
sequential_check = [is_sequential(counters[idx : idx + size]) for idx in indices]
|
|
288
|
-
return indices[sequential_check]
|
|
289
|
-
|
|
290
|
-
|
|
291
179
|
def update_ccsds_header_dims(sci_dataset: xr.Dataset) -> xr.Dataset:
|
|
292
180
|
"""
|
|
293
181
|
Update dimensions of CCSDS header fields.
|
|
@@ -334,8 +222,8 @@ def assemble_science_frames(sci_dataset: xr.Dataset) -> xr.Dataset:
|
|
|
334
222
|
The first six packets contain count rates data
|
|
335
223
|
The last 14 packets contain pulse height event data
|
|
336
224
|
|
|
337
|
-
These groups are added to the dataset as
|
|
338
|
-
and
|
|
225
|
+
These groups are added to the dataset as count_rates_raw
|
|
226
|
+
and pha_raw.
|
|
339
227
|
|
|
340
228
|
Parameters
|
|
341
229
|
----------
|
|
@@ -368,7 +256,7 @@ def assemble_science_frames(sci_dataset: xr.Dataset) -> xr.Dataset:
|
|
|
368
256
|
total_packets = len(epoch_data)
|
|
369
257
|
|
|
370
258
|
# Find starting indices for valid science frames
|
|
371
|
-
starting_indices =
|
|
259
|
+
starting_indices = get_valid_starting_indices(seq_flgs, seq_ctrs)
|
|
372
260
|
|
|
373
261
|
# Check for extra packets at start and end of file
|
|
374
262
|
# TODO: Will need to handle these extra packets when processing multiple files
|
|
@@ -400,19 +288,75 @@ def assemble_science_frames(sci_dataset: xr.Dataset) -> xr.Dataset:
|
|
|
400
288
|
pha.append("".join(science_data_frame[6:]))
|
|
401
289
|
# Get first packet's epoch for the science frame
|
|
402
290
|
epoch_per_science_frame = np.append(epoch_per_science_frame, epoch_data[idx])
|
|
403
|
-
# TODO: Filter ccsds header fields to only include packets from the
|
|
404
|
-
# valid science frames. Doesn't need to be grouped by frames though
|
|
405
291
|
|
|
406
292
|
# Add new data variables to the dataset
|
|
407
293
|
sci_dataset = sci_dataset.drop_vars("epoch")
|
|
408
294
|
sci_dataset.coords["epoch"] = epoch_per_science_frame
|
|
409
|
-
sci_dataset["
|
|
410
|
-
count_rates, dims=["epoch"], name="
|
|
295
|
+
sci_dataset["count_rates_raw"] = xr.DataArray(
|
|
296
|
+
count_rates, dims=["epoch"], name="count_rates_raw"
|
|
411
297
|
)
|
|
412
|
-
sci_dataset["
|
|
298
|
+
sci_dataset["pha_raw"] = xr.DataArray(pha, dims=["epoch"], name="pha_raw")
|
|
413
299
|
return sci_dataset
|
|
414
300
|
|
|
415
301
|
|
|
302
|
+
def decompress_rates_16_to_32(packed: int) -> int:
|
|
303
|
+
"""
|
|
304
|
+
Will decompress rates data from 16 bits to 32 bits.
|
|
305
|
+
|
|
306
|
+
This function decompresses the rates data from 16-bit integers
|
|
307
|
+
to 32-bit integers. The compressed integer (packed) combines
|
|
308
|
+
two parts:
|
|
309
|
+
|
|
310
|
+
1. Mantissa: Represents the significant digits of the value.
|
|
311
|
+
2. Exponent: Determines how much to scale the mantissa (using powers of 2).
|
|
312
|
+
|
|
313
|
+
These parts are packed together into a single 16-bit integer.
|
|
314
|
+
|
|
315
|
+
Parameters
|
|
316
|
+
----------
|
|
317
|
+
packed : int
|
|
318
|
+
Compressed 16-bit integer.
|
|
319
|
+
|
|
320
|
+
Returns
|
|
321
|
+
-------
|
|
322
|
+
decompressed_int : int
|
|
323
|
+
Decompressed integer.
|
|
324
|
+
"""
|
|
325
|
+
# In compressed formats, the exponent and mantissa are tightly packed together.
|
|
326
|
+
# The mask ensures you correctly separate the mantissa (useful for reconstructing
|
|
327
|
+
# the value) from the exponent (used for scaling).
|
|
328
|
+
# set to 16 bits
|
|
329
|
+
output_mask = 0xFFFF
|
|
330
|
+
|
|
331
|
+
# Packed is the compressed integer
|
|
332
|
+
# Right bit shift to get the exponent
|
|
333
|
+
power = packed >> MANTISSA_BITS
|
|
334
|
+
|
|
335
|
+
# Decompress the data depending on the value of the exponent
|
|
336
|
+
# If the exponent (power) extracted from the packed 16-bit integer is greater
|
|
337
|
+
# than 1, the compressed value needs to be decompressed by reconstructing the
|
|
338
|
+
# integer using the mantissa and exponent. If the condition is false, the
|
|
339
|
+
# compressed and uncompressed values are considered the same.
|
|
340
|
+
decompressed_int: int
|
|
341
|
+
if power > 1:
|
|
342
|
+
# Retrieve the "mantissa" portion of the packed value by masking out the
|
|
343
|
+
# exponent bits
|
|
344
|
+
mantissa_mask = output_mask >> EXPONENT_BITS
|
|
345
|
+
mantissa = packed & mantissa_mask
|
|
346
|
+
|
|
347
|
+
# Shift the mantissa to the left by 1 to account for the hidden bit
|
|
348
|
+
# (always set to 1)
|
|
349
|
+
mantissa_with_hidden_bit = mantissa | (0x0001 << MANTISSA_BITS)
|
|
350
|
+
|
|
351
|
+
# Scale the mantissa by the exponent by shifting it to the left by (power - 1)
|
|
352
|
+
decompressed_int = mantissa_with_hidden_bit << (power - 1)
|
|
353
|
+
else:
|
|
354
|
+
# The compressed and uncompressed values are the same
|
|
355
|
+
decompressed_int = packed
|
|
356
|
+
|
|
357
|
+
return decompressed_int
|
|
358
|
+
|
|
359
|
+
|
|
416
360
|
def decom_hit(sci_dataset: xr.Dataset) -> xr.Dataset:
|
|
417
361
|
"""
|
|
418
362
|
Group and decode HIT science data packets.
|
|
@@ -465,7 +409,7 @@ def decom_hit(sci_dataset: xr.Dataset) -> xr.Dataset:
|
|
|
465
409
|
# Parse count rates data from binary and add to dataset
|
|
466
410
|
parse_count_rates(sci_dataset)
|
|
467
411
|
|
|
468
|
-
#
|
|
469
|
-
|
|
412
|
+
# Remove raw binary data and unused spare bits from dataset
|
|
413
|
+
sci_dataset = sci_dataset.drop_vars(["count_rates_raw", "science_data", "spare"])
|
|
470
414
|
|
|
471
415
|
return sci_dataset
|