imap-processing 0.9.0__py3-none-any.whl → 0.11.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/cdf/config/imap_codice_l1a_variable_attrs.yaml +749 -442
- imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +7 -0
- imap_processing/cdf/config/imap_glows_l1a_variable_attrs.yaml +8 -2
- imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +0 -1
- imap_processing/cdf/config/imap_glows_l2_variable_attrs.yaml +358 -0
- imap_processing/cdf/config/imap_hi_variable_attrs.yaml +59 -25
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +22 -0
- imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +32 -8
- imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +94 -5
- imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +65 -37
- imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +16 -1
- imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +7 -0
- imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +14 -14
- imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +25 -24
- imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +238 -0
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +100 -92
- imap_processing/cdf/utils.py +2 -2
- imap_processing/cli.py +45 -9
- imap_processing/codice/codice_l1a.py +104 -58
- imap_processing/codice/constants.py +111 -155
- imap_processing/codice/data/esa_sweep_values.csv +256 -256
- imap_processing/codice/data/lo_stepping_values.csv +128 -128
- imap_processing/ena_maps/ena_maps.py +519 -0
- imap_processing/ena_maps/utils/map_utils.py +145 -0
- imap_processing/ena_maps/utils/spatial_utils.py +226 -0
- imap_processing/glows/__init__.py +3 -0
- imap_processing/glows/ancillary/imap_glows_pipeline_settings_v001.json +52 -0
- imap_processing/glows/l1a/glows_l1a.py +72 -14
- imap_processing/glows/l1b/glows_l1b.py +2 -1
- imap_processing/glows/l1b/glows_l1b_data.py +25 -1
- imap_processing/glows/l2/glows_l2.py +324 -0
- imap_processing/glows/l2/glows_l2_data.py +156 -51
- imap_processing/hi/l1a/science_direct_event.py +57 -51
- imap_processing/hi/l1b/hi_l1b.py +43 -28
- imap_processing/hi/l1c/hi_l1c.py +225 -42
- imap_processing/hi/utils.py +20 -3
- imap_processing/hit/l0/constants.py +2 -2
- imap_processing/hit/l0/decom_hit.py +1 -1
- imap_processing/hit/l1a/hit_l1a.py +94 -13
- imap_processing/hit/l1b/hit_l1b.py +158 -9
- imap_processing/ialirt/l0/process_codicehi.py +156 -0
- imap_processing/ialirt/l0/process_codicelo.py +5 -2
- imap_processing/ialirt/packet_definitions/ialirt.xml +28 -20
- imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +241 -0
- imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +170 -0
- imap_processing/ialirt/packet_definitions/ialirt_swe.xml +258 -0
- imap_processing/ialirt/process_ephemeris.py +72 -40
- imap_processing/idex/decode.py +241 -0
- imap_processing/idex/idex_l1a.py +143 -81
- imap_processing/idex/idex_l1b.py +244 -10
- imap_processing/lo/l0/lo_science.py +61 -0
- imap_processing/lo/l1a/lo_l1a.py +98 -10
- imap_processing/lo/l1b/lo_l1b.py +2 -2
- imap_processing/lo/l1c/lo_l1c.py +2 -2
- imap_processing/lo/packet_definitions/lo_xtce.xml +1082 -9178
- imap_processing/mag/l0/decom_mag.py +2 -2
- imap_processing/mag/l1a/mag_l1a.py +7 -7
- imap_processing/mag/l1a/mag_l1a_data.py +62 -30
- imap_processing/mag/l1b/mag_l1b.py +11 -6
- imap_processing/quality_flags.py +18 -3
- imap_processing/spice/geometry.py +149 -177
- imap_processing/spice/kernels.py +26 -26
- imap_processing/spice/spin.py +233 -0
- imap_processing/spice/time.py +96 -31
- imap_processing/swapi/l1/swapi_l1.py +60 -31
- imap_processing/swapi/packet_definitions/swapi_packet_definition.xml +363 -384
- imap_processing/swe/l1a/swe_l1a.py +8 -3
- imap_processing/swe/l1a/swe_science.py +24 -24
- imap_processing/swe/l1b/swe_l1b.py +2 -1
- imap_processing/swe/l1b/swe_l1b_science.py +181 -122
- imap_processing/swe/l2/swe_l2.py +337 -70
- imap_processing/swe/utils/swe_utils.py +28 -0
- imap_processing/tests/cdf/test_utils.py +2 -2
- imap_processing/tests/codice/conftest.py +20 -17
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hskp_20241110193622_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-singles_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-angular_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-priority_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-species_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-angular_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-priority_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-species_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/test_codice_l0.py +55 -121
- imap_processing/tests/codice/test_codice_l1a.py +147 -59
- imap_processing/tests/conftest.py +81 -22
- imap_processing/tests/ena_maps/test_ena_maps.py +309 -0
- imap_processing/tests/ena_maps/test_map_utils.py +286 -0
- imap_processing/tests/ena_maps/test_spatial_utils.py +161 -0
- imap_processing/tests/glows/conftest.py +7 -1
- imap_processing/tests/glows/test_glows_l1a_cdf.py +3 -7
- imap_processing/tests/glows/test_glows_l1a_data.py +34 -6
- imap_processing/tests/glows/test_glows_l1b_data.py +29 -17
- imap_processing/tests/glows/test_glows_l2.py +101 -0
- imap_processing/tests/hi/conftest.py +3 -3
- imap_processing/tests/hi/data/l1/imap_hi_l1b_45sensor-de_20250415_v999.cdf +0 -0
- imap_processing/tests/hi/data/l1/imap_his_pset-calibration-prod-config_20240101_v001.csv +31 -0
- imap_processing/tests/hi/test_hi_l1b.py +14 -9
- imap_processing/tests/hi/test_hi_l1c.py +136 -36
- imap_processing/tests/hi/test_l1a.py +0 -2
- imap_processing/tests/hi/test_science_direct_event.py +18 -14
- imap_processing/tests/hi/test_utils.py +16 -11
- imap_processing/tests/hit/helpers/__init__.py +0 -0
- imap_processing/tests/hit/helpers/l1_validation.py +405 -0
- imap_processing/tests/hit/test_data/sci_sample.ccsds +0 -0
- imap_processing/tests/hit/test_decom_hit.py +8 -10
- imap_processing/tests/hit/test_hit_l1a.py +117 -180
- imap_processing/tests/hit/test_hit_l1b.py +149 -55
- imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -0
- imap_processing/tests/hit/validation_data/sci_sample_raw.csv +62 -0
- imap_processing/tests/ialirt/test_data/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/eu_SWP_IAL_20240826_152033.csv +644 -0
- imap_processing/tests/ialirt/test_data/l0/hi_fsw_view_1_ccsds.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +914 -0
- imap_processing/tests/ialirt/test_data/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
- imap_processing/tests/ialirt/unit/test_process_codicehi.py +106 -0
- imap_processing/tests/ialirt/unit/test_process_ephemeris.py +33 -5
- imap_processing/tests/ialirt/unit/test_process_swapi.py +85 -0
- imap_processing/tests/ialirt/unit/test_process_swe.py +106 -0
- imap_processing/tests/idex/conftest.py +29 -1
- imap_processing/tests/idex/test_data/compressed_2023_102_14_24_55.pkts +0 -0
- imap_processing/tests/idex/test_data/non_compressed_2023_102_14_22_26.pkts +0 -0
- imap_processing/tests/idex/test_idex_l0.py +6 -3
- imap_processing/tests/idex/test_idex_l1a.py +151 -1
- imap_processing/tests/idex/test_idex_l1b.py +124 -2
- imap_processing/tests/lo/test_lo_l1a.py +62 -2
- imap_processing/tests/lo/test_lo_science.py +85 -0
- imap_processing/tests/lo/validation_data/Instrument_FM1_T104_R129_20240803_ILO_SPIN_EU.csv +2 -0
- imap_processing/tests/mag/conftest.py +16 -0
- imap_processing/tests/mag/test_mag_decom.py +6 -4
- imap_processing/tests/mag/test_mag_l1a.py +36 -7
- imap_processing/tests/mag/test_mag_l1b.py +55 -4
- imap_processing/tests/mag/test_mag_validation.py +148 -0
- imap_processing/tests/mag/validation/L1a/T001/all_p_ones.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T001/mag-l0-l1a-t001-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T001/mag-l0-l1a-t001-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T002/all_n_ones.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T002/mag-l0-l1a-t002-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T002/mag-l0-l1a-t002-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T003/field_like.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T003/mag-l0-l1a-t003-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T003/mag-l0-l1a-t003-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T004/field_like.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T004/mag-l0-l1a-t004-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T004/mag-l0-l1a-t004-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T005/field_like_range_change.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T005/mag-l0-l1a-t005-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T005/mag-l0-l1a-t005-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T006/hdr_field.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T006/mag-l0-l1a-t006-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T006/mag-l0-l1a-t006-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T007/hdr_field_and_range_change.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T007/mag-l0-l1a-t007-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T007/mag-l0-l1a-t007-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T008/field_like_range_change.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T008/mag-l0-l1a-t008-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T008/mag-l0-l1a-t008-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T009/data.bin +0 -0
- imap_processing/tests/mag/validation/L1b/T009/field_like_all_ranges.txt +19200 -0
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-in.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-magi-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-mago-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T010/data.bin +0 -0
- imap_processing/tests/mag/validation/L1b/T010/field_like_all_ranges.txt +19200 -0
- imap_processing/tests/mag/validation/L1b/T010/mag-l1a-l1b-t010-in.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T010/mag-l1a-l1b-t010-magi-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T010/mag-l1a-l1b-t010-mago-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/data.bin +0 -0
- imap_processing/tests/mag/validation/L1b/T011/field_like_all_ranges.txt +19200 -0
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-in.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-magi-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-mago-out.csv +17 -0
- imap_processing/tests/spice/test_geometry.py +128 -133
- imap_processing/tests/spice/test_kernels.py +37 -37
- imap_processing/tests/spice/test_spin.py +184 -0
- imap_processing/tests/spice/test_time.py +43 -20
- imap_processing/tests/swapi/test_swapi_l1.py +11 -10
- imap_processing/tests/swapi/test_swapi_l2.py +13 -3
- imap_processing/tests/swe/test_swe_l1a.py +1 -1
- imap_processing/tests/swe/test_swe_l1b.py +20 -3
- imap_processing/tests/swe/test_swe_l1b_science.py +54 -35
- imap_processing/tests/swe/test_swe_l2.py +148 -5
- imap_processing/tests/test_cli.py +39 -7
- imap_processing/tests/test_quality_flags.py +19 -19
- imap_processing/tests/test_utils.py +3 -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/mock_data.py +161 -0
- imap_processing/tests/ultra/unit/conftest.py +73 -0
- imap_processing/tests/ultra/unit/test_badtimes.py +58 -0
- imap_processing/tests/ultra/unit/test_cullingmask.py +87 -0
- imap_processing/tests/ultra/unit/test_de.py +61 -60
- imap_processing/tests/ultra/unit/test_ultra_l1a.py +3 -3
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +51 -77
- imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +5 -5
- imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +114 -0
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +86 -26
- imap_processing/tests/ultra/unit/test_ultra_l1c.py +1 -1
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +3 -3
- imap_processing/ultra/constants.py +11 -1
- imap_processing/ultra/l1a/ultra_l1a.py +2 -2
- imap_processing/ultra/l1b/badtimes.py +22 -5
- imap_processing/ultra/l1b/cullingmask.py +31 -5
- imap_processing/ultra/l1b/de.py +32 -37
- imap_processing/ultra/l1b/extendedspin.py +44 -20
- imap_processing/ultra/l1b/ultra_l1b.py +21 -22
- imap_processing/ultra/l1b/ultra_l1b_culling.py +190 -0
- imap_processing/ultra/l1b/ultra_l1b_extended.py +81 -30
- imap_processing/ultra/l1c/histogram.py +6 -2
- imap_processing/ultra/l1c/pset.py +6 -2
- imap_processing/ultra/l1c/ultra_l1c.py +2 -3
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +4 -3
- imap_processing/ultra/utils/ultra_l1_utils.py +70 -14
- imap_processing/utils.py +2 -2
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/METADATA +7 -2
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/RECORD +235 -152
- imap_processing/tests/codice/data/eu_unit_lookup_table.csv +0 -101
- imap_processing/tests/codice/data/idle_export_eu.COD_NHK_20230822_122700 2.csv +0 -100
- imap_processing/tests/codice/data/idle_export_raw.COD_NHK_20230822_122700.csv +0 -100
- imap_processing/tests/codice/data/imap_codice_l0_raw_20241110_v001.pkts +0 -0
- imap_processing/tests/hi/test_data/l1a/imap_hi_l1a_45sensor-de_20250415_v000.cdf +0 -0
- imap_processing/tests/hit/test_data/sci_sample1.ccsds +0 -0
- imap_processing/tests/ultra/unit/test_spatial_utils.py +0 -125
- imap_processing/ultra/utils/spatial_utils.py +0 -221
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_APP_NHK.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_APP_NHK.csv +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_SCI_CNT.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_SCI_DE.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/H90_NHK_20241104.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/H90_sci_cnt_20241104.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/H90_sci_de_20241104.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/README.txt +0 -0
- /imap_processing/tests/idex/{imap_idex_l0_raw_20231214_v001.pkts → test_data/imap_idex_l0_raw_20231214_v001.pkts} +0 -0
- /imap_processing/tests/idex/{impact_14_tof_high_data.txt → test_data/impact_14_tof_high_data.txt} +0 -0
- /imap_processing/tests/mag/{imap_mag_l1a_norm-magi_20251017_v001.cdf → validation/imap_mag_l1a_norm-magi_20251017_v001.cdf} +0 -0
- /imap_processing/tests/mag/{mag_l0_test_data.pkts → validation/mag_l0_test_data.pkts} +0 -0
- /imap_processing/tests/mag/{mag_l0_test_output.csv → validation/mag_l0_test_output.csv} +0 -0
- /imap_processing/tests/mag/{mag_l1_test_data.pkts → validation/mag_l1_test_data.pkts} +0 -0
- /imap_processing/tests/mag/{mag_l1a_test_output.csv → validation/mag_l1a_test_output.csv} +0 -0
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"""IMAP utils for spatial binning and az/el grid creation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import typing
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
from numpy.typing import NDArray
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def build_spatial_bins(
|
|
12
|
+
az_spacing_deg: float = 0.5,
|
|
13
|
+
el_spacing_deg: float = 0.5,
|
|
14
|
+
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
|
|
15
|
+
"""
|
|
16
|
+
Build spatial bin boundaries for azimuth and elevation.
|
|
17
|
+
|
|
18
|
+
Input angles in degrees for consistency with map inputs,
|
|
19
|
+
output angles in radians for internal use.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
az_spacing_deg : float, optional
|
|
24
|
+
The azimuth bin spacing in degrees (default is 0.5 degrees).
|
|
25
|
+
el_spacing_deg : float, optional
|
|
26
|
+
The elevation bin spacing in degrees (default is 0.5 degrees).
|
|
27
|
+
|
|
28
|
+
Returns
|
|
29
|
+
-------
|
|
30
|
+
az_bin_edges : np.ndarray
|
|
31
|
+
Array of azimuth bin boundary values in radians.
|
|
32
|
+
el_bin_edges : np.ndarray
|
|
33
|
+
Array of elevation bin boundary values in radians.
|
|
34
|
+
az_bin_midpoints : np.ndarray
|
|
35
|
+
Array of azimuth bin midpoint values in radians.
|
|
36
|
+
el_bin_midpoints : np.ndarray
|
|
37
|
+
Array of elevation bin midpoint values in radians.
|
|
38
|
+
"""
|
|
39
|
+
# Azimuth bins from 0 to 360 degrees.
|
|
40
|
+
az_bin_edges = np.arange(0, 360 + az_spacing_deg, az_spacing_deg)
|
|
41
|
+
az_bin_midpoints = az_bin_edges[:-1] + az_spacing_deg / 2 # Midpoints between edges
|
|
42
|
+
|
|
43
|
+
# Elevation bins from -90 to 90 degrees.
|
|
44
|
+
el_bin_edges = np.arange(-90, 90 + el_spacing_deg, el_spacing_deg)
|
|
45
|
+
el_bin_midpoints = el_bin_edges[:-1] + el_spacing_deg / 2 # Midpoints between edges
|
|
46
|
+
|
|
47
|
+
# Convert all angles to radians and return them
|
|
48
|
+
return (
|
|
49
|
+
np.deg2rad(az_bin_edges),
|
|
50
|
+
np.deg2rad(el_bin_edges),
|
|
51
|
+
np.deg2rad(az_bin_midpoints),
|
|
52
|
+
np.deg2rad(el_bin_midpoints),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def build_solid_angle_map(
|
|
57
|
+
spacing_deg: float,
|
|
58
|
+
) -> NDArray:
|
|
59
|
+
"""
|
|
60
|
+
Build a solid angle map in steradians for a given spacing in degrees.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
spacing_deg : float
|
|
65
|
+
The bin spacing in degrees.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
solid_angle_grid : np.ndarray
|
|
70
|
+
The solid angle map grid in steradians.
|
|
71
|
+
First index is latitude/el, second index is longitude/az.
|
|
72
|
+
"""
|
|
73
|
+
# Degrees are the preferred input units of angle, given map definitions,
|
|
74
|
+
# but we'll convert to radians for internal calculations and output steradians.
|
|
75
|
+
spacing = np.deg2rad(spacing_deg)
|
|
76
|
+
|
|
77
|
+
if spacing <= 0:
|
|
78
|
+
raise ValueError("Spacing must be positive valued, non-zero.")
|
|
79
|
+
|
|
80
|
+
if not np.isclose((np.pi / spacing) % 1, 0):
|
|
81
|
+
raise ValueError("Spacing must divide evenly into pi radians.")
|
|
82
|
+
|
|
83
|
+
latitudes = np.arange(-np.pi / 2, np.pi / 2 + spacing, step=spacing)
|
|
84
|
+
sine_latitudes = np.sin(latitudes)
|
|
85
|
+
delta_sine_latitudes = np.diff(sine_latitudes)
|
|
86
|
+
solid_angle_by_latitude = np.abs(spacing * delta_sine_latitudes)
|
|
87
|
+
|
|
88
|
+
# Order ensures agreement with build_az_el_grid's order of tiling az/el grid.
|
|
89
|
+
solid_angle_grid = np.repeat(
|
|
90
|
+
solid_angle_by_latitude[np.newaxis, :], (2 * np.pi) / spacing, axis=0
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
return solid_angle_grid
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@typing.no_type_check
|
|
97
|
+
def rewrap_even_spaced_az_el_grid(
|
|
98
|
+
raveled_values: NDArray,
|
|
99
|
+
shape: tuple[int] | None = None,
|
|
100
|
+
order: typing.Literal["C"] | typing.Literal["F"] = "C",
|
|
101
|
+
) -> NDArray:
|
|
102
|
+
"""
|
|
103
|
+
Take an unwrapped (raveled) 1D array and reshapes it into a 2D az/el grid.
|
|
104
|
+
|
|
105
|
+
Assumes the following must be true of the original grid:
|
|
106
|
+
1. Grid was evenly spaced in angular space,
|
|
107
|
+
2. Grid had the same spacing in both azimuth and elevation.
|
|
108
|
+
3. Azimuth is axis 0 (and extends a total of 360 degrees).
|
|
109
|
+
4. Elevation is axis 1 (and extends a total of 180 degrees),
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
raveled_values : NDArray
|
|
114
|
+
1D array of values to be reshaped into a 2D grid.
|
|
115
|
+
shape : tuple[int], optional
|
|
116
|
+
The shape of the original grid, if known, by default None.
|
|
117
|
+
If None, the shape will be inferred from the size of the input array.
|
|
118
|
+
order : {'C', 'F'}, optional
|
|
119
|
+
The order in which to rewrap the values, by default 'C'.
|
|
120
|
+
|
|
121
|
+
Returns
|
|
122
|
+
-------
|
|
123
|
+
NDArray
|
|
124
|
+
The reshaped 2D grid of values.
|
|
125
|
+
|
|
126
|
+
Raises
|
|
127
|
+
------
|
|
128
|
+
ValueError
|
|
129
|
+
If the input is not a 1D array or 2D array with an 'extra' non-spatial axis.
|
|
130
|
+
"""
|
|
131
|
+
if raveled_values.ndim > 2:
|
|
132
|
+
raise ValueError(
|
|
133
|
+
"Input must be a 1D array or 2D array with only one spatial axis as axis 0."
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# We can infer the shape if its evenly spaced and 2D
|
|
137
|
+
if not shape:
|
|
138
|
+
spacing_deg = 1 / np.sqrt(raveled_values.shape[0] / (360 * 180))
|
|
139
|
+
shape = (int(360 // spacing_deg), int(180 // spacing_deg))
|
|
140
|
+
|
|
141
|
+
if raveled_values.ndim == 2:
|
|
142
|
+
shape = (shape[0], shape[1], raveled_values.shape[1])
|
|
143
|
+
return raveled_values.reshape(shape, order=order)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class AzElSkyGrid:
|
|
147
|
+
"""
|
|
148
|
+
Representation of a 2D grid of azimuth and elevation angles covering the sky.
|
|
149
|
+
|
|
150
|
+
All angles are stored internally in radians.
|
|
151
|
+
Azimuth is within the range [0, 2*pi) radians,
|
|
152
|
+
elevation is within the range [-pi/2, pi/2) radians.
|
|
153
|
+
|
|
154
|
+
Parameters
|
|
155
|
+
----------
|
|
156
|
+
spacing_deg : float, optional
|
|
157
|
+
Spacing of the grid in degrees, by default 0.5.
|
|
158
|
+
reversed_elevation : bool, optional
|
|
159
|
+
Whether the elevation grid should be reversed, by default False.
|
|
160
|
+
If False, the elevation grid will be from -pi/2 to pi/2 radians (-90 to 90 deg).
|
|
161
|
+
If True, the elevation grid will be from pi/2 to -pi/2 radians (90 to -90 deg).
|
|
162
|
+
|
|
163
|
+
Raises
|
|
164
|
+
------
|
|
165
|
+
ValueError
|
|
166
|
+
If the spacing is not positive or does not divide evenly into pi radians.
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
def __init__(
|
|
170
|
+
self,
|
|
171
|
+
spacing_deg: float = 0.5,
|
|
172
|
+
reversed_elevation: bool = False,
|
|
173
|
+
) -> None:
|
|
174
|
+
# Store grid properties
|
|
175
|
+
self.reversed_elevation = reversed_elevation
|
|
176
|
+
|
|
177
|
+
# Internally, work in radians, regardless of desired output units
|
|
178
|
+
self.spacing = np.deg2rad(spacing_deg)
|
|
179
|
+
|
|
180
|
+
# Ensure valid grid spacing (positive, divides evenly into pi radians)
|
|
181
|
+
if self.spacing <= 0:
|
|
182
|
+
raise ValueError("Spacing must be positive valued, non-zero.")
|
|
183
|
+
|
|
184
|
+
if not np.isclose((np.pi / self.spacing) % 1, 0):
|
|
185
|
+
raise ValueError("Spacing must divide evenly into pi radians.")
|
|
186
|
+
|
|
187
|
+
# build_spacial_bins creates the bin edges and centers for azimuth and elevation
|
|
188
|
+
# E.g. for spacing=1, az_bin_edges = [0, 1, 2, ..., 359, 360] deg.
|
|
189
|
+
# However returned values are in radians.
|
|
190
|
+
(
|
|
191
|
+
self.az_bin_edges,
|
|
192
|
+
self.el_bin_edges,
|
|
193
|
+
self.az_bin_midpoints,
|
|
194
|
+
self.el_bin_midpoints,
|
|
195
|
+
) = build_spatial_bins(az_spacing_deg=spacing_deg, el_spacing_deg=spacing_deg)
|
|
196
|
+
|
|
197
|
+
# If desired, reverse the elevation range so that the grid is in the order
|
|
198
|
+
# defined by the Ultra prototype code (`build_dps_grid.m`).
|
|
199
|
+
if self.reversed_elevation:
|
|
200
|
+
self.el_bin_midpoints = self.el_bin_midpoints[::-1]
|
|
201
|
+
self.el_bin_edges = self.el_bin_edges[::-1]
|
|
202
|
+
|
|
203
|
+
# Deriving our az/el grids with indexing "ij" allows for ravel_multi_index
|
|
204
|
+
# to work correctly with 1D digitized indices in each az and el,
|
|
205
|
+
# using the same ravel order ('C' or 'F') as the grid points were unwrapped.
|
|
206
|
+
self.az_grid, self.el_grid = np.meshgrid(
|
|
207
|
+
self.az_bin_midpoints, self.el_bin_midpoints, indexing="ij"
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# Keep track of number of points on the grid
|
|
211
|
+
self.grid_shape = self.az_grid.shape
|
|
212
|
+
self.grid_size = self.az_grid.size
|
|
213
|
+
|
|
214
|
+
def __repr__(self) -> str:
|
|
215
|
+
"""
|
|
216
|
+
Return a string representation of the AzElSkyGrid.
|
|
217
|
+
|
|
218
|
+
Returns
|
|
219
|
+
-------
|
|
220
|
+
str
|
|
221
|
+
A string representation of the AzElSkyGrid.
|
|
222
|
+
"""
|
|
223
|
+
return (
|
|
224
|
+
f"AzElSkyGrid with a spacing of {self.spacing:.4e} radians. "
|
|
225
|
+
f"{self.grid_shape} Grid."
|
|
226
|
+
)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Settings for ground-processing pipeline for IMAP/GLOWS data",
|
|
3
|
+
"version": "0.1",
|
|
4
|
+
"date_of_creation_yyyymmdd": "20230527",
|
|
5
|
+
"filter_based_on_daily_statistical_error": {
|
|
6
|
+
"n_sigma_threshold_lower": 3.0,
|
|
7
|
+
"n_sigma_threshold_upper": 3.0
|
|
8
|
+
},
|
|
9
|
+
"filter_based_on_comparison_of_spin_periods": {
|
|
10
|
+
"relative_difference_threshold": 7.0e-5
|
|
11
|
+
},
|
|
12
|
+
"filter_based_on_temperature_std_dev": {
|
|
13
|
+
"std_dev_threshold__celsius_deg": 2.03
|
|
14
|
+
},
|
|
15
|
+
"filter_based_on_hv_voltage_std_dev": {
|
|
16
|
+
"std_dev_threshold__volt": 50.0
|
|
17
|
+
},
|
|
18
|
+
"filter_based_on_spin_period_std_dev": {
|
|
19
|
+
"std_dev_threshold__sec": 0.033333
|
|
20
|
+
},
|
|
21
|
+
"filter_based_on_pulse_length_std_dev": {
|
|
22
|
+
"std_dev_threshold__usec": 1.0
|
|
23
|
+
},
|
|
24
|
+
"filter_based_on_maps": {
|
|
25
|
+
"angular_distance_for_flaging__deg": 2.5
|
|
26
|
+
},
|
|
27
|
+
"active_bad_time_flags": {
|
|
28
|
+
"is_pps_missing": true,
|
|
29
|
+
"is_time_status_missing": true,
|
|
30
|
+
"is_phase_missing": true,
|
|
31
|
+
"is_spin_period_missing": true,
|
|
32
|
+
"is_overexposed": true,
|
|
33
|
+
"is_direct_event_non_monotonic": true,
|
|
34
|
+
"is_night": true,
|
|
35
|
+
"is_hv_test_in_progress": true,
|
|
36
|
+
"is_test_pulse_in_progress": true,
|
|
37
|
+
"is_memory_error_detected": true,
|
|
38
|
+
"is_generated_on_ground": true,
|
|
39
|
+
"is_beyond_daily_statistical_error": true,
|
|
40
|
+
"is_temperature_std_dev_beyond_threshold": true,
|
|
41
|
+
"is_hv_voltage_std_dev_beyond_threshold": true,
|
|
42
|
+
"is_spin_period_std_dev_beyond_threshold": true,
|
|
43
|
+
"is_pulse_length_std_dev_beyond_threshold": true,
|
|
44
|
+
"is_spin_period_difference_beyond_threshold": false
|
|
45
|
+
},
|
|
46
|
+
"active_bad_angle_flags": {
|
|
47
|
+
"is_close_to_uv_source": true,
|
|
48
|
+
"is_inside_excluded_region": true,
|
|
49
|
+
"is_excluded_by_instr_team": true,
|
|
50
|
+
"is_suspected_transient": true
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -2,15 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import Optional
|
|
5
6
|
|
|
6
7
|
import numpy as np
|
|
7
8
|
import xarray as xr
|
|
8
9
|
|
|
9
10
|
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
10
11
|
from imap_processing.glows.l0.decom_glows import decom_packets
|
|
11
|
-
from imap_processing.glows.l0.glows_l0_data import DirectEventL0
|
|
12
|
+
from imap_processing.glows.l0.glows_l0_data import DirectEventL0, HistogramL0
|
|
12
13
|
from imap_processing.glows.l1a.glows_l1a_data import DirectEventL1A, HistogramL1A
|
|
13
|
-
from imap_processing.
|
|
14
|
+
from imap_processing.glows.l1b.glows_l1b_data import HistogramL1B
|
|
15
|
+
from imap_processing.spice.time import (
|
|
16
|
+
met_to_datetime64,
|
|
17
|
+
met_to_ttj2000ns,
|
|
18
|
+
)
|
|
14
19
|
|
|
15
20
|
|
|
16
21
|
def create_glows_attr_obj(data_version: str) -> ImapCdfAttributes:
|
|
@@ -66,19 +71,25 @@ def glows_l1a(packet_filepath: Path, data_version: str) -> list[xr.Dataset]:
|
|
|
66
71
|
# Create dictionaries to group data by day
|
|
67
72
|
de_by_day = process_de_l0(de_l0)
|
|
68
73
|
hists_by_day = defaultdict(list)
|
|
74
|
+
# Assume the observational day starts with the first packet, then find any new
|
|
75
|
+
# observation days.
|
|
76
|
+
# TODO: replace determine_observational_day with spin table API
|
|
77
|
+
obs_days = [hist_l0[0].SEC]
|
|
78
|
+
obs_days += determine_observational_day(hist_l0)
|
|
69
79
|
|
|
70
|
-
# TODO: Make this its own function?
|
|
71
80
|
for hist in hist_l0:
|
|
72
81
|
hist_l1a = HistogramL1A(hist)
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
hist_day = (
|
|
82
|
+
# Determine the day the histogram belongs to. This finds the observation
|
|
83
|
+
# day in obs_day that is nearest the histogram timestamp without going over.
|
|
84
|
+
hist_day = next(
|
|
85
|
+
(day for day in reversed(obs_days) if day <= hist.SEC), obs_days[-1]
|
|
86
|
+
)
|
|
76
87
|
hists_by_day[hist_day].append(hist_l1a)
|
|
77
88
|
|
|
78
89
|
# Generate CDF files for each day
|
|
79
90
|
output_datasets = []
|
|
80
|
-
for hist_l1a_list in hists_by_day.
|
|
81
|
-
dataset = generate_histogram_dataset(hist_l1a_list, glows_attrs)
|
|
91
|
+
for obs_day, hist_l1a_list in hists_by_day.items():
|
|
92
|
+
dataset = generate_histogram_dataset(hist_l1a_list, glows_attrs, obs_day)
|
|
82
93
|
output_datasets.append(dataset)
|
|
83
94
|
|
|
84
95
|
for de_l1a_list in de_by_day.values():
|
|
@@ -88,6 +99,36 @@ def glows_l1a(packet_filepath: Path, data_version: str) -> list[xr.Dataset]:
|
|
|
88
99
|
return output_datasets
|
|
89
100
|
|
|
90
101
|
|
|
102
|
+
def determine_observational_day(hist_l0: list[HistogramL0]) -> list:
|
|
103
|
+
"""
|
|
104
|
+
Find the timestamps for each observational day.
|
|
105
|
+
|
|
106
|
+
This function temporarily uses the is_night flag to determine the start of a new
|
|
107
|
+
observational day, but should eventually use the spin table APIs.
|
|
108
|
+
|
|
109
|
+
Parameters
|
|
110
|
+
----------
|
|
111
|
+
hist_l0 : list[HistogramL0]
|
|
112
|
+
List of HistogramL0 objects.
|
|
113
|
+
|
|
114
|
+
Returns
|
|
115
|
+
-------
|
|
116
|
+
list
|
|
117
|
+
List of start times for each observational day.
|
|
118
|
+
"""
|
|
119
|
+
prev_is_night = -1
|
|
120
|
+
obs_day_change = []
|
|
121
|
+
for hist in hist_l0:
|
|
122
|
+
flags = HistogramL1B.deserialize_flags(hist.FLAGS)
|
|
123
|
+
is_night: int = int(flags[6])
|
|
124
|
+
if prev_is_night and not is_night:
|
|
125
|
+
obs_day_change.append(hist.SEC)
|
|
126
|
+
|
|
127
|
+
prev_is_night = is_night
|
|
128
|
+
|
|
129
|
+
return obs_day_change
|
|
130
|
+
|
|
131
|
+
|
|
91
132
|
def process_de_l0(
|
|
92
133
|
de_l0: list[DirectEventL0],
|
|
93
134
|
) -> dict[np.datetime64, list[DirectEventL1A]]:
|
|
@@ -111,7 +152,7 @@ def process_de_l0(
|
|
|
111
152
|
de_by_day = dict()
|
|
112
153
|
|
|
113
154
|
for de in de_l0:
|
|
114
|
-
de_day = (
|
|
155
|
+
de_day = (met_to_datetime64(de.MET)).astype("datetime64[D]")
|
|
115
156
|
if de_day not in de_by_day:
|
|
116
157
|
de_by_day[de_day] = [DirectEventL1A(de)]
|
|
117
158
|
# Putting not first data int o last direct event list.
|
|
@@ -186,7 +227,7 @@ def generate_de_dataset(
|
|
|
186
227
|
|
|
187
228
|
for index, de in enumerate(de_l1a_list):
|
|
188
229
|
# Set the timestamp to the first timestamp of the direct event list
|
|
189
|
-
epoch_time =
|
|
230
|
+
epoch_time = met_to_ttj2000ns(de.l0.MET).astype("datetime64[ns]")
|
|
190
231
|
|
|
191
232
|
# determine if the length of the direct_events numpy array is long enough,
|
|
192
233
|
# and extend the direct_events length dimension if necessary.
|
|
@@ -297,7 +338,9 @@ def generate_de_dataset(
|
|
|
297
338
|
|
|
298
339
|
|
|
299
340
|
def generate_histogram_dataset(
|
|
300
|
-
hist_l1a_list: list[HistogramL1A],
|
|
341
|
+
hist_l1a_list: list[HistogramL1A],
|
|
342
|
+
glows_cdf_attributes: ImapCdfAttributes,
|
|
343
|
+
obs_day: Optional[int] = None,
|
|
301
344
|
) -> xr.Dataset:
|
|
302
345
|
"""
|
|
303
346
|
Generate a dataset for GLOWS L1A histogram data CDF files.
|
|
@@ -308,6 +351,9 @@ def generate_histogram_dataset(
|
|
|
308
351
|
List of HistogramL1A objects for a given day.
|
|
309
352
|
glows_cdf_attributes : ImapCdfAttributes
|
|
310
353
|
Object containing l1a CDF attributes for instrument glows.
|
|
354
|
+
obs_day : int, optional
|
|
355
|
+
Observational day counter. If supplied, it will be included in the
|
|
356
|
+
output file name.
|
|
311
357
|
|
|
312
358
|
Returns
|
|
313
359
|
-------
|
|
@@ -315,7 +361,7 @@ def generate_histogram_dataset(
|
|
|
315
361
|
Dataset containing the GLOWS L1A histogram CDF output.
|
|
316
362
|
"""
|
|
317
363
|
# Store timestamps for each HistogramL1A object.
|
|
318
|
-
time_data = np.zeros(len(hist_l1a_list), dtype="
|
|
364
|
+
time_data = np.zeros(len(hist_l1a_list), dtype="int64")
|
|
319
365
|
# TODO Add daily average of histogram counts
|
|
320
366
|
# TODO compute average temperature etc
|
|
321
367
|
# Data in lists, for each of the 25 time varying datapoints in HistogramL1A
|
|
@@ -352,7 +398,7 @@ def generate_histogram_dataset(
|
|
|
352
398
|
|
|
353
399
|
for index, hist in enumerate(hist_l1a_list):
|
|
354
400
|
# TODO: Should this be MET?
|
|
355
|
-
epoch_time =
|
|
401
|
+
epoch_time = met_to_ttj2000ns(hist.imap_start_time.to_seconds())
|
|
356
402
|
hist_data[index] = hist.histogram
|
|
357
403
|
|
|
358
404
|
support_data["flags_set_onboard"].append(hist.flags["flags_set_onboard"])
|
|
@@ -384,6 +430,15 @@ def generate_histogram_dataset(
|
|
|
384
430
|
attrs=glows_cdf_attributes.get_variable_attributes("bins_attrs"),
|
|
385
431
|
)
|
|
386
432
|
|
|
433
|
+
bin_label = xr.DataArray(
|
|
434
|
+
bins.data.astype(str),
|
|
435
|
+
name="bins_label",
|
|
436
|
+
dims=["bins_label"],
|
|
437
|
+
attrs=glows_cdf_attributes.get_variable_attributes(
|
|
438
|
+
"bins_label", check_schema=False
|
|
439
|
+
),
|
|
440
|
+
)
|
|
441
|
+
|
|
387
442
|
hist = xr.DataArray(
|
|
388
443
|
hist_data,
|
|
389
444
|
name="histogram",
|
|
@@ -395,9 +450,12 @@ def generate_histogram_dataset(
|
|
|
395
450
|
)
|
|
396
451
|
|
|
397
452
|
attrs = glows_cdf_attributes.get_global_attributes("imap_glows_l1a_hist")
|
|
453
|
+
if obs_day:
|
|
454
|
+
# this needs to be 5 digits, so truncate it from the temporary obs day
|
|
455
|
+
attrs["Repointing"] = int(str(obs_day)[-5:])
|
|
398
456
|
|
|
399
457
|
output = xr.Dataset(
|
|
400
|
-
coords={"epoch": epoch_time, "bins": bins},
|
|
458
|
+
coords={"epoch": epoch_time, "bins": bins, "bins_label": bin_label},
|
|
401
459
|
attrs=attrs,
|
|
402
460
|
)
|
|
403
461
|
|
|
@@ -6,6 +6,7 @@ import numpy as np
|
|
|
6
6
|
import xarray as xr
|
|
7
7
|
|
|
8
8
|
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
9
|
+
from imap_processing.glows import FLAG_LENGTH
|
|
9
10
|
from imap_processing.glows.l1b.glows_l1b_data import DirectEventL1B, HistogramL1B
|
|
10
11
|
|
|
11
12
|
|
|
@@ -45,7 +46,7 @@ def glows_l1b(input_dataset: xr.Dataset, data_version: str) -> xr.Dataset:
|
|
|
45
46
|
|
|
46
47
|
if "hist" in logical_source:
|
|
47
48
|
flag_data = xr.DataArray(
|
|
48
|
-
np.arange(
|
|
49
|
+
np.arange(FLAG_LENGTH),
|
|
49
50
|
name="flag_dim",
|
|
50
51
|
dims=["flag_dim"],
|
|
51
52
|
attrs=cdf_attrs.get_variable_attributes("flag_dim"),
|
|
@@ -9,6 +9,7 @@ from typing import Optional
|
|
|
9
9
|
|
|
10
10
|
import numpy as np
|
|
11
11
|
|
|
12
|
+
from imap_processing.glows import FLAG_LENGTH
|
|
12
13
|
from imap_processing.glows.utils.constants import TimeTuple
|
|
13
14
|
|
|
14
15
|
|
|
@@ -595,7 +596,7 @@ class HistogramL1B:
|
|
|
595
596
|
# self.unique_block_identifier = np.datetime_as_string(
|
|
596
597
|
# np.datetime64(int(self.imap_start_time), "ns"), "s"
|
|
597
598
|
# )
|
|
598
|
-
self.flags = np.ones((
|
|
599
|
+
self.flags = np.ones((FLAG_LENGTH,), dtype=np.uint8)
|
|
599
600
|
|
|
600
601
|
def output_data(self) -> tuple:
|
|
601
602
|
"""
|
|
@@ -610,3 +611,26 @@ class HistogramL1B:
|
|
|
610
611
|
A tuple containing each attribute value in the class.
|
|
611
612
|
"""
|
|
612
613
|
return tuple(getattr(self, out.name) for out in dataclasses.fields(self))
|
|
614
|
+
|
|
615
|
+
@staticmethod
|
|
616
|
+
def deserialize_flags(raw: int) -> np.ndarray[int]:
|
|
617
|
+
"""
|
|
618
|
+
Deserialize the flags into a list.
|
|
619
|
+
|
|
620
|
+
Parameters
|
|
621
|
+
----------
|
|
622
|
+
raw : int
|
|
623
|
+
16 bit integer containing the on-board flags to deserialize.
|
|
624
|
+
|
|
625
|
+
Returns
|
|
626
|
+
-------
|
|
627
|
+
flags : np.ndarray
|
|
628
|
+
Array of flags as a boolean.
|
|
629
|
+
"""
|
|
630
|
+
# there are only 10 flags in the on-board flag array, additional flags are added
|
|
631
|
+
# later.
|
|
632
|
+
flags: np.ndarray[bool] = np.array(
|
|
633
|
+
[bool((raw >> i) & 1) for i in range(10)], dtype=bool
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
return flags
|