imap-processing 0.12.0__py3-none-any.whl → 0.13.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.
Potentially problematic release.
This version of imap-processing might be problematic. Click here for more details.
- imap_processing/__init__.py +1 -0
- imap_processing/_version.py +2 -2
- imap_processing/ccsds/ccsds_data.py +1 -2
- imap_processing/ccsds/excel_to_xtce.py +1 -2
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +18 -12
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +569 -0
- imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +5 -5
- imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +20 -1
- imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +6 -4
- imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +3 -3
- imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +15 -0
- imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
- imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +16 -0
- imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +178 -5
- imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +33 -19
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +8 -48
- imap_processing/cdf/utils.py +41 -33
- imap_processing/cli.py +463 -234
- imap_processing/codice/codice_l1a.py +260 -47
- imap_processing/codice/codice_l1b.py +51 -152
- imap_processing/codice/constants.py +38 -1
- imap_processing/ena_maps/ena_maps.py +658 -65
- imap_processing/ena_maps/utils/coordinates.py +1 -1
- imap_processing/ena_maps/utils/spatial_utils.py +10 -5
- imap_processing/glows/l1a/glows_l1a.py +28 -99
- imap_processing/glows/l1a/glows_l1a_data.py +2 -2
- imap_processing/glows/l1b/glows_l1b.py +1 -4
- imap_processing/glows/l1b/glows_l1b_data.py +1 -3
- imap_processing/glows/l2/glows_l2.py +2 -5
- imap_processing/hi/l1a/hi_l1a.py +31 -12
- imap_processing/hi/l1b/hi_l1b.py +80 -43
- imap_processing/hi/l1c/hi_l1c.py +12 -16
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
- imap_processing/hit/hit_utils.py +93 -35
- imap_processing/hit/l0/decom_hit.py +3 -1
- imap_processing/hit/l1a/hit_l1a.py +30 -25
- imap_processing/hit/l1b/constants.py +6 -2
- imap_processing/hit/l1b/hit_l1b.py +279 -318
- imap_processing/hit/l2/constants.py +37 -0
- imap_processing/hit/l2/hit_l2.py +373 -264
- imap_processing/ialirt/l0/parse_mag.py +138 -10
- imap_processing/ialirt/l0/process_swapi.py +69 -0
- imap_processing/ialirt/l0/process_swe.py +318 -22
- imap_processing/ialirt/packet_definitions/ialirt.xml +216 -212
- imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +1 -1
- imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +1 -1
- imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
- imap_processing/ialirt/utils/grouping.py +1 -1
- imap_processing/idex/idex_constants.py +9 -1
- imap_processing/idex/idex_l0.py +22 -8
- imap_processing/idex/idex_l1a.py +75 -44
- imap_processing/idex/idex_l1b.py +9 -8
- imap_processing/idex/idex_l2a.py +79 -45
- imap_processing/idex/idex_l2b.py +120 -0
- imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -39
- imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
- imap_processing/lo/l0/lo_science.py +1 -2
- imap_processing/lo/l1a/lo_l1a.py +1 -4
- imap_processing/lo/l1b/lo_l1b.py +527 -6
- imap_processing/lo/l1b/tof_conversions.py +11 -0
- imap_processing/lo/l1c/lo_l1c.py +1 -4
- imap_processing/mag/constants.py +43 -0
- imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
- imap_processing/mag/l1a/mag_l1a.py +2 -9
- imap_processing/mag/l1a/mag_l1a_data.py +10 -10
- imap_processing/mag/l1b/mag_l1b.py +84 -17
- imap_processing/mag/l1c/interpolation_methods.py +180 -3
- imap_processing/mag/l1c/mag_l1c.py +236 -70
- imap_processing/mag/l2/mag_l2.py +140 -0
- imap_processing/mag/l2/mag_l2_data.py +288 -0
- imap_processing/spacecraft/quaternions.py +1 -3
- imap_processing/spice/geometry.py +3 -3
- imap_processing/spice/kernels.py +0 -276
- imap_processing/spice/pointing_frame.py +257 -0
- imap_processing/spice/repoint.py +48 -19
- imap_processing/spice/spin.py +38 -33
- imap_processing/spice/time.py +24 -0
- imap_processing/swapi/l1/swapi_l1.py +16 -12
- imap_processing/swapi/l2/swapi_l2.py +116 -4
- imap_processing/swapi/swapi_utils.py +32 -0
- imap_processing/swe/l1a/swe_l1a.py +2 -9
- imap_processing/swe/l1a/swe_science.py +8 -11
- imap_processing/swe/l1b/swe_l1b.py +898 -23
- imap_processing/swe/l2/swe_l2.py +21 -77
- imap_processing/swe/utils/swe_constants.py +1 -0
- imap_processing/tests/ccsds/test_excel_to_xtce.py +1 -1
- imap_processing/tests/cdf/test_utils.py +14 -16
- imap_processing/tests/codice/conftest.py +44 -33
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/test_codice_l1a.py +20 -11
- imap_processing/tests/codice/test_codice_l1b.py +6 -7
- imap_processing/tests/conftest.py +78 -22
- imap_processing/tests/ena_maps/test_ena_maps.py +462 -33
- imap_processing/tests/ena_maps/test_spatial_utils.py +1 -1
- imap_processing/tests/glows/conftest.py +10 -14
- imap_processing/tests/glows/test_glows_decom.py +4 -4
- imap_processing/tests/glows/test_glows_l1a_cdf.py +6 -27
- imap_processing/tests/glows/test_glows_l1a_data.py +6 -8
- imap_processing/tests/glows/test_glows_l1b.py +11 -11
- imap_processing/tests/glows/test_glows_l1b_data.py +5 -5
- imap_processing/tests/glows/test_glows_l2.py +2 -8
- imap_processing/tests/hi/conftest.py +1 -1
- imap_processing/tests/hi/test_hi_l1b.py +10 -12
- imap_processing/tests/hi/test_hi_l1c.py +27 -24
- imap_processing/tests/hi/test_l1a.py +7 -9
- imap_processing/tests/hi/test_science_direct_event.py +2 -2
- imap_processing/tests/hit/helpers/l1_validation.py +44 -43
- imap_processing/tests/hit/test_decom_hit.py +1 -1
- imap_processing/tests/hit/test_hit_l1a.py +9 -9
- imap_processing/tests/hit/test_hit_l1b.py +172 -217
- imap_processing/tests/hit/test_hit_l2.py +380 -118
- imap_processing/tests/hit/test_hit_utils.py +122 -55
- imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
- imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
- imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
- imap_processing/tests/ialirt/unit/test_grouping.py +2 -2
- imap_processing/tests/ialirt/unit/test_parse_mag.py +71 -16
- imap_processing/tests/ialirt/unit/test_process_codicehi.py +3 -3
- imap_processing/tests/ialirt/unit/test_process_codicelo.py +3 -10
- imap_processing/tests/ialirt/unit/test_process_ephemeris.py +4 -4
- imap_processing/tests/ialirt/unit/test_process_hit.py +3 -3
- imap_processing/tests/ialirt/unit/test_process_swapi.py +24 -16
- imap_processing/tests/ialirt/unit/test_process_swe.py +115 -7
- imap_processing/tests/idex/conftest.py +72 -7
- imap_processing/tests/idex/test_data/imap_idex_l0_raw_20241206_v001.pkts +0 -0
- imap_processing/tests/idex/test_data/imap_idex_l0_raw_20250108_v001.pkts +0 -0
- imap_processing/tests/idex/test_idex_l0.py +33 -11
- imap_processing/tests/idex/test_idex_l1a.py +50 -23
- imap_processing/tests/idex/test_idex_l1b.py +104 -25
- imap_processing/tests/idex/test_idex_l2a.py +48 -32
- imap_processing/tests/idex/test_idex_l2b.py +93 -0
- imap_processing/tests/lo/test_lo_l1a.py +3 -3
- imap_processing/tests/lo/test_lo_l1b.py +371 -6
- imap_processing/tests/lo/test_lo_l1c.py +1 -1
- imap_processing/tests/lo/test_lo_science.py +6 -7
- imap_processing/tests/lo/test_star_sensor.py +1 -1
- imap_processing/tests/mag/conftest.py +58 -9
- imap_processing/tests/mag/test_mag_decom.py +4 -3
- imap_processing/tests/mag/test_mag_l1a.py +13 -7
- imap_processing/tests/mag/test_mag_l1b.py +9 -9
- imap_processing/tests/mag/test_mag_l1c.py +151 -47
- imap_processing/tests/mag/test_mag_l2.py +130 -0
- imap_processing/tests/mag/test_mag_validation.py +144 -7
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-out.csv +1857 -0
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-out.csv +1857 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-out.csv +1793 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-out.csv +1793 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-burst-in.csv +2561 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-in.csv +961 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-out.csv +1539 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-in.csv +1921 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-out.csv +2499 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-in.csv +865 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv +1196 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-in.csv +1729 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv +3053 -0
- imap_processing/tests/mag/validation/L2/imap_mag_l1b_norm-mago_20251017_v002.cdf +0 -0
- imap_processing/tests/mag/validation/calibration/imap_mag_l2-calibration-matrices_20251017_v004.cdf +0 -0
- imap_processing/tests/mag/validation/calibration/imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf +0 -0
- imap_processing/tests/spacecraft/test_quaternions.py +1 -1
- imap_processing/tests/spice/test_data/fake_repoint_data.csv +4 -4
- imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
- imap_processing/tests/spice/test_geometry.py +3 -3
- imap_processing/tests/spice/test_kernels.py +1 -200
- imap_processing/tests/spice/test_pointing_frame.py +185 -0
- imap_processing/tests/spice/test_repoint.py +20 -10
- imap_processing/tests/spice/test_spin.py +50 -9
- imap_processing/tests/spice/test_time.py +14 -0
- imap_processing/tests/swapi/lut/imap_swapi_esa-unit-conversion_20250211_v000.csv +73 -0
- imap_processing/tests/swapi/lut/imap_swapi_lut-notes_20250211_v000.csv +1025 -0
- imap_processing/tests/swapi/test_swapi_l1.py +7 -9
- imap_processing/tests/swapi/test_swapi_l2.py +180 -8
- imap_processing/tests/swe/lut/checker-board-indices.csv +24 -0
- imap_processing/tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv +385 -0
- imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv +3 -0
- imap_processing/tests/swe/test_swe_l1a.py +6 -6
- imap_processing/tests/swe/test_swe_l1a_science.py +3 -3
- imap_processing/tests/swe/test_swe_l1b.py +162 -24
- imap_processing/tests/swe/test_swe_l2.py +82 -102
- imap_processing/tests/test_cli.py +171 -88
- imap_processing/tests/test_utils.py +2 -1
- imap_processing/tests/ultra/data/mock_data.py +49 -21
- imap_processing/tests/ultra/unit/conftest.py +53 -70
- imap_processing/tests/ultra/unit/test_badtimes.py +2 -4
- imap_processing/tests/ultra/unit/test_cullingmask.py +4 -6
- imap_processing/tests/ultra/unit/test_de.py +3 -10
- imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
- imap_processing/tests/ultra/unit/test_decom_apid_881.py +15 -16
- imap_processing/tests/ultra/unit/test_decom_apid_883.py +12 -10
- imap_processing/tests/ultra/unit/test_decom_apid_896.py +202 -55
- imap_processing/tests/ultra/unit/test_lookup_utils.py +23 -1
- imap_processing/tests/ultra/unit/test_spacecraft_pset.py +3 -4
- imap_processing/tests/ultra/unit/test_ultra_l1a.py +84 -307
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +30 -12
- imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
- imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +4 -1
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +163 -29
- imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +32 -43
- imap_processing/tests/ultra/unit/test_ultra_l2.py +230 -0
- imap_processing/ultra/constants.py +1 -1
- imap_processing/ultra/l0/decom_tools.py +21 -34
- imap_processing/ultra/l0/decom_ultra.py +168 -204
- imap_processing/ultra/l0/ultra_utils.py +152 -136
- imap_processing/ultra/l1a/ultra_l1a.py +55 -243
- imap_processing/ultra/l1b/badtimes.py +1 -4
- imap_processing/ultra/l1b/cullingmask.py +2 -6
- imap_processing/ultra/l1b/de.py +62 -47
- imap_processing/ultra/l1b/extendedspin.py +8 -4
- imap_processing/ultra/l1b/lookup_utils.py +72 -9
- imap_processing/ultra/l1b/ultra_l1b.py +3 -8
- imap_processing/ultra/l1b/ultra_l1b_culling.py +4 -4
- imap_processing/ultra/l1b/ultra_l1b_extended.py +236 -78
- imap_processing/ultra/l1c/histogram.py +2 -6
- imap_processing/ultra/l1c/spacecraft_pset.py +2 -4
- imap_processing/ultra/l1c/ultra_l1c.py +1 -5
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +107 -60
- imap_processing/ultra/l2/ultra_l2.py +299 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -2
- imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
- imap_processing/ultra/packet_definitions/README.md +38 -0
- imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +15302 -482
- imap_processing/ultra/utils/ultra_l1_utils.py +13 -12
- imap_processing/utils.py +1 -1
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +3 -2
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/RECORD +264 -225
- imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
- imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +0 -6
- imap_processing/mag/l1b/__init__.py +0 -0
- imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
- imap_processing/swe/l1b/swe_l1b_science.py +0 -699
- imap_processing/tests/swe/test_swe_l1b_science.py +0 -103
- imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
- imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
- /imap_processing/idex/packet_definitions/{idex_packet_definition.xml → idex_science_packet_definition.xml} +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971383-404.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971384-405.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971385-406.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971386-407.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971387-408.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971388-409.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971389-410.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971390-411.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971391-412.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/IALiRT Raw Packet Telemetry.txt +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/apid01152.tlm +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/eu_SWP_IAL_20240826_152033.csv +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/hi_fsw_view_1_ccsds.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.ccsds +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.csv +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/sample_decoded_i-alirt_data.csv +0 -0
- /imap_processing/tests/mag/validation/{imap_calibration_mag_20240229_v01.cdf → calibration/imap_mag_l1b-calibration_20240229_v001.cdf} +0 -0
- /imap_processing/{swe/l1b/engineering_unit_convert_table.csv → tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv} +0 -0
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
imap_processing/tests/mag/validation/calibration/imap_mag_l2-calibration-matrices_20251017_v004.cdf
ADDED
|
Binary file
|
imap_processing/tests/mag/validation/calibration/imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf
ADDED
|
Binary file
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# This is a fake csv file for the sole purpose of testing repoint module functions
|
|
2
|
-
|
|
3
|
-
0,5,0
|
|
4
|
-
15,20,1
|
|
5
|
-
25,30,2
|
|
2
|
+
repoint_start_sec_sclk,repoint_start_subsec_sclk,repoint_end_sec_sclk,repoint_end_subsec_sclk,repoint_start_utc,repoint_end_utc,repoint_id
|
|
3
|
+
0,100000,5,100000,2025-04-10 00:00:00.000000,2025-04-10T00:00:05.000000,0
|
|
4
|
+
15,200000,20,200000,2025-04-10 00:00:15.000000,2025-04-10T00:00:20.000000,1
|
|
5
|
+
25,300000,30,300000,2025-04-10 00:00:25.000000,2025-04-10T00:00:30.000000,2
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# This is a fake csv file for the sole purpose of testing the get_spacecraft_spin_phase function
|
|
2
|
-
spin_number,
|
|
2
|
+
spin_number,spin_start_sec_sclk,spin_start_subsec_sclk,spin_start_utc,spin_period_sec,spin_period_valid,spin_phase_valid,spin_period_source,thruster_firing
|
|
3
3
|
# Start with thruster firing
|
|
4
|
-
0,0,0,15.0,1,1,0,1
|
|
4
|
+
0,0,0,2024-04-11 00:00:00.000000,15.0,1,1,0,1
|
|
5
5
|
# Turn thruster firing off then 3 valid spins
|
|
6
|
-
1,15,0,15.0,1,1,0,0
|
|
7
|
-
2,30,0,15.0,1,1,0,0
|
|
8
|
-
3,45,0,15.0,1,1,0,0
|
|
6
|
+
1,15,0,2024-04-11 00:00:15.000000,15.0,1,1,0,0
|
|
7
|
+
2,30,0,2024-04-11 00:00:30.000000,15.0,1,1,0,0
|
|
8
|
+
3,45,0,2024-04-11 00:00:45.000000,15.0,1,1,0,0
|
|
9
9
|
# Missing spin then 2 good spins
|
|
10
|
-
5,75,0,15.0,1,1,0,0
|
|
11
|
-
6,90,0,15.0,1,1,0,0
|
|
10
|
+
5,75,0,2024-04-11 00:01:15.000000,15.0,1,1,0,0
|
|
11
|
+
6,90,0,2024-04-11 00:01:30.000000,15.0,1,1,0,0
|
|
12
12
|
# invalid spin period
|
|
13
|
-
7,105,0,15.0,0,1,0,0
|
|
13
|
+
7,105,0,2024-04-11 00:01:45.000000,15.0,0,1,0,0
|
|
14
14
|
# invalid spin phase
|
|
15
|
-
8,120,0,15.0,1,0,0,0
|
|
15
|
+
8,120,0,2024-04-11 00:02:00.000000,15.0,1,0,0,0
|
|
16
16
|
# 1 good spin
|
|
17
|
-
9,135,0,15.0,1,1,0,0
|
|
17
|
+
9,135,0,2024-04-11 00:02:15.000000,15.0,1,1,0,0
|
|
18
18
|
# Thruster firing on
|
|
19
|
-
10,150,0,15.0,1,1,0,1
|
|
19
|
+
10,150,0,2024-04-11 00:02:30.000000,15.0,1,1,0,1
|
|
@@ -40,7 +40,7 @@ def test_imap_state(et, use_test_metakernel):
|
|
|
40
40
|
assert state.shape == (6,)
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
@pytest.mark.external_kernel
|
|
43
|
+
@pytest.mark.external_kernel
|
|
44
44
|
@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
|
|
45
45
|
def test_imap_state_ecliptic():
|
|
46
46
|
"""Tests retrieving IMAP state in the ECLIPJ2000 frame"""
|
|
@@ -51,7 +51,7 @@ def test_imap_state_ecliptic():
|
|
|
51
51
|
@pytest.mark.parametrize(
|
|
52
52
|
"instrument, expected_offset",
|
|
53
53
|
[
|
|
54
|
-
(SpiceFrame.
|
|
54
|
+
(SpiceFrame.IMAP_LO_BASE, 330 / 360),
|
|
55
55
|
(SpiceFrame.IMAP_HI_45, 255 / 360),
|
|
56
56
|
(SpiceFrame.IMAP_HI_90, 285 / 360),
|
|
57
57
|
(SpiceFrame.IMAP_ULTRA_45, 33 / 360),
|
|
@@ -287,7 +287,7 @@ def test_instrument_pointing(furnish_kernels):
|
|
|
287
287
|
assert ins_pointing.shape == (3, 3)
|
|
288
288
|
|
|
289
289
|
|
|
290
|
-
@pytest.mark.external_kernel
|
|
290
|
+
@pytest.mark.external_kernel
|
|
291
291
|
@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
|
|
292
292
|
def test_basis_vectors():
|
|
293
293
|
"""Test coverage for basis_vectors()."""
|
|
@@ -1,58 +1,10 @@
|
|
|
1
1
|
"""Tests coverage for imap_processing/spice/kernels.py"""
|
|
2
2
|
|
|
3
|
-
import numpy as np
|
|
4
3
|
import pytest
|
|
5
4
|
import spiceypy
|
|
6
5
|
from spiceypy.utils.exceptions import SpiceyError
|
|
7
6
|
|
|
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
|
-
spiceypy.furnsh(pointing_frame_kernels)
|
|
49
|
-
|
|
50
|
-
ck_kernel, _, _, _ = spiceypy.kdata(0, "ck")
|
|
51
|
-
ck_cover = spiceypy.ckcov(ck_kernel, -43000, True, "INTERVAL", 0, "TDB")
|
|
52
|
-
et_start, et_end = spiceypy.wnfetd(ck_cover, 0)
|
|
53
|
-
et_times = _get_et_times(et_start, et_end)
|
|
54
|
-
|
|
55
|
-
return et_times
|
|
7
|
+
from imap_processing.spice.kernels import ensure_spice
|
|
56
8
|
|
|
57
9
|
|
|
58
10
|
@ensure_spice
|
|
@@ -119,154 +71,3 @@ def test_ensure_spice_key_error():
|
|
|
119
71
|
# functions that it decorates.
|
|
120
72
|
with pytest.raises(SpiceyError):
|
|
121
73
|
_ = 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
|
-
spiceypy.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
|
-
spiceypy.furnsh(pointing_frame_kernels)
|
|
137
|
-
rotation_matrix = _create_rotation_matrix(et_times)
|
|
138
|
-
q_avg = _average_quaternions(et_times)
|
|
139
|
-
z_avg = spiceypy.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
|
-
spiceypy.kclear()
|
|
155
|
-
spiceypy.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
|
-
spiceypy.furnsh(dps_kernel)
|
|
165
|
-
rotation_matrix_1 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[0] + 100)
|
|
166
|
-
rotation_matrix_2 = spiceypy.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
|
-
spiceypy.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
|
-
spiceypy.furnsh(pointing_frame_kernels)
|
|
193
|
-
|
|
194
|
-
ck_kernel, _, _, _ = spiceypy.kdata(0, "ck")
|
|
195
|
-
ck_cover = spiceypy.ckcov(ck_kernel, -43000, True, "INTERVAL", 0, "TDB")
|
|
196
|
-
et_start, et_end = spiceypy.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
|
-
spiceypy.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 = spiceypy.ckcov(
|
|
216
|
-
str(tmp_path / "imap_dps.bc"), -43901, True, "INTERVAL", 0, "TDB"
|
|
217
|
-
)
|
|
218
|
-
num_intervals = spiceypy.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 = spiceypy.ckcov(
|
|
226
|
-
str(tmp_path / "imap_dps.bc"), -43901, True, "INTERVAL", 0, "TDB"
|
|
227
|
-
)
|
|
228
|
-
num_intervals = spiceypy.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
|
-
spiceypy.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 = spiceypy.ckcov(
|
|
241
|
-
str(tmp_path / "imap_pointing_frame.bc"),
|
|
242
|
-
-43901,
|
|
243
|
-
True,
|
|
244
|
-
"INTERVAL",
|
|
245
|
-
0,
|
|
246
|
-
"TDB",
|
|
247
|
-
)
|
|
248
|
-
num_intervals = spiceypy.wncard(ck_cover_pointing)
|
|
249
|
-
et_start_pointing, et_end_pointing = spiceypy.wnfetd(ck_cover_pointing, 0)
|
|
250
|
-
|
|
251
|
-
ck_cover = spiceypy.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 = spiceypy.wncard(ck_cover)
|
|
260
|
-
et_start_expected, et_end_expected = spiceypy.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
|
-
spiceypy.furnsh(str(tmp_path / "imap_pointing_frame.bc"))
|
|
269
|
-
rotation_matrix_1 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[100])
|
|
270
|
-
rotation_matrix_2 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[1000])
|
|
271
|
-
|
|
272
|
-
assert np.array_equal(rotation_matrix_1, rotation_matrix_2)
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""Test coverage for imap_processing.spice.repoint.py"""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
import spiceypy
|
|
6
|
+
|
|
7
|
+
from imap_processing.spice.pointing_frame import (
|
|
8
|
+
_average_quaternions,
|
|
9
|
+
_create_rotation_matrix,
|
|
10
|
+
create_pointing_frame,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.fixture
|
|
15
|
+
def pointing_frame_kernels(spice_test_data_path):
|
|
16
|
+
"""List SPICE kernels."""
|
|
17
|
+
required_kernels = [
|
|
18
|
+
"imap_science_0001.tf",
|
|
19
|
+
"imap_sclk_0000.tsc",
|
|
20
|
+
"imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
21
|
+
"imap_wkcp.tf",
|
|
22
|
+
"naif0012.tls",
|
|
23
|
+
]
|
|
24
|
+
kernels = [str(spice_test_data_path / kernel) for kernel in required_kernels]
|
|
25
|
+
return kernels
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@pytest.fixture
|
|
29
|
+
def et_times(pointing_frame_kernels):
|
|
30
|
+
"""Tests get_et_times function."""
|
|
31
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
32
|
+
|
|
33
|
+
ck_kernel, _, _, _ = spiceypy.kdata(0, "ck")
|
|
34
|
+
ck_cover = spiceypy.ckcov(ck_kernel, -43000, True, "INTERVAL", 0, "TDB")
|
|
35
|
+
et_start, et_end = spiceypy.wnfetd(ck_cover, 0)
|
|
36
|
+
|
|
37
|
+
# 1 spin/15 seconds; 10 quaternions / spin.
|
|
38
|
+
num_samples = (et_end - et_start) / 15 * 10
|
|
39
|
+
# There were rounding errors when using spiceypy.pxform so np.ceil and np.floor
|
|
40
|
+
# were used to ensure the start and end times were within the ck range.
|
|
41
|
+
et_times = np.linspace(
|
|
42
|
+
np.ceil(et_start * 1e6) / 1e6, np.floor(et_end * 1e6) / 1e6, int(num_samples)
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
return et_times
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@pytest.fixture
|
|
49
|
+
def fake_repoint_data(monkeypatch, spice_test_data_path):
|
|
50
|
+
"""Generate fake spin dataframe for testing"""
|
|
51
|
+
fake_repoint_path = spice_test_data_path / "fake_repoint_data.csv"
|
|
52
|
+
monkeypatch.setenv("REPOINT_DATA_FILEPATH", str(fake_repoint_path))
|
|
53
|
+
return fake_repoint_path
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_average_quaternions(et_times, pointing_frame_kernels):
|
|
57
|
+
"""Tests average_quaternions function."""
|
|
58
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
59
|
+
q_avg = _average_quaternions(et_times)
|
|
60
|
+
|
|
61
|
+
# Generated from MATLAB code results
|
|
62
|
+
q_avg_expected = np.array([-0.6611, 0.4981, -0.5019, -0.2509])
|
|
63
|
+
np.testing.assert_allclose(q_avg, q_avg_expected, atol=1e-4)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_create_rotation_matrix(et_times, pointing_frame_kernels):
|
|
67
|
+
"""Tests create_rotation_matrix function."""
|
|
68
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
69
|
+
rotation_matrix = _create_rotation_matrix(et_times)
|
|
70
|
+
q_avg = _average_quaternions(et_times)
|
|
71
|
+
z_avg = spiceypy.q2m(list(q_avg))[:, 2]
|
|
72
|
+
|
|
73
|
+
rotation_matrix_expected = np.array(
|
|
74
|
+
[[0.0000, 0.0000, 1.0000], [0.9104, -0.4136, 0.0000], [0.4136, 0.9104, 0.0000]]
|
|
75
|
+
)
|
|
76
|
+
z_avg_expected = np.array([0.4136, 0.9104, 0.0000])
|
|
77
|
+
|
|
78
|
+
np.testing.assert_allclose(z_avg, z_avg_expected, atol=1e-4)
|
|
79
|
+
np.testing.assert_allclose(rotation_matrix, rotation_matrix_expected, atol=1e-4)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_create_pointing_frame(
|
|
83
|
+
spice_test_data_path, pointing_frame_kernels, tmp_path, et_times, fake_repoint_data
|
|
84
|
+
):
|
|
85
|
+
"""Tests create_pointing_frame function."""
|
|
86
|
+
|
|
87
|
+
# This is how the repoint data is generated.
|
|
88
|
+
# We will use fake data for now to match the coverage of the attitude kernel.
|
|
89
|
+
# repoint_df = get_repoint_data()
|
|
90
|
+
# repoint_start = repoint_df["repoint_end_met"].values[:-1]
|
|
91
|
+
# repoint_end_met = repoint_df["repoint_start_met"].values[1:]
|
|
92
|
+
|
|
93
|
+
spiceypy.kclear()
|
|
94
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
95
|
+
create_pointing_frame(
|
|
96
|
+
tmp_path / "imap_dps.bc",
|
|
97
|
+
spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
98
|
+
np.array([486432004]), # repoint_df["repoint_start_met"].values
|
|
99
|
+
np.array([486439201]), # repoint_df["repoint_end_met"].values
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# After imap_dps.bc has been created.
|
|
103
|
+
dps_kernel = str(tmp_path / "imap_dps.bc")
|
|
104
|
+
|
|
105
|
+
spiceypy.furnsh(dps_kernel)
|
|
106
|
+
rotation_matrix_1 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[0] + 100)
|
|
107
|
+
rotation_matrix_2 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[0] + 1000)
|
|
108
|
+
|
|
109
|
+
# All the rotation matrices should be the same.
|
|
110
|
+
assert np.array_equal(rotation_matrix_1, rotation_matrix_2)
|
|
111
|
+
|
|
112
|
+
# Nick Dutton's MATLAB code result
|
|
113
|
+
rotation_matrix_expected = np.array(
|
|
114
|
+
[[0.0000, 0.0000, 1.0000], [0.9104, -0.4136, 0.0000], [0.4136, 0.9104, 0.0000]]
|
|
115
|
+
)
|
|
116
|
+
np.testing.assert_allclose(rotation_matrix_1, rotation_matrix_expected, atol=1e-4)
|
|
117
|
+
|
|
118
|
+
# Verify imap_dps.bc has been created.
|
|
119
|
+
assert (tmp_path / "imap_dps.bc").exists()
|
|
120
|
+
|
|
121
|
+
# Tests error handling when incorrect kernel is loaded.
|
|
122
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
123
|
+
with pytest.raises(
|
|
124
|
+
ValueError, match="Error: Expected CK kernel badname_kernel.bc"
|
|
125
|
+
): # Replace match string with expected error message
|
|
126
|
+
create_pointing_frame(
|
|
127
|
+
tmp_path / "imap_dps.bc",
|
|
128
|
+
"badname_kernel.bc",
|
|
129
|
+
np.array([486432004]),
|
|
130
|
+
np.array([486439201]),
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_multiple_pointings(pointing_frame_kernels, spice_test_data_path, tmp_path):
|
|
135
|
+
"""Tests create_pointing_frame function with multiple pointing kernels."""
|
|
136
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
137
|
+
|
|
138
|
+
create_pointing_frame(
|
|
139
|
+
tmp_path / "imap_pointing_frame.bc",
|
|
140
|
+
spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
141
|
+
np.array([486432003]), # repoint_df["repoint_start_met"].values
|
|
142
|
+
np.array([486439201]), # repoint_df["repoint_end_met"].values
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
ck_cover_pointing = spiceypy.ckcov(
|
|
146
|
+
str(tmp_path / "imap_pointing_frame.bc"),
|
|
147
|
+
-43901,
|
|
148
|
+
True,
|
|
149
|
+
"INTERVAL",
|
|
150
|
+
0,
|
|
151
|
+
"TDB",
|
|
152
|
+
)
|
|
153
|
+
num_intervals = spiceypy.wncard(ck_cover_pointing)
|
|
154
|
+
et_start_pointing, et_end_pointing = spiceypy.wnfetd(ck_cover_pointing, 0)
|
|
155
|
+
|
|
156
|
+
ck_cover = spiceypy.ckcov(
|
|
157
|
+
str(spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc"),
|
|
158
|
+
-43000,
|
|
159
|
+
True,
|
|
160
|
+
"INTERVAL",
|
|
161
|
+
0,
|
|
162
|
+
"TDB",
|
|
163
|
+
)
|
|
164
|
+
num_intervals_expected = spiceypy.wncard(ck_cover)
|
|
165
|
+
et_start_expected, et_end_expected = spiceypy.wnfetd(ck_cover, 0)
|
|
166
|
+
|
|
167
|
+
assert num_intervals == num_intervals_expected
|
|
168
|
+
np.testing.assert_allclose(et_start_pointing, et_start_expected, atol=1e-2)
|
|
169
|
+
np.testing.assert_allclose(et_end_pointing, et_end_expected, atol=1e-2)
|
|
170
|
+
|
|
171
|
+
# 1 spin/15 seconds; 10 quaternions / spin.
|
|
172
|
+
num_samples = (et_end_pointing - et_start_pointing) / 15 * 10
|
|
173
|
+
# There were rounding errors when using spiceypy.pxform so np.ceil and np.floor
|
|
174
|
+
# were used to ensure the start and end times were within the ck range.
|
|
175
|
+
et_times = np.linspace(
|
|
176
|
+
np.ceil(et_start_pointing * 1e6) / 1e6,
|
|
177
|
+
np.floor(et_end_pointing * 1e6) / 1e6,
|
|
178
|
+
int(num_samples),
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
spiceypy.furnsh(str(tmp_path / "imap_pointing_frame.bc"))
|
|
182
|
+
rotation_matrix_1 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[100])
|
|
183
|
+
rotation_matrix_2 = spiceypy.pxform("ECLIPJ2000", "IMAP_DPS", et_times[1000])
|
|
184
|
+
|
|
185
|
+
assert np.array_equal(rotation_matrix_1, rotation_matrix_2)
|
|
@@ -7,7 +7,7 @@ import pytest
|
|
|
7
7
|
from imap_processing.spice.repoint import get_repoint_data, interpolate_repoint_data
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
@pytest.fixture
|
|
10
|
+
@pytest.fixture
|
|
11
11
|
def fake_repoint_data(monkeypatch, spice_test_data_path):
|
|
12
12
|
"""Generate fake spin dataframe for testing"""
|
|
13
13
|
fake_repoint_path = spice_test_data_path / "fake_repoint_data.csv"
|
|
@@ -16,12 +16,18 @@ def fake_repoint_data(monkeypatch, spice_test_data_path):
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def test_get_repoint_data(fake_repoint_data):
|
|
19
|
-
"""Test
|
|
19
|
+
"""Test coverage for get_repoint_data function."""
|
|
20
20
|
repoint_df = get_repoint_data()
|
|
21
21
|
assert isinstance(repoint_df, pd.DataFrame)
|
|
22
22
|
assert set(repoint_df.columns) == {
|
|
23
|
-
"
|
|
24
|
-
"
|
|
23
|
+
"repoint_start_sec_sclk",
|
|
24
|
+
"repoint_start_subsec_sclk",
|
|
25
|
+
"repoint_start_met",
|
|
26
|
+
"repoint_start_utc",
|
|
27
|
+
"repoint_end_sec_sclk",
|
|
28
|
+
"repoint_end_subsec_sclk",
|
|
29
|
+
"repoint_end_met",
|
|
30
|
+
"repoint_end_utc",
|
|
25
31
|
"repoint_id",
|
|
26
32
|
}
|
|
27
33
|
|
|
@@ -36,10 +42,14 @@ def test_spin_data_no_table():
|
|
|
36
42
|
|
|
37
43
|
def test_interpolate_repoint_data(fake_repoint_data):
|
|
38
44
|
"""Test coverage for get_repoint_data function."""
|
|
39
|
-
query_times = np.array([0, 6, 32])
|
|
45
|
+
query_times = np.array([0.1, 6, 32])
|
|
40
46
|
expected_vals = {
|
|
41
|
-
"
|
|
42
|
-
"
|
|
47
|
+
"repoint_start_sec_sclk": np.array([0, 0, 25]),
|
|
48
|
+
"repoint_start_subsec_sclk": np.array([100000, 100000, 300000]),
|
|
49
|
+
"repoint_start_met": np.array([0.1, 0.1, 25.3]),
|
|
50
|
+
"repoint_end_sec_sclk": np.array([5, 5, 30]),
|
|
51
|
+
"repoint_end_subsec_sclk": np.array([100000, 100000, 300000]),
|
|
52
|
+
"repoint_end_met": np.array([5.1, 5.1, 30.3]),
|
|
43
53
|
"repoint_id": np.array([0, 0, 2]),
|
|
44
54
|
"repoint_in_progress": np.array([True, False, False]),
|
|
45
55
|
}
|
|
@@ -57,7 +67,7 @@ def test_interpolate_repoint_data(fake_repoint_data):
|
|
|
57
67
|
"1 query times are before",
|
|
58
68
|
), # Query times before start of table
|
|
59
69
|
(
|
|
60
|
-
np.array([
|
|
70
|
+
np.array([1, 24 * 60 * 60 + 26]),
|
|
61
71
|
"1 query times are after",
|
|
62
72
|
), # Query times after end of valid range
|
|
63
73
|
],
|
|
@@ -81,12 +91,12 @@ def test_interpolate_repoint_data_with_use_fake_fixture(use_fake_repoint_data_fo
|
|
|
81
91
|
|
|
82
92
|
# Expected repoint_start_times are the seeded start times array repeated twice
|
|
83
93
|
np.testing.assert_array_equal(
|
|
84
|
-
repoint_df["
|
|
94
|
+
repoint_df["repoint_start_met"].values,
|
|
85
95
|
np.concat([repoint_start_times, repoint_start_times]),
|
|
86
96
|
)
|
|
87
97
|
# Expected repoint_end_times are the seeded start times + 15 minutes
|
|
88
98
|
np.testing.assert_array_equal(
|
|
89
|
-
repoint_df["
|
|
99
|
+
repoint_df["repoint_end_met"].values,
|
|
90
100
|
np.concat([repoint_start_times + 15 * 60, repoint_start_times + 15 * 60]),
|
|
91
101
|
)
|
|
92
102
|
# Expected repoint_id
|
|
@@ -14,7 +14,7 @@ from imap_processing.spice.spin import (
|
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
@pytest.fixture
|
|
17
|
+
@pytest.fixture
|
|
18
18
|
def fake_spin_data(monkeypatch, spice_test_data_path):
|
|
19
19
|
"""Generate fake spin dataframe for testing"""
|
|
20
20
|
fake_spin_path = spice_test_data_path / "fake_spin_data.csv"
|
|
@@ -27,13 +27,51 @@ def fake_spin_data(monkeypatch, spice_test_data_path):
|
|
|
27
27
|
[
|
|
28
28
|
(
|
|
29
29
|
15,
|
|
30
|
-
[
|
|
30
|
+
[
|
|
31
|
+
[
|
|
32
|
+
1,
|
|
33
|
+
15,
|
|
34
|
+
0,
|
|
35
|
+
"2024-04-11 00:00:15.000000",
|
|
36
|
+
15.0,
|
|
37
|
+
True,
|
|
38
|
+
1,
|
|
39
|
+
0,
|
|
40
|
+
False,
|
|
41
|
+
15.0,
|
|
42
|
+
0.0,
|
|
43
|
+
]
|
|
44
|
+
],
|
|
31
45
|
), # Scalar test at spin start time
|
|
32
46
|
(
|
|
33
47
|
np.array([15.1, 30.2]),
|
|
34
48
|
[
|
|
35
|
-
[
|
|
36
|
-
|
|
49
|
+
[
|
|
50
|
+
1,
|
|
51
|
+
15,
|
|
52
|
+
0,
|
|
53
|
+
"2024-04-11 00:00:15.000000",
|
|
54
|
+
15.0,
|
|
55
|
+
True,
|
|
56
|
+
1,
|
|
57
|
+
0,
|
|
58
|
+
False,
|
|
59
|
+
15.0,
|
|
60
|
+
0.1 / 15,
|
|
61
|
+
],
|
|
62
|
+
[
|
|
63
|
+
2,
|
|
64
|
+
30,
|
|
65
|
+
0,
|
|
66
|
+
"2024-04-11 00:00:30.000000",
|
|
67
|
+
15.0,
|
|
68
|
+
True,
|
|
69
|
+
1,
|
|
70
|
+
0,
|
|
71
|
+
False,
|
|
72
|
+
30.0,
|
|
73
|
+
0.2 / 15,
|
|
74
|
+
],
|
|
37
75
|
],
|
|
38
76
|
), # Array test
|
|
39
77
|
],
|
|
@@ -45,7 +83,9 @@ def test_interpolate_spin_data(query_met_times, expected, fake_spin_data):
|
|
|
45
83
|
|
|
46
84
|
# Test the value
|
|
47
85
|
for i_row, row in enumerate(expected):
|
|
48
|
-
|
|
86
|
+
pd.testing.assert_series_equal(
|
|
87
|
+
spin_df.iloc[i_row], pd.Series(row), check_index=False, check_names=False
|
|
88
|
+
)
|
|
49
89
|
|
|
50
90
|
|
|
51
91
|
@pytest.mark.parametrize(
|
|
@@ -144,21 +184,22 @@ def test_get_spin_data(use_fake_spin_data_for_time):
|
|
|
144
184
|
|
|
145
185
|
assert set(spin_data.columns) == {
|
|
146
186
|
"spin_number",
|
|
147
|
-
"
|
|
148
|
-
"
|
|
187
|
+
"spin_start_sec_sclk",
|
|
188
|
+
"spin_start_subsec_sclk",
|
|
189
|
+
"spin_start_utc",
|
|
149
190
|
"spin_period_sec",
|
|
150
191
|
"spin_period_valid",
|
|
151
192
|
"spin_phase_valid",
|
|
152
193
|
"spin_period_source",
|
|
153
194
|
"thruster_firing",
|
|
154
|
-
"
|
|
195
|
+
"spin_start_met",
|
|
155
196
|
}, "Spin data must have the specified fields."
|
|
156
197
|
|
|
157
198
|
|
|
158
199
|
@pytest.mark.parametrize(
|
|
159
200
|
"instrument",
|
|
160
201
|
[
|
|
161
|
-
SpiceFrame.
|
|
202
|
+
SpiceFrame.IMAP_LO_BASE,
|
|
162
203
|
SpiceFrame.IMAP_HI_45,
|
|
163
204
|
SpiceFrame.IMAP_HI_90,
|
|
164
205
|
SpiceFrame.IMAP_ULTRA_45,
|
|
@@ -7,6 +7,7 @@ import spiceypy
|
|
|
7
7
|
from imap_processing.spice import IMAP_SC_ID
|
|
8
8
|
from imap_processing.spice.time import (
|
|
9
9
|
TICK_DURATION,
|
|
10
|
+
epoch_to_doy,
|
|
10
11
|
et_to_utc,
|
|
11
12
|
met_to_datetime64,
|
|
12
13
|
met_to_sclkticks,
|
|
@@ -202,3 +203,16 @@ def test_et_to_utc(furnish_time_kernels):
|
|
|
202
203
|
)
|
|
203
204
|
actual_utc_array = et_to_utc(array_of_et)
|
|
204
205
|
assert np.array_equal(expected_utc_array, actual_utc_array)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def test_epoch_to_doy():
|
|
209
|
+
"""Tests that epoch_to_doy() produces expected doys."""
|
|
210
|
+
epoch = 756196488384840064
|
|
211
|
+
et = epoch * 1e-9
|
|
212
|
+
# Extract DOY from output date string
|
|
213
|
+
expected_doy = int(et_to_utc(et, "D").split("//")[0].split("-")[1])
|
|
214
|
+
example_epoch = np.full(10, epoch)
|
|
215
|
+
doy = epoch_to_doy(example_epoch)
|
|
216
|
+
|
|
217
|
+
# Assert that every calculated DOY is equal to the DOY extracted from the string.
|
|
218
|
+
assert np.all(doy == expected_doy)
|