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,631 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Perform IDEX L1a Processing.
|
|
3
|
+
|
|
4
|
+
This module processes decommutated IDEX packets and creates L1a data products.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from collections import namedtuple
|
|
9
|
+
from enum import IntEnum
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Union
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
import numpy.typing as npt
|
|
15
|
+
import space_packet_parser
|
|
16
|
+
import xarray as xr
|
|
17
|
+
|
|
18
|
+
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
19
|
+
from imap_processing.idex.idex_l0 import decom_packets
|
|
20
|
+
from imap_processing.spice.time import met_to_j2000ns
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
# TODO: Generate quicklook plots
|
|
25
|
+
|
|
26
|
+
# Create a large dictionary of values from the FPGA header that need to be
|
|
27
|
+
# captured into the CDF file. They are lumped together because they share
|
|
28
|
+
# similar attributes.
|
|
29
|
+
# Notes about the variables are set here, acting as comments and will also be
|
|
30
|
+
# placed into the CDF in the VAR_NOTES attribute.
|
|
31
|
+
TRIGGER_DESCRIPTION = namedtuple(
|
|
32
|
+
"TRIGGER_DESCRIPTION",
|
|
33
|
+
["name", "packet_name"],
|
|
34
|
+
)
|
|
35
|
+
TRIGGER_DESCRIPTION_DICT = {
|
|
36
|
+
trigger.name: trigger
|
|
37
|
+
for trigger in [
|
|
38
|
+
TRIGGER_DESCRIPTION("event_number", "IDX__TXHDREVTNUM"),
|
|
39
|
+
TRIGGER_DESCRIPTION("tof_high_trigger_level", "IDX__TXHDRHGTRIGLVL"),
|
|
40
|
+
TRIGGER_DESCRIPTION("tof_high_trigger_num_max_1_2", "IDX__TXHDRHGTRIGNMAX12"),
|
|
41
|
+
TRIGGER_DESCRIPTION("tof_high_trigger_num_min_1_2", "IDX__TXHDRHGTRIGNMIN12"),
|
|
42
|
+
TRIGGER_DESCRIPTION("tof_high_trigger_num_min_1", "IDX__TXHDRHGTRIGNMIN1"),
|
|
43
|
+
TRIGGER_DESCRIPTION("tof_high_trigger_num_max_1", "IDX__TXHDRHGTRIGNMAX1"),
|
|
44
|
+
TRIGGER_DESCRIPTION("tof_high_trigger_num_min_2", "IDX__TXHDRHGTRIGNMIN2"),
|
|
45
|
+
TRIGGER_DESCRIPTION("tof_high_trigger_num_max_2", "IDX__TXHDRHGTRIGNMAX2"),
|
|
46
|
+
TRIGGER_DESCRIPTION("tof_low_trigger_level", "IDX__TXHDRLGTRIGLVL"),
|
|
47
|
+
TRIGGER_DESCRIPTION("tof_low_trigger_num_max_1_2", "IDX__TXHDRLGTRIGNMAX12"),
|
|
48
|
+
TRIGGER_DESCRIPTION("tof_low_trigger_num_min_1_2", "IDX__TXHDRLGTRIGNMIN12"),
|
|
49
|
+
TRIGGER_DESCRIPTION("tof_low_trigger_num_min_1", "IDX__TXHDRLGTRIGNMIN1"),
|
|
50
|
+
TRIGGER_DESCRIPTION("tof_low_trigger_num_max_1", "IDX__TXHDRLGTRIGNMAX1"),
|
|
51
|
+
TRIGGER_DESCRIPTION("tof_low_trigger_num_min_2", "IDX__TXHDRLGTRIGNMIN2"),
|
|
52
|
+
TRIGGER_DESCRIPTION("tof_low_trigger_num_max_2", "IDX__TXHDRLGTRIGNMAX2"),
|
|
53
|
+
TRIGGER_DESCRIPTION("tof_mid_trigger_level", "IDX__TXHDRMGTRIGLVL"),
|
|
54
|
+
TRIGGER_DESCRIPTION("tof_mid_trigger_num_max_1_2", "IDX__TXHDRMGTRIGNMAX12"),
|
|
55
|
+
TRIGGER_DESCRIPTION("tof_mid_trigger_num_min_1_2", "IDX__TXHDRMGTRIGNMIN12"),
|
|
56
|
+
TRIGGER_DESCRIPTION("tof_mid_trigger_num_min_1", "IDX__TXHDRMGTRIGNMIN1"),
|
|
57
|
+
TRIGGER_DESCRIPTION("tof_mid_trigger_num_max_1", "IDX__TXHDRMGTRIGNMAX1"),
|
|
58
|
+
TRIGGER_DESCRIPTION("tof_mid_trigger_num_min_2", "IDX__TXHDRMGTRIGNMIN2"),
|
|
59
|
+
TRIGGER_DESCRIPTION("tof_mid_trigger_num_max_2", "IDX__TXHDRMGTRIGNMAX2"),
|
|
60
|
+
TRIGGER_DESCRIPTION("low_sample_coincidence_mode_blocks", "IDX__TXHDRLSTRIGCMBLOCKS"), # noqa
|
|
61
|
+
TRIGGER_DESCRIPTION("low_sample_trigger_polarity", "IDX__TXHDRLSTRIGPOL"),
|
|
62
|
+
TRIGGER_DESCRIPTION("low_sample_trigger_level", "IDX__TXHDRLSTRIGLVL"),
|
|
63
|
+
TRIGGER_DESCRIPTION("low_sample_trigger_num_min", "IDX__TXHDRLSTRIGNMIN"),
|
|
64
|
+
TRIGGER_DESCRIPTION("low_sample_trigger_mode", "IDX__TXHDRLSTRIGMODE"),
|
|
65
|
+
TRIGGER_DESCRIPTION("tof_low_trigger_mode", "IDX__TXHDRLSTRIGMODE"),
|
|
66
|
+
TRIGGER_DESCRIPTION("tof_mid_trigger_mode", "IDX__TXHDRMGTRIGMODE"),
|
|
67
|
+
TRIGGER_DESCRIPTION("tof_high_trigger_mode", "IDX__TXHDRHGTRIGMODE"),
|
|
68
|
+
TRIGGER_DESCRIPTION("detector_voltage", "IDX__TXHDRHVPSHKCH0"),
|
|
69
|
+
TRIGGER_DESCRIPTION("sensor_voltage", "IDX__TXHDRHVPSHKCH1"),
|
|
70
|
+
TRIGGER_DESCRIPTION("target_voltage", "IDX__TXHDRHVPSHKCH2"),
|
|
71
|
+
TRIGGER_DESCRIPTION("reflectron_voltage", "IDX__TXHDRHVPSHKCH3"),
|
|
72
|
+
TRIGGER_DESCRIPTION("rejection_voltage", "IDX__TXHDRHVPSHKCH4"),
|
|
73
|
+
TRIGGER_DESCRIPTION("detector_current", "IDX__TXHDRHVPSHKCH5"),
|
|
74
|
+
]
|
|
75
|
+
} # fmt: skip
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class Scitype(IntEnum):
|
|
79
|
+
"""Define parameters for IDEX Science Type."""
|
|
80
|
+
|
|
81
|
+
FIRST_PACKET = 1
|
|
82
|
+
TOF_HIGH = 2
|
|
83
|
+
TOF_LOW = 4
|
|
84
|
+
TOF_MID = 8
|
|
85
|
+
TARGET_LOW = 16
|
|
86
|
+
TARGET_HIGH = 32
|
|
87
|
+
ION_GRID = 64
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class PacketParser:
|
|
91
|
+
"""
|
|
92
|
+
IDEX L1a packet parsing class.
|
|
93
|
+
|
|
94
|
+
Encapsulates the decom work needed to decom a daily file of IDEX L0 data
|
|
95
|
+
received from the POC. The class is instantiated with a reference to a L0
|
|
96
|
+
file as it exists on the local file system.
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
packet_file : str
|
|
101
|
+
The path and filename to the L0 file to read.
|
|
102
|
+
data_version : str
|
|
103
|
+
The version of the data product being created.
|
|
104
|
+
|
|
105
|
+
Examples
|
|
106
|
+
--------
|
|
107
|
+
.. code-block:: python
|
|
108
|
+
|
|
109
|
+
from imap_processing.idex.idex_l1a import PacketParser
|
|
110
|
+
l0_file = "imap_processing/tests/idex/imap_idex_l0_sci_20230725_v001.pkts"
|
|
111
|
+
l1a_data = PacketParser(l0_file, data_version)
|
|
112
|
+
l1a_data.write_l1a_cdf()
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
def __init__(self, packet_file: Union[str, Path], data_version: str) -> None:
|
|
116
|
+
"""
|
|
117
|
+
Read a L0 pkts file and perform all of the decom work.
|
|
118
|
+
|
|
119
|
+
Parameters
|
|
120
|
+
----------
|
|
121
|
+
packet_file : pathlib.Path | str
|
|
122
|
+
The path and filename to the L0 file to read.
|
|
123
|
+
data_version : str
|
|
124
|
+
The version of the data product being created.
|
|
125
|
+
|
|
126
|
+
Notes
|
|
127
|
+
-----
|
|
128
|
+
Currently assumes one L0 file will generate exactly one L1a file.
|
|
129
|
+
"""
|
|
130
|
+
decom_packet_list = decom_packets(packet_file)
|
|
131
|
+
|
|
132
|
+
dust_events = {}
|
|
133
|
+
for packet in decom_packet_list:
|
|
134
|
+
if "IDX__SCI0TYPE" in packet.data:
|
|
135
|
+
scitype = packet.data["IDX__SCI0TYPE"].raw_value
|
|
136
|
+
event_number = packet.data["IDX__SCI0EVTNUM"].derived_value
|
|
137
|
+
if scitype == Scitype.FIRST_PACKET:
|
|
138
|
+
# Initial packet for new dust event
|
|
139
|
+
# Further packets will fill in data
|
|
140
|
+
dust_events[event_number] = RawDustEvent(packet, data_version)
|
|
141
|
+
elif event_number not in dust_events:
|
|
142
|
+
raise KeyError(
|
|
143
|
+
f"Have not receive header information from event number\
|
|
144
|
+
{event_number}. Packets are possibly out of order!"
|
|
145
|
+
)
|
|
146
|
+
else:
|
|
147
|
+
# Populate the IDEXRawDustEvent with 1's and 0's
|
|
148
|
+
dust_events[event_number]._populate_bit_strings(packet)
|
|
149
|
+
else:
|
|
150
|
+
logger.warning(f"Unhandled packet received: {packet}")
|
|
151
|
+
|
|
152
|
+
processed_dust_impact_list = [
|
|
153
|
+
dust_event.process() for dust_event in dust_events.values()
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
self.data = xr.concat(processed_dust_impact_list, dim="epoch")
|
|
157
|
+
idex_attrs = get_idex_attrs(data_version)
|
|
158
|
+
self.data.attrs = idex_attrs.get_global_attributes("imap_idex_l1a_sci")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class RawDustEvent:
|
|
162
|
+
"""
|
|
163
|
+
Encapsulate IDEX Raw Dust Event.
|
|
164
|
+
|
|
165
|
+
Encapsulates the work needed to convert a single dust event into a processed
|
|
166
|
+
``xarray`` ``dateset`` object.
|
|
167
|
+
|
|
168
|
+
Parameters
|
|
169
|
+
----------
|
|
170
|
+
header_packet : space_packet_parser.parser.Packet
|
|
171
|
+
The FPGA metadata event header.
|
|
172
|
+
data_version : str
|
|
173
|
+
The version of the data product being created.
|
|
174
|
+
|
|
175
|
+
Attributes
|
|
176
|
+
----------
|
|
177
|
+
HIGH_SAMPLE_RATE: float
|
|
178
|
+
The high sample rate in microseconds per sample.
|
|
179
|
+
LOW_SAMPLE_RATE: float
|
|
180
|
+
The low sample rate in microseconds per sample.
|
|
181
|
+
NUMBER_SAMPLES_PER_LOW_SAMPLE_BLOCK: int
|
|
182
|
+
The number of samples in a "block" of low sample data.
|
|
183
|
+
NUMBER_SAMPLES_PER_HIGH_SAMPLE_BLOCK: int
|
|
184
|
+
The number of samples in a "block" of high sample data.
|
|
185
|
+
|
|
186
|
+
Methods
|
|
187
|
+
-------
|
|
188
|
+
_append_raw_data(scitype, bits)
|
|
189
|
+
Append data to the appropriate bit string.
|
|
190
|
+
_set_impact_time(packet)
|
|
191
|
+
Calculate the datetime64 from the FPGA header information.
|
|
192
|
+
_set_sample_trigger_times(packet)
|
|
193
|
+
Calculate the actual sample trigger time.
|
|
194
|
+
_parse_high_sample_waveform(waveform_raw)
|
|
195
|
+
Will process the high sample waveform.
|
|
196
|
+
_parse_low_sample_waveform(waveform_raw)
|
|
197
|
+
Will process the low sample waveform.
|
|
198
|
+
_calc_low_sample_resolution(num_samples)
|
|
199
|
+
Calculate the resolution of the low samples.
|
|
200
|
+
_calc_high_sample_resolution(num_samples)
|
|
201
|
+
Calculate the resolution of high samples.
|
|
202
|
+
_populate_bit_strings(packet)
|
|
203
|
+
Parse IDEX data packets to populate bit strings.
|
|
204
|
+
process()
|
|
205
|
+
Will process the raw data into a xarray.Dataset.
|
|
206
|
+
"""
|
|
207
|
+
|
|
208
|
+
# Constants
|
|
209
|
+
HIGH_SAMPLE_RATE = 1 / 260 # microseconds per sample
|
|
210
|
+
LOW_SAMPLE_RATE = 1 / 4.0625 # microseconds per sample
|
|
211
|
+
|
|
212
|
+
NUMBER_SAMPLES_PER_LOW_SAMPLE_BLOCK = (
|
|
213
|
+
8 # The number of samples in a "block" of low sample data
|
|
214
|
+
)
|
|
215
|
+
NUMBER_SAMPLES_PER_HIGH_SAMPLE_BLOCK = (
|
|
216
|
+
512 # The number of samples in a "block" of high sample data
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
def __init__(
|
|
220
|
+
self, header_packet: space_packet_parser.parser.Packet, data_version: str
|
|
221
|
+
) -> None:
|
|
222
|
+
"""
|
|
223
|
+
Initialize a raw dust event, with an FPGA Header Packet from IDEX.
|
|
224
|
+
|
|
225
|
+
The values we care about are:
|
|
226
|
+
|
|
227
|
+
self.impact_time - When the impact occurred.
|
|
228
|
+
self.low_sample_trigger_time - When the low sample stuff actually triggered.
|
|
229
|
+
self.high_sample_trigger_time - When the high sample stuff actually triggered.
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
header_packet : space_packet_parser.parser.Packet
|
|
234
|
+
The FPGA metadata event header.
|
|
235
|
+
data_version : str
|
|
236
|
+
Data version for CDF filename, in the format ``vXXX``.
|
|
237
|
+
"""
|
|
238
|
+
# Calculate the impact time in seconds since epoch
|
|
239
|
+
self.impact_time = 0
|
|
240
|
+
self._set_impact_time(header_packet)
|
|
241
|
+
|
|
242
|
+
# The actual trigger time for the low and high sample rate in
|
|
243
|
+
# microseconds since the impact time
|
|
244
|
+
self.low_sample_trigger_time = 0
|
|
245
|
+
self.high_sample_trigger_time = 0
|
|
246
|
+
self._set_sample_trigger_times(header_packet)
|
|
247
|
+
|
|
248
|
+
# Iterate through the trigger description dictionary and pull out the values
|
|
249
|
+
self.trigger_values = {
|
|
250
|
+
trigger.name: header_packet.data[trigger.packet_name].raw_value
|
|
251
|
+
for trigger in TRIGGER_DESCRIPTION_DICT.values()
|
|
252
|
+
}
|
|
253
|
+
logger.debug(
|
|
254
|
+
f"trigger_values:\n{self.trigger_values}"
|
|
255
|
+
) # Log values here in case of error
|
|
256
|
+
|
|
257
|
+
# Initialize the binary data received from future packets
|
|
258
|
+
self.TOF_High_bits = ""
|
|
259
|
+
self.TOF_Mid_bits = ""
|
|
260
|
+
self.TOF_Low_bits = ""
|
|
261
|
+
self.Target_Low_bits = ""
|
|
262
|
+
self.Target_High_bits = ""
|
|
263
|
+
self.Ion_Grid_bits = ""
|
|
264
|
+
|
|
265
|
+
self.cdf_attrs = get_idex_attrs(data_version)
|
|
266
|
+
|
|
267
|
+
def _append_raw_data(self, scitype: Scitype, bits: str) -> None:
|
|
268
|
+
"""
|
|
269
|
+
Append data to the appropriate bit string.
|
|
270
|
+
|
|
271
|
+
This function determines which variable to append the bits to, given a
|
|
272
|
+
specific scitype.
|
|
273
|
+
|
|
274
|
+
Parameters
|
|
275
|
+
----------
|
|
276
|
+
scitype : Scitype
|
|
277
|
+
The science type of the data.
|
|
278
|
+
bits : str
|
|
279
|
+
The binary data to append.
|
|
280
|
+
"""
|
|
281
|
+
if scitype == Scitype.TOF_HIGH:
|
|
282
|
+
self.TOF_High_bits += bits
|
|
283
|
+
elif scitype == Scitype.TOF_LOW:
|
|
284
|
+
self.TOF_Low_bits += bits
|
|
285
|
+
elif scitype == Scitype.TOF_MID:
|
|
286
|
+
self.TOF_Mid_bits += bits
|
|
287
|
+
elif scitype == Scitype.TARGET_LOW:
|
|
288
|
+
self.Target_Low_bits += bits
|
|
289
|
+
elif scitype == Scitype.TARGET_HIGH:
|
|
290
|
+
self.Target_High_bits += bits
|
|
291
|
+
elif scitype == Scitype.ION_GRID:
|
|
292
|
+
self.Ion_Grid_bits += bits
|
|
293
|
+
else:
|
|
294
|
+
logger.warning("Unknown science type received: [%s]", scitype)
|
|
295
|
+
|
|
296
|
+
def _set_impact_time(self, packet: space_packet_parser.parser.Packet) -> None:
|
|
297
|
+
"""
|
|
298
|
+
Calculate the impact time from the FPGA header information.
|
|
299
|
+
|
|
300
|
+
We are given the MET seconds, we need convert it to UTC in type
|
|
301
|
+
``np.datetime64``.
|
|
302
|
+
|
|
303
|
+
Parameters
|
|
304
|
+
----------
|
|
305
|
+
packet : space_packet_parser.parser.Packet
|
|
306
|
+
The IDEX FPGA header packet.
|
|
307
|
+
|
|
308
|
+
Notes
|
|
309
|
+
-----
|
|
310
|
+
TODO: This conversion is temporary for now, and will need SPICE in the
|
|
311
|
+
future. IDEX has set the time launch to Jan 1 2012 for calibration
|
|
312
|
+
testing.
|
|
313
|
+
"""
|
|
314
|
+
# Number of seconds since epoch (nominally the launch time)
|
|
315
|
+
seconds_since_launch = packet.data["SHCOARSE"].derived_value
|
|
316
|
+
# Number of 20 microsecond "ticks" since the last second
|
|
317
|
+
num_of_20_microsecond_increments = packet.data["SHFINE"].derived_value
|
|
318
|
+
# Number of microseconds since the last second
|
|
319
|
+
microseconds_since_last_second = 20 * num_of_20_microsecond_increments
|
|
320
|
+
# Get the datetime of Jan 1 2012 as the start date
|
|
321
|
+
met = seconds_since_launch + microseconds_since_last_second * 1e-6
|
|
322
|
+
|
|
323
|
+
self.impact_time = met_to_j2000ns(met)
|
|
324
|
+
|
|
325
|
+
def _set_sample_trigger_times(
|
|
326
|
+
self, packet: space_packet_parser.parser.Packet
|
|
327
|
+
) -> None:
|
|
328
|
+
"""
|
|
329
|
+
Calculate the actual sample trigger time.
|
|
330
|
+
|
|
331
|
+
Determines how many samples of data are included before the dust impact
|
|
332
|
+
triggered the instrument.
|
|
333
|
+
|
|
334
|
+
Parameters
|
|
335
|
+
----------
|
|
336
|
+
packet : space_packet_parser.parser.Packet
|
|
337
|
+
The IDEX FPGA header packet info.
|
|
338
|
+
|
|
339
|
+
Notes
|
|
340
|
+
-----
|
|
341
|
+
A "sample" is one single data point.
|
|
342
|
+
|
|
343
|
+
A "block" is ~1.969 microseconds of data collection (8/4.0625). The only
|
|
344
|
+
time that a block of data matters is in this function.
|
|
345
|
+
|
|
346
|
+
Because the low sample data are taken every 1/4.0625 microseconds, there
|
|
347
|
+
are 8 samples in one block of data.
|
|
348
|
+
|
|
349
|
+
Because the high sample data are taken every 1/260 microseconds, there
|
|
350
|
+
are 512 samples in one block of High Sample data.
|
|
351
|
+
|
|
352
|
+
The header has information about the number of blocks before triggering,
|
|
353
|
+
rather than the number of samples before triggering.
|
|
354
|
+
"""
|
|
355
|
+
# Retrieve the number of samples of high gain delay
|
|
356
|
+
high_gain_delay = packet.data["IDX__TXHDRADC0IDELAY"].raw_value
|
|
357
|
+
|
|
358
|
+
# Retrieve number of low/high sample pre-trigger blocks
|
|
359
|
+
num_low_sample_pretrigger_blocks = packet.data[
|
|
360
|
+
"IDX__TXHDRLSPREBLOCKS"
|
|
361
|
+
].derived_value
|
|
362
|
+
num_high_sample_pretrigger_blocks = packet.data[
|
|
363
|
+
"IDX__TXHDRHSPREBLOCKS"
|
|
364
|
+
].derived_value
|
|
365
|
+
|
|
366
|
+
# Calculate the low and high sample trigger times based on the high gain delay
|
|
367
|
+
# and the number of high sample/low sample pretrigger blocks
|
|
368
|
+
self.low_sample_trigger_time = (
|
|
369
|
+
self.LOW_SAMPLE_RATE
|
|
370
|
+
* (num_low_sample_pretrigger_blocks + 1)
|
|
371
|
+
* self.NUMBER_SAMPLES_PER_LOW_SAMPLE_BLOCK
|
|
372
|
+
- self.HIGH_SAMPLE_RATE * high_gain_delay
|
|
373
|
+
)
|
|
374
|
+
self.high_sample_trigger_time = (
|
|
375
|
+
self.HIGH_SAMPLE_RATE
|
|
376
|
+
* (num_high_sample_pretrigger_blocks + 1)
|
|
377
|
+
* self.NUMBER_SAMPLES_PER_HIGH_SAMPLE_BLOCK
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
def _parse_high_sample_waveform(self, waveform_raw: str) -> list[int]:
|
|
381
|
+
"""
|
|
382
|
+
Will process the high sample waveform.
|
|
383
|
+
|
|
384
|
+
Parse a binary string representing a high sample waveform.
|
|
385
|
+
Data arrives in 32 bit chunks, divided up into:
|
|
386
|
+
* 2 bits of padding
|
|
387
|
+
* 3x10 bits of integer data.
|
|
388
|
+
|
|
389
|
+
The very last 4 numbers are bad usually, so remove those.
|
|
390
|
+
|
|
391
|
+
Parameters
|
|
392
|
+
----------
|
|
393
|
+
waveform_raw : str
|
|
394
|
+
The binary string representing the high sample waveform.
|
|
395
|
+
|
|
396
|
+
Returns
|
|
397
|
+
-------
|
|
398
|
+
ints : list
|
|
399
|
+
List of the high sample waveform.
|
|
400
|
+
"""
|
|
401
|
+
ints = []
|
|
402
|
+
for i in range(0, len(waveform_raw), 32):
|
|
403
|
+
# 32 bit chunks, divided up into 2, 10, 10, 10
|
|
404
|
+
# skip first two bits
|
|
405
|
+
ints += [
|
|
406
|
+
int(waveform_raw[i + 2 : i + 12], 2),
|
|
407
|
+
int(waveform_raw[i + 12 : i + 22], 2),
|
|
408
|
+
int(waveform_raw[i + 22 : i + 32], 2),
|
|
409
|
+
]
|
|
410
|
+
return ints[:-4] # Remove last 4 numbers
|
|
411
|
+
|
|
412
|
+
def _parse_low_sample_waveform(self, waveform_raw: str) -> list[int]:
|
|
413
|
+
"""
|
|
414
|
+
Will process the low sample waveform.
|
|
415
|
+
|
|
416
|
+
Parse a binary string representing a low sample waveform
|
|
417
|
+
Data arrives in 32 bit chunks, divided up into:
|
|
418
|
+
* 8 bits of padding
|
|
419
|
+
* 2x12 bits of integer data.
|
|
420
|
+
|
|
421
|
+
Parameters
|
|
422
|
+
----------
|
|
423
|
+
waveform_raw : str
|
|
424
|
+
The binary string representing the low sample waveform.
|
|
425
|
+
|
|
426
|
+
Returns
|
|
427
|
+
-------
|
|
428
|
+
ints : list
|
|
429
|
+
List of processed low sample waveform.
|
|
430
|
+
"""
|
|
431
|
+
ints = []
|
|
432
|
+
for i in range(0, len(waveform_raw), 32):
|
|
433
|
+
ints += [
|
|
434
|
+
int(waveform_raw[i + 8 : i + 20], 2),
|
|
435
|
+
int(waveform_raw[i + 20 : i + 32], 2),
|
|
436
|
+
]
|
|
437
|
+
return ints
|
|
438
|
+
|
|
439
|
+
def _calc_low_sample_resolution(self, num_samples: int) -> npt.NDArray:
|
|
440
|
+
"""
|
|
441
|
+
Calculate the resolution of the low samples.
|
|
442
|
+
|
|
443
|
+
Calculates the low sample time array based on the number
|
|
444
|
+
of samples of data taken.
|
|
445
|
+
|
|
446
|
+
Multiply a linear array by the sample rate.
|
|
447
|
+
Subtract the calculated trigger time.
|
|
448
|
+
|
|
449
|
+
Parameters
|
|
450
|
+
----------
|
|
451
|
+
num_samples : int
|
|
452
|
+
The number of samples.
|
|
453
|
+
|
|
454
|
+
Returns
|
|
455
|
+
-------
|
|
456
|
+
time_low_sr_data : numpy.ndarray
|
|
457
|
+
Low time sample data array.
|
|
458
|
+
"""
|
|
459
|
+
time_low_sr_init = np.linspace(0, num_samples, num_samples)
|
|
460
|
+
time_low_sr_data = (
|
|
461
|
+
self.LOW_SAMPLE_RATE * time_low_sr_init - self.low_sample_trigger_time
|
|
462
|
+
)
|
|
463
|
+
return time_low_sr_data
|
|
464
|
+
|
|
465
|
+
def _calc_high_sample_resolution(self, num_samples: int) -> npt.NDArray:
|
|
466
|
+
"""
|
|
467
|
+
Calculate the resolution of high samples.
|
|
468
|
+
|
|
469
|
+
Calculates the high sample time array based on the number
|
|
470
|
+
of samples of data taken.
|
|
471
|
+
|
|
472
|
+
Multiply a linear array by the sample rate.
|
|
473
|
+
Subtract the calculated trigger time.
|
|
474
|
+
|
|
475
|
+
Parameters
|
|
476
|
+
----------
|
|
477
|
+
num_samples : int
|
|
478
|
+
The number of samples.
|
|
479
|
+
|
|
480
|
+
Returns
|
|
481
|
+
-------
|
|
482
|
+
time_high_sr_data : numpy.ndarray
|
|
483
|
+
High sample time data array.
|
|
484
|
+
"""
|
|
485
|
+
time_high_sr_init = np.linspace(0, num_samples, num_samples)
|
|
486
|
+
time_high_sr_data = (
|
|
487
|
+
self.HIGH_SAMPLE_RATE * time_high_sr_init - self.high_sample_trigger_time
|
|
488
|
+
)
|
|
489
|
+
return time_high_sr_data
|
|
490
|
+
|
|
491
|
+
def _populate_bit_strings(self, packet: space_packet_parser.parser.Packet) -> None:
|
|
492
|
+
"""
|
|
493
|
+
Parse IDEX data packets to populate bit strings.
|
|
494
|
+
|
|
495
|
+
Parameters
|
|
496
|
+
----------
|
|
497
|
+
packet : space_packet_parser.parser.Packet
|
|
498
|
+
A single science data packet for one of the 6.
|
|
499
|
+
IDEX observables.
|
|
500
|
+
"""
|
|
501
|
+
scitype = packet.data["IDX__SCI0TYPE"].raw_value
|
|
502
|
+
raw_science_bits = packet.data["IDX__SCI0RAW"].raw_value
|
|
503
|
+
self._append_raw_data(scitype, raw_science_bits)
|
|
504
|
+
|
|
505
|
+
def process(self) -> xr.Dataset:
|
|
506
|
+
"""
|
|
507
|
+
Will process the raw data into a ``xarray.Dataset``.
|
|
508
|
+
|
|
509
|
+
To be called after all packets for the IDEX event have been parsed.
|
|
510
|
+
Parses the binary data into numpy integer arrays, and combines them into
|
|
511
|
+
a ``xarray.Dataset`` object.
|
|
512
|
+
|
|
513
|
+
Returns
|
|
514
|
+
-------
|
|
515
|
+
dataset : xarray.Dataset
|
|
516
|
+
A Dataset object containing the data from a single impact.
|
|
517
|
+
"""
|
|
518
|
+
# Create object for CDF attrs
|
|
519
|
+
idex_attrs = self.cdf_attrs
|
|
520
|
+
|
|
521
|
+
# Gather the huge number of trigger info metadata
|
|
522
|
+
trigger_vars = {}
|
|
523
|
+
for var, value in self.trigger_values.items():
|
|
524
|
+
trigger_desc = TRIGGER_DESCRIPTION_DICT[var]
|
|
525
|
+
trigger_vars[var] = xr.DataArray(
|
|
526
|
+
name=var,
|
|
527
|
+
data=[value],
|
|
528
|
+
dims=("epoch"),
|
|
529
|
+
attrs=idex_attrs.get_variable_attributes(trigger_desc.name),
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
# Process the 6 primary data variables
|
|
533
|
+
tof_high_xr = xr.DataArray(
|
|
534
|
+
name="TOF_High",
|
|
535
|
+
data=[self._parse_high_sample_waveform(self.TOF_High_bits)],
|
|
536
|
+
dims=("epoch", "time_high_ssr_dim"),
|
|
537
|
+
attrs=idex_attrs.get_variable_attributes("tof_high_attrs"),
|
|
538
|
+
)
|
|
539
|
+
tof_low_xr = xr.DataArray(
|
|
540
|
+
name="TOF_Low",
|
|
541
|
+
data=[self._parse_high_sample_waveform(self.TOF_Low_bits)],
|
|
542
|
+
dims=("epoch", "time_high_sr"),
|
|
543
|
+
attrs=idex_attrs.get_variable_attributes("tof_low_attrs"),
|
|
544
|
+
)
|
|
545
|
+
tof_mid_xr = xr.DataArray(
|
|
546
|
+
name="TOF_Mid",
|
|
547
|
+
data=[self._parse_high_sample_waveform(self.TOF_Mid_bits)],
|
|
548
|
+
dims=("epoch", "time_high_sr"),
|
|
549
|
+
attrs=idex_attrs.get_variable_attributes("tof_mid_attrs"),
|
|
550
|
+
)
|
|
551
|
+
target_high_xr = xr.DataArray(
|
|
552
|
+
name="Target_High",
|
|
553
|
+
data=[self._parse_low_sample_waveform(self.Target_High_bits)],
|
|
554
|
+
dims=("epoch", "time_low_sr"),
|
|
555
|
+
attrs=idex_attrs.get_variable_attributes("target_high_attrs"),
|
|
556
|
+
)
|
|
557
|
+
target_low_xr = xr.DataArray(
|
|
558
|
+
name="Target_Low",
|
|
559
|
+
data=[self._parse_low_sample_waveform(self.Target_Low_bits)],
|
|
560
|
+
dims=("epoch", "time_low_sr"),
|
|
561
|
+
attrs=idex_attrs.get_variable_attributes("target_low_attrs"),
|
|
562
|
+
)
|
|
563
|
+
ion_grid_xr = xr.DataArray(
|
|
564
|
+
name="Ion_Grid",
|
|
565
|
+
data=[self._parse_low_sample_waveform(self.Ion_Grid_bits)],
|
|
566
|
+
dims=("epoch", "time_low_sr"),
|
|
567
|
+
attrs=idex_attrs.get_variable_attributes("ion_grid_attrs"),
|
|
568
|
+
)
|
|
569
|
+
|
|
570
|
+
# Determine the 3 coordinate variables
|
|
571
|
+
epoch_xr = xr.DataArray(
|
|
572
|
+
name="epoch",
|
|
573
|
+
data=[self.impact_time],
|
|
574
|
+
dims=("epoch"),
|
|
575
|
+
attrs=idex_attrs.get_variable_attributes("epoch"),
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
time_low_sr_xr = xr.DataArray(
|
|
579
|
+
name="time_low_sr",
|
|
580
|
+
data=[self._calc_low_sample_resolution(len(target_low_xr[0]))],
|
|
581
|
+
dims=("epoch", "time_low_sr_dim"),
|
|
582
|
+
attrs=idex_attrs.get_variable_attributes("low_sr_attrs"),
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
time_high_sr_xr = xr.DataArray(
|
|
586
|
+
name="time_high_sr",
|
|
587
|
+
data=[self._calc_high_sample_resolution(len(tof_low_xr[0]))],
|
|
588
|
+
dims=("epoch", "time_high_sr_dim"),
|
|
589
|
+
attrs=idex_attrs.get_variable_attributes("high_sr_attrs"),
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
# Combine to return a dataset object
|
|
593
|
+
dataset = xr.Dataset(
|
|
594
|
+
data_vars={
|
|
595
|
+
"TOF_Low": tof_low_xr,
|
|
596
|
+
"TOF_High": tof_high_xr,
|
|
597
|
+
"TOF_Mid": tof_mid_xr,
|
|
598
|
+
"Target_High": target_high_xr,
|
|
599
|
+
"Target_Low": target_low_xr,
|
|
600
|
+
"Ion_Grid": ion_grid_xr,
|
|
601
|
+
}
|
|
602
|
+
| trigger_vars,
|
|
603
|
+
coords={
|
|
604
|
+
"epoch": epoch_xr,
|
|
605
|
+
"time_low_sr": time_low_sr_xr,
|
|
606
|
+
"time_high_sr": time_high_sr_xr,
|
|
607
|
+
},
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
return dataset
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
def get_idex_attrs(data_version: str) -> ImapCdfAttributes:
|
|
614
|
+
"""
|
|
615
|
+
Load in CDF attributes for IDEX instrument.
|
|
616
|
+
|
|
617
|
+
Parameters
|
|
618
|
+
----------
|
|
619
|
+
data_version : str
|
|
620
|
+
Data version for CDF filename, in the format "vXXX".
|
|
621
|
+
|
|
622
|
+
Returns
|
|
623
|
+
-------
|
|
624
|
+
idex_attrs : ImapCdfAttributes
|
|
625
|
+
The IDEX L1a CDF attributes.
|
|
626
|
+
"""
|
|
627
|
+
idex_attrs = ImapCdfAttributes()
|
|
628
|
+
idex_attrs.add_instrument_global_attrs("idex")
|
|
629
|
+
idex_attrs.add_instrument_variable_attrs("idex", "l1a")
|
|
630
|
+
idex_attrs.add_global_attribute("Data_version", data_version)
|
|
631
|
+
return idex_attrs
|