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,34 @@
|
|
|
1
|
+
"""Interstellar Mapping and Acceleration Probe (IMAP) data processing package.
|
|
2
|
+
|
|
3
|
+
This package contains the IMAP data processing software. The package is
|
|
4
|
+
organized into submodules for each instrument. Each instrument submodule
|
|
5
|
+
contains code for each processing level.
|
|
6
|
+
|
|
7
|
+
There are utilities to read and write IMAP data files in
|
|
8
|
+
the CDF file format, and to interact with the SPICE toolkit.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# When imap_processing is installed using pip, we need to be able to find the
|
|
12
|
+
# packet definitions directory path.
|
|
13
|
+
#
|
|
14
|
+
# This directory is used by the imap_processing package to find the packet definitions.
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from imap_processing._version import __version__, __version_tuple__ # noqa: F401
|
|
18
|
+
|
|
19
|
+
# Eg. imap_module_directory = /usr/local/lib/python3.11/site-packages/imap_processing
|
|
20
|
+
imap_module_directory = Path(__file__).parent
|
|
21
|
+
|
|
22
|
+
# TODO: should we move this to imap-data-access?
|
|
23
|
+
PROCESSING_LEVELS = {
|
|
24
|
+
"codice": ["l0", "l1a", "l1b", "l2"],
|
|
25
|
+
"glows": ["l0", "l1a", "l1b", "l2"],
|
|
26
|
+
"hi": ["l0", "l1a", "l1b", "l1c", "l2"],
|
|
27
|
+
"hit": ["l0", "l1a", "l1b", "l2"],
|
|
28
|
+
"idex": ["l0", "l1a", "l1b", "l2"],
|
|
29
|
+
"lo": ["l0", "l1a", "l1b", "l1c", "l2"],
|
|
30
|
+
"mag": ["l0", "l1a", "l1b", "l1c", "l2pre", "l2"],
|
|
31
|
+
"swapi": ["l0", "l1", "l2", "l3a", "l3b"],
|
|
32
|
+
"swe": ["l0", "l1a", "l1b", "l2"],
|
|
33
|
+
"ultra": ["l0", "l1a", "l1b", "l1c", "l2"],
|
|
34
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Contain a data class for CCSDS data."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, fields
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class CcsdsData:
|
|
8
|
+
"""
|
|
9
|
+
Data class for CCSDS header.
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
packet_header : dict
|
|
14
|
+
Dictionary of packet headers.
|
|
15
|
+
|
|
16
|
+
Attributes
|
|
17
|
+
----------
|
|
18
|
+
VERSION: int
|
|
19
|
+
CCSDS Packet Version Number.
|
|
20
|
+
TYPE: int
|
|
21
|
+
CCSDS Packet Type Indicator.
|
|
22
|
+
SEC_HDR_FLG: int
|
|
23
|
+
CCSDS Packet Secondary Header Flag.
|
|
24
|
+
PKT_APID: int
|
|
25
|
+
CCSDS Packet Application Process ID.
|
|
26
|
+
SEQ_FLGS: int
|
|
27
|
+
CCSDS Packet Grouping Flags.
|
|
28
|
+
SRC_SEQ_CTR: int
|
|
29
|
+
CCSDS Packet Sequence Count.
|
|
30
|
+
PKT_LEN: int
|
|
31
|
+
CCSDS Packet Length.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
VERSION: int
|
|
35
|
+
TYPE: int
|
|
36
|
+
SEC_HDR_FLG: int
|
|
37
|
+
PKT_APID: int
|
|
38
|
+
SEQ_FLGS: int
|
|
39
|
+
SRC_SEQ_CTR: int
|
|
40
|
+
PKT_LEN: int
|
|
41
|
+
|
|
42
|
+
def __init__(self, packet_header: dict):
|
|
43
|
+
attributes = [field.name for field in fields(self)]
|
|
44
|
+
|
|
45
|
+
for key, item in packet_header.items():
|
|
46
|
+
value = (
|
|
47
|
+
item.derived_value if item.derived_value is not None else item.raw_value
|
|
48
|
+
)
|
|
49
|
+
if key in attributes:
|
|
50
|
+
setattr(self, key, value)
|
|
51
|
+
else:
|
|
52
|
+
raise KeyError(
|
|
53
|
+
f"Did not find matching attribute in Histogram data class for "
|
|
54
|
+
f"{key}"
|
|
55
|
+
)
|
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Convert an Excel file of packet definitions into the XTCE format.
|
|
3
|
+
|
|
4
|
+
This script reads in an Excel file containing packet definitions and converts
|
|
5
|
+
them into an XTCE file.
|
|
6
|
+
|
|
7
|
+
.. code::
|
|
8
|
+
imap_xtce /path/to/excel_file.xlsx --output /path/to/output.xml
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import xml.etree.ElementTree as Et
|
|
13
|
+
from importlib.util import find_spec
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
import pandas as pd
|
|
17
|
+
|
|
18
|
+
_CCSDS_PARAMETERS = [
|
|
19
|
+
{
|
|
20
|
+
"name": "VERSION",
|
|
21
|
+
"lengthInBits": 3,
|
|
22
|
+
"description": "CCSDS Packet Version Number (always 0)",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "TYPE",
|
|
26
|
+
"lengthInBits": 1,
|
|
27
|
+
"description": "CCSDS Packet Type Indicator (0=telemetry)",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "SEC_HDR_FLG",
|
|
31
|
+
"lengthInBits": 1,
|
|
32
|
+
"description": "CCSDS Packet Secondary Header Flag (always 1)",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "PKT_APID",
|
|
36
|
+
"lengthInBits": 11,
|
|
37
|
+
"description": "CCSDS Packet Application Process ID",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "SEQ_FLGS",
|
|
41
|
+
"lengthInBits": 2,
|
|
42
|
+
"description": "CCSDS Packet Grouping Flags (3=not part of group)",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "SRC_SEQ_CTR",
|
|
46
|
+
"lengthInBits": 14,
|
|
47
|
+
"description": "CCSDS Packet Sequence Count "
|
|
48
|
+
"(increments with each new packet)",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "PKT_LEN",
|
|
52
|
+
"lengthInBits": 16,
|
|
53
|
+
"description": "CCSDS Packet Length "
|
|
54
|
+
"(number of bytes after Packet length minus 1)",
|
|
55
|
+
},
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class XTCEGenerator:
|
|
60
|
+
"""
|
|
61
|
+
Automatically generate XTCE files from excel definition files.
|
|
62
|
+
|
|
63
|
+
The excel file should have the following columns: mnemonic, sequence, lengthInBits,
|
|
64
|
+
startBit, dataType, convertAs, units, source, and either shortDescription or
|
|
65
|
+
longDescription.
|
|
66
|
+
|
|
67
|
+
This class will correctly generate a CCSDS header and the provided data types.
|
|
68
|
+
|
|
69
|
+
It is intended for use as a first pass of XTCE generation, and most cases, the
|
|
70
|
+
packet definitions will require manual updates.
|
|
71
|
+
|
|
72
|
+
Use ``to_xml`` to write the output xml file.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
path_to_excel_file : Path
|
|
77
|
+
Path to the excel file.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
def __init__(self, path_to_excel_file: Path):
|
|
81
|
+
# Read in all sheets from the excel file
|
|
82
|
+
self.sheets = pd.read_excel(path_to_excel_file, sheet_name=None)
|
|
83
|
+
# Set up the packet mapping from packetName to Apid
|
|
84
|
+
packet_sheet = self.sheets["Packets"]
|
|
85
|
+
if "apId" not in packet_sheet.columns:
|
|
86
|
+
# Create the apId column from the apIdHex (base=0 works with the 0x prefix)
|
|
87
|
+
packet_sheet["apId"] = packet_sheet["apIdHex"].apply(int, base=0)
|
|
88
|
+
self._packet_mapping = packet_sheet.set_index("packetName")["apId"].to_dict()
|
|
89
|
+
|
|
90
|
+
# Create the XML containers that will be populated later
|
|
91
|
+
self._setup_xml_containers()
|
|
92
|
+
# Add the CCSDS Header information to the containers
|
|
93
|
+
self._setup_ccsds_header()
|
|
94
|
+
# Create the sequence containers (also adding parameters within)
|
|
95
|
+
self._create_container_sets()
|
|
96
|
+
|
|
97
|
+
def _setup_xml_containers(self) -> None:
|
|
98
|
+
"""Create an XML representation of telemetry data."""
|
|
99
|
+
# Register the XML namespace
|
|
100
|
+
source_link = "http://www.omg.org/space/xtce"
|
|
101
|
+
Et.register_namespace("xtce", source_link)
|
|
102
|
+
|
|
103
|
+
# Create the root element and add namespaces
|
|
104
|
+
root = Et.Element("xtce:SpaceSystem")
|
|
105
|
+
self._root = root
|
|
106
|
+
root.attrib["xmlns:xtce"] = source_link
|
|
107
|
+
# Subsystem sheet name is used as the base name for this XTCE definition
|
|
108
|
+
subsystem = self.sheets["Subsystem"]
|
|
109
|
+
root.attrib["name"] = str(
|
|
110
|
+
subsystem.loc[subsystem["infoField"] == "subsystem", "infoValue"].values[0]
|
|
111
|
+
)
|
|
112
|
+
# Create the Header element with attributes 'date', 'version', and 'author'
|
|
113
|
+
# Versioning is used to keep track of changes to the XML file.
|
|
114
|
+
header = Et.SubElement(root, "xtce:Header")
|
|
115
|
+
header.attrib["date"] = str(
|
|
116
|
+
subsystem.loc[
|
|
117
|
+
subsystem["infoField"] == "sheetReleaseDate", "infoValue"
|
|
118
|
+
].values[0]
|
|
119
|
+
)
|
|
120
|
+
header.attrib["version"] = str(
|
|
121
|
+
subsystem.loc[
|
|
122
|
+
subsystem["infoField"] == "sheetReleaseRev", "infoValue"
|
|
123
|
+
].values[0]
|
|
124
|
+
)
|
|
125
|
+
header.attrib["author"] = "IMAP SDC"
|
|
126
|
+
|
|
127
|
+
# Create the TelemetryMetaData element
|
|
128
|
+
self._telemetry_metadata = Et.SubElement(root, "xtce:TelemetryMetaData")
|
|
129
|
+
|
|
130
|
+
# Create the ParameterTypeSet element
|
|
131
|
+
self._parameter_type_set = Et.SubElement(
|
|
132
|
+
self._telemetry_metadata, "xtce:ParameterTypeSet"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Create the ParameterSet element
|
|
136
|
+
self._parameter_set = Et.SubElement(
|
|
137
|
+
self._telemetry_metadata, "xtce:ParameterSet"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Create ContainerSet element
|
|
141
|
+
self._container_sets = Et.SubElement(
|
|
142
|
+
self._telemetry_metadata, "xtce:ContainerSet"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
def _setup_ccsds_header(self) -> None:
|
|
146
|
+
"""Fill in the default CCSDS header information."""
|
|
147
|
+
# Create CCSDSPacket SequenceContainer
|
|
148
|
+
ccsds_container = Et.SubElement(self._container_sets, "xtce:SequenceContainer")
|
|
149
|
+
ccsds_container.attrib["name"] = "CCSDSPacket"
|
|
150
|
+
ccsds_container.attrib["abstract"] = "true"
|
|
151
|
+
ccsds_entry_list = Et.SubElement(ccsds_container, "xtce:EntryList")
|
|
152
|
+
|
|
153
|
+
# Populate EntryList for CCSDSPacket SequenceContainer
|
|
154
|
+
for parameter_data in _CCSDS_PARAMETERS:
|
|
155
|
+
parameter_ref_entry = Et.SubElement(
|
|
156
|
+
ccsds_entry_list, "xtce:ParameterRefEntry"
|
|
157
|
+
)
|
|
158
|
+
name = str(parameter_data["name"])
|
|
159
|
+
|
|
160
|
+
parameter_ref_entry.attrib["parameterRef"] = name
|
|
161
|
+
|
|
162
|
+
# Add the parameter to the ParameterSet
|
|
163
|
+
parameter = Et.SubElement(self._parameter_set, "xtce:Parameter")
|
|
164
|
+
parameter.attrib["name"] = name
|
|
165
|
+
parameter.attrib["parameterTypeRef"] = name
|
|
166
|
+
|
|
167
|
+
description = Et.SubElement(parameter, "xtce:LongDescription")
|
|
168
|
+
description.text = str(parameter_data["description"])
|
|
169
|
+
|
|
170
|
+
# Add the typeref to the parameter type set
|
|
171
|
+
parameter_type = Et.SubElement(
|
|
172
|
+
self._parameter_type_set, "xtce:IntegerParameterType"
|
|
173
|
+
)
|
|
174
|
+
parameter_type.attrib["name"] = name
|
|
175
|
+
parameter_type.attrib["signed"] = "false"
|
|
176
|
+
|
|
177
|
+
encoding = Et.SubElement(parameter_type, "xtce:IntegerDataEncoding")
|
|
178
|
+
encoding.attrib["sizeInBits"] = str(parameter_data["lengthInBits"])
|
|
179
|
+
encoding.attrib["encoding"] = "unsigned"
|
|
180
|
+
|
|
181
|
+
def _create_container_sets(self) -> None:
|
|
182
|
+
"""Create a container set for each packet in the Excel file."""
|
|
183
|
+
# Iterate over all packets and create Packet SequenceContainers
|
|
184
|
+
for packet_name, apid in self._packet_mapping.items():
|
|
185
|
+
# Populate EntryList for packet SequenceContainers
|
|
186
|
+
# The sheets are sometimes prefixed with P_, so we need to try both options
|
|
187
|
+
try:
|
|
188
|
+
packet_df = self.sheets[packet_name]
|
|
189
|
+
except KeyError:
|
|
190
|
+
try:
|
|
191
|
+
packet_df = self.sheets[f"P_{packet_name}"]
|
|
192
|
+
except KeyError:
|
|
193
|
+
print(
|
|
194
|
+
f"Packet definition for {packet_name} "
|
|
195
|
+
"not found in the excel file."
|
|
196
|
+
)
|
|
197
|
+
continue
|
|
198
|
+
|
|
199
|
+
# Create Packet SequenceContainer that use the CCSDSPacket SequenceContainer
|
|
200
|
+
# as the base container
|
|
201
|
+
science_container = Et.SubElement(
|
|
202
|
+
self._container_sets, "xtce:SequenceContainer"
|
|
203
|
+
)
|
|
204
|
+
science_container.attrib["name"] = packet_name
|
|
205
|
+
|
|
206
|
+
# Every container should inherit from the base container, CCSDSPacket
|
|
207
|
+
base_container = Et.SubElement(science_container, "xtce:BaseContainer")
|
|
208
|
+
base_container.attrib["containerRef"] = "CCSDSPacket"
|
|
209
|
+
|
|
210
|
+
# Add RestrictionCriteria element to use the given APID for comparison
|
|
211
|
+
restriction_criteria = Et.SubElement(
|
|
212
|
+
base_container, "xtce:RestrictionCriteria"
|
|
213
|
+
)
|
|
214
|
+
comparison = Et.SubElement(restriction_criteria, "xtce:Comparison")
|
|
215
|
+
comparison.attrib["parameterRef"] = "PKT_APID"
|
|
216
|
+
comparison.attrib["value"] = str(apid)
|
|
217
|
+
comparison.attrib["useCalibratedValue"] = "false"
|
|
218
|
+
|
|
219
|
+
packet_entry_list = Et.SubElement(science_container, "xtce:EntryList")
|
|
220
|
+
# Needed for dynamic binary packet length
|
|
221
|
+
total_packet_bits = int(packet_df["lengthInBits"].sum())
|
|
222
|
+
for i, row in packet_df.iterrows():
|
|
223
|
+
if i < 7:
|
|
224
|
+
# Skip first 7 rows as they are the CCSDS header elements
|
|
225
|
+
continue
|
|
226
|
+
if pd.isna(row.get("packetName")):
|
|
227
|
+
# This is a poorly formatted row, skip it
|
|
228
|
+
continue
|
|
229
|
+
# separate the packet name and mnemonic with a period
|
|
230
|
+
# a hyphen is sometimes in the packet name or mnemonic already
|
|
231
|
+
name = f"{row['packetName']}.{row['mnemonic']}"
|
|
232
|
+
parameter_ref_entry = Et.SubElement(
|
|
233
|
+
packet_entry_list, "xtce:ParameterRefEntry"
|
|
234
|
+
)
|
|
235
|
+
parameter_ref_entry.attrib["parameterRef"] = name
|
|
236
|
+
# Add this parameter to the ParameterSet too
|
|
237
|
+
self._add_parameter(row, total_packet_bits)
|
|
238
|
+
|
|
239
|
+
def _add_parameter(self, row: pd.Series, total_packet_bits: int) -> None:
|
|
240
|
+
"""
|
|
241
|
+
Row from a packet definition to be added to the XTCE file.
|
|
242
|
+
|
|
243
|
+
Parameters
|
|
244
|
+
----------
|
|
245
|
+
row : pandas.Row
|
|
246
|
+
Row to be added to the XTCE file, containing mnemonic, lengthInBits, ...
|
|
247
|
+
total_packet_bits : int
|
|
248
|
+
Total number of bits in the packet, as summed from the lengthInBits column.
|
|
249
|
+
"""
|
|
250
|
+
parameter = Et.SubElement(self._parameter_set, "xtce:Parameter")
|
|
251
|
+
# Combine the packet name and mnemonic to create a unique parameter name
|
|
252
|
+
name = f"{row['packetName']}.{row['mnemonic']}"
|
|
253
|
+
parameter.attrib["name"] = name
|
|
254
|
+
parameter.attrib["parameterTypeRef"] = name
|
|
255
|
+
|
|
256
|
+
# Add descriptions if they exist
|
|
257
|
+
if pd.notna(row.get("shortDescription")):
|
|
258
|
+
parameter.attrib["shortDescription"] = row.get("shortDescription")
|
|
259
|
+
if pd.notna(row.get("longDescription")):
|
|
260
|
+
description = Et.SubElement(parameter, "xtce:LongDescription")
|
|
261
|
+
description.text = row.get("longDescription")
|
|
262
|
+
|
|
263
|
+
length_in_bits = int(row["lengthInBits"])
|
|
264
|
+
|
|
265
|
+
# Add the parameterTypeRef for this row
|
|
266
|
+
if "UINT" in row["dataType"] or "FILL" in row["dataType"]:
|
|
267
|
+
parameter_type = Et.SubElement(
|
|
268
|
+
self._parameter_type_set, "xtce:IntegerParameterType"
|
|
269
|
+
)
|
|
270
|
+
parameter_type.attrib["name"] = name
|
|
271
|
+
parameter_type.attrib["signed"] = "false"
|
|
272
|
+
|
|
273
|
+
encoding = Et.SubElement(parameter_type, "xtce:IntegerDataEncoding")
|
|
274
|
+
encoding.attrib["sizeInBits"] = str(length_in_bits)
|
|
275
|
+
encoding.attrib["encoding"] = "unsigned"
|
|
276
|
+
|
|
277
|
+
elif any(x in row["dataType"] for x in ["SINT", "INT"]):
|
|
278
|
+
parameter_type = Et.SubElement(
|
|
279
|
+
self._parameter_type_set, "xtce:IntegerParameterType"
|
|
280
|
+
)
|
|
281
|
+
parameter_type.attrib["name"] = name
|
|
282
|
+
parameter_type.attrib["signed"] = "true"
|
|
283
|
+
encoding = Et.SubElement(parameter_type, "xtce:IntegerDataEncoding")
|
|
284
|
+
encoding.attrib["sizeInBits"] = str(length_in_bits)
|
|
285
|
+
encoding.attrib["encoding"] = "signed"
|
|
286
|
+
|
|
287
|
+
elif "FLOAT" in row["dataType"]:
|
|
288
|
+
parameter_type = Et.SubElement(
|
|
289
|
+
self._parameter_type_set, "xtce:FloatParameterType"
|
|
290
|
+
)
|
|
291
|
+
parameter_type.attrib["name"] = name
|
|
292
|
+
encoding = Et.SubElement(parameter_type, "xtce:FloatDataEncoding")
|
|
293
|
+
encoding.attrib["sizeInBits"] = str(length_in_bits)
|
|
294
|
+
encoding.attrib["encoding"] = "IEEE-754"
|
|
295
|
+
|
|
296
|
+
elif "BYTE" in row["dataType"]:
|
|
297
|
+
parameter_type = Et.SubElement(
|
|
298
|
+
self._parameter_type_set, "xtce:BinaryParameterType"
|
|
299
|
+
)
|
|
300
|
+
parameter_type.attrib["name"] = name
|
|
301
|
+
|
|
302
|
+
encoding = Et.SubElement(parameter_type, "xtce:BinaryDataEncoding")
|
|
303
|
+
encoding.attrib["bitOrder"] = "mostSignificantBitFirst"
|
|
304
|
+
|
|
305
|
+
size_in_bits = Et.SubElement(encoding, "xtce:SizeInBits")
|
|
306
|
+
|
|
307
|
+
# If it is a byte field consider it a dynamic value.
|
|
308
|
+
dynamic_value = Et.SubElement(size_in_bits, "xtce:DynamicValue")
|
|
309
|
+
param_ref = Et.SubElement(dynamic_value, "xtce:ParameterInstanceRef")
|
|
310
|
+
param_ref.attrib["parameterRef"] = "PKT_LEN"
|
|
311
|
+
linear_adjustment = Et.SubElement(dynamic_value, "xtce:LinearAdjustment")
|
|
312
|
+
linear_adjustment.attrib["slope"] = str(8)
|
|
313
|
+
# The length of all other variables (other than this specific one)
|
|
314
|
+
other_variable_bits = total_packet_bits - length_in_bits
|
|
315
|
+
# PKT_LEN == number of bytes in the packet data field - 1
|
|
316
|
+
# So we need to subtract the header bytes plus 1 to get the offset
|
|
317
|
+
# The amount to subtract to get the intercept is then:
|
|
318
|
+
# number of other bits in the packet - (6 + 1) * 8
|
|
319
|
+
linear_adjustment.attrib["intercept"] = str(-int(other_variable_bits - 56))
|
|
320
|
+
|
|
321
|
+
# TODO: Do we want to allow fixed length values?
|
|
322
|
+
# fixed_value = Et.SubElement(size_in_bits, "xtce:FixedValue")
|
|
323
|
+
# fixed_value.text = str(row["lengthInBits"])
|
|
324
|
+
else:
|
|
325
|
+
raise ValueError(f"Unknown data type for {name}: {row['dataType']}")
|
|
326
|
+
|
|
327
|
+
if row["convertAs"] == "ANALOG":
|
|
328
|
+
# Go look up the conversion in the AnalogConversions tab
|
|
329
|
+
# and add it to the encoding
|
|
330
|
+
self._add_analog_conversion(row, encoding)
|
|
331
|
+
elif row["convertAs"] == "STATE":
|
|
332
|
+
# Go look up the states in the States tab
|
|
333
|
+
# and add them to the parameter type
|
|
334
|
+
self._add_state_conversion(row, parameter_type)
|
|
335
|
+
|
|
336
|
+
def _add_analog_conversion(self, row: pd.Series, encoding: Et.Element) -> None:
|
|
337
|
+
"""
|
|
338
|
+
Add an analog conversion to the encoding element.
|
|
339
|
+
|
|
340
|
+
Parameters
|
|
341
|
+
----------
|
|
342
|
+
row : pandas.Row
|
|
343
|
+
Row to be added to the XTCE file, containing mnemonic, packetName.
|
|
344
|
+
encoding : Element
|
|
345
|
+
The encoding element to add the conversion to.
|
|
346
|
+
"""
|
|
347
|
+
# Look up the conversion in the AnalogConversions tab
|
|
348
|
+
analog_conversion = self.sheets["AnalogConversions"]
|
|
349
|
+
# conversion is a row from the AnalogConversions sheet
|
|
350
|
+
conversion = analog_conversion.loc[
|
|
351
|
+
(analog_conversion["mnemonic"] == row["mnemonic"])
|
|
352
|
+
& (analog_conversion["packetName"] == row["packetName"])
|
|
353
|
+
].iloc[0]
|
|
354
|
+
|
|
355
|
+
# Create the Conversion element
|
|
356
|
+
default_calibrator = Et.SubElement(encoding, "xtce:DefaultCalibrator")
|
|
357
|
+
polynomial_calibrator = Et.SubElement(
|
|
358
|
+
default_calibrator, "xtce:PolynomialCalibrator"
|
|
359
|
+
)
|
|
360
|
+
# FIXME: Use lowValue / highValue from the conversion sheet
|
|
361
|
+
# FIXME: Handle segmented polynomials (only using first segment now)
|
|
362
|
+
for i in range(8):
|
|
363
|
+
col = f"c{i}"
|
|
364
|
+
if conversion[col] != 0:
|
|
365
|
+
term = Et.SubElement(polynomial_calibrator, "xtce:Term")
|
|
366
|
+
term.attrib["coefficient"] = str(conversion[col])
|
|
367
|
+
term.attrib["exponent"] = str(i)
|
|
368
|
+
|
|
369
|
+
def _add_state_conversion(self, row: pd.Series, parameter_type: Et.Element) -> None:
|
|
370
|
+
"""
|
|
371
|
+
Add a state conversion to the parameter type.
|
|
372
|
+
|
|
373
|
+
Changing from an IntegerParameterType to an EnumeratedParameterType. Adding
|
|
374
|
+
the list of state mappings to the parameter type.
|
|
375
|
+
|
|
376
|
+
Parameters
|
|
377
|
+
----------
|
|
378
|
+
row : pandas.Row
|
|
379
|
+
Row to be added to the XTCE file, containing mnemonic, packetName.
|
|
380
|
+
parameter_type : Element
|
|
381
|
+
The parameter type element to add the conversion to.
|
|
382
|
+
"""
|
|
383
|
+
# It is an EnumeratedParameterType rather than an IntegerParameterType
|
|
384
|
+
parameter_type.tag = "xtce:EnumeratedParameterType"
|
|
385
|
+
enumeration_list = Et.SubElement(parameter_type, "xtce:EnumerationList")
|
|
386
|
+
# Lookup the enumeration states for this parameter from the States sheet
|
|
387
|
+
state_sheet = self.sheets["States"]
|
|
388
|
+
state_sheet = state_sheet.loc[
|
|
389
|
+
(state_sheet["packetName"] == row["packetName"])
|
|
390
|
+
& (state_sheet["mnemonic"] == row["mnemonic"])
|
|
391
|
+
]
|
|
392
|
+
for _, state_row in state_sheet.iterrows():
|
|
393
|
+
enumeration = Et.SubElement(enumeration_list, "xtce:Enumeration")
|
|
394
|
+
enumeration.attrib["value"] = str(state_row["value"])
|
|
395
|
+
enumeration.attrib["label"] = str(state_row["state"])
|
|
396
|
+
|
|
397
|
+
def to_xml(self, output_xml_path: Path) -> None:
|
|
398
|
+
"""
|
|
399
|
+
Create and output an XTCE file from the Element Tree representation.
|
|
400
|
+
|
|
401
|
+
Parameters
|
|
402
|
+
----------
|
|
403
|
+
output_xml_path : Path
|
|
404
|
+
Path to the output XML file.
|
|
405
|
+
"""
|
|
406
|
+
# Create the XML tree and save the document
|
|
407
|
+
tree = Et.ElementTree(self._root)
|
|
408
|
+
Et.indent(tree, space="\t", level=0)
|
|
409
|
+
|
|
410
|
+
# Use the provided output_xml_path
|
|
411
|
+
tree.write(output_xml_path, encoding="utf-8", xml_declaration=True)
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
# Function to parse command line arguments
|
|
415
|
+
def _parse_args() -> argparse.Namespace:
|
|
416
|
+
"""
|
|
417
|
+
Parse the command line arguments.
|
|
418
|
+
|
|
419
|
+
The expected input format is a required argument of "/path/to/excel_file.xlsx"
|
|
420
|
+
with an optional argument containing the output path for the XTCE file
|
|
421
|
+
"/path/to/output.xml".
|
|
422
|
+
|
|
423
|
+
Returns
|
|
424
|
+
-------
|
|
425
|
+
args : argparse.Namespace
|
|
426
|
+
An object containing the parsed arguments and their values.
|
|
427
|
+
"""
|
|
428
|
+
description = (
|
|
429
|
+
"This command line program generates an instrument specific XTCE file. "
|
|
430
|
+
"Example usage: imap_xtce "
|
|
431
|
+
"path/to/excel_packet_file.xlsx --output path/to/output_packet_definition.xml"
|
|
432
|
+
)
|
|
433
|
+
output_help = (
|
|
434
|
+
"Where to save the output XTCE file. "
|
|
435
|
+
"If not provided, the input file name will be used with a "
|
|
436
|
+
".xml extension."
|
|
437
|
+
)
|
|
438
|
+
file_path_help = "Provide the full path to the input excel file."
|
|
439
|
+
|
|
440
|
+
parser = argparse.ArgumentParser(prog="imap_xtce", description=description)
|
|
441
|
+
parser.add_argument("excel_file", type=Path, help=file_path_help)
|
|
442
|
+
parser.add_argument("--output", type=Path, required=False, help=output_help)
|
|
443
|
+
|
|
444
|
+
if not find_spec("openpyxl"):
|
|
445
|
+
parser.error(
|
|
446
|
+
"The openpyxl package is required for this script. "
|
|
447
|
+
"Please install it using 'pip install openpyxl'."
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
args = parser.parse_args()
|
|
451
|
+
|
|
452
|
+
if not args.excel_file.exists():
|
|
453
|
+
parser.error(f"File not found: {args.excel_file}")
|
|
454
|
+
|
|
455
|
+
if not args.output:
|
|
456
|
+
args.output = args.excel_file.with_suffix(".xml")
|
|
457
|
+
|
|
458
|
+
return args
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def main() -> None:
|
|
462
|
+
"""
|
|
463
|
+
Generate xtce file from CLI information given.
|
|
464
|
+
|
|
465
|
+
The xtce file will be written in an instrument specific subfolder.
|
|
466
|
+
"""
|
|
467
|
+
# Parse arguments from the command line
|
|
468
|
+
args = _parse_args()
|
|
469
|
+
|
|
470
|
+
xtce_generator = XTCEGenerator(
|
|
471
|
+
path_to_excel_file=args.excel_file,
|
|
472
|
+
)
|
|
473
|
+
xtce_generator.to_xml(args.output)
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
if __name__ == "__main__":
|
|
477
|
+
main()
|
|
File without changes
|