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
imap_processing/utils.py
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
"""Common functions that every instrument can use."""
|
|
2
|
+
|
|
3
|
+
import collections
|
|
4
|
+
import logging
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional, Union
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import xarray as xr
|
|
11
|
+
from space_packet_parser import parser, xtcedef
|
|
12
|
+
|
|
13
|
+
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
14
|
+
from imap_processing.spice.time import met_to_j2000ns
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def sort_by_time(packets: list, time_key: str) -> list:
|
|
20
|
+
"""
|
|
21
|
+
Sort packets by specified key.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
packets : list
|
|
26
|
+
Decom data packets.
|
|
27
|
+
time_key : str
|
|
28
|
+
Key to sort by. Must be a key in the packets data dictionary.
|
|
29
|
+
e.g. "SHCOARSE" or "MET_TIME" or "ACQ_START_COARSE".
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
sorted_packets : list
|
|
34
|
+
Sorted packets.
|
|
35
|
+
"""
|
|
36
|
+
sorted_packets = sorted(packets, key=lambda x: x.data[time_key].raw_value)
|
|
37
|
+
return sorted_packets
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def group_by_apid(packets: list) -> dict:
|
|
41
|
+
"""
|
|
42
|
+
Group data by apid.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
packets : list
|
|
47
|
+
Packet list.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
grouped_packets : dict
|
|
52
|
+
Grouped data by apid.
|
|
53
|
+
"""
|
|
54
|
+
grouped_packets: dict[list] = collections.defaultdict(list)
|
|
55
|
+
for packet in packets:
|
|
56
|
+
apid = packet.header["PKT_APID"].raw_value
|
|
57
|
+
grouped_packets.setdefault(apid, []).append(packet)
|
|
58
|
+
return grouped_packets
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def convert_raw_to_eu(
|
|
62
|
+
dataset: xr.Dataset,
|
|
63
|
+
conversion_table_path: str,
|
|
64
|
+
packet_name: str,
|
|
65
|
+
**read_csv_kwargs: dict,
|
|
66
|
+
) -> xr.Dataset:
|
|
67
|
+
"""
|
|
68
|
+
Convert raw data to engineering unit.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
dataset : xr.Dataset
|
|
73
|
+
Raw data.
|
|
74
|
+
conversion_table_path : str,
|
|
75
|
+
Path object or file-like object
|
|
76
|
+
Path to engineering unit conversion table.
|
|
77
|
+
Eg:
|
|
78
|
+
f"{imap_module_directory}/swe/l1b/engineering_unit_convert_table.csv"
|
|
79
|
+
Engineering unit conversion table must be a csv file with required
|
|
80
|
+
informational columns: ('packetName', 'mnemonic', 'convertAs') and
|
|
81
|
+
conversion columns named 'c0', 'c1', 'c2', etc. Conversion columns
|
|
82
|
+
specify the array of polynomial coefficients used for the conversion.
|
|
83
|
+
Comment lines are allowed in the csv file specified by starting with
|
|
84
|
+
the '#' character.
|
|
85
|
+
packet_name : str
|
|
86
|
+
Packet name.
|
|
87
|
+
**read_csv_kwargs : dict
|
|
88
|
+
In order to allow for some flexibility in the format of the csv
|
|
89
|
+
conversion table, any additional keywords passed to this function are
|
|
90
|
+
passed in the call to `pandas.read_csv()`. See pandas documentation
|
|
91
|
+
for a list of keywords and their functionality:
|
|
92
|
+
https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html.
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
dataset : xr.Dataset
|
|
97
|
+
Raw data converted to engineering unit as needed.
|
|
98
|
+
"""
|
|
99
|
+
# Make sure there is column called "index" with unique
|
|
100
|
+
# value such as 0, 1, 2, 3, ...
|
|
101
|
+
eu_conversion_df = pd.read_csv(
|
|
102
|
+
conversion_table_path,
|
|
103
|
+
**read_csv_kwargs,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Look up all metadata fields for the packet name
|
|
107
|
+
packet_df = eu_conversion_df.loc[eu_conversion_df["packetName"] == packet_name]
|
|
108
|
+
|
|
109
|
+
# for each metadata field, convert raw value to engineering unit
|
|
110
|
+
for _, row in packet_df.iterrows():
|
|
111
|
+
if row["convertAs"] == "UNSEGMENTED_POLY":
|
|
112
|
+
# On this line, we are getting the coefficients from the
|
|
113
|
+
# table and then reverse them because the np.polyval is
|
|
114
|
+
# expecting coefficient in descending order
|
|
115
|
+
# coeff columns must have names 'c0', 'c1', 'c2', ...
|
|
116
|
+
coeff_values = row.filter(regex=r"c\d").values[::-1]
|
|
117
|
+
row_key = row["mnemonic"]
|
|
118
|
+
# TODO: remove this check once everyone has lowercase
|
|
119
|
+
# all of CDF data variable names to match SPDF requirement.
|
|
120
|
+
# Right now, check if dataset mnemonics is lowercase of row mnemonics.
|
|
121
|
+
# If so, make them match
|
|
122
|
+
mnemonics = row_key.lower() if row_key.lower() in dataset else row_key
|
|
123
|
+
try:
|
|
124
|
+
# Convert the raw value to engineering unit
|
|
125
|
+
dataset[mnemonics].data = np.polyval(
|
|
126
|
+
coeff_values, dataset[mnemonics].data
|
|
127
|
+
)
|
|
128
|
+
# Modify units attribute
|
|
129
|
+
if "unit" in row:
|
|
130
|
+
dataset[mnemonics].attrs.update({"units": row["unit"]})
|
|
131
|
+
except KeyError:
|
|
132
|
+
# TODO: Don't catch this error once packet definitions stabilize
|
|
133
|
+
logger.warning(f"Input dataset does not contain key: {row_key}")
|
|
134
|
+
else:
|
|
135
|
+
raise ValueError(
|
|
136
|
+
f"Unexpected conversion type: {row['convertAs']} encountered in"
|
|
137
|
+
f" engineering unit conversion table: {conversion_table_path}"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
return dataset
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def create_dataset(
|
|
144
|
+
packets: list[parser.Packet],
|
|
145
|
+
spacecraft_time_key: str = "shcoarse",
|
|
146
|
+
include_header: bool = True,
|
|
147
|
+
skip_keys: Optional[list[str]] = None,
|
|
148
|
+
) -> xr.Dataset:
|
|
149
|
+
"""
|
|
150
|
+
Create dataset for each metadata field.
|
|
151
|
+
|
|
152
|
+
Parameters
|
|
153
|
+
----------
|
|
154
|
+
packets : list[Packet]
|
|
155
|
+
Packet list.
|
|
156
|
+
spacecraft_time_key : str
|
|
157
|
+
Default is "shcoarse" because many instrument uses it, optional.
|
|
158
|
+
This key is used to get spacecraft time for epoch dimension.
|
|
159
|
+
include_header : bool
|
|
160
|
+
Whether to include CCSDS header data in the dataset, optional.
|
|
161
|
+
skip_keys : list
|
|
162
|
+
Keys to skip in the metadata, optional.
|
|
163
|
+
|
|
164
|
+
Returns
|
|
165
|
+
-------
|
|
166
|
+
dataset : xr.dataset
|
|
167
|
+
Dataset with all metadata field data in xr.DataArray.
|
|
168
|
+
"""
|
|
169
|
+
metadata_arrays = collections.defaultdict(list)
|
|
170
|
+
description_dict = {}
|
|
171
|
+
|
|
172
|
+
sorted_packets = sort_by_time(packets, spacecraft_time_key.upper())
|
|
173
|
+
|
|
174
|
+
for data_packet in sorted_packets:
|
|
175
|
+
data_to_include = (
|
|
176
|
+
(data_packet.header | data_packet.data)
|
|
177
|
+
if include_header
|
|
178
|
+
else data_packet.data
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Drop keys using skip_keys
|
|
182
|
+
if skip_keys is not None:
|
|
183
|
+
for key in skip_keys:
|
|
184
|
+
data_to_include.pop(key, None)
|
|
185
|
+
|
|
186
|
+
# Add metadata to array
|
|
187
|
+
for key, value in data_to_include.items():
|
|
188
|
+
# convert key to lower case to match SPDF requirement
|
|
189
|
+
data_key = key.lower()
|
|
190
|
+
metadata_arrays[data_key].append(value.raw_value)
|
|
191
|
+
# description should be same for all packets
|
|
192
|
+
description_dict[data_key] = (
|
|
193
|
+
value.long_description or value.short_description
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# NOTE: At this point, we keep epoch time as raw value from packet
|
|
197
|
+
# which is in seconds and spacecraft time. Some instrument uses this
|
|
198
|
+
# raw value in processing.
|
|
199
|
+
# Load the CDF attributes
|
|
200
|
+
cdf_manager = ImapCdfAttributes()
|
|
201
|
+
epoch_time = xr.DataArray(
|
|
202
|
+
metadata_arrays[spacecraft_time_key],
|
|
203
|
+
name="epoch",
|
|
204
|
+
dims=["epoch"],
|
|
205
|
+
attrs=cdf_manager.get_variable_attributes("epoch"),
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
dataset = xr.Dataset(
|
|
209
|
+
coords={"epoch": epoch_time},
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# create xarray dataset for each metadata field
|
|
213
|
+
for key, value in metadata_arrays.items():
|
|
214
|
+
# replace description and fieldname
|
|
215
|
+
data_attrs = cdf_manager.get_variable_attributes("metadata_attrs")
|
|
216
|
+
data_attrs["CATDESC"] = description_dict[key]
|
|
217
|
+
data_attrs["FIELDNAM"] = key
|
|
218
|
+
data_attrs["LABLAXIS"] = key
|
|
219
|
+
|
|
220
|
+
dataset[key] = xr.DataArray(
|
|
221
|
+
value,
|
|
222
|
+
dims=["epoch"],
|
|
223
|
+
attrs=data_attrs,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
return dataset
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _get_minimum_numpy_datatype( # noqa: PLR0912 - Too many branches
|
|
230
|
+
name: str, definition: xtcedef.XtcePacketDefinition, use_derived_value: bool = True
|
|
231
|
+
) -> Optional[str]:
|
|
232
|
+
"""
|
|
233
|
+
Get the minimum datatype for a given variable.
|
|
234
|
+
|
|
235
|
+
Parameters
|
|
236
|
+
----------
|
|
237
|
+
name : str
|
|
238
|
+
The variable name.
|
|
239
|
+
definition : xtcedef.XtcePacketDefinition
|
|
240
|
+
The XTCE packet definition.
|
|
241
|
+
use_derived_value : bool, default True
|
|
242
|
+
Whether or not the derived value from the XTCE definition was used.
|
|
243
|
+
|
|
244
|
+
Returns
|
|
245
|
+
-------
|
|
246
|
+
datatype : str
|
|
247
|
+
The minimum datatype.
|
|
248
|
+
"""
|
|
249
|
+
data_encoding = definition.named_parameters[name].parameter_type.encoding
|
|
250
|
+
|
|
251
|
+
if use_derived_value and isinstance(
|
|
252
|
+
definition.named_parameters[name].parameter_type,
|
|
253
|
+
xtcedef.EnumeratedParameterType,
|
|
254
|
+
):
|
|
255
|
+
# We don't have a way of knowing what is enumerated,
|
|
256
|
+
# let numpy infer the datatype
|
|
257
|
+
return None
|
|
258
|
+
elif isinstance(data_encoding, xtcedef.NumericDataEncoding):
|
|
259
|
+
if use_derived_value and (
|
|
260
|
+
data_encoding.context_calibrators is not None
|
|
261
|
+
or data_encoding.default_calibrator is not None
|
|
262
|
+
):
|
|
263
|
+
# If there are calibrators, we need to default to None and
|
|
264
|
+
# let numpy infer the datatype
|
|
265
|
+
return None
|
|
266
|
+
nbits = data_encoding.size_in_bits
|
|
267
|
+
if isinstance(data_encoding, xtcedef.IntegerDataEncoding):
|
|
268
|
+
datatype = "int"
|
|
269
|
+
if data_encoding.encoding == "unsigned":
|
|
270
|
+
datatype = "uint"
|
|
271
|
+
if nbits <= 8:
|
|
272
|
+
datatype += "8"
|
|
273
|
+
elif nbits <= 16:
|
|
274
|
+
datatype += "16"
|
|
275
|
+
elif nbits <= 32:
|
|
276
|
+
datatype += "32"
|
|
277
|
+
else:
|
|
278
|
+
datatype += "64"
|
|
279
|
+
elif isinstance(data_encoding, xtcedef.FloatDataEncoding):
|
|
280
|
+
datatype = "float"
|
|
281
|
+
if nbits == 32:
|
|
282
|
+
datatype += "32"
|
|
283
|
+
else:
|
|
284
|
+
datatype += "64"
|
|
285
|
+
elif isinstance(data_encoding, xtcedef.BinaryDataEncoding):
|
|
286
|
+
# TODO: Binary string representation right now, do we want bytes or
|
|
287
|
+
# something else like the new StringDType instead?
|
|
288
|
+
datatype = "str"
|
|
289
|
+
elif isinstance(data_encoding, xtcedef.StringDataEncoding):
|
|
290
|
+
# TODO: Use the new StringDType instead?
|
|
291
|
+
datatype = "str"
|
|
292
|
+
else:
|
|
293
|
+
raise ValueError(f"Unsupported data encoding: {data_encoding}")
|
|
294
|
+
|
|
295
|
+
return datatype
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def packet_file_to_datasets(
|
|
299
|
+
packet_file: Union[str, Path],
|
|
300
|
+
xtce_packet_definition: Union[str, Path],
|
|
301
|
+
use_derived_value: bool = False,
|
|
302
|
+
) -> dict[int, xr.Dataset]:
|
|
303
|
+
"""
|
|
304
|
+
Convert a packet file to xarray datasets.
|
|
305
|
+
|
|
306
|
+
The packet file can contain multiple apids and these will be separated
|
|
307
|
+
into distinct datasets, one per apid. The datasets will contain the
|
|
308
|
+
``derived_value``s of the data fields, and the ``raw_value``s if no
|
|
309
|
+
``derived_value`` is available. If there are conversions in the XTCE
|
|
310
|
+
packet definition, the ``derived_value`` will be the converted value.
|
|
311
|
+
The dimension of the dataset will be the time field in J2000 nanoseconds.
|
|
312
|
+
|
|
313
|
+
Parameters
|
|
314
|
+
----------
|
|
315
|
+
packet_file : str
|
|
316
|
+
Path to data packet path with filename.
|
|
317
|
+
xtce_packet_definition : str
|
|
318
|
+
Path to XTCE file with filename.
|
|
319
|
+
use_derived_value : bool, default False
|
|
320
|
+
Whether or not to use the derived value from the XTCE definition.
|
|
321
|
+
|
|
322
|
+
Returns
|
|
323
|
+
-------
|
|
324
|
+
datasets : dict
|
|
325
|
+
Mapping from apid to xarray dataset, one dataset per apid.
|
|
326
|
+
|
|
327
|
+
Notes
|
|
328
|
+
-----
|
|
329
|
+
This function only handles packet definitions with the same variable structure
|
|
330
|
+
across all packets with the same ApId. For example, this cannot be used for IDEX
|
|
331
|
+
due to the conditional XML structure defined for their science packet.
|
|
332
|
+
"""
|
|
333
|
+
# Set up containers to store our data
|
|
334
|
+
# We are getting a packet file that may contain multiple apids
|
|
335
|
+
# Each apid has consistent data fields, so we want to create a
|
|
336
|
+
# dataset per apid.
|
|
337
|
+
# {apid1: dataset1, apid2: dataset2, ...}
|
|
338
|
+
data_dict: dict[int, dict] = dict()
|
|
339
|
+
# Also keep track of the datatype mapping for each field
|
|
340
|
+
datatype_mapping: dict[int, dict] = dict()
|
|
341
|
+
# Keep track of which variables (keys) are in the dataset
|
|
342
|
+
variable_mapping: dict[int, set] = dict()
|
|
343
|
+
|
|
344
|
+
# Set up the parser from the input packet definition
|
|
345
|
+
packet_definition = xtcedef.XtcePacketDefinition(xtce_packet_definition)
|
|
346
|
+
packet_parser = parser.PacketParser(packet_definition)
|
|
347
|
+
|
|
348
|
+
with open(packet_file, "rb") as binary_data:
|
|
349
|
+
packet_generator = packet_parser.generator(binary_data)
|
|
350
|
+
for packet in packet_generator:
|
|
351
|
+
apid = packet.header["PKT_APID"].raw_value
|
|
352
|
+
if apid not in data_dict:
|
|
353
|
+
# This is the first packet for this APID
|
|
354
|
+
data_dict[apid] = collections.defaultdict(list)
|
|
355
|
+
datatype_mapping[apid] = dict()
|
|
356
|
+
variable_mapping[apid] = packet.data.keys()
|
|
357
|
+
if variable_mapping[apid] != packet.data.keys():
|
|
358
|
+
raise ValueError(
|
|
359
|
+
f"Packet fields do not match for APID {apid}. This could be "
|
|
360
|
+
f"due to a conditional packet definition in the XTCE, while this "
|
|
361
|
+
f"function currently only supports flat packet definitions."
|
|
362
|
+
f"\nExpected: {variable_mapping[apid]},\ngot: {packet.data.keys()}"
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
# TODO: Do we want to give an option to remove the header content?
|
|
366
|
+
packet_content = packet.data | packet.header
|
|
367
|
+
|
|
368
|
+
for key, value in packet_content.items():
|
|
369
|
+
val = value.raw_value
|
|
370
|
+
if use_derived_value:
|
|
371
|
+
# Use the derived value if it exists, otherwise use the raw value
|
|
372
|
+
val = value.derived_value or val
|
|
373
|
+
data_dict[apid][key].append(val)
|
|
374
|
+
if key not in datatype_mapping[apid]:
|
|
375
|
+
# Add this datatype to the mapping
|
|
376
|
+
datatype_mapping[apid][key] = _get_minimum_numpy_datatype(
|
|
377
|
+
key, packet_definition, use_derived_value=use_derived_value
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
dataset_by_apid = {}
|
|
381
|
+
|
|
382
|
+
for apid, data in data_dict.items():
|
|
383
|
+
# The time key is always the first key in the data dictionary on IMAP
|
|
384
|
+
time_key = next(iter(data.keys()))
|
|
385
|
+
# Convert to J2000 time and use that as our primary dimension
|
|
386
|
+
time_data = met_to_j2000ns(data[time_key])
|
|
387
|
+
ds = xr.Dataset(
|
|
388
|
+
{
|
|
389
|
+
key.lower(): (
|
|
390
|
+
"epoch",
|
|
391
|
+
np.asarray(list_of_values, dtype=datatype_mapping[apid][key]),
|
|
392
|
+
)
|
|
393
|
+
for key, list_of_values in data.items()
|
|
394
|
+
},
|
|
395
|
+
coords={"epoch": time_data},
|
|
396
|
+
)
|
|
397
|
+
ds = ds.sortby("epoch")
|
|
398
|
+
|
|
399
|
+
# Strip any leading characters before "." from the field names which was due
|
|
400
|
+
# to the packet_name being a part of the variable name in the XTCE definition
|
|
401
|
+
ds = ds.rename(
|
|
402
|
+
{
|
|
403
|
+
# partition splits the string into 3 parts: before ".", ".", after "."
|
|
404
|
+
# if there was no ".", the second part is an empty string, so we use
|
|
405
|
+
# the original key in that case
|
|
406
|
+
key: key.partition(".")[2] or key
|
|
407
|
+
for key in ds.variables
|
|
408
|
+
}
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
dataset_by_apid[apid] = ds
|
|
412
|
+
|
|
413
|
+
return dataset_by_apid
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 The Regents of the University of Colorado.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: imap-processing
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: IMAP Science Operations Center Processing
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: IMAP,SDC,SOC,Science Operations
|
|
7
|
+
Author: IMAP SDC Developers
|
|
8
|
+
Author-email: imap-sdc@lists.lasp.colorado.edu
|
|
9
|
+
Requires-Python: >=3.9,<4
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Natural Language :: English
|
|
14
|
+
Classifier: Operating System :: MacOS
|
|
15
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
16
|
+
Classifier: Operating System :: POSIX
|
|
17
|
+
Classifier: Operating System :: Unix
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering
|
|
24
|
+
Classifier: Topic :: Software Development
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Provides-Extra: doc
|
|
27
|
+
Provides-Extra: test
|
|
28
|
+
Provides-Extra: tools
|
|
29
|
+
Requires-Dist: cdflib (==1.2.6)
|
|
30
|
+
Requires-Dist: imap-data-access (>=0.5.0)
|
|
31
|
+
Requires-Dist: mypy (==1.10.1) ; extra == "dev"
|
|
32
|
+
Requires-Dist: numpy (<=3)
|
|
33
|
+
Requires-Dist: numpydoc (>=1.5.0,<2.0.0) ; extra == "doc"
|
|
34
|
+
Requires-Dist: openpyxl (>=3.0.7) ; extra == "test" or extra == "tools"
|
|
35
|
+
Requires-Dist: pandas (>=2.0.0) ; extra == "tools"
|
|
36
|
+
Requires-Dist: pre-commit (>=3.3.3,<4.0.0) ; extra == "dev"
|
|
37
|
+
Requires-Dist: pydata-sphinx-theme ; extra == "doc"
|
|
38
|
+
Requires-Dist: pytest (>=6.2.5) ; extra == "test"
|
|
39
|
+
Requires-Dist: pytest-cov (>=4.0.0,<5.0.0) ; extra == "test"
|
|
40
|
+
Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
|
|
41
|
+
Requires-Dist: requests (>=2.32.3,<3.0.0) ; extra == "test"
|
|
42
|
+
Requires-Dist: ruff (==0.2.1) ; extra == "dev"
|
|
43
|
+
Requires-Dist: space_packet_parser (>=4.2.0)
|
|
44
|
+
Requires-Dist: sphinx ; extra == "doc"
|
|
45
|
+
Requires-Dist: sphinxcontrib-openapi (>=0.8.3,<0.9.0) ; extra == "doc"
|
|
46
|
+
Requires-Dist: spiceypy (>=6.0.0)
|
|
47
|
+
Requires-Dist: xarray (>=2023.0.0)
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# IMAP (Interstellar Mapping and Acceleration Probe)
|
|
51
|
+
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
52
|
+
[](#contributors-)
|
|
53
|
+
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
54
|
+
[](https://imap-processing.readthedocs.io/en/latest/)
|
|
55
|
+
<!-- DOI-BADGE -->
|
|
56
|
+
[](https://zenodo.org/badge/latestdoi/654679818)
|
|
57
|
+
|
|
58
|
+
The Interstellar Mapping and Acceleration Probe (IMAP) is an exciting project aimed at studying the interstellar medium and investigating the acceleration mechanisms of particles within our galaxy. IMAP utilizes cutting-edge technology and advanced instrumentation to gather valuable data and expand our understanding of space.
|
|
59
|
+
|
|
60
|
+
The IMAP project's Git repository serves as a centralized hub for collaboration among researchers, scientists, and developers involved in the project. It provides a platform for version control, code sharing, issue tracking, and documentation, fostering a collaborative environment for advancing the goals of the IMAP mission.
|
|
61
|
+
|
|
62
|
+
Through the Git repository, contributors can access project resources, explore the codebase, propose enhancements or bug fixes, and participate in discussions with other team members. This collaborative approach promotes efficient development and fosters innovation in the pursuit of interstellar mapping and particle acceleration research.
|
|
63
|
+
|
|
64
|
+
Join the IMAP Git repository to be part of an exciting scientific endeavor, contribute your expertise, and help unlock the mysteries of the interstellar medium and particle acceleration in our galaxy. Together, we can advance our knowledge of the cosmos and pave the way for future discoveries in space exploration.
|
|
65
|
+
|
|
66
|
+
[IMAP Website](https://imap.princeton.edu/)
|
|
67
|
+
|
|
68
|
+
[IMAP Processing Documentation](https://imap-processing.readthedocs.io/en/latest/)
|
|
69
|
+
|
|
70
|
+
# Credits
|
|
71
|
+
[LASP (Laboratory of Atmospheric and Space Physics)](https://lasp.colorado.edu/)
|
|
72
|
+
## Contributors ✨
|
|
73
|
+
|
|
74
|
+
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
|
75
|
+
|
|
76
|
+
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
|
77
|
+
<!-- prettier-ignore-start -->
|
|
78
|
+
<!-- markdownlint-disable -->
|
|
79
|
+
<table>
|
|
80
|
+
<tbody>
|
|
81
|
+
<tr>
|
|
82
|
+
<td align="center" valign="top" width="14.28%"><a href="http://greglucas.github.io"><img src="https://avatars.githubusercontent.com/u/12417828?v=4?s=100" width="100px;" alt="Greg Lucas"/><br /><sub><b>Greg Lucas</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=greglucas" title="Code">💻</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=greglucas" title="Documentation">📖</a> <a href="#ideas-greglucas" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-greglucas" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-greglucas" title="Maintenance">🚧</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/pulls?q=is%3Apr+reviewed-by%3Agreglucas" title="Reviewed Pull Requests">👀</a></td>
|
|
83
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tech3371"><img src="https://avatars.githubusercontent.com/u/36522642?v=4?s=100" width="100px;" alt="Tenzin Choedon"/><br /><sub><b>Tenzin Choedon</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=tech3371" title="Code">💻</a> <a href="#ideas-tech3371" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-tech3371" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#example-tech3371" title="Examples">💡</a> <a href="#maintenance-tech3371" title="Maintenance">🚧</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/pulls?q=is%3Apr+reviewed-by%3Atech3371" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=tech3371" title="Documentation">📖</a></td>
|
|
84
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/laspsandoval"><img src="https://avatars.githubusercontent.com/u/46567335?v=4?s=100" width="100px;" alt="Laura Sandoval"/><br /><sub><b>Laura Sandoval</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/pulls?q=is%3Apr+reviewed-by%3Alaspsandoval" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=laspsandoval" title="Code">💻</a> <a href="#infra-laspsandoval" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#ideas-laspsandoval" title="Ideas, Planning, & Feedback">🤔</a></td>
|
|
85
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sdhoyt"><img src="https://avatars.githubusercontent.com/u/7146374?v=4?s=100" width="100px;" alt="Sean Hoyt"/><br /><sub><b>Sean Hoyt</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=sdhoyt" title="Code">💻</a> <a href="#ideas-sdhoyt" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-sdhoyt" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/pulls?q=is%3Apr+reviewed-by%3Asdhoyt" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=sdhoyt" title="Documentation">📖</a> <a href="#maintenance-sdhoyt" title="Maintenance">🚧</a></td>
|
|
86
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/GFMoraga"><img src="https://avatars.githubusercontent.com/u/104743000?v=4?s=100" width="100px;" alt="Gabriel M."/><br /><sub><b>Gabriel M.</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=GFMoraga" title="Code">💻</a> <a href="#ideas-GFMoraga" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-GFMoraga" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/pulls?q=is%3Apr+reviewed-by%3AGFMoraga" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-GFMoraga" title="Maintenance">🚧</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=GFMoraga" title="Documentation">📖</a></td>
|
|
87
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bourque"><img src="https://avatars.githubusercontent.com/u/2250769?v=4?s=100" width="100px;" alt="Matthew Bourque"/><br /><sub><b>Matthew Bourque</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=bourque" title="Code">💻</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=bourque" title="Documentation">📖</a> <a href="#ideas-bourque" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-bourque" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/pulls?q=is%3Apr+reviewed-by%3Abourque" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-bourque" title="Maintenance">🚧</a></td>
|
|
88
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/maxinelasp"><img src="https://avatars.githubusercontent.com/u/117409426?v=4?s=100" width="100px;" alt="Maxine Hartnett"/><br /><sub><b>Maxine Hartnett</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=maxinelasp" title="Code">💻</a> <a href="#ideas-maxinelasp" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-maxinelasp" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/pulls?q=is%3Apr+reviewed-by%3Amaxinelasp" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=maxinelasp" title="Documentation">📖</a> <a href="#maintenance-maxinelasp" title="Maintenance">🚧</a></td>
|
|
89
|
+
</tr>
|
|
90
|
+
<tr>
|
|
91
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bryan-harter"><img src="https://avatars.githubusercontent.com/u/41062454?v=4?s=100" width="100px;" alt="Bryan Harter"/><br /><sub><b>Bryan Harter</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=bryan-harter" title="Code">💻</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=bryan-harter" title="Documentation">📖</a></td>
|
|
92
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mstrumik"><img src="https://avatars.githubusercontent.com/u/142874888?v=4?s=100" width="100px;" alt="mstrumik"/><br /><sub><b>mstrumik</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/pulls?q=is%3Apr+reviewed-by%3Amstrumik" title="Reviewed Pull Requests">👀</a></td>
|
|
93
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vmartinez-cu"><img src="https://avatars.githubusercontent.com/u/39746325?v=4?s=100" width="100px;" alt="vmartinez-cu"/><br /><sub><b>vmartinez-cu</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/pulls?q=is%3Apr+reviewed-by%3Avmartinez-cu" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=vmartinez-cu" title="Code">💻</a></td>
|
|
94
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/subagonsouth"><img src="https://avatars.githubusercontent.com/u/16110870?v=4?s=100" width="100px;" alt="Tim Plummer"/><br /><sub><b>Tim Plummer</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/pulls?q=is%3Apr+reviewed-by%3Asubagonsouth" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=subagonsouth" title="Code">💻</a></td>
|
|
95
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/daralynnrhode"><img src="https://avatars.githubusercontent.com/u/143308810?v=4?s=100" width="100px;" alt="Daralynn Rhode"/><br /><sub><b>Daralynn Rhode</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=daralynnrhode" title="Code">💻</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=daralynnrhode" title="Documentation">📖</a></td>
|
|
96
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/anamanica"><img src="https://avatars.githubusercontent.com/u/171708990?v=4?s=100" width="100px;" alt="anamanica"/><br /><sub><b>anamanica</b></sub></a><br /><a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=anamanica" title="Code">💻</a> <a href="https://github.com/IMAP-Science-Operations-Center/imap_processing/commits?author=anamanica" title="Documentation">📖</a></td>
|
|
97
|
+
</tr>
|
|
98
|
+
</tbody>
|
|
99
|
+
</table>
|
|
100
|
+
|
|
101
|
+
<!-- markdownlint-restore -->
|
|
102
|
+
<!-- prettier-ignore-end -->
|
|
103
|
+
|
|
104
|
+
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
|
105
|
+
|
|
106
|
+
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
|
107
|
+
|