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,108 @@
|
|
|
1
|
+
"""Collection of constant types or values for MAG."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DataMode(Enum):
|
|
9
|
+
"""
|
|
10
|
+
Enum for MAG data modes: burst and normal (BURST + NORM).
|
|
11
|
+
|
|
12
|
+
Attributes
|
|
13
|
+
----------
|
|
14
|
+
BURST: str
|
|
15
|
+
Burst data mode - higher frequency data
|
|
16
|
+
NORM: str
|
|
17
|
+
Normal data mode - lower frequency data (downsampled from burst)
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
BURST = "BURST"
|
|
21
|
+
NORM = "NORM"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Sensor(Enum):
|
|
25
|
+
"""
|
|
26
|
+
Enum for MAG sensors: raw, MAGo, and MAGi (RAW, MAGO, MAGI).
|
|
27
|
+
|
|
28
|
+
Attributes
|
|
29
|
+
----------
|
|
30
|
+
MAGO : str
|
|
31
|
+
MAGo sensor - for the outboard sensor. This is nominally expected to be the
|
|
32
|
+
primary sensor.
|
|
33
|
+
MAGI : str
|
|
34
|
+
MAGi sensor - for the inboard sensor.
|
|
35
|
+
RAW : str
|
|
36
|
+
RAW data - contains both sensors. Here, the vectors are unprocessed.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
MAGO = "MAGO"
|
|
40
|
+
MAGI = "MAGI"
|
|
41
|
+
RAW = "RAW"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class PrimarySensor(Enum):
|
|
45
|
+
"""
|
|
46
|
+
Enum for primary sensor: MAGo and MAGi (MAGO, MAGI).
|
|
47
|
+
|
|
48
|
+
This corresponds to the PRI_SENS field in the MAG Level 0 data.
|
|
49
|
+
|
|
50
|
+
Attributes
|
|
51
|
+
----------
|
|
52
|
+
MAGO : int
|
|
53
|
+
Primary sensor is MAGo.
|
|
54
|
+
MAGI : int
|
|
55
|
+
Primary sensor is MAGi.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
MAGO = 0
|
|
59
|
+
MAGI = 1
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
FIBONACCI_SEQUENCE = [
|
|
63
|
+
1,
|
|
64
|
+
2,
|
|
65
|
+
3,
|
|
66
|
+
5,
|
|
67
|
+
8,
|
|
68
|
+
13,
|
|
69
|
+
21,
|
|
70
|
+
34,
|
|
71
|
+
55,
|
|
72
|
+
89,
|
|
73
|
+
144,
|
|
74
|
+
233,
|
|
75
|
+
377,
|
|
76
|
+
610,
|
|
77
|
+
987,
|
|
78
|
+
1597,
|
|
79
|
+
2584,
|
|
80
|
+
4181,
|
|
81
|
+
6765,
|
|
82
|
+
10946,
|
|
83
|
+
17711,
|
|
84
|
+
28657,
|
|
85
|
+
46368,
|
|
86
|
+
75025,
|
|
87
|
+
121393,
|
|
88
|
+
196418,
|
|
89
|
+
317811,
|
|
90
|
+
514229,
|
|
91
|
+
832040,
|
|
92
|
+
1346269,
|
|
93
|
+
2178309,
|
|
94
|
+
3524578,
|
|
95
|
+
5702887,
|
|
96
|
+
9227465,
|
|
97
|
+
14930352,
|
|
98
|
+
24157817,
|
|
99
|
+
39088169,
|
|
100
|
+
63245986,
|
|
101
|
+
102334155,
|
|
102
|
+
165580141,
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
MAX_FINE_TIME = np.iinfo(np.uint16).max # maximum 16 bit unsigned int
|
|
106
|
+
AXIS_COUNT = 3
|
|
107
|
+
RANGE_BIT_WIDTH = 2
|
|
108
|
+
MAX_COMPRESSED_VECTOR_BITS = 60
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""Methods for processing raw MAG packets into CDF files for level 0 and level 1a."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import dataclasses
|
|
6
|
+
import logging
|
|
7
|
+
from collections import defaultdict
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
import xarray as xr
|
|
12
|
+
from space_packet_parser import parser, xtcedef
|
|
13
|
+
|
|
14
|
+
from imap_processing import imap_module_directory
|
|
15
|
+
from imap_processing.ccsds.ccsds_data import CcsdsData
|
|
16
|
+
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
17
|
+
from imap_processing.mag.constants import DataMode
|
|
18
|
+
from imap_processing.mag.l0.mag_l0_data import MagL0, Mode
|
|
19
|
+
from imap_processing.spice.time import met_to_j2000ns
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def decom_packets(packet_file_path: str | Path) -> dict[str, list[MagL0]]:
|
|
25
|
+
"""
|
|
26
|
+
Decom MAG data packets using MAG packet definition.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
packet_file_path : str
|
|
31
|
+
Path to data packet path with filename.
|
|
32
|
+
|
|
33
|
+
Returns
|
|
34
|
+
-------
|
|
35
|
+
data_dict : dict[str, list[MagL0]]
|
|
36
|
+
A dict with 2 keys pointing to lists of MAG L0 data classes. "norm" corresponds
|
|
37
|
+
to normal mode packets, "burst" corresponds to burst mode packets.
|
|
38
|
+
"""
|
|
39
|
+
# Define paths
|
|
40
|
+
xtce_document = Path(
|
|
41
|
+
f"{imap_module_directory}/mag/packet_definitions/MAG_SCI_COMBINED.xml"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
packet_definition = xtcedef.XtcePacketDefinition(xtce_document)
|
|
45
|
+
mag_parser = parser.PacketParser(packet_definition)
|
|
46
|
+
|
|
47
|
+
norm_data = []
|
|
48
|
+
burst_data = []
|
|
49
|
+
|
|
50
|
+
with open(packet_file_path, "rb") as binary_data:
|
|
51
|
+
mag_packets = mag_parser.generator(binary_data)
|
|
52
|
+
|
|
53
|
+
for packet in mag_packets:
|
|
54
|
+
apid = packet.header["PKT_APID"].derived_value
|
|
55
|
+
if apid in (Mode.BURST, Mode.NORMAL):
|
|
56
|
+
values = [
|
|
57
|
+
item.derived_value
|
|
58
|
+
if item.derived_value is not None
|
|
59
|
+
else item.raw_value
|
|
60
|
+
for item in packet.data.values()
|
|
61
|
+
]
|
|
62
|
+
if apid == Mode.NORMAL:
|
|
63
|
+
norm_data.append(MagL0(CcsdsData(packet.header), *values))
|
|
64
|
+
else:
|
|
65
|
+
burst_data.append(MagL0(CcsdsData(packet.header), *values))
|
|
66
|
+
|
|
67
|
+
return {"norm": norm_data, "burst": burst_data}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def generate_dataset(
|
|
71
|
+
l0_data: list[MagL0], mode: DataMode, attribute_manager: ImapCdfAttributes
|
|
72
|
+
) -> xr.Dataset:
|
|
73
|
+
"""
|
|
74
|
+
Generate a CDF dataset from the sorted raw L0 MAG data.
|
|
75
|
+
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
l0_data : list[MagL0]
|
|
79
|
+
List of sorted L0 MAG data.
|
|
80
|
+
|
|
81
|
+
mode : DataMode
|
|
82
|
+
The mode of the CDF file - burst or norm.
|
|
83
|
+
|
|
84
|
+
attribute_manager : ImapCdfAttributes
|
|
85
|
+
Attribute manager for the dataset, including all MAG L1A attributes.
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
dataset : xarray.Dataset
|
|
90
|
+
The xarray dataset with proper CDF attributes and shape.
|
|
91
|
+
"""
|
|
92
|
+
# TODO: Correct CDF attributes from email
|
|
93
|
+
|
|
94
|
+
vector_data = np.zeros((len(l0_data), len(l0_data[0].VECTORS)))
|
|
95
|
+
shcoarse_data = np.zeros(len(l0_data), dtype="datetime64[ns]")
|
|
96
|
+
|
|
97
|
+
support_data = defaultdict(list)
|
|
98
|
+
|
|
99
|
+
for index, datapoint in enumerate(l0_data):
|
|
100
|
+
vector_len = len(datapoint.VECTORS)
|
|
101
|
+
if vector_len > vector_data.shape[1]:
|
|
102
|
+
# If the new vector is longer than the existing shape, first reshape
|
|
103
|
+
# vector_data and pad the existing vectors with zeros.
|
|
104
|
+
vector_data = np.pad(
|
|
105
|
+
vector_data,
|
|
106
|
+
(
|
|
107
|
+
(
|
|
108
|
+
0,
|
|
109
|
+
0,
|
|
110
|
+
),
|
|
111
|
+
(0, vector_len - vector_data.shape[1]),
|
|
112
|
+
),
|
|
113
|
+
"constant",
|
|
114
|
+
constant_values=(0,),
|
|
115
|
+
)
|
|
116
|
+
vector_data[index, :vector_len] = datapoint.VECTORS
|
|
117
|
+
|
|
118
|
+
shcoarse_data[index] = met_to_j2000ns(datapoint.SHCOARSE)
|
|
119
|
+
# Add remaining pieces to arrays
|
|
120
|
+
for key, value in dataclasses.asdict(datapoint).items():
|
|
121
|
+
if key not in ("ccsds_header", "VECTORS", "SHCOARSE"):
|
|
122
|
+
support_data[key].append(value)
|
|
123
|
+
if key == "ccsds_header":
|
|
124
|
+
for ccsds_key, ccsds_value in value.items():
|
|
125
|
+
support_data[ccsds_key].append(ccsds_value)
|
|
126
|
+
|
|
127
|
+
# Used in L1A vectors
|
|
128
|
+
direction = xr.DataArray(
|
|
129
|
+
np.arange(vector_data.shape[1]),
|
|
130
|
+
name="direction",
|
|
131
|
+
dims=["direction"],
|
|
132
|
+
attrs=attribute_manager.get_variable_attributes("raw_direction_attrs"),
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# TODO: Epoch here refers to the start of the sample. Confirm that this is
|
|
136
|
+
# what mag is expecting, and if it is, CATDESC needs to be updated.
|
|
137
|
+
epoch_time = xr.DataArray(
|
|
138
|
+
shcoarse_data,
|
|
139
|
+
name="epoch",
|
|
140
|
+
dims=["epoch"],
|
|
141
|
+
attrs=attribute_manager.get_variable_attributes("epoch"),
|
|
142
|
+
)
|
|
143
|
+
# TODO: raw vectors units
|
|
144
|
+
raw_vectors = xr.DataArray(
|
|
145
|
+
vector_data,
|
|
146
|
+
name="raw_vectors",
|
|
147
|
+
dims=["epoch", "direction"],
|
|
148
|
+
attrs=attribute_manager.get_variable_attributes("raw_vector_attrs"),
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
logical_id = f"imap_mag_l1a_{mode.value.lower()}-raw"
|
|
152
|
+
|
|
153
|
+
output = xr.Dataset(
|
|
154
|
+
coords={"epoch": epoch_time, "direction": direction},
|
|
155
|
+
attrs=attribute_manager.get_global_attributes(logical_id),
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
output["raw_vectors"] = raw_vectors
|
|
159
|
+
|
|
160
|
+
for key, value in support_data.items():
|
|
161
|
+
# Time varying values
|
|
162
|
+
if key not in ["SHCOARSE", "VECTORS"]:
|
|
163
|
+
output[key] = xr.DataArray(
|
|
164
|
+
value,
|
|
165
|
+
name=key.lower(),
|
|
166
|
+
dims=["epoch"],
|
|
167
|
+
attrs=attribute_manager.get_variable_attributes(key),
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
return output
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Dataclasses for Level 0 MAG data."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from enum import IntEnum
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from imap_processing.ccsds.ccsds_data import CcsdsData
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Mode(IntEnum):
|
|
14
|
+
"""
|
|
15
|
+
Enum class for MAG mode.
|
|
16
|
+
|
|
17
|
+
Attributes
|
|
18
|
+
----------
|
|
19
|
+
BURST : int
|
|
20
|
+
APID for Burst mode data.
|
|
21
|
+
NORMAL : int
|
|
22
|
+
ApID for Normal mode data.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
BURST = 1068
|
|
26
|
+
NORMAL = 1052
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class MagL0:
|
|
31
|
+
"""
|
|
32
|
+
Data class for MAG Level 0 data.
|
|
33
|
+
|
|
34
|
+
Attributes
|
|
35
|
+
----------
|
|
36
|
+
ccsds_header: CcsdsData
|
|
37
|
+
CCSDS Header data.
|
|
38
|
+
SHCOARSE: int
|
|
39
|
+
Mission elapsed time.
|
|
40
|
+
PUS_SPARE1: int
|
|
41
|
+
ESA standard headers, PUS Spare 1.
|
|
42
|
+
PUS_VERSION: int
|
|
43
|
+
PUS Version Number.
|
|
44
|
+
PUS_SPARE2: int
|
|
45
|
+
PUS Spare 2.
|
|
46
|
+
PUS_STYPE: int
|
|
47
|
+
PUS Service Type.
|
|
48
|
+
PUS_SSUBTYPE: int
|
|
49
|
+
PUS Service Subtype - tells number of seconds of data.
|
|
50
|
+
COMPRESSION: int
|
|
51
|
+
Science Data Compression Flag - indicates if the data compressed - throw error
|
|
52
|
+
if 1.
|
|
53
|
+
MAGO_ACT: int
|
|
54
|
+
MAGO Active Status - if MAGo is active. May also be referred to as "FOB".
|
|
55
|
+
MAGI_ACT: int
|
|
56
|
+
MAGI Active Status - if MAGi is active. May also be referred to as "FIB".
|
|
57
|
+
PRI_SENS: int
|
|
58
|
+
Primary Sensor - 0 is MAGo, 1 is MAGi.
|
|
59
|
+
SPARE1: int
|
|
60
|
+
Spare.
|
|
61
|
+
PRI_VECSEC: int
|
|
62
|
+
Primary Vectors per Second - lookup for L1b.
|
|
63
|
+
SEC_VECSEC: int
|
|
64
|
+
Secondary Vectors per second.
|
|
65
|
+
SPARE2: int
|
|
66
|
+
Spare.
|
|
67
|
+
PRI_COARSETM: int
|
|
68
|
+
Primary Coarse Time for first vector, seconds.
|
|
69
|
+
PRI_FNTM: int
|
|
70
|
+
Primary Fine Time for first vector, subseconds.
|
|
71
|
+
SEC_COARSETM: int
|
|
72
|
+
Secondary Coarse Time for first vector, seconds.
|
|
73
|
+
SEC_FNTM: int
|
|
74
|
+
Secondary Fine Time for first vector, subseconds.
|
|
75
|
+
VECTORS: numpy.ndarray or str
|
|
76
|
+
MAG Science Vectors - divide based on PRI_VECSEC and PUS_SSUBTYPE for vector
|
|
77
|
+
counts. There is a post init call to convert a string into a numpy array -
|
|
78
|
+
the only place it is a string is in the class initialization.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
ccsds_header: CcsdsData
|
|
82
|
+
SHCOARSE: int
|
|
83
|
+
PUS_SPARE1: int
|
|
84
|
+
PUS_VERSION: int
|
|
85
|
+
PUS_SPARE2: int
|
|
86
|
+
PUS_STYPE: int
|
|
87
|
+
PUS_SSUBTYPE: int
|
|
88
|
+
COMPRESSION: int
|
|
89
|
+
MAGO_ACT: int
|
|
90
|
+
MAGI_ACT: int
|
|
91
|
+
PRI_SENS: int
|
|
92
|
+
SPARE1: int
|
|
93
|
+
PRI_VECSEC: int
|
|
94
|
+
SEC_VECSEC: int
|
|
95
|
+
SPARE2: int
|
|
96
|
+
PRI_COARSETM: int
|
|
97
|
+
PRI_FNTM: int
|
|
98
|
+
SEC_COARSETM: int
|
|
99
|
+
SEC_FNTM: int
|
|
100
|
+
VECTORS: np.ndarray | str
|
|
101
|
+
|
|
102
|
+
def __post_init__(self) -> None:
|
|
103
|
+
"""
|
|
104
|
+
Convert Vectors attribute from string to bytearray if needed.
|
|
105
|
+
|
|
106
|
+
Also convert encoded "VECSEC" (vectors per second) into proper vectors per
|
|
107
|
+
second values.
|
|
108
|
+
"""
|
|
109
|
+
if isinstance(self.VECTORS, str):
|
|
110
|
+
# Convert string output from space_packet_parser to numpy array of
|
|
111
|
+
# big-endian bytes
|
|
112
|
+
self.VECTORS = np.frombuffer(
|
|
113
|
+
int(self.VECTORS, 2).to_bytes(len(self.VECTORS) // 8, "big"),
|
|
114
|
+
dtype=np.dtype(">B"),
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
self.PRI_VECSEC = 2**self.PRI_VECSEC
|
|
118
|
+
self.SEC_VECSEC = 2**self.SEC_VECSEC
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"""Methods for decomming packets, processing to level 1A, and writing CDFs for MAG."""
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
import logging
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import xarray as xr
|
|
9
|
+
|
|
10
|
+
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
11
|
+
from imap_processing.cdf.utils import J2000_EPOCH
|
|
12
|
+
from imap_processing.mag.constants import DataMode, PrimarySensor
|
|
13
|
+
from imap_processing.mag.l0 import decom_mag
|
|
14
|
+
from imap_processing.mag.l0.mag_l0_data import MagL0
|
|
15
|
+
from imap_processing.mag.l1a.mag_l1a_data import (
|
|
16
|
+
MagL1a,
|
|
17
|
+
MagL1aPacketProperties,
|
|
18
|
+
TimeTuple,
|
|
19
|
+
)
|
|
20
|
+
from imap_processing.spice.time import met_to_j2000ns
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def mag_l1a(packet_filepath: Path, data_version: str) -> list[xr.Dataset]:
|
|
26
|
+
"""
|
|
27
|
+
Will process MAG L0 data into L1A CDF files at cdf_filepath.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
packet_filepath : pathlib.Path
|
|
32
|
+
Packet files for processing.
|
|
33
|
+
data_version : str
|
|
34
|
+
Data version to write to CDF files.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
generated_files : list[xarray.Dataset]
|
|
39
|
+
A list of generated filenames.
|
|
40
|
+
"""
|
|
41
|
+
packets = decom_mag.decom_packets(packet_filepath)
|
|
42
|
+
|
|
43
|
+
norm_data = packets["norm"]
|
|
44
|
+
burst_data = packets["burst"]
|
|
45
|
+
|
|
46
|
+
input_files = [packet_filepath.name]
|
|
47
|
+
|
|
48
|
+
# Create attribute manager and add MAG L1A attributes and global variables
|
|
49
|
+
attribute_manager = ImapCdfAttributes()
|
|
50
|
+
attribute_manager.add_instrument_global_attrs("mag")
|
|
51
|
+
attribute_manager.add_instrument_variable_attrs("mag", "l1")
|
|
52
|
+
|
|
53
|
+
attribute_manager.add_global_attribute("Data_version", data_version)
|
|
54
|
+
attribute_manager.add_global_attribute("Input_files", str(input_files))
|
|
55
|
+
attribute_manager.add_global_attribute(
|
|
56
|
+
"Generation_date",
|
|
57
|
+
np.datetime64(
|
|
58
|
+
"now",
|
|
59
|
+
).astype(str),
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
generated_datasets = create_l1a(norm_data, DataMode.NORM, attribute_manager)
|
|
63
|
+
generated_datasets += create_l1a(burst_data, DataMode.BURST, attribute_manager)
|
|
64
|
+
|
|
65
|
+
return generated_datasets
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def create_l1a(
|
|
69
|
+
packet_data: list[MagL0], data_mode: DataMode, attribute_manager: ImapCdfAttributes
|
|
70
|
+
) -> list[xr.Dataset]:
|
|
71
|
+
"""
|
|
72
|
+
Will process MAG L0 data into L1A, then create and write out CDF files.
|
|
73
|
+
|
|
74
|
+
Norm and burst mode descriptors are distinguished with the passed in attrs.
|
|
75
|
+
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
packet_data : list[MagL0]
|
|
79
|
+
List of MagL0 packets to process, containing primary and secondary sensor data.
|
|
80
|
+
|
|
81
|
+
data_mode : DataMode
|
|
82
|
+
Enum for distinguishing between norm and burst mode data.
|
|
83
|
+
|
|
84
|
+
attribute_manager : ImapCdfAttributes
|
|
85
|
+
Attribute manager for CDF files for MAG L1A.
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
generated_files : list[xarray.Dataset]
|
|
90
|
+
A list of generated filenames.
|
|
91
|
+
"""
|
|
92
|
+
if not packet_data:
|
|
93
|
+
return []
|
|
94
|
+
|
|
95
|
+
mag_raw = decom_mag.generate_dataset(packet_data, data_mode, attribute_manager)
|
|
96
|
+
|
|
97
|
+
generated_datasets = [mag_raw]
|
|
98
|
+
|
|
99
|
+
l1a = process_packets(packet_data)
|
|
100
|
+
|
|
101
|
+
# TODO: Rearrange generate_dataset to combine these two for loops
|
|
102
|
+
# Split into MAGo and MAGi
|
|
103
|
+
for _, mago in l1a["mago"].items():
|
|
104
|
+
logical_file_id = f"imap_mag_l1a_{data_mode.value.lower()}-mago"
|
|
105
|
+
norm_mago_output = generate_dataset(mago, logical_file_id, attribute_manager)
|
|
106
|
+
generated_datasets.append(norm_mago_output)
|
|
107
|
+
|
|
108
|
+
for _, magi in l1a["magi"].items():
|
|
109
|
+
logical_file_id = f"imap_mag_l1a_{data_mode.value.lower()}-magi"
|
|
110
|
+
norm_magi_output = generate_dataset(
|
|
111
|
+
magi,
|
|
112
|
+
logical_file_id,
|
|
113
|
+
attribute_manager,
|
|
114
|
+
)
|
|
115
|
+
generated_datasets.append(norm_magi_output)
|
|
116
|
+
|
|
117
|
+
return generated_datasets
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def process_packets(
|
|
121
|
+
mag_l0_list: list[MagL0],
|
|
122
|
+
) -> dict[str, dict[np.datetime64, MagL1a]]:
|
|
123
|
+
"""
|
|
124
|
+
Given a list of MagL0 packets, process them into MagO and MagI L1A data classes.
|
|
125
|
+
|
|
126
|
+
This splits the MagL0 packets into MagO and MagI data, returning a dictionary with
|
|
127
|
+
keys "mago" and "magi."
|
|
128
|
+
|
|
129
|
+
Parameters
|
|
130
|
+
----------
|
|
131
|
+
mag_l0_list : list[MagL0]
|
|
132
|
+
List of Mag L0 packets to process.
|
|
133
|
+
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
packet_dict : dict[str, dict[numpy.datetime64, MagL1a]]
|
|
137
|
+
Dictionary containing two keys: "mago" which points to a dictionary of mago
|
|
138
|
+
MagL1A objects, and "magi" which points to a dictionary of magi MagL1A objects.
|
|
139
|
+
Each dictionary has keys of days and values of MagL1A objects, so each day
|
|
140
|
+
corresponds to one MagL1A object.
|
|
141
|
+
"""
|
|
142
|
+
magi = {}
|
|
143
|
+
mago = {}
|
|
144
|
+
|
|
145
|
+
for mag_l0 in mag_l0_list:
|
|
146
|
+
primary_start_time = TimeTuple(mag_l0.PRI_COARSETM, mag_l0.PRI_FNTM)
|
|
147
|
+
secondary_start_time = TimeTuple(mag_l0.SEC_COARSETM, mag_l0.SEC_FNTM)
|
|
148
|
+
|
|
149
|
+
mago_is_primary = mag_l0.PRI_SENS == PrimarySensor.MAGO.value
|
|
150
|
+
|
|
151
|
+
primary_day = (
|
|
152
|
+
J2000_EPOCH
|
|
153
|
+
+ met_to_j2000ns(primary_start_time.to_seconds()).astype("timedelta64[ns]")
|
|
154
|
+
).astype("datetime64[D]")
|
|
155
|
+
secondary_day = (
|
|
156
|
+
J2000_EPOCH
|
|
157
|
+
+ met_to_j2000ns(secondary_start_time.to_seconds()).astype(
|
|
158
|
+
"timedelta64[ns]"
|
|
159
|
+
)
|
|
160
|
+
).astype("datetime64[D]")
|
|
161
|
+
|
|
162
|
+
primary_packet_data = MagL1aPacketProperties(
|
|
163
|
+
mag_l0.SHCOARSE,
|
|
164
|
+
primary_start_time,
|
|
165
|
+
mag_l0.PRI_VECSEC,
|
|
166
|
+
mag_l0.PUS_SSUBTYPE,
|
|
167
|
+
mag_l0.ccsds_header.SRC_SEQ_CTR,
|
|
168
|
+
mag_l0.COMPRESSION,
|
|
169
|
+
mago_is_primary,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
secondary_packet_data = dataclasses.replace(
|
|
173
|
+
primary_packet_data,
|
|
174
|
+
start_time=secondary_start_time,
|
|
175
|
+
vectors_per_second=mag_l0.SEC_VECSEC,
|
|
176
|
+
pus_ssubtype=mag_l0.PUS_SSUBTYPE,
|
|
177
|
+
)
|
|
178
|
+
# now we know the number of secs of data in the packet, and the data rates of
|
|
179
|
+
# each sensor, we can calculate how much data is in this packet and where the
|
|
180
|
+
# byte boundaries are.
|
|
181
|
+
primary_vectors, secondary_vectors = MagL1a.process_vector_data(
|
|
182
|
+
mag_l0.VECTORS, # type: ignore
|
|
183
|
+
primary_packet_data.total_vectors,
|
|
184
|
+
secondary_packet_data.total_vectors,
|
|
185
|
+
mag_l0.COMPRESSION,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
primary_timestamped_vectors = MagL1a.calculate_vector_time(
|
|
189
|
+
primary_vectors,
|
|
190
|
+
primary_packet_data.vectors_per_second,
|
|
191
|
+
primary_packet_data.start_time,
|
|
192
|
+
)
|
|
193
|
+
secondary_timestamped_vectors = MagL1a.calculate_vector_time(
|
|
194
|
+
secondary_vectors,
|
|
195
|
+
secondary_packet_data.vectors_per_second,
|
|
196
|
+
secondary_packet_data.start_time,
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
# Sort primary and secondary into MAGo and MAGi by 24 hour chunks
|
|
200
|
+
mago_day = primary_day if mago_is_primary else secondary_day
|
|
201
|
+
magi_day = primary_day if not mago_is_primary else secondary_day
|
|
202
|
+
|
|
203
|
+
if mago_day not in mago:
|
|
204
|
+
mago[mago_day] = MagL1a(
|
|
205
|
+
True,
|
|
206
|
+
mag_l0.MAGO_ACT,
|
|
207
|
+
mag_l0.SHCOARSE,
|
|
208
|
+
primary_timestamped_vectors
|
|
209
|
+
if mago_is_primary
|
|
210
|
+
else secondary_timestamped_vectors,
|
|
211
|
+
primary_packet_data if mago_is_primary else secondary_packet_data,
|
|
212
|
+
)
|
|
213
|
+
else:
|
|
214
|
+
mago[mago_day].append_vectors(
|
|
215
|
+
(
|
|
216
|
+
primary_timestamped_vectors
|
|
217
|
+
if mago_is_primary
|
|
218
|
+
else secondary_timestamped_vectors
|
|
219
|
+
),
|
|
220
|
+
primary_packet_data if mago_is_primary else secondary_packet_data,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
if magi_day not in magi:
|
|
224
|
+
magi[magi_day] = MagL1a(
|
|
225
|
+
False,
|
|
226
|
+
mag_l0.MAGI_ACT,
|
|
227
|
+
mag_l0.SHCOARSE,
|
|
228
|
+
primary_timestamped_vectors
|
|
229
|
+
if not mago_is_primary
|
|
230
|
+
else secondary_timestamped_vectors,
|
|
231
|
+
primary_packet_data if not mago_is_primary else secondary_packet_data,
|
|
232
|
+
)
|
|
233
|
+
else:
|
|
234
|
+
magi[magi_day].append_vectors(
|
|
235
|
+
(
|
|
236
|
+
primary_timestamped_vectors
|
|
237
|
+
if not mago_is_primary
|
|
238
|
+
else secondary_timestamped_vectors
|
|
239
|
+
),
|
|
240
|
+
primary_packet_data if not mago_is_primary else secondary_packet_data,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
return {"mago": mago, "magi": magi}
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def generate_dataset(
|
|
247
|
+
single_file_l1a: MagL1a,
|
|
248
|
+
logical_file_id: str,
|
|
249
|
+
attribute_manager: ImapCdfAttributes,
|
|
250
|
+
) -> xr.Dataset:
|
|
251
|
+
"""
|
|
252
|
+
Generate a Xarray dataset for L1A data to output to CDF files.
|
|
253
|
+
|
|
254
|
+
Global_attrs should contain all info about mago/magi and burst/norm distinction, as
|
|
255
|
+
well as any general info in the global attributes.
|
|
256
|
+
|
|
257
|
+
Assumes each MagL1a object is a single day of data, so one MagL1a object has one
|
|
258
|
+
CDF file output.
|
|
259
|
+
|
|
260
|
+
Parameters
|
|
261
|
+
----------
|
|
262
|
+
single_file_l1a : MagL1a
|
|
263
|
+
L1A data covering one day to process into a xarray dataset.
|
|
264
|
+
logical_file_id : str
|
|
265
|
+
Indicates which sensor (MagO or MAGi) and mode (burst or norm) the data is from.
|
|
266
|
+
This is used to retrieve the global attributes from attribute_manager.
|
|
267
|
+
attribute_manager : ImapCdfAttributes
|
|
268
|
+
Attributes for the dataset, as created by ImapCdfAttributes.
|
|
269
|
+
|
|
270
|
+
Returns
|
|
271
|
+
-------
|
|
272
|
+
dataset : xarray.Dataset
|
|
273
|
+
One xarray dataset with proper CDF attributes and shape containing MAG L1A data.
|
|
274
|
+
"""
|
|
275
|
+
# TODO: add:
|
|
276
|
+
# gaps_in_data global attr
|
|
277
|
+
# magl1avectordefinition data
|
|
278
|
+
|
|
279
|
+
# TODO: Just leave time in datetime64 type with vector as dtype object to avoid this
|
|
280
|
+
# Get the timestamp from the end of the vector
|
|
281
|
+
time_data = single_file_l1a.vectors[:, 4].astype(
|
|
282
|
+
np.dtype("datetime64[ns]"), copy=False
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
direction = xr.DataArray(
|
|
286
|
+
np.arange(4),
|
|
287
|
+
name="direction",
|
|
288
|
+
dims=["direction"],
|
|
289
|
+
attrs=attribute_manager.get_variable_attributes("direction_attrs"),
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# TODO: Epoch here refers to the start of the sample. Confirm that this is
|
|
293
|
+
# what mag is expecting, and if it is, CATDESC needs to be updated.
|
|
294
|
+
epoch_time = xr.DataArray(
|
|
295
|
+
time_data,
|
|
296
|
+
name="epoch",
|
|
297
|
+
dims=["epoch"],
|
|
298
|
+
attrs=attribute_manager.get_variable_attributes("epoch"),
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
vectors = xr.DataArray(
|
|
302
|
+
single_file_l1a.vectors[:, :4],
|
|
303
|
+
name="vectors",
|
|
304
|
+
dims=["epoch", "direction"],
|
|
305
|
+
attrs=attribute_manager.get_variable_attributes("vector_attrs"),
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
output = xr.Dataset(
|
|
309
|
+
coords={"epoch": epoch_time, "direction": direction},
|
|
310
|
+
attrs=attribute_manager.get_global_attributes(logical_file_id),
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
output["vectors"] = vectors
|
|
314
|
+
|
|
315
|
+
# TODO: Put is_mago and active in the header
|
|
316
|
+
|
|
317
|
+
return output
|