imap-processing 0.6.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.
- imap_processing/__init__.py +34 -0
- imap_processing/_version.py +3 -0
- imap_processing/ccsds/__init__.py +0 -0
- imap_processing/ccsds/ccsds_data.py +55 -0
- imap_processing/ccsds/excel_to_xtce.py +477 -0
- imap_processing/cdf/__init__.py +0 -0
- imap_processing/cdf/cdf_attribute_manager.py +322 -0
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +212 -0
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +1358 -0
- imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +391 -0
- imap_processing/cdf/config/imap_constant_attrs.yaml +33 -0
- imap_processing/cdf/config/imap_default_global_cdf_attrs.yaml +17 -0
- imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +41 -0
- imap_processing/cdf/config/imap_glows_l1a_variable_attrs.yaml +499 -0
- imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +334 -0
- imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +51 -0
- imap_processing/cdf/config/imap_hi_variable_attrs.yaml +435 -0
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +27 -0
- imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +493 -0
- imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +564 -0
- imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +24 -0
- imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +426 -0
- imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +90 -0
- imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +487 -0
- imap_processing/cdf/config/imap_lo_l1b_variable_attrs.yaml +121 -0
- imap_processing/cdf/config/imap_lo_l1c_variable_attrs.yaml +179 -0
- imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +97 -0
- imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +201 -0
- imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +33 -0
- imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +137 -0
- imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +24 -0
- imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +234 -0
- imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +273 -0
- imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +100 -0
- imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +52 -0
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +297 -0
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +121 -0
- imap_processing/cdf/config/shared/default_global_cdf_attrs_schema.yaml +246 -0
- imap_processing/cdf/config/shared/default_variable_cdf_attrs_schema.yaml +466 -0
- imap_processing/cdf/imap_cdf_manager.py +64 -0
- imap_processing/cdf/utils.py +147 -0
- imap_processing/cli.py +863 -0
- imap_processing/codice/__init__.py +1 -0
- imap_processing/codice/codice_l0.py +54 -0
- imap_processing/codice/codice_l1a.py +558 -0
- imap_processing/codice/codice_l1b.py +194 -0
- imap_processing/codice/constants.py +986 -0
- imap_processing/codice/data/esa_sweep_values.csv +257 -0
- imap_processing/codice/data/lo_stepping_values.csv +129 -0
- imap_processing/codice/decompress.py +142 -0
- imap_processing/codice/packet_definitions/P_COD_NHK.xml +618 -0
- imap_processing/codice/packet_definitions/codice_packet_definition.xml +5073 -0
- imap_processing/codice/utils.py +95 -0
- imap_processing/decom.py +40 -0
- imap_processing/glows/__init__.py +1 -0
- imap_processing/glows/ancillary/l1b_conversion_table_v001.json +42 -0
- imap_processing/glows/l0/__init__.py +0 -0
- imap_processing/glows/l0/decom_glows.py +91 -0
- imap_processing/glows/l0/glows_l0_data.py +194 -0
- imap_processing/glows/l1a/glows_l1a.py +424 -0
- imap_processing/glows/l1a/glows_l1a_data.py +555 -0
- imap_processing/glows/l1b/glows_l1b.py +270 -0
- imap_processing/glows/l1b/glows_l1b_data.py +583 -0
- imap_processing/glows/packet_definitions/GLX_COMBINED.xml +254 -0
- imap_processing/glows/packet_definitions/P_GLX_TMSCDE.xml +97 -0
- imap_processing/glows/packet_definitions/P_GLX_TMSCHIST.xml +215 -0
- imap_processing/glows/utils/__init__.py +0 -0
- imap_processing/glows/utils/constants.py +105 -0
- imap_processing/hi/__init__.py +1 -0
- imap_processing/hi/l0/__init__.py +0 -0
- imap_processing/hi/l0/decom_hi.py +24 -0
- imap_processing/hi/l1a/__init__.py +0 -0
- imap_processing/hi/l1a/hi_l1a.py +73 -0
- imap_processing/hi/l1a/histogram.py +142 -0
- imap_processing/hi/l1a/housekeeping.py +27 -0
- imap_processing/hi/l1a/science_direct_event.py +341 -0
- imap_processing/hi/l1b/__init__.py +0 -0
- imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +154 -0
- imap_processing/hi/l1b/hi_l1b.py +127 -0
- imap_processing/hi/l1c/__init__.py +0 -0
- imap_processing/hi/l1c/hi_l1c.py +228 -0
- imap_processing/hi/packet_definitions/__init__.py +0 -0
- imap_processing/hi/packet_definitions/hi_packet_definition.xml +482 -0
- imap_processing/hi/utils.py +27 -0
- imap_processing/hit/__init__.py +1 -0
- imap_processing/hit/l0/__init__.py +0 -0
- imap_processing/hit/l0/data_classes/housekeeping.py +240 -0
- imap_processing/hit/l0/data_classes/science_packet.py +259 -0
- imap_processing/hit/l0/decom_hit.py +467 -0
- imap_processing/hit/l0/utils/hit_base.py +57 -0
- imap_processing/hit/l1a/__init__.py +0 -0
- imap_processing/hit/l1a/hit_l1a.py +254 -0
- imap_processing/hit/l1b/hit_l1b.py +179 -0
- imap_processing/hit/packet_definitions/hit_packet_definitions.xml +1276 -0
- imap_processing/ialirt/__init__.py +0 -0
- imap_processing/ialirt/l0/__init__.py +0 -0
- imap_processing/ialirt/l0/process_hit.py +220 -0
- imap_processing/ialirt/packet_definitions/__init__.py +0 -0
- imap_processing/ialirt/packet_definitions/ialirt.xml +778 -0
- imap_processing/ialirt/packet_definitions/ialirt_hit.xml +186 -0
- imap_processing/idex/__init__.py +2 -0
- imap_processing/idex/idex_constants.py +27 -0
- imap_processing/idex/idex_l0.py +31 -0
- imap_processing/idex/idex_l1a.py +631 -0
- imap_processing/idex/packet_definitions/idex_packet_definition.xml +3162 -0
- imap_processing/lo/__init__.py +1 -0
- imap_processing/lo/l0/__init__.py +0 -0
- imap_processing/lo/l0/data_classes/science_direct_events.py +215 -0
- imap_processing/lo/l0/data_classes/star_sensor.py +98 -0
- imap_processing/lo/l0/decompression_tables/12_to_16_bit.csv +4097 -0
- imap_processing/lo/l0/decompression_tables/8_to_12_bit.csv +257 -0
- imap_processing/lo/l0/decompression_tables/8_to_16_bit.csv +257 -0
- imap_processing/lo/l0/decompression_tables/decompression_tables.py +75 -0
- imap_processing/lo/l0/lo_apid.py +15 -0
- imap_processing/lo/l0/lo_science.py +150 -0
- imap_processing/lo/l0/utils/binary_string.py +59 -0
- imap_processing/lo/l0/utils/bit_decompression.py +62 -0
- imap_processing/lo/l0/utils/lo_base.py +57 -0
- imap_processing/lo/l1a/__init__.py +0 -0
- imap_processing/lo/l1a/lo_l1a.py +157 -0
- imap_processing/lo/l1b/lo_l1b.py +160 -0
- imap_processing/lo/l1c/lo_l1c.py +180 -0
- imap_processing/lo/packet_definitions/lo_xtce.xml +3541 -0
- imap_processing/mag/__init__.py +2 -0
- imap_processing/mag/constants.py +108 -0
- imap_processing/mag/l0/decom_mag.py +170 -0
- imap_processing/mag/l0/mag_l0_data.py +118 -0
- imap_processing/mag/l1a/mag_l1a.py +317 -0
- imap_processing/mag/l1a/mag_l1a_data.py +1007 -0
- imap_processing/mag/l1b/__init__.py +0 -0
- imap_processing/mag/l1b/imap_calibration_mag_20240229_v01.cdf +0 -0
- imap_processing/mag/l1b/mag_l1b.py +125 -0
- imap_processing/mag/l1c/mag_l1c.py +57 -0
- imap_processing/mag/packet_definitions/MAG_SCI_COMBINED.xml +235 -0
- imap_processing/quality_flags.py +91 -0
- imap_processing/spice/__init__.py +1 -0
- imap_processing/spice/geometry.py +322 -0
- imap_processing/spice/kernels.py +459 -0
- imap_processing/spice/time.py +72 -0
- imap_processing/swapi/__init__.py +1 -0
- imap_processing/swapi/l1/__init__.py +0 -0
- imap_processing/swapi/l1/swapi_l1.py +685 -0
- imap_processing/swapi/l2/__init__.py +0 -0
- imap_processing/swapi/l2/swapi_l2.py +107 -0
- imap_processing/swapi/packet_definitions/__init__.py +0 -0
- imap_processing/swapi/packet_definitions/swapi_packet_definition.xml +708 -0
- imap_processing/swapi/swapi_utils.py +25 -0
- imap_processing/swe/__init__.py +1 -0
- imap_processing/swe/l1a/__init__.py +0 -0
- imap_processing/swe/l1a/swe_l1a.py +48 -0
- imap_processing/swe/l1a/swe_science.py +223 -0
- imap_processing/swe/l1b/engineering_unit_convert_table.csv +65 -0
- imap_processing/swe/l1b/swe_esa_lookup_table.csv +1441 -0
- imap_processing/swe/l1b/swe_l1b.py +49 -0
- imap_processing/swe/l1b/swe_l1b_science.py +557 -0
- imap_processing/swe/packet_definitions/__init__.py +0 -0
- imap_processing/swe/packet_definitions/swe_packet_definition.xml +303 -0
- imap_processing/swe/utils/__init__.py +0 -0
- imap_processing/swe/utils/swe_utils.py +9 -0
- imap_processing/tests/__init__.py +0 -0
- imap_processing/tests/ccsds/test_data/expected_output.xml +171 -0
- imap_processing/tests/ccsds/test_excel_to_xtce.py +285 -0
- imap_processing/tests/cdf/__init__.py +0 -0
- imap_processing/tests/cdf/imap_default_global_cdf_attrs.yaml +8 -0
- imap_processing/tests/cdf/shared/default_global_cdf_attrs_schema.yaml +246 -0
- imap_processing/tests/cdf/shared/default_variable_cdf_attrs_schema.yaml +466 -0
- imap_processing/tests/cdf/test_cdf_attribute_manager.py +353 -0
- imap_processing/tests/cdf/test_data/imap_default_global_test_cdf_attrs.yaml +7 -0
- imap_processing/tests/cdf/test_data/imap_instrument1_global_cdf_attrs.yaml +14 -0
- imap_processing/tests/cdf/test_data/imap_instrument1_level1_variable_attrs.yaml +23 -0
- imap_processing/tests/cdf/test_data/imap_instrument2_global_cdf_attrs.yaml +23 -0
- imap_processing/tests/cdf/test_data/imap_instrument2_level2_variable_attrs.yaml +30 -0
- imap_processing/tests/cdf/test_data/imap_test_global.yaml +26 -0
- imap_processing/tests/cdf/test_data/imap_test_variable.yaml +41 -0
- imap_processing/tests/cdf/test_imap_cdf_manager.py +62 -0
- imap_processing/tests/cdf/test_utils.py +109 -0
- imap_processing/tests/codice/__init__.py +0 -0
- imap_processing/tests/codice/conftest.py +56 -0
- imap_processing/tests/codice/data/eu_unit_lookup_table.csv +101 -0
- imap_processing/tests/codice/data/idle_export_eu.COD_NHK_20230822_122700 2.csv +100 -0
- imap_processing/tests/codice/data/idle_export_raw.COD_NHK_20230822_122700.csv +100 -0
- 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/codice/data/imap_codice_l1a_hi-counters-aggregated_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-singles_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_hi-omni_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_hi-sectored_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_hskp_20100101_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-aggregated_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-singles_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-angular_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-priority_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-species_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-angular_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-priority_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-species_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-aggregated_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-singles_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_hi-omni_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_hi-sectored_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_hskp_20100101_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-aggregated_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-singles_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-angular_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-priority_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-species_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-angular_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-priority_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-species_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/test_codice_l0.py +144 -0
- imap_processing/tests/codice/test_codice_l1a.py +187 -0
- imap_processing/tests/codice/test_codice_l1b.py +60 -0
- imap_processing/tests/codice/test_decompress.py +50 -0
- imap_processing/tests/conftest.py +372 -0
- imap_processing/tests/glows/direct_events_validation_data_l1a.csv +5704 -0
- imap_processing/tests/glows/glows_test_packet_20110921_v01.pkts +0 -0
- imap_processing/tests/glows/test_glows_decom.py +133 -0
- imap_processing/tests/glows/test_glows_l1a_cdf.py +85 -0
- imap_processing/tests/glows/test_glows_l1a_data.py +510 -0
- imap_processing/tests/glows/test_glows_l1b.py +348 -0
- imap_processing/tests/glows/test_glows_l1b_data.py +70 -0
- imap_processing/tests/hi/__init__.py +0 -0
- imap_processing/tests/hi/conftest.py +133 -0
- imap_processing/tests/hi/test_data/l0/20231030_H45_APP_NHK.bin +0 -0
- imap_processing/tests/hi/test_data/l0/20231030_H45_APP_NHK.csv +201 -0
- imap_processing/tests/hi/test_data/l0/20231030_H45_SCI_CNT.bin +0 -0
- imap_processing/tests/hi/test_data/l0/20231030_H45_SCI_DE.bin +0 -0
- imap_processing/tests/hi/test_data/l0/README.txt +54 -0
- imap_processing/tests/hi/test_decom.py +55 -0
- imap_processing/tests/hi/test_hi_l1b.py +31 -0
- imap_processing/tests/hi/test_hi_l1c.py +69 -0
- imap_processing/tests/hi/test_l1a.py +96 -0
- imap_processing/tests/hi/test_l1a_sci_de.py +72 -0
- imap_processing/tests/hi/test_utils.py +15 -0
- imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1251.pkts +0 -0
- imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1252.pkts +0 -0
- imap_processing/tests/hit/__init__.py +0 -0
- imap_processing/tests/hit/test_data/imap_hit_l0_hk_20100105_v001.pkts +0 -0
- imap_processing/tests/hit/test_data/sci_sample.ccsds +0 -0
- imap_processing/tests/hit/test_hit_decom.py +230 -0
- imap_processing/tests/hit/test_hit_l1a.py +224 -0
- imap_processing/tests/hit/test_hit_l1b.py +52 -0
- imap_processing/tests/hit/validation_data/hskp_sample_raw.csv +88 -0
- imap_processing/tests/ialirt/__init__.py +0 -0
- imap_processing/tests/ialirt/test_data/l0/IALiRT Raw Packet Telemetry.txt +33 -0
- imap_processing/tests/ialirt/test_data/l0/hit_ialirt_sample.ccsds +0 -0
- imap_processing/tests/ialirt/test_data/l0/hit_ialirt_sample.csv +1001 -0
- imap_processing/tests/ialirt/unit/__init__.py +0 -0
- imap_processing/tests/ialirt/unit/test_decom_ialirt.py +94 -0
- imap_processing/tests/ialirt/unit/test_process_hit.py +226 -0
- imap_processing/tests/idex/__init__.py +0 -0
- imap_processing/tests/idex/conftest.py +22 -0
- imap_processing/tests/idex/imap_idex_l0_raw_20230725_v001.pkts +0 -0
- imap_processing/tests/idex/impact_14_tof_high_data.txt +8189 -0
- imap_processing/tests/idex/test_idex_l0.py +45 -0
- imap_processing/tests/idex/test_idex_l1a.py +91 -0
- imap_processing/tests/lo/__init__.py +0 -0
- imap_processing/tests/lo/test_binary_string.py +21 -0
- imap_processing/tests/lo/test_bit_decompression.py +39 -0
- imap_processing/tests/lo/test_cdfs/imap_lo_l0_raw_20240627_v001.pkts +0 -0
- imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20100101_v001.cdf +0 -0
- imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20100101_v001.cdf +0 -0
- imap_processing/tests/lo/test_cdfs/imap_lo_l1b_de_20100101_v001.cdf +0 -0
- imap_processing/tests/lo/test_lo_l1a.py +66 -0
- imap_processing/tests/lo/test_lo_l1b.py +74 -0
- imap_processing/tests/lo/test_lo_l1c.py +66 -0
- imap_processing/tests/lo/test_science_counts.py +41 -0
- imap_processing/tests/lo/test_science_direct_events.py +209 -0
- imap_processing/tests/lo/test_star_sensor.py +35 -0
- imap_processing/tests/mag/imap_mag_l1a_burst-magi_20231025_v001.cdf +0 -0
- imap_processing/tests/mag/mag_l0_test_data.pkts +0 -0
- imap_processing/tests/mag/mag_l0_test_output.csv +37 -0
- imap_processing/tests/mag/mag_l1_test_data.pkts +0 -0
- imap_processing/tests/mag/mag_l1a_test_output.csv +97 -0
- imap_processing/tests/mag/test_mag_decom.py +117 -0
- imap_processing/tests/mag/test_mag_l1a.py +856 -0
- imap_processing/tests/mag/test_mag_l1b.py +77 -0
- imap_processing/tests/mag/test_mag_l1c.py +40 -0
- imap_processing/tests/spice/__init__.py +0 -0
- imap_processing/tests/spice/test_data/imap_ena_sim_metakernel.template +4 -0
- imap_processing/tests/spice/test_data/imap_science_0001.tf +171 -0
- imap_processing/tests/spice/test_data/imap_sclk_0000.tsc +156 -0
- imap_processing/tests/spice/test_data/imap_sim_ck_2hr_2secsampling_with_nutation.bc +0 -0
- imap_processing/tests/spice/test_data/imap_simple_metakernel.template +3 -0
- imap_processing/tests/spice/test_data/imap_spk_demo.bsp +0 -0
- imap_processing/tests/spice/test_data/imap_wkcp.tf +1806 -0
- imap_processing/tests/spice/test_data/naif0012.tls +150 -0
- imap_processing/tests/spice/test_data/sim_1yr_imap_attitude.bc +0 -0
- imap_processing/tests/spice/test_data/sim_1yr_imap_pointing_frame.bc +0 -0
- imap_processing/tests/spice/test_geometry.py +214 -0
- imap_processing/tests/spice/test_kernels.py +272 -0
- imap_processing/tests/spice/test_time.py +35 -0
- imap_processing/tests/swapi/__init__.py +0 -0
- imap_processing/tests/swapi/conftest.py +16 -0
- imap_processing/tests/swapi/l0_data/__init__.py +0 -0
- imap_processing/tests/swapi/l0_data/imap_swapi_l0_raw_20231012_v001.pkts +0 -0
- imap_processing/tests/swapi/l0_validation_data/__init__.py +0 -0
- imap_processing/tests/swapi/l0_validation_data/idle_export_eu.SWP_AUT_20231012_125245.csv +124 -0
- imap_processing/tests/swapi/l0_validation_data/idle_export_eu.SWP_HK_20231012_125245.csv +98 -0
- imap_processing/tests/swapi/l0_validation_data/idle_export_eu.SWP_MG_20231012_125245.csv +9 -0
- imap_processing/tests/swapi/l0_validation_data/idle_export_eu.SWP_SCI_20231012_125245.csv +72 -0
- imap_processing/tests/swapi/l0_validation_data/idle_export_raw.SWP_AUT_20231012_125245.csv +124 -0
- imap_processing/tests/swapi/l0_validation_data/idle_export_raw.SWP_HK_20231012_125245.csv +98 -0
- imap_processing/tests/swapi/l0_validation_data/idle_export_raw.SWP_MG_20231012_125245.csv +9 -0
- imap_processing/tests/swapi/l0_validation_data/idle_export_raw.SWP_SCI_20231012_125245.csv +72 -0
- imap_processing/tests/swapi/test_swapi_decom.py +135 -0
- imap_processing/tests/swapi/test_swapi_l1.py +354 -0
- imap_processing/tests/swapi/test_swapi_l2.py +21 -0
- imap_processing/tests/swe/__init__.py +0 -0
- imap_processing/tests/swe/conftest.py +35 -0
- imap_processing/tests/swe/decompressed/20230927173238_4th_quarter_decompressed.csv +181 -0
- imap_processing/tests/swe/decompressed/20230927173253_1st_quarter_decompressed.csv +181 -0
- imap_processing/tests/swe/decompressed/20230927173308_2nd_quarter_decompressed.csv +181 -0
- imap_processing/tests/swe/decompressed/20230927173323_3rd_quarter_decompressed.csv +181 -0
- imap_processing/tests/swe/l0_data/2024051010_SWE_SCIENCE_packet.bin +0 -0
- imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_SCIENCE_20240510_092742.csv +544 -0
- imap_processing/tests/swe/l0_validation_data/idle_export_raw.SWE_SCIENCE_20240510_092742.csv +363 -0
- imap_processing/tests/swe/test_swe_l1a.py +12 -0
- imap_processing/tests/swe/test_swe_l1a_science.py +129 -0
- imap_processing/tests/swe/test_swe_l1b.py +61 -0
- imap_processing/tests/swe/test_swe_l1b_science.py +65 -0
- imap_processing/tests/test_cli.py +229 -0
- imap_processing/tests/test_decom.py +66 -0
- imap_processing/tests/test_quality_flags.py +71 -0
- imap_processing/tests/test_utils.py +107 -0
- imap_processing/tests/ultra/__init__.py +0 -0
- imap_processing/tests/ultra/test_data/l0/FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00_20240207T102740.CCSDS +0 -0
- imap_processing/tests/ultra/test_data/l0/FM45_7P_Phi0.0_BeamCal_LinearScan_phi0.04_theta-0.01_20230821T121304.CCSDS +0 -0
- imap_processing/tests/ultra/test_data/l0/FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.CCSDS +0 -0
- imap_processing/tests/ultra/test_data/l0/Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.CCSDS +0 -0
- imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_auxdata_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +24 -0
- imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_enaphxtofhangimg_FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.csv +105 -0
- imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultraimgrates_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +24 -0
- imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3314 -0
- imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultrarawimgevent_FM45_7P_Phi00_BeamCal_LinearScan_phi004_theta-001_20230821T121304.csv +702 -0
- imap_processing/tests/ultra/unit/__init__.py +0 -0
- imap_processing/tests/ultra/unit/conftest.py +210 -0
- imap_processing/tests/ultra/unit/test_decom_apid_880.py +98 -0
- imap_processing/tests/ultra/unit/test_decom_apid_881.py +50 -0
- imap_processing/tests/ultra/unit/test_decom_apid_883.py +44 -0
- imap_processing/tests/ultra/unit/test_decom_apid_896.py +104 -0
- imap_processing/tests/ultra/unit/test_lookup_utils.py +68 -0
- imap_processing/tests/ultra/unit/test_ultra_l1a.py +338 -0
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +122 -0
- imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +57 -0
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +342 -0
- imap_processing/tests/ultra/unit/test_ultra_l1c.py +104 -0
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +35 -0
- imap_processing/ultra/__init__.py +1 -0
- imap_processing/ultra/constants.py +60 -0
- imap_processing/ultra/l0/__init__.py +0 -0
- imap_processing/ultra/l0/decom_tools.py +281 -0
- imap_processing/ultra/l0/decom_ultra.py +278 -0
- imap_processing/ultra/l0/ultra_utils.py +326 -0
- imap_processing/ultra/l1a/__init__.py +0 -0
- imap_processing/ultra/l1a/ultra_l1a.py +319 -0
- imap_processing/ultra/l1b/badtimes.py +26 -0
- imap_processing/ultra/l1b/cullingmask.py +26 -0
- imap_processing/ultra/l1b/de.py +59 -0
- imap_processing/ultra/l1b/extendedspin.py +45 -0
- imap_processing/ultra/l1b/lookup_utils.py +165 -0
- imap_processing/ultra/l1b/ultra_l1b.py +65 -0
- imap_processing/ultra/l1b/ultra_l1b_annotated.py +54 -0
- imap_processing/ultra/l1b/ultra_l1b_extended.py +764 -0
- imap_processing/ultra/l1c/histogram.py +36 -0
- imap_processing/ultra/l1c/pset.py +36 -0
- imap_processing/ultra/l1c/ultra_l1c.py +52 -0
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +54 -0
- imap_processing/ultra/lookup_tables/EgyNorm.mem.csv +32769 -0
- imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
- imap_processing/ultra/lookup_tables/ultra45_back-pos-luts.csv +4097 -0
- imap_processing/ultra/lookup_tables/ultra45_tdc_norm.csv +2050 -0
- imap_processing/ultra/lookup_tables/ultra90_back-pos-luts.csv +4097 -0
- imap_processing/ultra/lookup_tables/ultra90_tdc_norm.csv +2050 -0
- imap_processing/ultra/lookup_tables/yadjust.csv +257 -0
- imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +547 -0
- imap_processing/ultra/packet_definitions/__init__.py +0 -0
- imap_processing/ultra/utils/__init__.py +0 -0
- imap_processing/ultra/utils/ultra_l1_utils.py +50 -0
- imap_processing/utils.py +413 -0
- imap_processing-0.6.0.dist-info/LICENSE +21 -0
- imap_processing-0.6.0.dist-info/METADATA +107 -0
- imap_processing-0.6.0.dist-info/RECORD +398 -0
- imap_processing-0.6.0.dist-info/WHEEL +4 -0
- imap_processing-0.6.0.dist-info/entry_points.txt +4 -0
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
"""Data classes to support GLOWS L1A processing."""
|
|
2
|
+
|
|
3
|
+
import struct
|
|
4
|
+
from dataclasses import InitVar, dataclass, field
|
|
5
|
+
|
|
6
|
+
from imap_processing.glows import __version__
|
|
7
|
+
from imap_processing.glows.l0.glows_l0_data import DirectEventL0, HistogramL0
|
|
8
|
+
from imap_processing.glows.utils.constants import DirectEvent, TimeTuple
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class StatusData:
|
|
13
|
+
"""
|
|
14
|
+
Data structure for GLOWS status data, also known as "data_every_second".
|
|
15
|
+
|
|
16
|
+
This is used to generate the housekeeping info for each direct event from the
|
|
17
|
+
compressed structure in the first 40 bytes of each direct event data field.
|
|
18
|
+
|
|
19
|
+
Each DirectEventL1A instance covers one second of direct events data. Each second
|
|
20
|
+
has metadata associated with it, which is described in this class. The first 40
|
|
21
|
+
bytes of each direct event grouping is used to create this class. A second of
|
|
22
|
+
direct events data may span multiple packets, but each second only has one set of
|
|
23
|
+
StatusData attributes.
|
|
24
|
+
|
|
25
|
+
Attributes must match byte_attribute_mapping in generate_status_data.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
general_data_subset : bytearray
|
|
30
|
+
40 bytes containing the information for general data (data_every_second).
|
|
31
|
+
|
|
32
|
+
Attributes
|
|
33
|
+
----------
|
|
34
|
+
imap_sclk_last_pps: int
|
|
35
|
+
IMAP seconds for last PPS
|
|
36
|
+
glows_sclk_last_pps: int
|
|
37
|
+
GLOWS seconds for last PPS
|
|
38
|
+
glows_ssclk_last_pps: int
|
|
39
|
+
GLOWS subseconds for last PPS
|
|
40
|
+
imap_sclk_next_pps: int
|
|
41
|
+
IMAP seconds for next PPS
|
|
42
|
+
catbed_heater_active: int
|
|
43
|
+
Flag - heater active
|
|
44
|
+
spin_period_valid: int
|
|
45
|
+
Flag - spin phase valid
|
|
46
|
+
spin_phase_at_next_pps_valid: int
|
|
47
|
+
Flag - spin phase at next PPS valid
|
|
48
|
+
spin_period_source: int
|
|
49
|
+
Flag - Spin period source
|
|
50
|
+
spin_period: int
|
|
51
|
+
Uint encoded spin period value
|
|
52
|
+
spin_phase_at_next_pps: int
|
|
53
|
+
Uint encoded next spin phase value
|
|
54
|
+
number_of_completed_spins: int
|
|
55
|
+
Number of spins, from onboard
|
|
56
|
+
filter_temperature: int
|
|
57
|
+
Uint encoded temperature
|
|
58
|
+
hv_voltage: int
|
|
59
|
+
Uint encoded voltage
|
|
60
|
+
glows_time_on_pps_valid: int
|
|
61
|
+
Flag - is glows time valid
|
|
62
|
+
time_status_valid: int
|
|
63
|
+
Flag - valid time status
|
|
64
|
+
housekeeping_valid: int
|
|
65
|
+
Flag - valid housekeeping
|
|
66
|
+
is_pps_autogenerated: int
|
|
67
|
+
Flag
|
|
68
|
+
hv_test_in_progress: int
|
|
69
|
+
Flag
|
|
70
|
+
pulse_test_in_progress: int
|
|
71
|
+
Flag
|
|
72
|
+
memory_error_detected: int
|
|
73
|
+
Flag
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
imap_sclk_last_pps: int
|
|
77
|
+
glows_sclk_last_pps: int
|
|
78
|
+
glows_ssclk_last_pps: int
|
|
79
|
+
imap_sclk_next_pps: int
|
|
80
|
+
catbed_heater_active: int
|
|
81
|
+
spin_period_valid: int
|
|
82
|
+
spin_phase_at_next_pps_valid: int
|
|
83
|
+
spin_period_source: int
|
|
84
|
+
spin_period: int
|
|
85
|
+
spin_phase_at_next_pps: int
|
|
86
|
+
number_of_completed_spins: int
|
|
87
|
+
filter_temperature: int
|
|
88
|
+
hv_voltage: int
|
|
89
|
+
glows_time_on_pps_valid: int
|
|
90
|
+
time_status_valid: int
|
|
91
|
+
housekeeping_valid: int
|
|
92
|
+
is_pps_autogenerated: int
|
|
93
|
+
hv_test_in_progress: int
|
|
94
|
+
pulse_test_in_progress: int
|
|
95
|
+
memory_error_detected: int
|
|
96
|
+
|
|
97
|
+
def __init__(self, general_data_subset: bytearray):
|
|
98
|
+
"""
|
|
99
|
+
Generate the flag and encoded information from 40 bytes of direct event data.
|
|
100
|
+
|
|
101
|
+
The 40 bytes also includes one extra byte of padding at the end.
|
|
102
|
+
"""
|
|
103
|
+
byte_attribute_mapping = {
|
|
104
|
+
"imap_sclk_last_pps": 4,
|
|
105
|
+
"glows_sclk_last_pps": 4,
|
|
106
|
+
"glows_ssclk_last_pps": 4,
|
|
107
|
+
"imap_sclk_next_pps": 4,
|
|
108
|
+
"catbed_heater_active": 1,
|
|
109
|
+
"spin_period_valid": 1,
|
|
110
|
+
"spin_phase_at_next_pps_valid": 1,
|
|
111
|
+
"spin_period_source": 1,
|
|
112
|
+
"spin_period": 2,
|
|
113
|
+
"spin_phase_at_next_pps": 2,
|
|
114
|
+
"number_of_completed_spins": 4,
|
|
115
|
+
"filter_temperature": 2,
|
|
116
|
+
"hv_voltage": 2,
|
|
117
|
+
"glows_time_on_pps_valid": 1,
|
|
118
|
+
"time_status_valid": 1,
|
|
119
|
+
"housekeeping_valid": 1,
|
|
120
|
+
"is_pps_autogenerated": 1,
|
|
121
|
+
"hv_test_in_progress": 1,
|
|
122
|
+
"pulse_test_in_progress": 1,
|
|
123
|
+
"memory_error_detected": 1,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
prev_byte = 0
|
|
127
|
+
|
|
128
|
+
for item in byte_attribute_mapping.items():
|
|
129
|
+
self.__setattr__(
|
|
130
|
+
item[0],
|
|
131
|
+
int.from_bytes(
|
|
132
|
+
general_data_subset[prev_byte : prev_byte + item[1]], "big"
|
|
133
|
+
),
|
|
134
|
+
)
|
|
135
|
+
prev_byte = prev_byte + item[1]
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@dataclass
|
|
139
|
+
class HistogramL1A:
|
|
140
|
+
"""
|
|
141
|
+
Data structure for GLOWS Histogram Level 1A data.
|
|
142
|
+
|
|
143
|
+
Attributes
|
|
144
|
+
----------
|
|
145
|
+
l0: InitVar[HistogramL0]
|
|
146
|
+
HistogramL0 Data class containing the raw data from the histogram packet. This
|
|
147
|
+
is only used to create the class and cannot be accessed from an instance.
|
|
148
|
+
histograms: list[int]
|
|
149
|
+
List of histogram data values
|
|
150
|
+
flight_software_version: int
|
|
151
|
+
Version of the flight software used to generate the data. Part of block header.
|
|
152
|
+
ground_software_version: str
|
|
153
|
+
Version of the ground software used to process the data. Part of block header.
|
|
154
|
+
pkts_file_name: str
|
|
155
|
+
Name of the packet file used to generate the data. Part of block header.
|
|
156
|
+
seq_count_in_pkts_file: int
|
|
157
|
+
Sequence count in the packet file, equal to SRC_SEQ_CTR Part of block header.
|
|
158
|
+
last_spin_id: int
|
|
159
|
+
ID of the last spin in block (computed with start spin and offset)
|
|
160
|
+
imap_start_time: tuple[int, int]
|
|
161
|
+
IMAP start time for the block, in the form (seconds, subseconds)
|
|
162
|
+
imap_time_offset: tuple[int, int]
|
|
163
|
+
IMAP end time offset for the block, in the form (seconds, subseconds). In
|
|
164
|
+
algorithm document as "imap_end_time_offset"
|
|
165
|
+
glows_start_time: tuple[int, int]
|
|
166
|
+
GLOWS start time for the block, in the form (seconds, subseconds)
|
|
167
|
+
glows_time_offset: tuple[int, int]
|
|
168
|
+
GLOWS end time offset for the block, in the form (seconds, subseconds). In
|
|
169
|
+
algorithm document as "glows_end_time_offset"
|
|
170
|
+
number_of_spins_per_block: int
|
|
171
|
+
Number of spins in the block, from L0.SPINS
|
|
172
|
+
number_of_bins_per_histogram: int
|
|
173
|
+
Number of bins in the histogram, from L0.NBINS
|
|
174
|
+
number_of_events: int
|
|
175
|
+
Number of events in the block, from L0.EVENTS
|
|
176
|
+
filter_temperature_average: int
|
|
177
|
+
Average filter temperature in the block, from L0.TEMPAVG. Uint encoded.
|
|
178
|
+
filter_temperature_variance: int
|
|
179
|
+
Variance of filter temperature in the block, from L0.TEMPVAR. Uint encoded.
|
|
180
|
+
hv_voltage_average: int
|
|
181
|
+
Average HV voltage in the block, from L0.HVAVG. Uint encoded.
|
|
182
|
+
hv_voltage_variance: int
|
|
183
|
+
Variance of HV voltage in the block, from L0.HVVAR. Uint encoded.
|
|
184
|
+
spin_period_average: int
|
|
185
|
+
Average spin period in the block, from L0.SPAVG. Uint encoded.
|
|
186
|
+
spin_period_variance: int
|
|
187
|
+
Variance of spin period in the block, from L0.SPVAR. Uint encoded.
|
|
188
|
+
pulse_length_average: int
|
|
189
|
+
Average pulse length in the block, from L0.ELAVG. Uint encoded.
|
|
190
|
+
pulse_length_variance: int
|
|
191
|
+
Variance of pulse length in the block, from L0.ELVAR. Uint encoded.
|
|
192
|
+
flags: dict
|
|
193
|
+
Dictionary containing "flags_set_onboard" from L0, and "is_generated_on_ground",
|
|
194
|
+
which is set to "False" for decommed packets.
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
l0: InitVar[HistogramL0]
|
|
198
|
+
histograms: list[int] = field(init=False)
|
|
199
|
+
# next four are in block header
|
|
200
|
+
flight_software_version: int = field(init=False)
|
|
201
|
+
ground_software_version: str = field(init=False)
|
|
202
|
+
pkts_file_name: str = field(init=False)
|
|
203
|
+
seq_count_in_pkts_file: int = field(init=False)
|
|
204
|
+
last_spin_id: int = field(init=False)
|
|
205
|
+
imap_start_time: TimeTuple = field(init=False)
|
|
206
|
+
imap_time_offset: TimeTuple = field(init=False)
|
|
207
|
+
glows_start_time: TimeTuple = field(init=False)
|
|
208
|
+
glows_time_offset: TimeTuple = field(init=False)
|
|
209
|
+
# Following variables are copied from L0
|
|
210
|
+
number_of_spins_per_block: int = field(init=False)
|
|
211
|
+
number_of_bins_per_histogram: int = field(init=False)
|
|
212
|
+
number_of_events: int = field(init=False)
|
|
213
|
+
filter_temperature_average: int = field(init=False)
|
|
214
|
+
filter_temperature_variance: int = field(init=False)
|
|
215
|
+
hv_voltage_average: int = field(init=False)
|
|
216
|
+
hv_voltage_variance: int = field(init=False)
|
|
217
|
+
spin_period_average: int = field(init=False)
|
|
218
|
+
spin_period_variance: int = field(init=False)
|
|
219
|
+
pulse_length_average: int = field(init=False)
|
|
220
|
+
pulse_length_variance: int = field(init=False)
|
|
221
|
+
flags: dict = field(init=False)
|
|
222
|
+
|
|
223
|
+
def __post_init__(self, l0: HistogramL0) -> None:
|
|
224
|
+
"""
|
|
225
|
+
Set the attributes based on the given L0 histogram data.
|
|
226
|
+
|
|
227
|
+
This includes generating a block header and converting the time attributes from
|
|
228
|
+
HistogramL0 into TimeTuple pairs.
|
|
229
|
+
|
|
230
|
+
Parameters
|
|
231
|
+
----------
|
|
232
|
+
l0 : HistogramL0
|
|
233
|
+
Lo histogram data.
|
|
234
|
+
"""
|
|
235
|
+
self.histograms = list(l0.HISTOGRAM_DATA)
|
|
236
|
+
|
|
237
|
+
self.flight_software_version = l0.SWVER
|
|
238
|
+
self.ground_software_version = __version__
|
|
239
|
+
self.pkts_file_name = l0.packet_file_name
|
|
240
|
+
# note: packet number is seq_count (per apid!) field in CCSDS header
|
|
241
|
+
self.seq_count_in_pkts_file = l0.ccsds_header.SRC_SEQ_CTR
|
|
242
|
+
|
|
243
|
+
# use start ID and offset to calculate the last spin ID in the block
|
|
244
|
+
self.last_spin_id = l0.STARTID + l0.ENDID
|
|
245
|
+
# TODO add first spin ID
|
|
246
|
+
|
|
247
|
+
# TODO: This sanity check should probably exist in the final code. However,
|
|
248
|
+
# the emulator code does not properly set these values.
|
|
249
|
+
# if self.l0.ENDID != self.l0.SPINS:
|
|
250
|
+
# raise ValueError(f"Inconsistency between L0 spin-numbering field ENDID "
|
|
251
|
+
# f"[{self.l0.ENDID}] and histogram parameter field SPINS "
|
|
252
|
+
# f"[{self.l0.SPINS}]")
|
|
253
|
+
|
|
254
|
+
# Create time tuples based on second and subsecond pairs
|
|
255
|
+
self.imap_start_time = TimeTuple(l0.SEC, l0.SUBSEC)
|
|
256
|
+
self.imap_time_offset = TimeTuple(l0.OFFSETSEC, l0.OFFSETSUBSEC)
|
|
257
|
+
self.glows_start_time = TimeTuple(l0.GLXSEC, l0.GLXSUBSEC)
|
|
258
|
+
self.glows_time_offset = TimeTuple(l0.GLXOFFSEC, l0.GLXOFFSUBSEC)
|
|
259
|
+
|
|
260
|
+
# In L1a, these are left as unit encoded values.
|
|
261
|
+
self.number_of_spins_per_block = l0.SPINS
|
|
262
|
+
self.number_of_bins_per_histogram = l0.NBINS
|
|
263
|
+
self.number_of_events = l0.EVENTS
|
|
264
|
+
self.filter_temperature_average = l0.TEMPAVG
|
|
265
|
+
self.filter_temperature_variance = l0.TEMPVAR
|
|
266
|
+
self.hv_voltage_average = l0.HVAVG
|
|
267
|
+
self.hv_voltage_variance = l0.HVVAR
|
|
268
|
+
self.spin_period_average = l0.SPAVG
|
|
269
|
+
self.spin_period_variance = l0.SPVAR
|
|
270
|
+
self.pulse_length_average = l0.ELAVG
|
|
271
|
+
self.pulse_length_variance = l0.ELVAR
|
|
272
|
+
|
|
273
|
+
# Flags
|
|
274
|
+
self.flags = {
|
|
275
|
+
"flags_set_onboard": l0.FLAGS,
|
|
276
|
+
"is_generated_on_ground": False,
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
@dataclass
|
|
281
|
+
class DirectEventL1A:
|
|
282
|
+
"""
|
|
283
|
+
Data structure for GLOWS Histogram Level 1A data.
|
|
284
|
+
|
|
285
|
+
This includes steps for merging multiple Direct Event packets into one class,
|
|
286
|
+
so this class may span multiple packets. This is determined by the SEQ and LEN,
|
|
287
|
+
by each packet having an incremental SEQ until LEN number of packets.
|
|
288
|
+
|
|
289
|
+
Block header information is retrieved from l0:
|
|
290
|
+
{
|
|
291
|
+
"flight_software_version" = l0.ccsds_header.VERSION
|
|
292
|
+
"ground_software_version" = __version__
|
|
293
|
+
"pkts_file_name" = l0.packet_file_name
|
|
294
|
+
"seq_count_in_pkts_file" = l0.ccsds_header.SRC_SEQ_CTR
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
Parameters
|
|
298
|
+
----------
|
|
299
|
+
level0 : DirectEventL0
|
|
300
|
+
Level 0 data.
|
|
301
|
+
|
|
302
|
+
Attributes
|
|
303
|
+
----------
|
|
304
|
+
l0 : DirectEventL0
|
|
305
|
+
Level 0 data. In the case of multiple L0 direct events, this is the first L0
|
|
306
|
+
data class in the sequence. This is used to verify all events in the sequence
|
|
307
|
+
match.
|
|
308
|
+
de_data : bytearray
|
|
309
|
+
Bytearray of raw DirectEvent data, which is converted into direct_events
|
|
310
|
+
most_recent_seq : int
|
|
311
|
+
The most recent sequence added to the L1A dataclass - for counting gaps
|
|
312
|
+
missing_seq : list[int]
|
|
313
|
+
Any missing sequence counts in the data. Should be an empty array in normal
|
|
314
|
+
operation
|
|
315
|
+
status_data : StatusData
|
|
316
|
+
StatusData generated from the first 40 bytes of direct events data. This
|
|
317
|
+
includes information on flags and ancillary housekeeping info from the
|
|
318
|
+
spacecraft.
|
|
319
|
+
direct_events : list[DirectEvent]
|
|
320
|
+
List of DirectEvent objects, which is created when the final level 0 packet in
|
|
321
|
+
the sequence is added to de_data. Defaults to None.
|
|
322
|
+
|
|
323
|
+
Methods
|
|
324
|
+
-------
|
|
325
|
+
append
|
|
326
|
+
Add another Level0 instance.
|
|
327
|
+
"""
|
|
328
|
+
|
|
329
|
+
l0: DirectEventL0
|
|
330
|
+
de_data: bytearray = field(repr=False) # Do not include in prints
|
|
331
|
+
most_recent_seq: int
|
|
332
|
+
missing_seq: list[int]
|
|
333
|
+
status_data: StatusData = field(init=False)
|
|
334
|
+
direct_events: list[DirectEvent] = field(init=False, default=None) # type: ignore[arg-type]
|
|
335
|
+
|
|
336
|
+
def __init__(self, level0: DirectEventL0):
|
|
337
|
+
self.l0 = level0
|
|
338
|
+
self.most_recent_seq = self.l0.SEQ
|
|
339
|
+
self.de_data = bytearray(level0.DE_DATA)
|
|
340
|
+
self.missing_seq = []
|
|
341
|
+
|
|
342
|
+
if level0.LEN == 1:
|
|
343
|
+
self._process_de_data()
|
|
344
|
+
|
|
345
|
+
def append(self, second_l0: DirectEventL0) -> None:
|
|
346
|
+
"""
|
|
347
|
+
Merge an additional direct event packet to this DirectEventL1A class.
|
|
348
|
+
|
|
349
|
+
Direct event data can span multiple packets, as marked by the SEQ and LEN
|
|
350
|
+
attributes. This method will add the next piece of data in the sequence
|
|
351
|
+
to this data class. The two packets are compared with
|
|
352
|
+
DirectEventL0.sequence_match_check. If they don't match, the method throws
|
|
353
|
+
a ValueError.
|
|
354
|
+
|
|
355
|
+
If the sequence is broken, the missing sequence numbers are added to
|
|
356
|
+
missing_seq. Once the last value in the sequence is reached, the data is
|
|
357
|
+
processed from raw bytes to useful information.
|
|
358
|
+
|
|
359
|
+
Parameters
|
|
360
|
+
----------
|
|
361
|
+
second_l0 : DirectEventL0
|
|
362
|
+
Additional L0 packet to add to the DirectEventL1A class.
|
|
363
|
+
"""
|
|
364
|
+
# if SEQ is missing or if the sequence is out of order, do not continue.
|
|
365
|
+
if not second_l0.SEQ or second_l0.SEQ < self.most_recent_seq:
|
|
366
|
+
raise ValueError(
|
|
367
|
+
f"Sequence for direct event L1A is out of order or "
|
|
368
|
+
f"incorrect. Attempted to append sequence counter "
|
|
369
|
+
f"{second_l0.SEQ} after {self.most_recent_seq}."
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
# Track any missing sequence counts
|
|
373
|
+
if second_l0.SEQ != self.most_recent_seq + 1:
|
|
374
|
+
self.missing_seq.extend(range(self.most_recent_seq + 1, second_l0.SEQ))
|
|
375
|
+
|
|
376
|
+
# Determine if new L0 packet matches existing L0 packet
|
|
377
|
+
match = self.l0.within_same_sequence(second_l0)
|
|
378
|
+
|
|
379
|
+
# TODO: Should this raise an error? Log? something else?
|
|
380
|
+
if not match:
|
|
381
|
+
raise ValueError(
|
|
382
|
+
f"While attempting to merge L0 packet {second_l0} "
|
|
383
|
+
f"with {self.l0} mismatched values"
|
|
384
|
+
f"were found. "
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
self.de_data.extend(bytearray(second_l0.DE_DATA))
|
|
388
|
+
|
|
389
|
+
self.most_recent_seq = second_l0.SEQ
|
|
390
|
+
# if this is the last packet in the sequence, process the DE data
|
|
391
|
+
# TODO: What if the last packet never arrives?
|
|
392
|
+
if self.l0.LEN == self.most_recent_seq + 1:
|
|
393
|
+
self._process_de_data()
|
|
394
|
+
|
|
395
|
+
def _process_de_data(self) -> None:
|
|
396
|
+
"""
|
|
397
|
+
Will process direct event bytes.
|
|
398
|
+
|
|
399
|
+
Once the packets are complete, create the status data table from the first 40
|
|
400
|
+
bytes in de_data, and the direct events from the remaining bytes.
|
|
401
|
+
"""
|
|
402
|
+
self.status_data = StatusData(self.de_data[:40])
|
|
403
|
+
self.direct_events = self._generate_direct_events(self.de_data[40:])
|
|
404
|
+
|
|
405
|
+
def _generate_direct_events(self, direct_events: bytearray) -> list[DirectEvent]:
|
|
406
|
+
"""
|
|
407
|
+
Generate the list of direct events from the raw bytearray.
|
|
408
|
+
|
|
409
|
+
First, the starting timestamp is created from the first 8 bytes in the direct
|
|
410
|
+
event array. Then, the remaining events are processed based on a marker in the
|
|
411
|
+
first two bits of each section. If the marker is 0, it is uncompressed, and
|
|
412
|
+
the event is processed from the following 7 bytes. If it is 1, it is compressed
|
|
413
|
+
to two bytes, and if it is 2, the direct event is compressed to 3 bytes.
|
|
414
|
+
|
|
415
|
+
Parameters
|
|
416
|
+
----------
|
|
417
|
+
direct_events : bytearray
|
|
418
|
+
Bytearray containing direct event data.
|
|
419
|
+
|
|
420
|
+
Returns
|
|
421
|
+
-------
|
|
422
|
+
processed_events : list[DirectEvent]
|
|
423
|
+
An array containing DirectEvent objects.
|
|
424
|
+
"""
|
|
425
|
+
# read the first direct event, which is always uncompressed
|
|
426
|
+
current_event = self._build_uncompressed_event(direct_events[:8])
|
|
427
|
+
processed_events = [current_event]
|
|
428
|
+
|
|
429
|
+
i = 8
|
|
430
|
+
while i < len(direct_events) - 1:
|
|
431
|
+
first_byte = int(direct_events[i])
|
|
432
|
+
i += 1
|
|
433
|
+
# Remove first two bits, which are used to mark compression
|
|
434
|
+
oldest_diff = first_byte & 0x3F
|
|
435
|
+
marker = first_byte >> 6
|
|
436
|
+
|
|
437
|
+
if (
|
|
438
|
+
marker == 0x0 and i < len(direct_events) - 7
|
|
439
|
+
): # uncompressed time stamp (8-bytes)
|
|
440
|
+
rest_bytes = direct_events[i : i + 7]
|
|
441
|
+
i += 7
|
|
442
|
+
part = bytearray([oldest_diff])
|
|
443
|
+
part.extend(rest_bytes)
|
|
444
|
+
current_event = self._build_uncompressed_event(part)
|
|
445
|
+
|
|
446
|
+
elif (
|
|
447
|
+
marker == 0x2 and i < len(direct_events) - 1
|
|
448
|
+
): # 2-byte compression of timedelta
|
|
449
|
+
current_event = self._build_compressed_event(
|
|
450
|
+
direct_events[i : i + 2], oldest_diff, current_event.timestamp
|
|
451
|
+
)
|
|
452
|
+
i += 2
|
|
453
|
+
|
|
454
|
+
elif (
|
|
455
|
+
marker == 0x3 and i < len(direct_events) - 2
|
|
456
|
+
): # 3-byte compression of timedelta
|
|
457
|
+
current_event = self._build_compressed_event(
|
|
458
|
+
direct_events[i : i + 3], oldest_diff, current_event.timestamp
|
|
459
|
+
)
|
|
460
|
+
i += 3
|
|
461
|
+
|
|
462
|
+
else: # wrong-marker or hitting-the-buffer-end case
|
|
463
|
+
raise IndexError(
|
|
464
|
+
f"Error: Unexpected marker {marker} or out of bounds index {i} for "
|
|
465
|
+
f"direct events list of length {len(direct_events)}. Unable to "
|
|
466
|
+
f"process direct events."
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
processed_events.append(current_event)
|
|
470
|
+
|
|
471
|
+
return processed_events
|
|
472
|
+
|
|
473
|
+
def _build_compressed_event(
|
|
474
|
+
self, raw: bytearray, oldest_diff: int, previous_time: TimeTuple
|
|
475
|
+
) -> "DirectEvent":
|
|
476
|
+
"""
|
|
477
|
+
Build direct event from data with timestamps compressed as timedeltas.
|
|
478
|
+
|
|
479
|
+
This process requires adding onto a previous timestamp to create a new
|
|
480
|
+
timestamp. If raw is three bytes, the three byte method of compression is used,
|
|
481
|
+
if raw is two bytes, then the two byte method is used. Any other length raises
|
|
482
|
+
a ValueError.
|
|
483
|
+
|
|
484
|
+
Parameters
|
|
485
|
+
----------
|
|
486
|
+
raw : bytearray
|
|
487
|
+
Raw 2 or 3 byte compressed data to process.
|
|
488
|
+
oldest_diff : int
|
|
489
|
+
Last 6 bits of the byte immediately before raw.
|
|
490
|
+
previous_time : TimeTuple
|
|
491
|
+
The previous timestamp to build off of.
|
|
492
|
+
|
|
493
|
+
Returns
|
|
494
|
+
-------
|
|
495
|
+
DirectEvent
|
|
496
|
+
Built by the input data.
|
|
497
|
+
"""
|
|
498
|
+
if len(raw) == 2:
|
|
499
|
+
rest = raw[0]
|
|
500
|
+
|
|
501
|
+
diff = oldest_diff << 8 | rest
|
|
502
|
+
length = raw[1]
|
|
503
|
+
|
|
504
|
+
elif len(raw) == 3:
|
|
505
|
+
rest = int.from_bytes(raw[0:2], "big")
|
|
506
|
+
diff = oldest_diff << 16 | rest
|
|
507
|
+
length = int(raw[2])
|
|
508
|
+
|
|
509
|
+
else:
|
|
510
|
+
raise ValueError(
|
|
511
|
+
f"Incorrect length {len(raw)} for {raw}, expecting 2 or 3"
|
|
512
|
+
f"bit compressed direct event data"
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
subseconds = previous_time.subseconds + diff
|
|
516
|
+
seconds = previous_time.seconds
|
|
517
|
+
|
|
518
|
+
return DirectEvent(TimeTuple(seconds, subseconds), length, False)
|
|
519
|
+
|
|
520
|
+
def _build_uncompressed_event(self, raw: bytearray) -> DirectEvent:
|
|
521
|
+
"""
|
|
522
|
+
Build direct event from raw binary 8-byte array.
|
|
523
|
+
|
|
524
|
+
This method assumes that the raw binary contains uncompressed timestamps.
|
|
525
|
+
|
|
526
|
+
Parameters
|
|
527
|
+
----------
|
|
528
|
+
raw : bytearray
|
|
529
|
+
8 bytes of data to build the event with.
|
|
530
|
+
|
|
531
|
+
Returns
|
|
532
|
+
-------
|
|
533
|
+
DirectEvent
|
|
534
|
+
Object built from raw.
|
|
535
|
+
"""
|
|
536
|
+
if len(raw) != 8:
|
|
537
|
+
raise ValueError(
|
|
538
|
+
f"Incorrect length {len(raw)} for {raw}, expecting 8 bytes of "
|
|
539
|
+
f"uncompressed direct event data"
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
values = struct.unpack(">II", raw)
|
|
543
|
+
|
|
544
|
+
seconds = values[0]
|
|
545
|
+
|
|
546
|
+
# subsecond encoding on the least significant 21 bits
|
|
547
|
+
subseconds = values[1] & 0x1FFFFF
|
|
548
|
+
|
|
549
|
+
timestamp = TimeTuple(seconds, subseconds)
|
|
550
|
+
# first byte encodes the impulse length
|
|
551
|
+
impulse_length = (values[1] >> 24) & 0xFF
|
|
552
|
+
|
|
553
|
+
# KPLabs says it is set by FPGA and currently not used by AppSW at all
|
|
554
|
+
multi_event = bool((values[1] >> 23) & 0b1)
|
|
555
|
+
return DirectEvent(timestamp, impulse_length, multi_event)
|