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,150 @@
|
|
|
1
|
+
KPL/LSK
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
LEAPSECONDS KERNEL FILE
|
|
5
|
+
===========================================================================
|
|
6
|
+
|
|
7
|
+
Modifications:
|
|
8
|
+
--------------
|
|
9
|
+
|
|
10
|
+
2016, Jul. 14 NJB Modified file to account for the leapsecond that
|
|
11
|
+
will occur on December 31, 2016.
|
|
12
|
+
|
|
13
|
+
2015, Jan. 5 NJB Modified file to account for the leapsecond that
|
|
14
|
+
will occur on June 30, 2015.
|
|
15
|
+
|
|
16
|
+
2012, Jan. 5 NJB Modified file to account for the leapsecond that
|
|
17
|
+
will occur on June 30, 2012.
|
|
18
|
+
|
|
19
|
+
2008, Jul. 7 NJB Modified file to account for the leapsecond that
|
|
20
|
+
will occur on December 31, 2008.
|
|
21
|
+
|
|
22
|
+
2005, Aug. 3 NJB Modified file to account for the leapsecond that
|
|
23
|
+
will occur on December 31, 2005.
|
|
24
|
+
|
|
25
|
+
1998, Jul 17 WLT Modified file to account for the leapsecond that
|
|
26
|
+
will occur on December 31, 1998.
|
|
27
|
+
|
|
28
|
+
1997, Feb 22 WLT Modified file to account for the leapsecond that
|
|
29
|
+
will occur on June 30, 1997.
|
|
30
|
+
|
|
31
|
+
1995, Dec 14 KSZ Corrected date of last leapsecond from 1-1-95
|
|
32
|
+
to 1-1-96.
|
|
33
|
+
|
|
34
|
+
1995, Oct 25 WLT Modified file to account for the leapsecond that
|
|
35
|
+
will occur on Dec 31, 1995.
|
|
36
|
+
|
|
37
|
+
1994, Jun 16 WLT Modified file to account for the leapsecond on
|
|
38
|
+
June 30, 1994.
|
|
39
|
+
|
|
40
|
+
1993, Feb. 22 CHA Modified file to account for the leapsecond on
|
|
41
|
+
June 30, 1993.
|
|
42
|
+
|
|
43
|
+
1992, Mar. 6 HAN Modified file to account for the leapsecond on
|
|
44
|
+
June 30, 1992.
|
|
45
|
+
|
|
46
|
+
1990, Oct. 8 HAN Modified file to account for the leapsecond on
|
|
47
|
+
Dec. 31, 1990.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
Explanation:
|
|
51
|
+
------------
|
|
52
|
+
|
|
53
|
+
The contents of this file are used by the routine DELTET to compute the
|
|
54
|
+
time difference
|
|
55
|
+
|
|
56
|
+
[1] DELTA_ET = ET - UTC
|
|
57
|
+
|
|
58
|
+
the increment to be applied to UTC to give ET.
|
|
59
|
+
|
|
60
|
+
The difference between UTC and TAI,
|
|
61
|
+
|
|
62
|
+
[2] DELTA_AT = TAI - UTC
|
|
63
|
+
|
|
64
|
+
is always an integral number of seconds. The value of DELTA_AT was 10
|
|
65
|
+
seconds in January 1972, and increases by one each time a leap second
|
|
66
|
+
is declared. Combining [1] and [2] gives
|
|
67
|
+
|
|
68
|
+
[3] DELTA_ET = ET - (TAI - DELTA_AT)
|
|
69
|
+
|
|
70
|
+
= (ET - TAI) + DELTA_AT
|
|
71
|
+
|
|
72
|
+
The difference (ET - TAI) is periodic, and is given by
|
|
73
|
+
|
|
74
|
+
[4] ET - TAI = DELTA_T_A + K sin E
|
|
75
|
+
|
|
76
|
+
where DELTA_T_A and K are constant, and E is the eccentric anomaly of the
|
|
77
|
+
heliocentric orbit of the Earth-Moon barycenter. Equation [4], which ignores
|
|
78
|
+
small-period fluctuations, is accurate to about 0.000030 seconds.
|
|
79
|
+
|
|
80
|
+
The eccentric anomaly E is given by
|
|
81
|
+
|
|
82
|
+
[5] E = M + EB sin M
|
|
83
|
+
|
|
84
|
+
where M is the mean anomaly, which in turn is given by
|
|
85
|
+
|
|
86
|
+
[6] M = M + M t
|
|
87
|
+
0 1
|
|
88
|
+
|
|
89
|
+
where t is the number of ephemeris seconds past J2000.
|
|
90
|
+
|
|
91
|
+
Thus, in order to compute DELTA_ET, the following items are necessary.
|
|
92
|
+
|
|
93
|
+
DELTA_TA
|
|
94
|
+
K
|
|
95
|
+
EB
|
|
96
|
+
M0
|
|
97
|
+
M1
|
|
98
|
+
DELTA_AT after each leap second.
|
|
99
|
+
|
|
100
|
+
The numbers, and the formulation, are taken from the following sources.
|
|
101
|
+
|
|
102
|
+
1) Moyer, T.D., Transformation from Proper Time on Earth to
|
|
103
|
+
Coordinate Time in Solar System Barycentric Space-Time Frame
|
|
104
|
+
of Reference, Parts 1 and 2, Celestial Mechanics 23 (1981),
|
|
105
|
+
33-56 and 57-68.
|
|
106
|
+
|
|
107
|
+
2) Moyer, T.D., Effects of Conversion to the J2000 Astronomical
|
|
108
|
+
Reference System on Algorithms for Computing Time Differences
|
|
109
|
+
and Clock Rates, JPL IOM 314.5--942, 1 October 1985.
|
|
110
|
+
|
|
111
|
+
The variable names used above are consistent with those used in the
|
|
112
|
+
Astronomical Almanac.
|
|
113
|
+
|
|
114
|
+
\begindata
|
|
115
|
+
|
|
116
|
+
DELTET/DELTA_T_A = 32.184
|
|
117
|
+
DELTET/K = 1.657D-3
|
|
118
|
+
DELTET/EB = 1.671D-2
|
|
119
|
+
DELTET/M = ( 6.239996D0 1.99096871D-7 )
|
|
120
|
+
|
|
121
|
+
DELTET/DELTA_AT = ( 10, @1972-JAN-1
|
|
122
|
+
11, @1972-JUL-1
|
|
123
|
+
12, @1973-JAN-1
|
|
124
|
+
13, @1974-JAN-1
|
|
125
|
+
14, @1975-JAN-1
|
|
126
|
+
15, @1976-JAN-1
|
|
127
|
+
16, @1977-JAN-1
|
|
128
|
+
17, @1978-JAN-1
|
|
129
|
+
18, @1979-JAN-1
|
|
130
|
+
19, @1980-JAN-1
|
|
131
|
+
20, @1981-JUL-1
|
|
132
|
+
21, @1982-JUL-1
|
|
133
|
+
22, @1983-JUL-1
|
|
134
|
+
23, @1985-JUL-1
|
|
135
|
+
24, @1988-JAN-1
|
|
136
|
+
25, @1990-JAN-1
|
|
137
|
+
26, @1991-JAN-1
|
|
138
|
+
27, @1992-JUL-1
|
|
139
|
+
28, @1993-JUL-1
|
|
140
|
+
29, @1994-JUL-1
|
|
141
|
+
30, @1996-JAN-1
|
|
142
|
+
31, @1997-JUL-1
|
|
143
|
+
32, @1999-JAN-1
|
|
144
|
+
33, @2006-JAN-1
|
|
145
|
+
34, @2009-JAN-1
|
|
146
|
+
35, @2012-JUL-1
|
|
147
|
+
36, @2015-JUL-1
|
|
148
|
+
37, @2017-JAN-1 )
|
|
149
|
+
|
|
150
|
+
\begintext
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"""Tests coverage for imap_processing/spice/geometry.py"""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import pytest
|
|
6
|
+
import spiceypy as spice
|
|
7
|
+
|
|
8
|
+
from imap_processing.spice.geometry import (
|
|
9
|
+
SpiceBody,
|
|
10
|
+
SpiceFrame,
|
|
11
|
+
frame_transform,
|
|
12
|
+
get_rotation_matrix,
|
|
13
|
+
get_spacecraft_spin_phase,
|
|
14
|
+
get_spin_data,
|
|
15
|
+
imap_state,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.mark.parametrize(
|
|
20
|
+
"et",
|
|
21
|
+
[
|
|
22
|
+
798033670,
|
|
23
|
+
np.linspace(798033670, 798033770),
|
|
24
|
+
],
|
|
25
|
+
)
|
|
26
|
+
def test_imap_state(et, use_test_metakernel):
|
|
27
|
+
"""Test coverage for imap_state()"""
|
|
28
|
+
state = imap_state(et, observer=SpiceBody.EARTH)
|
|
29
|
+
if hasattr(et, "__len__"):
|
|
30
|
+
np.testing.assert_array_equal(state.shape, (len(et), 6))
|
|
31
|
+
else:
|
|
32
|
+
assert state.shape == (6,)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@pytest.mark.external_kernel()
|
|
36
|
+
@pytest.mark.metakernel("imap_ena_sim_metakernel.template")
|
|
37
|
+
def test_imap_state_ecliptic(use_test_metakernel):
|
|
38
|
+
"""Tests retrieving IMAP state in the ECLIPJ2000 frame"""
|
|
39
|
+
state = imap_state(798033670)
|
|
40
|
+
assert state.shape == (6,)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@pytest.mark.usefixtures("_set_spin_data_filepath")
|
|
44
|
+
@pytest.mark.parametrize(
|
|
45
|
+
"query_met_times, expected_type, expected_length",
|
|
46
|
+
[
|
|
47
|
+
(453051323.0, float, None), # Scalar test
|
|
48
|
+
(np.array([453051323.0, 453051324.0]), float, 2), # Array test
|
|
49
|
+
(np.array([]), None, 0), # Empty array test
|
|
50
|
+
(np.array([453051323.0]), float, 1), # Single element array test
|
|
51
|
+
# 452995203.0 is a midnight time which should have invalid spin
|
|
52
|
+
# phase and period flags on in the spin data file. The spin phase
|
|
53
|
+
# should be invalid.
|
|
54
|
+
(452995203.0, np.nan, None),
|
|
55
|
+
# Test that five minutes after midnight is also invalid since
|
|
56
|
+
# first 10 minutes after midnight are invalid.
|
|
57
|
+
(np.arange(452995203.0, 452995203.0 + 300), np.nan, 300),
|
|
58
|
+
(
|
|
59
|
+
[453011323.0],
|
|
60
|
+
np.nan,
|
|
61
|
+
1,
|
|
62
|
+
), # Test for spin phase that's outside of spin phase range
|
|
63
|
+
(
|
|
64
|
+
453011323.0,
|
|
65
|
+
np.nan,
|
|
66
|
+
None,
|
|
67
|
+
), # Test for spin phase that's outside of spin phase range
|
|
68
|
+
],
|
|
69
|
+
)
|
|
70
|
+
def test_get_spacecraft_spin_phase(query_met_times, expected_type, expected_length):
|
|
71
|
+
"""Test get_spacecraft_spin_phase() with generated spin data."""
|
|
72
|
+
# Call the function
|
|
73
|
+
spin_phases = get_spacecraft_spin_phase(query_met_times=query_met_times)
|
|
74
|
+
|
|
75
|
+
# Check the type of the result
|
|
76
|
+
if expected_type is np.nan:
|
|
77
|
+
assert np.isnan(spin_phases).all(), "Spin phase must be NaN."
|
|
78
|
+
elif isinstance(expected_type, float):
|
|
79
|
+
assert isinstance(spin_phases, float), "Spin phase must be a float."
|
|
80
|
+
|
|
81
|
+
# If the expected length is None, it means we're testing a scalar
|
|
82
|
+
if expected_length is None:
|
|
83
|
+
assert isinstance(spin_phases, float), "Spin phase must be a float."
|
|
84
|
+
else:
|
|
85
|
+
assert (
|
|
86
|
+
len(spin_phases) == expected_length
|
|
87
|
+
), f"Spin phase must have length {expected_length} for array input."
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@pytest.mark.usefixtures("_set_spin_data_filepath")
|
|
91
|
+
def test_get_spin_data():
|
|
92
|
+
"""Test get_spin_data() with generated spin data."""
|
|
93
|
+
|
|
94
|
+
spin_data = get_spin_data()
|
|
95
|
+
|
|
96
|
+
(
|
|
97
|
+
np.testing.assert_array_equal(spin_data["spin_number"], np.arange(5761)),
|
|
98
|
+
"One day should have 5,761 records of 15 seconds when including end_met.",
|
|
99
|
+
)
|
|
100
|
+
assert isinstance(spin_data, pd.DataFrame), "Return type must be pandas.DataFrame."
|
|
101
|
+
|
|
102
|
+
assert set(spin_data.columns) == {
|
|
103
|
+
"spin_number",
|
|
104
|
+
"spin_start_sec",
|
|
105
|
+
"spin_start_subsec",
|
|
106
|
+
"spin_period_sec",
|
|
107
|
+
"spin_period_valid",
|
|
108
|
+
"spin_phase_valid",
|
|
109
|
+
"spin_period_source",
|
|
110
|
+
"thruster_firing",
|
|
111
|
+
"spin_start_time",
|
|
112
|
+
}, "Spin data must have the specified fields."
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def test_frame_transform(furnish_kernels):
|
|
116
|
+
"""Test transformation of vectors from one frame to another, with the option
|
|
117
|
+
to normalize the result."""
|
|
118
|
+
# This test requires an IMAP attitude kernel and pointing (despun) kernel
|
|
119
|
+
kernels = [
|
|
120
|
+
"naif0012.tls",
|
|
121
|
+
"imap_wkcp.tf",
|
|
122
|
+
"imap_science_0001.tf",
|
|
123
|
+
"sim_1yr_imap_attitude.bc",
|
|
124
|
+
"sim_1yr_imap_pointing_frame.bc",
|
|
125
|
+
]
|
|
126
|
+
with furnish_kernels(kernels):
|
|
127
|
+
# Test single et and position calculation
|
|
128
|
+
et_0 = spice.utc2et("2025-04-30T12:00:00.000")
|
|
129
|
+
position = np.arange(3) + 1
|
|
130
|
+
result_0 = frame_transform(
|
|
131
|
+
et_0, position, SpiceFrame.IMAP_ULTRA_45, SpiceFrame.IMAP_DPS
|
|
132
|
+
)
|
|
133
|
+
# compare against pure SPICE calculation
|
|
134
|
+
rotation_matrix = spice.pxform(
|
|
135
|
+
SpiceFrame.IMAP_ULTRA_45.name, SpiceFrame.IMAP_DPS.name, et_0
|
|
136
|
+
)
|
|
137
|
+
spice_result = spice.mxv(rotation_matrix, position)
|
|
138
|
+
np.testing.assert_allclose(result_0, spice_result, atol=1e-12)
|
|
139
|
+
|
|
140
|
+
# test multiple et and position calculation
|
|
141
|
+
ets = np.array([et_0, et_0 + 10])
|
|
142
|
+
positions = np.array([[1, 1, 1], [1, 2, 3]])
|
|
143
|
+
vec_result = frame_transform(
|
|
144
|
+
ets, positions, SpiceFrame.IMAP_HI_90, SpiceFrame.IMAP_DPS
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
assert vec_result.shape == (2, 3)
|
|
148
|
+
# compare with direct spice calculations
|
|
149
|
+
for et, pos, result in zip(ets, positions, vec_result):
|
|
150
|
+
rotation_matrix = spice.pxform(
|
|
151
|
+
SpiceFrame.IMAP_HI_90.name, SpiceFrame.IMAP_DPS.name, et
|
|
152
|
+
)
|
|
153
|
+
spice_result = spice.mxv(rotation_matrix, pos)
|
|
154
|
+
np.testing.assert_allclose(result, spice_result, atol=1e-12)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def test_frame_transform_exceptions():
|
|
158
|
+
"""Test that the proper exceptions get raised when input arguments are invalid."""
|
|
159
|
+
with pytest.raises(
|
|
160
|
+
ValueError, match="Position vectors with one dimension must have 3 elements."
|
|
161
|
+
):
|
|
162
|
+
frame_transform(
|
|
163
|
+
0, np.arange(4), SpiceFrame.IMAP_SPACECRAFT, SpiceFrame.IMAP_CODICE
|
|
164
|
+
)
|
|
165
|
+
with pytest.raises(
|
|
166
|
+
ValueError,
|
|
167
|
+
match="Ephemeris time must be float when single position vector is provided.",
|
|
168
|
+
):
|
|
169
|
+
frame_transform(
|
|
170
|
+
np.asarray(0),
|
|
171
|
+
np.array([1, 0, 0]),
|
|
172
|
+
SpiceFrame.ECLIPJ2000,
|
|
173
|
+
SpiceFrame.IMAP_HIT,
|
|
174
|
+
)
|
|
175
|
+
with pytest.raises(ValueError, match="Invalid position shape: "):
|
|
176
|
+
frame_transform(
|
|
177
|
+
np.arange(2),
|
|
178
|
+
np.arange(4).reshape((2, 2)),
|
|
179
|
+
SpiceFrame.ECLIPJ2000,
|
|
180
|
+
SpiceFrame.IMAP_HIT,
|
|
181
|
+
)
|
|
182
|
+
with pytest.raises(
|
|
183
|
+
ValueError,
|
|
184
|
+
match="Mismatch in number of position vectors and Ephemeris times provided.",
|
|
185
|
+
):
|
|
186
|
+
frame_transform(
|
|
187
|
+
np.arange(2),
|
|
188
|
+
np.arange(9).reshape((3, 3)),
|
|
189
|
+
SpiceFrame.ECLIPJ2000,
|
|
190
|
+
SpiceFrame.IMAP_HIT,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def test_get_rotation_matrix(furnish_kernels):
|
|
195
|
+
"""Test coverage for get_rotation_matrix()."""
|
|
196
|
+
kernels = [
|
|
197
|
+
"naif0012.tls",
|
|
198
|
+
"imap_wkcp.tf",
|
|
199
|
+
"imap_science_0001.tf",
|
|
200
|
+
"sim_1yr_imap_attitude.bc",
|
|
201
|
+
"sim_1yr_imap_pointing_frame.bc",
|
|
202
|
+
]
|
|
203
|
+
with furnish_kernels(kernels):
|
|
204
|
+
et = spice.utc2et("2025-09-30T12:00:00.000")
|
|
205
|
+
# test input of float
|
|
206
|
+
rotation = get_rotation_matrix(
|
|
207
|
+
et, SpiceFrame.IMAP_IDEX, SpiceFrame.IMAP_SPACECRAFT
|
|
208
|
+
)
|
|
209
|
+
assert rotation.shape == (3, 3)
|
|
210
|
+
# test array of et input
|
|
211
|
+
rotation = get_rotation_matrix(
|
|
212
|
+
np.arange(10) + et, SpiceFrame.IMAP_IDEX, SpiceFrame.IMAP_SPACECRAFT
|
|
213
|
+
)
|
|
214
|
+
assert rotation.shape == (10, 3, 3)
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"""Tests coverage for imap_processing/spice/kernels.py"""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
import spiceypy as spice
|
|
6
|
+
from spiceypy.utils.exceptions import SpiceyError
|
|
7
|
+
|
|
8
|
+
from imap_processing.spice.kernels import (
|
|
9
|
+
_average_quaternions,
|
|
10
|
+
_create_rotation_matrix,
|
|
11
|
+
_get_et_times,
|
|
12
|
+
create_pointing_frame,
|
|
13
|
+
ensure_spice,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture()
|
|
18
|
+
def pointing_frame_kernels(spice_test_data_path):
|
|
19
|
+
"""List SPICE kernels."""
|
|
20
|
+
required_kernels = [
|
|
21
|
+
"imap_science_0001.tf",
|
|
22
|
+
"imap_sclk_0000.tsc",
|
|
23
|
+
"imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
24
|
+
"imap_wkcp.tf",
|
|
25
|
+
"naif0012.tls",
|
|
26
|
+
]
|
|
27
|
+
kernels = [str(spice_test_data_path / kernel) for kernel in required_kernels]
|
|
28
|
+
return kernels
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.fixture()
|
|
32
|
+
def multiple_pointing_kernels(spice_test_data_path):
|
|
33
|
+
"""List SPICE kernels."""
|
|
34
|
+
required_kernels = [
|
|
35
|
+
"imap_science_0001.tf",
|
|
36
|
+
"imap_sclk_0000.tsc",
|
|
37
|
+
"sim_1yr_imap_attitude.bc",
|
|
38
|
+
"imap_wkcp.tf",
|
|
39
|
+
"naif0012.tls",
|
|
40
|
+
]
|
|
41
|
+
kernels = [str(spice_test_data_path / kernel) for kernel in required_kernels]
|
|
42
|
+
return kernels
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@pytest.fixture()
|
|
46
|
+
def et_times(pointing_frame_kernels):
|
|
47
|
+
"""Tests get_et_times function."""
|
|
48
|
+
spice.furnsh(pointing_frame_kernels)
|
|
49
|
+
|
|
50
|
+
ck_kernel, _, _, _ = spice.kdata(0, "ck")
|
|
51
|
+
ck_cover = spice.ckcov(ck_kernel, -43000, True, "INTERVAL", 0, "TDB")
|
|
52
|
+
et_start, et_end = spice.wnfetd(ck_cover, 0)
|
|
53
|
+
et_times = _get_et_times(et_start, et_end)
|
|
54
|
+
|
|
55
|
+
return et_times
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@ensure_spice
|
|
59
|
+
def single_wrap_et2utc(et, fmt, prec):
|
|
60
|
+
"""Directly decorate a spice function with ensure_spice for use in tests"""
|
|
61
|
+
return spice.et2utc(et, fmt, prec)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@ensure_spice
|
|
65
|
+
def double_wrap_et2utc(et, fmt, prec):
|
|
66
|
+
"""Decorate a spice function twice with ensure_spice for use in tests. This
|
|
67
|
+
simulates some decorated outer functions that call lower level functions
|
|
68
|
+
that are already decorated."""
|
|
69
|
+
return single_wrap_et2utc(et, fmt, prec)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@ensure_spice(time_kernels_only=True)
|
|
73
|
+
def single_wrap_et2utc_tk_only(et, fmt, prec):
|
|
74
|
+
"""Directly wrap a spice function with optional time_kernels_only set True"""
|
|
75
|
+
return spice.et2utc(et, fmt, prec)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@ensure_spice(time_kernels_only=True)
|
|
79
|
+
def double_wrap_et2utc_tk_only(et, fmt, prec):
|
|
80
|
+
"""Decorate a spice function twice with ensure_spice for use in tests. This
|
|
81
|
+
simulates some decorated outer functions that call lower level functions
|
|
82
|
+
that are already decorated."""
|
|
83
|
+
return single_wrap_et2utc(et, fmt, prec)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@pytest.mark.parametrize(
|
|
87
|
+
"func",
|
|
88
|
+
[
|
|
89
|
+
single_wrap_et2utc,
|
|
90
|
+
single_wrap_et2utc_tk_only,
|
|
91
|
+
double_wrap_et2utc,
|
|
92
|
+
double_wrap_et2utc_tk_only,
|
|
93
|
+
],
|
|
94
|
+
)
|
|
95
|
+
def test_ensure_spice_emus_mk_path(func, use_test_metakernel):
|
|
96
|
+
"""Test functionality of ensure spice with SPICE_METAKERNEL set"""
|
|
97
|
+
assert func(577365941.184, "ISOC", 3) == "2018-04-18T23:24:31.998"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@pytest.mark.xfail(reason="Fix this test once we add metakernel in the imap_cli")
|
|
101
|
+
@pytest.mark.usefixtures("_unset_metakernel_path")
|
|
102
|
+
def test_ensure_spice_time_kernels():
|
|
103
|
+
"""Test functionality of ensure spice with timekernels set"""
|
|
104
|
+
wrapped = ensure_spice(spice.et2utc, time_kernels_only=True)
|
|
105
|
+
# TODO: Update/remove this test when a decision has been made about
|
|
106
|
+
# whether IMAP will use the time_kernels_only functionality and the
|
|
107
|
+
# ensure_spice decorator has been update.
|
|
108
|
+
with pytest.raises(NotImplementedError):
|
|
109
|
+
_ = wrapped(577365941.184, "ISOC", 3) == "2018-04-18T23:24:31.998"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@pytest.mark.xfail(reason="Fix this test once we add metakernel in the imap_cli")
|
|
113
|
+
@pytest.mark.usefixtures("_unset_metakernel_path")
|
|
114
|
+
def test_ensure_spice_key_error():
|
|
115
|
+
"""Test functionality of ensure spice when all branches fail"""
|
|
116
|
+
wrapped = ensure_spice(spice.et2utc)
|
|
117
|
+
# The ensure_spice decorator should raise a SpiceyError when all attempts to
|
|
118
|
+
# furnish a set of kernels with sufficient coverage for the spiceypy
|
|
119
|
+
# functions that it decorates.
|
|
120
|
+
with pytest.raises(SpiceyError):
|
|
121
|
+
_ = wrapped(577365941.184, "ISOC", 3) == "2018-04-18T23:24:31.998"
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_average_quaternions(et_times, pointing_frame_kernels):
|
|
125
|
+
"""Tests average_quaternions function."""
|
|
126
|
+
spice.furnsh(pointing_frame_kernels)
|
|
127
|
+
q_avg = _average_quaternions(et_times)
|
|
128
|
+
|
|
129
|
+
# Generated from MATLAB code results
|
|
130
|
+
q_avg_expected = np.array([-0.6611, 0.4981, -0.5019, -0.2509])
|
|
131
|
+
np.testing.assert_allclose(q_avg, q_avg_expected, atol=1e-4)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_create_rotation_matrix(et_times, pointing_frame_kernels):
|
|
135
|
+
"""Tests create_rotation_matrix function."""
|
|
136
|
+
spice.furnsh(pointing_frame_kernels)
|
|
137
|
+
rotation_matrix = _create_rotation_matrix(et_times)
|
|
138
|
+
q_avg = _average_quaternions(et_times)
|
|
139
|
+
z_avg = spice.q2m(list(q_avg))[:, 2]
|
|
140
|
+
|
|
141
|
+
rotation_matrix_expected = np.array(
|
|
142
|
+
[[0.0000, 0.0000, 1.0000], [0.9104, -0.4136, 0.0000], [0.4136, 0.9104, 0.0000]]
|
|
143
|
+
)
|
|
144
|
+
z_avg_expected = np.array([0.4136, 0.9104, 0.0000])
|
|
145
|
+
|
|
146
|
+
np.testing.assert_allclose(z_avg, z_avg_expected, atol=1e-4)
|
|
147
|
+
np.testing.assert_allclose(rotation_matrix, rotation_matrix_expected, atol=1e-4)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def test_create_pointing_frame(
|
|
151
|
+
spice_test_data_path, pointing_frame_kernels, tmp_path, et_times
|
|
152
|
+
):
|
|
153
|
+
"""Tests create_pointing_frame function."""
|
|
154
|
+
spice.kclear()
|
|
155
|
+
spice.furnsh(pointing_frame_kernels)
|
|
156
|
+
create_pointing_frame(
|
|
157
|
+
pointing_frame_path=tmp_path / "imap_dps.bc",
|
|
158
|
+
ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# After imap_dps.bc has been created.
|
|
162
|
+
dps_kernel = str(tmp_path / "imap_dps.bc")
|
|
163
|
+
|
|
164
|
+
spice.furnsh(dps_kernel)
|
|
165
|
+
rotation_matrix_1 = spice.pxform("ECLIPJ2000", "IMAP_DPS", et_times[0] + 100)
|
|
166
|
+
rotation_matrix_2 = spice.pxform("ECLIPJ2000", "IMAP_DPS", et_times[0] + 1000)
|
|
167
|
+
|
|
168
|
+
# All the rotation matrices should be the same.
|
|
169
|
+
assert np.array_equal(rotation_matrix_1, rotation_matrix_2)
|
|
170
|
+
|
|
171
|
+
# Nick Dutton's MATLAB code result
|
|
172
|
+
rotation_matrix_expected = np.array(
|
|
173
|
+
[[0.0000, 0.0000, 1.0000], [0.9104, -0.4136, 0.0000], [0.4136, 0.9104, 0.0000]]
|
|
174
|
+
)
|
|
175
|
+
np.testing.assert_allclose(rotation_matrix_1, rotation_matrix_expected, atol=1e-4)
|
|
176
|
+
|
|
177
|
+
# Verify imap_dps.bc has been created.
|
|
178
|
+
assert (tmp_path / "imap_dps.bc").exists()
|
|
179
|
+
|
|
180
|
+
# Tests error handling when incorrect kernel is loaded.
|
|
181
|
+
spice.furnsh(pointing_frame_kernels)
|
|
182
|
+
with pytest.raises(
|
|
183
|
+
ValueError, match="Error: Expected CK kernel badname_kernel.bc"
|
|
184
|
+
): # Replace match string with expected error message
|
|
185
|
+
create_pointing_frame(
|
|
186
|
+
pointing_frame_path=tmp_path / "imap_dps.bc", ck_path="badname_kernel.bc"
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def test_et_times(pointing_frame_kernels):
|
|
191
|
+
"""Tests get_et_times function."""
|
|
192
|
+
spice.furnsh(pointing_frame_kernels)
|
|
193
|
+
|
|
194
|
+
ck_kernel, _, _, _ = spice.kdata(0, "ck")
|
|
195
|
+
ck_cover = spice.ckcov(ck_kernel, -43000, True, "INTERVAL", 0, "TDB")
|
|
196
|
+
et_start, et_end = spice.wnfetd(ck_cover, 0)
|
|
197
|
+
et_times = _get_et_times(et_start, et_end)
|
|
198
|
+
|
|
199
|
+
assert et_times[0] == et_start
|
|
200
|
+
assert et_times[-1] == et_end
|
|
201
|
+
|
|
202
|
+
return et_times
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def test_multiple_attempts(pointing_frame_kernels, tmp_path, spice_test_data_path):
|
|
206
|
+
"""Tests create_pointing_frame function with multiple pointing kernels."""
|
|
207
|
+
spice.furnsh(pointing_frame_kernels)
|
|
208
|
+
|
|
209
|
+
# Check that a single segment is added regardless of how many times
|
|
210
|
+
# create_pointing_frame is called.
|
|
211
|
+
create_pointing_frame(
|
|
212
|
+
pointing_frame_path=tmp_path / "imap_dps.bc",
|
|
213
|
+
ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
214
|
+
)
|
|
215
|
+
ck_cover = spice.ckcov(
|
|
216
|
+
str(tmp_path / "imap_dps.bc"), -43901, True, "INTERVAL", 0, "TDB"
|
|
217
|
+
)
|
|
218
|
+
num_intervals = spice.wncard(ck_cover)
|
|
219
|
+
assert num_intervals == 1
|
|
220
|
+
|
|
221
|
+
create_pointing_frame(
|
|
222
|
+
pointing_frame_path=tmp_path / "imap_dps.bc",
|
|
223
|
+
ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
224
|
+
)
|
|
225
|
+
ck_cover = spice.ckcov(
|
|
226
|
+
str(tmp_path / "imap_dps.bc"), -43901, True, "INTERVAL", 0, "TDB"
|
|
227
|
+
)
|
|
228
|
+
num_intervals = spice.wncard(ck_cover)
|
|
229
|
+
assert num_intervals == 1
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def test_multiple_pointings(pointing_frame_kernels, spice_test_data_path, tmp_path):
|
|
233
|
+
"""Tests create_pointing_frame function with multiple pointing kernels."""
|
|
234
|
+
spice.furnsh(pointing_frame_kernels)
|
|
235
|
+
|
|
236
|
+
create_pointing_frame(
|
|
237
|
+
pointing_frame_path=tmp_path / "imap_pointing_frame.bc",
|
|
238
|
+
ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
239
|
+
)
|
|
240
|
+
ck_cover_pointing = spice.ckcov(
|
|
241
|
+
str(tmp_path / "imap_pointing_frame.bc"),
|
|
242
|
+
-43901,
|
|
243
|
+
True,
|
|
244
|
+
"INTERVAL",
|
|
245
|
+
0,
|
|
246
|
+
"TDB",
|
|
247
|
+
)
|
|
248
|
+
num_intervals = spice.wncard(ck_cover_pointing)
|
|
249
|
+
et_start_pointing, et_end_pointing = spice.wnfetd(ck_cover_pointing, 0)
|
|
250
|
+
|
|
251
|
+
ck_cover = spice.ckcov(
|
|
252
|
+
str(spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc"),
|
|
253
|
+
-43000,
|
|
254
|
+
True,
|
|
255
|
+
"INTERVAL",
|
|
256
|
+
0,
|
|
257
|
+
"TDB",
|
|
258
|
+
)
|
|
259
|
+
num_intervals_expected = spice.wncard(ck_cover)
|
|
260
|
+
et_start_expected, et_end_expected = spice.wnfetd(ck_cover, 0)
|
|
261
|
+
|
|
262
|
+
assert num_intervals == num_intervals_expected
|
|
263
|
+
assert et_start_pointing == et_start_expected
|
|
264
|
+
assert et_end_pointing == et_end_expected
|
|
265
|
+
|
|
266
|
+
et_times = _get_et_times(et_start_pointing, et_end_pointing)
|
|
267
|
+
|
|
268
|
+
spice.furnsh(str(tmp_path / "imap_pointing_frame.bc"))
|
|
269
|
+
rotation_matrix_1 = spice.pxform("ECLIPJ2000", "IMAP_DPS", et_times[100])
|
|
270
|
+
rotation_matrix_2 = spice.pxform("ECLIPJ2000", "IMAP_DPS", et_times[1000])
|
|
271
|
+
|
|
272
|
+
assert np.array_equal(rotation_matrix_1, rotation_matrix_2)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Tests coverage for imap_processing/spice/time.py"""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
import spiceypy as spice
|
|
6
|
+
|
|
7
|
+
from imap_processing.spice import IMAP_SC_ID
|
|
8
|
+
from imap_processing.spice.time import _sct2e_wrapper, met_to_j2000ns
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_met_to_j2000ns(furnish_time_kernels):
|
|
12
|
+
"""Test coverage for met_to_j2000ns function."""
|
|
13
|
+
utc = "2026-01-01T00:00:00.125"
|
|
14
|
+
et = spice.str2et(utc)
|
|
15
|
+
sclk_str = spice.sce2s(IMAP_SC_ID, et)
|
|
16
|
+
seconds, ticks = sclk_str.split("/")[1].split(":")
|
|
17
|
+
# There is some floating point error calculating tick duration from 1 clock
|
|
18
|
+
# tick so average over many clock ticks for better accuracy
|
|
19
|
+
spice_tick_duration = (
|
|
20
|
+
spice.sct2e(IMAP_SC_ID, 1e12) - spice.sct2e(IMAP_SC_ID, 0)
|
|
21
|
+
) / 1e12
|
|
22
|
+
met = float(seconds) + float(ticks) * spice_tick_duration
|
|
23
|
+
j2000ns = met_to_j2000ns(met)
|
|
24
|
+
assert j2000ns.dtype == np.int64
|
|
25
|
+
np.testing.assert_array_equal(j2000ns, np.array(et * 1e9))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@pytest.mark.parametrize("sclk_ticks", [0.0, np.arange(10)])
|
|
29
|
+
def test_sct2e_wrapper(sclk_ticks):
|
|
30
|
+
"""Test for `_sct2e_wrapper` function."""
|
|
31
|
+
et = _sct2e_wrapper(sclk_ticks)
|
|
32
|
+
if isinstance(sclk_ticks, float):
|
|
33
|
+
assert isinstance(et, float)
|
|
34
|
+
else:
|
|
35
|
+
assert len(et) == len(sclk_ticks)
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@pytest.fixture(scope="session")
|
|
5
|
+
def swapi_test_data_path(imap_tests_path):
|
|
6
|
+
return imap_tests_path / "swapi/"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.fixture(scope="session")
|
|
10
|
+
def swapi_l0_test_data_path(swapi_test_data_path):
|
|
11
|
+
return swapi_test_data_path / "l0_data/"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.fixture(scope="session")
|
|
15
|
+
def swapi_l0_validation_data_path(swapi_test_data_path):
|
|
16
|
+
return swapi_test_data_path / "l0_validation_data/"
|
|
File without changes
|
|
Binary file
|