imap-processing 0.9.0__py3-none-any.whl → 0.11.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/_version.py +2 -2
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +749 -442
- imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +7 -0
- imap_processing/cdf/config/imap_glows_l1a_variable_attrs.yaml +8 -2
- imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +0 -1
- imap_processing/cdf/config/imap_glows_l2_variable_attrs.yaml +358 -0
- imap_processing/cdf/config/imap_hi_variable_attrs.yaml +59 -25
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +22 -0
- imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +32 -8
- imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +94 -5
- imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +65 -37
- imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +16 -1
- imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +7 -0
- imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +14 -14
- imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +25 -24
- imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +238 -0
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +100 -92
- imap_processing/cdf/utils.py +2 -2
- imap_processing/cli.py +45 -9
- imap_processing/codice/codice_l1a.py +104 -58
- imap_processing/codice/constants.py +111 -155
- imap_processing/codice/data/esa_sweep_values.csv +256 -256
- imap_processing/codice/data/lo_stepping_values.csv +128 -128
- imap_processing/ena_maps/ena_maps.py +519 -0
- imap_processing/ena_maps/utils/map_utils.py +145 -0
- imap_processing/ena_maps/utils/spatial_utils.py +226 -0
- imap_processing/glows/__init__.py +3 -0
- imap_processing/glows/ancillary/imap_glows_pipeline_settings_v001.json +52 -0
- imap_processing/glows/l1a/glows_l1a.py +72 -14
- imap_processing/glows/l1b/glows_l1b.py +2 -1
- imap_processing/glows/l1b/glows_l1b_data.py +25 -1
- imap_processing/glows/l2/glows_l2.py +324 -0
- imap_processing/glows/l2/glows_l2_data.py +156 -51
- imap_processing/hi/l1a/science_direct_event.py +57 -51
- imap_processing/hi/l1b/hi_l1b.py +43 -28
- imap_processing/hi/l1c/hi_l1c.py +225 -42
- imap_processing/hi/utils.py +20 -3
- imap_processing/hit/l0/constants.py +2 -2
- imap_processing/hit/l0/decom_hit.py +1 -1
- imap_processing/hit/l1a/hit_l1a.py +94 -13
- imap_processing/hit/l1b/hit_l1b.py +158 -9
- imap_processing/ialirt/l0/process_codicehi.py +156 -0
- imap_processing/ialirt/l0/process_codicelo.py +5 -2
- imap_processing/ialirt/packet_definitions/ialirt.xml +28 -20
- imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +241 -0
- imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +170 -0
- imap_processing/ialirt/packet_definitions/ialirt_swe.xml +258 -0
- imap_processing/ialirt/process_ephemeris.py +72 -40
- imap_processing/idex/decode.py +241 -0
- imap_processing/idex/idex_l1a.py +143 -81
- imap_processing/idex/idex_l1b.py +244 -10
- imap_processing/lo/l0/lo_science.py +61 -0
- imap_processing/lo/l1a/lo_l1a.py +98 -10
- imap_processing/lo/l1b/lo_l1b.py +2 -2
- imap_processing/lo/l1c/lo_l1c.py +2 -2
- imap_processing/lo/packet_definitions/lo_xtce.xml +1082 -9178
- imap_processing/mag/l0/decom_mag.py +2 -2
- imap_processing/mag/l1a/mag_l1a.py +7 -7
- imap_processing/mag/l1a/mag_l1a_data.py +62 -30
- imap_processing/mag/l1b/mag_l1b.py +11 -6
- imap_processing/quality_flags.py +18 -3
- imap_processing/spice/geometry.py +149 -177
- imap_processing/spice/kernels.py +26 -26
- imap_processing/spice/spin.py +233 -0
- imap_processing/spice/time.py +96 -31
- imap_processing/swapi/l1/swapi_l1.py +60 -31
- imap_processing/swapi/packet_definitions/swapi_packet_definition.xml +363 -384
- imap_processing/swe/l1a/swe_l1a.py +8 -3
- imap_processing/swe/l1a/swe_science.py +24 -24
- imap_processing/swe/l1b/swe_l1b.py +2 -1
- imap_processing/swe/l1b/swe_l1b_science.py +181 -122
- imap_processing/swe/l2/swe_l2.py +337 -70
- imap_processing/swe/utils/swe_utils.py +28 -0
- imap_processing/tests/cdf/test_utils.py +2 -2
- imap_processing/tests/codice/conftest.py +20 -17
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hskp_20241110193622_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-singles_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-angular_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-priority_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-species_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-angular_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-priority_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-species_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/test_codice_l0.py +55 -121
- imap_processing/tests/codice/test_codice_l1a.py +147 -59
- imap_processing/tests/conftest.py +81 -22
- imap_processing/tests/ena_maps/test_ena_maps.py +309 -0
- imap_processing/tests/ena_maps/test_map_utils.py +286 -0
- imap_processing/tests/ena_maps/test_spatial_utils.py +161 -0
- imap_processing/tests/glows/conftest.py +7 -1
- imap_processing/tests/glows/test_glows_l1a_cdf.py +3 -7
- imap_processing/tests/glows/test_glows_l1a_data.py +34 -6
- imap_processing/tests/glows/test_glows_l1b_data.py +29 -17
- imap_processing/tests/glows/test_glows_l2.py +101 -0
- imap_processing/tests/hi/conftest.py +3 -3
- imap_processing/tests/hi/data/l1/imap_hi_l1b_45sensor-de_20250415_v999.cdf +0 -0
- imap_processing/tests/hi/data/l1/imap_his_pset-calibration-prod-config_20240101_v001.csv +31 -0
- imap_processing/tests/hi/test_hi_l1b.py +14 -9
- imap_processing/tests/hi/test_hi_l1c.py +136 -36
- imap_processing/tests/hi/test_l1a.py +0 -2
- imap_processing/tests/hi/test_science_direct_event.py +18 -14
- imap_processing/tests/hi/test_utils.py +16 -11
- imap_processing/tests/hit/helpers/__init__.py +0 -0
- imap_processing/tests/hit/helpers/l1_validation.py +405 -0
- imap_processing/tests/hit/test_data/sci_sample.ccsds +0 -0
- imap_processing/tests/hit/test_decom_hit.py +8 -10
- imap_processing/tests/hit/test_hit_l1a.py +117 -180
- imap_processing/tests/hit/test_hit_l1b.py +149 -55
- imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -0
- imap_processing/tests/hit/validation_data/sci_sample_raw.csv +62 -0
- imap_processing/tests/ialirt/test_data/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/eu_SWP_IAL_20240826_152033.csv +644 -0
- imap_processing/tests/ialirt/test_data/l0/hi_fsw_view_1_ccsds.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +914 -0
- imap_processing/tests/ialirt/test_data/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
- imap_processing/tests/ialirt/unit/test_process_codicehi.py +106 -0
- imap_processing/tests/ialirt/unit/test_process_ephemeris.py +33 -5
- imap_processing/tests/ialirt/unit/test_process_swapi.py +85 -0
- imap_processing/tests/ialirt/unit/test_process_swe.py +106 -0
- imap_processing/tests/idex/conftest.py +29 -1
- imap_processing/tests/idex/test_data/compressed_2023_102_14_24_55.pkts +0 -0
- imap_processing/tests/idex/test_data/non_compressed_2023_102_14_22_26.pkts +0 -0
- imap_processing/tests/idex/test_idex_l0.py +6 -3
- imap_processing/tests/idex/test_idex_l1a.py +151 -1
- imap_processing/tests/idex/test_idex_l1b.py +124 -2
- imap_processing/tests/lo/test_lo_l1a.py +62 -2
- imap_processing/tests/lo/test_lo_science.py +85 -0
- imap_processing/tests/lo/validation_data/Instrument_FM1_T104_R129_20240803_ILO_SPIN_EU.csv +2 -0
- imap_processing/tests/mag/conftest.py +16 -0
- imap_processing/tests/mag/test_mag_decom.py +6 -4
- imap_processing/tests/mag/test_mag_l1a.py +36 -7
- imap_processing/tests/mag/test_mag_l1b.py +55 -4
- imap_processing/tests/mag/test_mag_validation.py +148 -0
- imap_processing/tests/mag/validation/L1a/T001/all_p_ones.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T001/mag-l0-l1a-t001-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T001/mag-l0-l1a-t001-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T002/all_n_ones.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T002/mag-l0-l1a-t002-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T002/mag-l0-l1a-t002-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T003/field_like.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T003/mag-l0-l1a-t003-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T003/mag-l0-l1a-t003-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T004/field_like.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T004/mag-l0-l1a-t004-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T004/mag-l0-l1a-t004-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T005/field_like_range_change.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T005/mag-l0-l1a-t005-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T005/mag-l0-l1a-t005-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T006/hdr_field.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T006/mag-l0-l1a-t006-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T006/mag-l0-l1a-t006-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T007/hdr_field_and_range_change.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T007/mag-l0-l1a-t007-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T007/mag-l0-l1a-t007-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T008/field_like_range_change.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T008/mag-l0-l1a-t008-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T008/mag-l0-l1a-t008-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T009/data.bin +0 -0
- imap_processing/tests/mag/validation/L1b/T009/field_like_all_ranges.txt +19200 -0
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-in.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-magi-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-mago-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T010/data.bin +0 -0
- imap_processing/tests/mag/validation/L1b/T010/field_like_all_ranges.txt +19200 -0
- imap_processing/tests/mag/validation/L1b/T010/mag-l1a-l1b-t010-in.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T010/mag-l1a-l1b-t010-magi-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T010/mag-l1a-l1b-t010-mago-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/data.bin +0 -0
- imap_processing/tests/mag/validation/L1b/T011/field_like_all_ranges.txt +19200 -0
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-in.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-magi-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-mago-out.csv +17 -0
- imap_processing/tests/spice/test_geometry.py +128 -133
- imap_processing/tests/spice/test_kernels.py +37 -37
- imap_processing/tests/spice/test_spin.py +184 -0
- imap_processing/tests/spice/test_time.py +43 -20
- imap_processing/tests/swapi/test_swapi_l1.py +11 -10
- imap_processing/tests/swapi/test_swapi_l2.py +13 -3
- imap_processing/tests/swe/test_swe_l1a.py +1 -1
- imap_processing/tests/swe/test_swe_l1b.py +20 -3
- imap_processing/tests/swe/test_swe_l1b_science.py +54 -35
- imap_processing/tests/swe/test_swe_l2.py +148 -5
- imap_processing/tests/test_cli.py +39 -7
- imap_processing/tests/test_quality_flags.py +19 -19
- imap_processing/tests/test_utils.py +3 -2
- imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3314 -3314
- imap_processing/tests/ultra/test_data/mock_data.py +161 -0
- imap_processing/tests/ultra/unit/conftest.py +73 -0
- imap_processing/tests/ultra/unit/test_badtimes.py +58 -0
- imap_processing/tests/ultra/unit/test_cullingmask.py +87 -0
- imap_processing/tests/ultra/unit/test_de.py +61 -60
- imap_processing/tests/ultra/unit/test_ultra_l1a.py +3 -3
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +51 -77
- imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +5 -5
- imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +114 -0
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +86 -26
- imap_processing/tests/ultra/unit/test_ultra_l1c.py +1 -1
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +3 -3
- imap_processing/ultra/constants.py +11 -1
- imap_processing/ultra/l1a/ultra_l1a.py +2 -2
- imap_processing/ultra/l1b/badtimes.py +22 -5
- imap_processing/ultra/l1b/cullingmask.py +31 -5
- imap_processing/ultra/l1b/de.py +32 -37
- imap_processing/ultra/l1b/extendedspin.py +44 -20
- imap_processing/ultra/l1b/ultra_l1b.py +21 -22
- imap_processing/ultra/l1b/ultra_l1b_culling.py +190 -0
- imap_processing/ultra/l1b/ultra_l1b_extended.py +81 -30
- imap_processing/ultra/l1c/histogram.py +6 -2
- imap_processing/ultra/l1c/pset.py +6 -2
- imap_processing/ultra/l1c/ultra_l1c.py +2 -3
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +4 -3
- imap_processing/ultra/utils/ultra_l1_utils.py +70 -14
- imap_processing/utils.py +2 -2
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/METADATA +7 -2
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/RECORD +235 -152
- imap_processing/tests/codice/data/eu_unit_lookup_table.csv +0 -101
- imap_processing/tests/codice/data/idle_export_eu.COD_NHK_20230822_122700 2.csv +0 -100
- imap_processing/tests/codice/data/idle_export_raw.COD_NHK_20230822_122700.csv +0 -100
- imap_processing/tests/codice/data/imap_codice_l0_raw_20241110_v001.pkts +0 -0
- imap_processing/tests/hi/test_data/l1a/imap_hi_l1a_45sensor-de_20250415_v000.cdf +0 -0
- imap_processing/tests/hit/test_data/sci_sample1.ccsds +0 -0
- imap_processing/tests/ultra/unit/test_spatial_utils.py +0 -125
- imap_processing/ultra/utils/spatial_utils.py +0 -221
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_APP_NHK.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_APP_NHK.csv +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_SCI_CNT.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_SCI_DE.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/H90_NHK_20241104.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/H90_sci_cnt_20241104.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/H90_sci_de_20241104.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/README.txt +0 -0
- /imap_processing/tests/idex/{imap_idex_l0_raw_20231214_v001.pkts → test_data/imap_idex_l0_raw_20231214_v001.pkts} +0 -0
- /imap_processing/tests/idex/{impact_14_tof_high_data.txt → test_data/impact_14_tof_high_data.txt} +0 -0
- /imap_processing/tests/mag/{imap_mag_l1a_norm-magi_20251017_v001.cdf → validation/imap_mag_l1a_norm-magi_20251017_v001.cdf} +0 -0
- /imap_processing/tests/mag/{mag_l0_test_data.pkts → validation/mag_l0_test_data.pkts} +0 -0
- /imap_processing/tests/mag/{mag_l0_test_output.csv → validation/mag_l0_test_output.csv} +0 -0
- /imap_processing/tests/mag/{mag_l1_test_data.pkts → validation/mag_l1_test_data.pkts} +0 -0
- /imap_processing/tests/mag/{mag_l1a_test_output.csv → validation/mag_l1a_test_output.csv} +0 -0
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
sequence,x_pri,y_pri,z_pri,rng_pri,x_sec,y_sec,z_sec,rng_sec,pri_coarse,pri_fine,sec_coarse,sec_fine,compression,compression_width_bits
|
|
2
|
+
14,13,-27,-1,1,2,-5,7,0,476381218,64355,476381218,64357,0,16
|
|
3
|
+
14,26,-30,-13,1,7,-10,-5,0,476381218,64355,476381218,64357,0,16
|
|
4
|
+
14,38,-51,-24,1,0,-14,0,0,476381218,64355,476381218,64357,0,16
|
|
5
|
+
14,44,-53,-39,2,-1,-20,5,0,476381218,64355,476381218,64357,0,16
|
|
6
|
+
14,50,-48,-50,2,12,-27,8,1,476381218,64355,476381218,64357,0,16
|
|
7
|
+
14,52,-59,-48,2,9,-32,4,1,476381218,64355,476381218,64357,0,16
|
|
8
|
+
14,53,-78,-44,2,17,-26,-4,1,476381218,64355,476381218,64357,0,16
|
|
9
|
+
14,58,-87,-51,2,29,-36,-16,1,476381218,64355,476381218,64357,0,16
|
|
10
|
+
14,51,-100,-68,3,41,-54,-29,1,476381218,64355,476381218,64357,0,16
|
|
11
|
+
14,26,-114,-70,3,47,-51,-43,2,476381218,64355,476381218,64357,0,16
|
|
12
|
+
14,34,-125,-67,3,50,-49,-49,2,476381218,64355,476381218,64357,0,16
|
|
13
|
+
14,39,-121,-70,3,53,-66,-48,2,476381218,64355,476381218,64357,0,16
|
|
14
|
+
14,29,-96,-54,3,54,-80,-44,2,476381218,64355,476381218,64357,0,16
|
|
15
|
+
14,3,-9,-2,0,59,-91,-56,2,476381218,64355,476381218,64357,0,16
|
|
16
|
+
14,0,-1,8,0,43,-103,-71,3,476381218,64355,476381218,64357,0,16
|
|
17
|
+
14,5,-10,-2,0,23,-119,-67,3,476381218,64355,476381218,64357,0,16
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
t,coarse,fine,sequence,x,y,z,range,compression,compression_width
|
|
2
|
+
2025-02-04T16:06:58.982024,476381218,64357,14,4.55075124996,-11.19786196854,15.77425592322,0,0,16
|
|
3
|
+
2025-02-04T16:06:59.482024,476381218,64357,14,15.92762937486,-22.40731698594,-11.07018889848,0,0,16
|
|
4
|
+
2025-02-04T16:06:59.982024,476381218,64357,14,0,-31.33237315404,0.16302044052,0,0,16
|
|
5
|
+
2025-02-04T16:07:00.482024,476381218,64357,14,-2.27537562498,-44.75666872758,11.44735711164,0,0,16
|
|
6
|
+
2025-02-04T16:07:00.982024,476381218,64357,14,0.885096288,-1.952868096,0.590544504,1,0,16
|
|
7
|
+
2025-02-04T16:07:01.482024,476381218,64357,14,0.663822216,-2.313845568,0.302605344,1,0,16
|
|
8
|
+
2025-02-04T16:07:01.982024,476381218,64357,14,1.253886408,-1.881232704,-0.277225488,1,0,16
|
|
9
|
+
2025-02-04T16:07:02.482024,476381218,64357,14,2.138982696,-2.605478976,-1.139884128,1,0,16
|
|
10
|
+
2025-02-04T16:07:02.982024,476381218,64357,14,3.024078984,-3.907900224,-2.071901592,1,0,16
|
|
11
|
+
2025-02-04T16:07:03.482024,476381218,64357,14,0.88482713616,-0.9431913528,-0.78778074834,2,0,16
|
|
12
|
+
2025-02-04T16:07:03.982024,476381218,64357,14,0.941305464,-0.90634074822,-0.89873597394,2,0,16
|
|
13
|
+
2025-02-04T16:07:04.482024,476381218,64357,14,0.99778379184,-1.22037879546,-0.87847855812,2,0,16
|
|
14
|
+
2025-02-04T16:07:04.982024,476381218,64357,14,1.01660990112,-1.47895667604,-0.80315324496,2,0,16
|
|
15
|
+
2025-02-04T16:07:05.482024,476381218,64357,14,1.11074044752,-1.68224447592,-1.02364442208,2,0,16
|
|
16
|
+
2025-02-04T16:07:05.982024,476381218,64357,14,0.19710391041,-0.46535117637,-0.31706811786,3,0,16
|
|
17
|
+
2025-02-04T16:07:06.482024,476381218,64357,14,0.10542767301,-0.53738602233,-0.29896071126,3,0,16
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
t,coarse,fine,sequence,x,y,z,range,compression,compression_width
|
|
2
|
+
2025-02-04T16:06:58.981994,476381218,64355,14,0.959660208,-1.952789976,-0.065792592,1,0,16
|
|
3
|
+
2025-02-04T16:06:59.481994,476381218,64355,14,1.919320416,-2.168504496,-0.934627104,1,0,16
|
|
4
|
+
2025-02-04T16:06:59.981994,476381218,64355,14,2.805160608,-3.687134832,-1.725878016,1,0,16
|
|
5
|
+
2025-02-04T16:07:00.481994,476381218,64355,14,0.82931140512,-0.97823230506,-0.71816753502,2,0,16
|
|
6
|
+
2025-02-04T16:07:00.981994,476381218,64355,14,0.942399324,-0.8856151974,-0.922033134,2,0,16
|
|
7
|
+
2025-02-04T16:07:01.481994,476381218,64355,14,0.98009529696,-1.08887713398,-0.88430215752,2,0,16
|
|
8
|
+
2025-02-04T16:07:01.981994,476381218,64355,14,0.99894328344,-1.44004598082,-0.8089813125,2,0,16
|
|
9
|
+
2025-02-04T16:07:02.481994,476381218,64355,14,1.09318321584,-1.60624150722,-0.93784261842,2,0,16
|
|
10
|
+
2025-02-04T16:07:02.981994,476381218,64355,14,0.23448643983,-0.4504876167,-0.30422097897,3,0,16
|
|
11
|
+
2025-02-04T16:07:03.481994,476381218,64355,14,0.11954210658,-0.5137174926,-0.31298135118,3,0,16
|
|
12
|
+
2025-02-04T16:07:03.981994,476381218,64355,14,0.15632429322,-0.5632591128,-0.29918061558,3,0,16
|
|
13
|
+
2025-02-04T16:07:04.481994,476381218,64355,14,0.17931315987,-0.5452042089,-0.31278820557,3,0,16
|
|
14
|
+
2025-02-04T16:07:04.981994,476381218,64355,14,0.13333542657,-0.4325684769,-0.24123552375,3,0,16
|
|
15
|
+
2025-02-04T16:07:05.481994,476381218,64355,14,6.89166060498,-20.13180037308,-4.42656442566,0,0,16
|
|
16
|
+
2025-02-04T16:07:05.981994,476381218,64355,14,0,-2.23802879004,18.00488498574,0,0,16
|
|
17
|
+
2025-02-04T16:07:06.481994,476381218,64355,14,11.4861010083,-22.3628566716,-4.42269580368,0,0,16
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
"""Tests coverage for imap_processing/spice/geometry.py"""
|
|
2
2
|
|
|
3
|
+
from unittest import mock
|
|
4
|
+
|
|
3
5
|
import numpy as np
|
|
4
|
-
import pandas as pd
|
|
5
6
|
import pytest
|
|
6
|
-
import spiceypy
|
|
7
|
+
import spiceypy
|
|
7
8
|
|
|
8
9
|
from imap_processing.spice.geometry import (
|
|
9
10
|
SpiceBody,
|
|
10
11
|
SpiceFrame,
|
|
11
12
|
basis_vectors,
|
|
13
|
+
cartesian_to_latitudinal,
|
|
12
14
|
cartesian_to_spherical,
|
|
13
15
|
frame_transform,
|
|
14
|
-
|
|
16
|
+
frame_transform_az_el,
|
|
15
17
|
get_rotation_matrix,
|
|
16
|
-
get_spacecraft_spin_phase,
|
|
17
18
|
get_spacecraft_to_instrument_spin_phase_offset,
|
|
18
|
-
get_spin_data,
|
|
19
19
|
imap_state,
|
|
20
20
|
instrument_pointing,
|
|
21
|
+
solar_longitude,
|
|
21
22
|
spherical_to_cartesian,
|
|
22
23
|
)
|
|
23
24
|
from imap_processing.spice.kernels import ensure_spice
|
|
@@ -47,116 +48,6 @@ def test_imap_state_ecliptic():
|
|
|
47
48
|
assert state.shape == (6,)
|
|
48
49
|
|
|
49
50
|
|
|
50
|
-
@pytest.fixture()
|
|
51
|
-
def fake_spin_data(monkeypatch, spice_test_data_path):
|
|
52
|
-
"""Generate fake spin dataframe for testing"""
|
|
53
|
-
fake_spin_path = spice_test_data_path / "fake_spin_data.csv"
|
|
54
|
-
monkeypatch.setenv("SPIN_DATA_FILEPATH", str(fake_spin_path))
|
|
55
|
-
return fake_spin_path
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
@pytest.mark.parametrize(
|
|
59
|
-
"query_met_times, expected",
|
|
60
|
-
[
|
|
61
|
-
(15, 0.0), # Scalar test
|
|
62
|
-
(np.array([15.1, 30.1]), np.array([0.1 / 15, 0.1 / 15])), # Array test
|
|
63
|
-
(np.array([]), None), # Empty array test
|
|
64
|
-
(np.array([50]), np.array([5 / 15])), # Single element array test
|
|
65
|
-
# The first spin has thruster firing set, but should return valid value
|
|
66
|
-
(5.0, 5 / 15),
|
|
67
|
-
# Test invalid spin period flag causes nan
|
|
68
|
-
(106.0, np.nan),
|
|
69
|
-
# Test invalid spin phase flag causes nans
|
|
70
|
-
(np.array([121, 122, 123]), np.full(3, np.nan)),
|
|
71
|
-
# Test that invalid spin period causes nans
|
|
72
|
-
(np.array([110, 111]), np.full(2, np.nan)),
|
|
73
|
-
# Test for time in missing spin
|
|
74
|
-
(65, np.nan),
|
|
75
|
-
(np.array([65.1, 66]), np.full(2, np.nan)),
|
|
76
|
-
# Combined test
|
|
77
|
-
(
|
|
78
|
-
np.array([7.5, 30, 61, 75, 106, 121, 136]),
|
|
79
|
-
np.array([0.5, 0, np.nan, 0, np.nan, np.nan, 1 / 15]),
|
|
80
|
-
),
|
|
81
|
-
],
|
|
82
|
-
)
|
|
83
|
-
def test_get_spacecraft_spin_phase(query_met_times, expected, fake_spin_data):
|
|
84
|
-
"""Test get_spacecraft_spin_phase() with generated spin data."""
|
|
85
|
-
# Call the function
|
|
86
|
-
spin_phases = get_spacecraft_spin_phase(query_met_times=query_met_times)
|
|
87
|
-
|
|
88
|
-
# Test the returned type
|
|
89
|
-
if isinstance(expected, float):
|
|
90
|
-
assert isinstance(spin_phases, float), "Spin phase must be a float."
|
|
91
|
-
elif expected is None:
|
|
92
|
-
assert len(spin_phases) == 0, "Spin phase must be empty."
|
|
93
|
-
else:
|
|
94
|
-
assert spin_phases.shape == expected.shape
|
|
95
|
-
# Test the value
|
|
96
|
-
np.testing.assert_array_almost_equal(spin_phases, expected)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
@pytest.mark.parametrize("query_met_times", [-1, 165])
|
|
100
|
-
def test_get_spacecraft_spin_phase_value_error(query_met_times, fake_spin_data):
|
|
101
|
-
"""Test get_spacecraft_spin_phase() for raising ValueError."""
|
|
102
|
-
with pytest.raises(ValueError, match="Query times"):
|
|
103
|
-
_ = get_spacecraft_spin_phase(query_met_times)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
@pytest.mark.usefixtures("use_fake_spin_data_for_time")
|
|
107
|
-
def test_get_spin_data(use_fake_spin_data_for_time):
|
|
108
|
-
"""Test get_spin_data() with generated spin data."""
|
|
109
|
-
use_fake_spin_data_for_time(453051323.0 - 56120)
|
|
110
|
-
spin_data = get_spin_data()
|
|
111
|
-
|
|
112
|
-
(
|
|
113
|
-
np.testing.assert_array_equal(spin_data["spin_number"], np.arange(5761)),
|
|
114
|
-
"One day should have 5,761 records of 15 seconds when including end_met.",
|
|
115
|
-
)
|
|
116
|
-
assert isinstance(spin_data, pd.DataFrame), "Return type must be pandas.DataFrame."
|
|
117
|
-
|
|
118
|
-
assert set(spin_data.columns) == {
|
|
119
|
-
"spin_number",
|
|
120
|
-
"spin_start_sec",
|
|
121
|
-
"spin_start_subsec",
|
|
122
|
-
"spin_period_sec",
|
|
123
|
-
"spin_period_valid",
|
|
124
|
-
"spin_phase_valid",
|
|
125
|
-
"spin_period_source",
|
|
126
|
-
"thruster_firing",
|
|
127
|
-
"spin_start_time",
|
|
128
|
-
}, "Spin data must have the specified fields."
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
@pytest.mark.parametrize(
|
|
132
|
-
"instrument",
|
|
133
|
-
[
|
|
134
|
-
SpiceFrame.IMAP_LO,
|
|
135
|
-
SpiceFrame.IMAP_HI_45,
|
|
136
|
-
SpiceFrame.IMAP_HI_90,
|
|
137
|
-
SpiceFrame.IMAP_ULTRA_45,
|
|
138
|
-
SpiceFrame.IMAP_ULTRA_90,
|
|
139
|
-
SpiceFrame.IMAP_SWAPI,
|
|
140
|
-
SpiceFrame.IMAP_IDEX,
|
|
141
|
-
SpiceFrame.IMAP_CODICE,
|
|
142
|
-
SpiceFrame.IMAP_HIT,
|
|
143
|
-
SpiceFrame.IMAP_SWE,
|
|
144
|
-
SpiceFrame.IMAP_GLOWS,
|
|
145
|
-
SpiceFrame.IMAP_MAG,
|
|
146
|
-
],
|
|
147
|
-
)
|
|
148
|
-
def test_get_instrument_spin_phase(instrument, fake_spin_data):
|
|
149
|
-
"""Test coverage for get_instrument_spin_phase()"""
|
|
150
|
-
met_times = np.array([7.5, 30, 61, 75, 106, 121, 136])
|
|
151
|
-
expected_nan_mask = np.array([False, False, True, False, True, True, False])
|
|
152
|
-
inst_phase = get_instrument_spin_phase(met_times, instrument)
|
|
153
|
-
assert inst_phase.shape == met_times.shape
|
|
154
|
-
np.testing.assert_array_equal(np.isnan(inst_phase), expected_nan_mask)
|
|
155
|
-
assert np.logical_and(
|
|
156
|
-
0 <= inst_phase[~expected_nan_mask], inst_phase[~expected_nan_mask] < 1
|
|
157
|
-
).all()
|
|
158
|
-
|
|
159
|
-
|
|
160
51
|
@pytest.mark.parametrize(
|
|
161
52
|
"instrument, expected_offset",
|
|
162
53
|
[
|
|
@@ -233,7 +124,7 @@ def test_frame_transform(et_strings, position, from_frame, to_frame, furnish_ker
|
|
|
233
124
|
]
|
|
234
125
|
with furnish_kernels(kernels):
|
|
235
126
|
# Test single et and position calculation
|
|
236
|
-
et = np.array([
|
|
127
|
+
et = np.array([spiceypy.utc2et(et_str) for et_str in et_strings])
|
|
237
128
|
et_arg = et[0] if len(et) == 1 else et
|
|
238
129
|
result = frame_transform(et_arg, position, from_frame, to_frame)
|
|
239
130
|
# check the result shape before modifying for value checking.
|
|
@@ -255,11 +146,33 @@ def test_frame_transform(et_strings, position, from_frame, to_frame, furnish_ker
|
|
|
255
146
|
position = np.broadcast_to(position, (len(et), 3))
|
|
256
147
|
result = np.broadcast_to(result, (len(et), 3))
|
|
257
148
|
for spice_et, spice_position, test_result in zip(et, position, result):
|
|
258
|
-
rotation_matrix =
|
|
259
|
-
spice_result =
|
|
149
|
+
rotation_matrix = spiceypy.pxform(from_frame.name, to_frame.name, spice_et)
|
|
150
|
+
spice_result = spiceypy.mxv(rotation_matrix, spice_position)
|
|
260
151
|
np.testing.assert_allclose(test_result, spice_result, atol=1e-12)
|
|
261
152
|
|
|
262
153
|
|
|
154
|
+
@pytest.mark.parametrize(
|
|
155
|
+
"spice_frame",
|
|
156
|
+
[
|
|
157
|
+
SpiceFrame.IMAP_DPS,
|
|
158
|
+
SpiceFrame.IMAP_SPACECRAFT,
|
|
159
|
+
SpiceFrame.ECLIPJ2000,
|
|
160
|
+
],
|
|
161
|
+
)
|
|
162
|
+
@pytest.mark.parametrize(
|
|
163
|
+
"position",
|
|
164
|
+
[
|
|
165
|
+
np.array([1, 0, 0]),
|
|
166
|
+
np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
|
|
167
|
+
np.random.rand(10, 3),
|
|
168
|
+
],
|
|
169
|
+
)
|
|
170
|
+
def test_frame_transform_same_frame(position, spice_frame):
|
|
171
|
+
"""Test that frame_transform returns position when input/output frames are same."""
|
|
172
|
+
result = frame_transform(0, position, spice_frame, spice_frame)
|
|
173
|
+
assert result is position
|
|
174
|
+
|
|
175
|
+
|
|
263
176
|
def test_frame_transform_exceptions():
|
|
264
177
|
"""Test that the proper exceptions get raised when input arguments are invalid."""
|
|
265
178
|
with pytest.raises(
|
|
@@ -287,6 +200,45 @@ def test_frame_transform_exceptions():
|
|
|
287
200
|
)
|
|
288
201
|
|
|
289
202
|
|
|
203
|
+
@pytest.mark.parametrize(
|
|
204
|
+
"spice_frame",
|
|
205
|
+
[
|
|
206
|
+
SpiceFrame.IMAP_DPS,
|
|
207
|
+
SpiceFrame.IMAP_SPACECRAFT,
|
|
208
|
+
SpiceFrame.ECLIPJ2000,
|
|
209
|
+
],
|
|
210
|
+
)
|
|
211
|
+
@pytest.mark.parametrize("degrees_bool", [True, False])
|
|
212
|
+
def test_frame_transform_az_el_same_frame(spice_frame, degrees_bool):
|
|
213
|
+
"""Test that frame_transform returns az/el when input/output frames are same."""
|
|
214
|
+
az_el_points = np.array(
|
|
215
|
+
[
|
|
216
|
+
[0, -90],
|
|
217
|
+
[0, 0],
|
|
218
|
+
[0, 89.999999],
|
|
219
|
+
[90, -90],
|
|
220
|
+
[90, 0],
|
|
221
|
+
[90, 89.999999],
|
|
222
|
+
[180, -90],
|
|
223
|
+
[180, 0],
|
|
224
|
+
[180, 89.999999],
|
|
225
|
+
[270, -90],
|
|
226
|
+
[270, 0],
|
|
227
|
+
[270, 89.999999],
|
|
228
|
+
[359.999999, -90],
|
|
229
|
+
[359.999999, 0],
|
|
230
|
+
[359.999999, 89.999999],
|
|
231
|
+
[360, 90],
|
|
232
|
+
]
|
|
233
|
+
)
|
|
234
|
+
if not degrees_bool:
|
|
235
|
+
az_el_points = np.deg2rad(az_el_points)
|
|
236
|
+
result = frame_transform_az_el(
|
|
237
|
+
0, az_el_points, spice_frame, spice_frame, degrees=degrees_bool
|
|
238
|
+
)
|
|
239
|
+
np.testing.assert_allclose(result, az_el_points)
|
|
240
|
+
|
|
241
|
+
|
|
290
242
|
def test_get_rotation_matrix(furnish_kernels):
|
|
291
243
|
"""Test coverage for get_rotation_matrix()."""
|
|
292
244
|
kernels = [
|
|
@@ -297,7 +249,7 @@ def test_get_rotation_matrix(furnish_kernels):
|
|
|
297
249
|
"sim_1yr_imap_pointing_frame.bc",
|
|
298
250
|
]
|
|
299
251
|
with furnish_kernels(kernels):
|
|
300
|
-
et =
|
|
252
|
+
et = spiceypy.utc2et("2025-09-30T12:00:00.000")
|
|
301
253
|
# test input of float
|
|
302
254
|
rotation = get_rotation_matrix(
|
|
303
255
|
et, SpiceFrame.IMAP_IDEX, SpiceFrame.IMAP_SPACECRAFT
|
|
@@ -319,7 +271,7 @@ def test_instrument_pointing(furnish_kernels):
|
|
|
319
271
|
"sim_1yr_imap_pointing_frame.bc",
|
|
320
272
|
]
|
|
321
273
|
with furnish_kernels(kernels):
|
|
322
|
-
et =
|
|
274
|
+
et = spiceypy.utc2et("2025-06-12T12:00:00.000")
|
|
323
275
|
# Single et input
|
|
324
276
|
ins_pointing = instrument_pointing(
|
|
325
277
|
et, SpiceFrame.IMAP_HI_90, SpiceFrame.ECLIPJ2000
|
|
@@ -344,7 +296,7 @@ def test_basis_vectors():
|
|
|
344
296
|
"""Test coverage for basis_vectors()."""
|
|
345
297
|
# This call to SPICE needs to be wrapped with `ensure_spice` so that kernels
|
|
346
298
|
# get furnished automatically
|
|
347
|
-
et = ensure_spice(
|
|
299
|
+
et = ensure_spice(spiceypy.utc2et)("2025-09-30T12:00:00.000")
|
|
348
300
|
# test input of float
|
|
349
301
|
sc_axes = basis_vectors(et, SpiceFrame.IMAP_SPACECRAFT, SpiceFrame.IMAP_SPACECRAFT)
|
|
350
302
|
np.testing.assert_array_equal(sc_axes, np.eye(3))
|
|
@@ -378,18 +330,11 @@ def test_cartesian_to_spherical():
|
|
|
378
330
|
|
|
379
331
|
for point in cartesian_points:
|
|
380
332
|
r, az, el = cartesian_to_spherical(point)
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
# Convert SPICE co-latitude to elevation
|
|
384
|
-
el_spice = 90 - np.degrees(colat_spice)
|
|
385
|
-
az_spice = np.degrees(slong_spice)
|
|
386
|
-
|
|
387
|
-
# Normalize azimuth to [0, 360]
|
|
388
|
-
az_spice = az_spice % 360
|
|
333
|
+
range, ra, dec = spiceypy.recrad(point)
|
|
389
334
|
|
|
390
|
-
np.testing.assert_allclose(r,
|
|
391
|
-
np.testing.assert_allclose(az,
|
|
392
|
-
np.testing.assert_allclose(el,
|
|
335
|
+
np.testing.assert_allclose(r, range, atol=1e-5)
|
|
336
|
+
np.testing.assert_allclose(az, np.degrees(ra), atol=1e-5)
|
|
337
|
+
np.testing.assert_allclose(el, np.degrees(dec), atol=1e-5)
|
|
393
338
|
|
|
394
339
|
|
|
395
340
|
def test_spherical_to_cartesian():
|
|
@@ -403,12 +348,62 @@ def test_spherical_to_cartesian():
|
|
|
403
348
|
spherical_points = np.stack(
|
|
404
349
|
(r * np.ones_like(theta).ravel(), theta.ravel(), elev.ravel()), axis=-1
|
|
405
350
|
)
|
|
351
|
+
spherical_points_degrees = np.stack(
|
|
352
|
+
(
|
|
353
|
+
r * np.ones_like(theta).ravel(),
|
|
354
|
+
np.degrees(theta.ravel()),
|
|
355
|
+
np.degrees(elev.ravel()),
|
|
356
|
+
),
|
|
357
|
+
axis=-1,
|
|
358
|
+
)
|
|
406
359
|
|
|
407
360
|
# Convert elevation to colatitude for SPICE
|
|
408
361
|
colat = np.pi / 2 - spherical_points[:, 2]
|
|
409
362
|
|
|
363
|
+
cartesian_from_degrees = spherical_to_cartesian(
|
|
364
|
+
spherical_points_degrees, degrees=True
|
|
365
|
+
)
|
|
366
|
+
|
|
410
367
|
for i in range(len(colat)):
|
|
411
368
|
cartesian_coords = spherical_to_cartesian(np.array([spherical_points[i]]))
|
|
412
|
-
spice_coords =
|
|
369
|
+
spice_coords = spiceypy.sphrec(r, colat[i], spherical_points[i, 1])
|
|
413
370
|
|
|
414
371
|
np.testing.assert_allclose(cartesian_coords[0], spice_coords, atol=1e-5)
|
|
372
|
+
np.testing.assert_allclose(cartesian_from_degrees[i], spice_coords, atol=1e-5)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def test_cartesian_to_latitudinal():
|
|
376
|
+
"""Test cartesian_to_latitudinal()."""
|
|
377
|
+
# example cartesian coords
|
|
378
|
+
coords = np.ones(3)
|
|
379
|
+
|
|
380
|
+
# test with one coord vector
|
|
381
|
+
lat_coords = cartesian_to_latitudinal(coords, degrees=True)
|
|
382
|
+
assert lat_coords.shape == (3,)
|
|
383
|
+
assert lat_coords[1] == 45
|
|
384
|
+
assert lat_coords[2] == 35.264389682754654
|
|
385
|
+
|
|
386
|
+
# Test with multiple coord vectors
|
|
387
|
+
coords = np.tile(coords, (10, 1))
|
|
388
|
+
lat_coords = cartesian_to_latitudinal(coords, degrees=True)
|
|
389
|
+
assert lat_coords.shape == (10, 3)
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
@mock.patch("imap_processing.spice.geometry.imap_state")
|
|
393
|
+
def test_solar_longitude(mock_state):
|
|
394
|
+
"""Test solar_longitude()."""
|
|
395
|
+
|
|
396
|
+
mock_state.side_effect = lambda t, observer: (
|
|
397
|
+
np.ones(6) if (isinstance(t, int)) else np.ones((len(t), 6))
|
|
398
|
+
)
|
|
399
|
+
# example et time
|
|
400
|
+
et = 798033670
|
|
401
|
+
|
|
402
|
+
# test for one time interval
|
|
403
|
+
lon = solar_longitude(et, degrees=True)
|
|
404
|
+
assert lon == 45
|
|
405
|
+
|
|
406
|
+
# Test with multiple time intervals
|
|
407
|
+
et = np.tile(et, (10, 1))
|
|
408
|
+
lon = solar_longitude(et, degrees=True)
|
|
409
|
+
assert lon.shape == (10,)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pytest
|
|
5
|
-
import spiceypy
|
|
5
|
+
import spiceypy
|
|
6
6
|
from spiceypy.utils.exceptions import SpiceyError
|
|
7
7
|
|
|
8
8
|
from imap_processing.spice.kernels import (
|
|
@@ -45,11 +45,11 @@ def multiple_pointing_kernels(spice_test_data_path):
|
|
|
45
45
|
@pytest.fixture()
|
|
46
46
|
def et_times(pointing_frame_kernels):
|
|
47
47
|
"""Tests get_et_times function."""
|
|
48
|
-
|
|
48
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
49
49
|
|
|
50
|
-
ck_kernel, _, _, _ =
|
|
51
|
-
ck_cover =
|
|
52
|
-
et_start, et_end =
|
|
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
53
|
et_times = _get_et_times(et_start, et_end)
|
|
54
54
|
|
|
55
55
|
return et_times
|
|
@@ -58,7 +58,7 @@ def et_times(pointing_frame_kernels):
|
|
|
58
58
|
@ensure_spice
|
|
59
59
|
def single_wrap_et2utc(et, fmt, prec):
|
|
60
60
|
"""Directly decorate a spice function with ensure_spice for use in tests"""
|
|
61
|
-
return
|
|
61
|
+
return spiceypy.et2utc(et, fmt, prec)
|
|
62
62
|
|
|
63
63
|
|
|
64
64
|
@ensure_spice
|
|
@@ -72,7 +72,7 @@ def double_wrap_et2utc(et, fmt, prec):
|
|
|
72
72
|
@ensure_spice(time_kernels_only=True)
|
|
73
73
|
def single_wrap_et2utc_tk_only(et, fmt, prec):
|
|
74
74
|
"""Directly wrap a spice function with optional time_kernels_only set True"""
|
|
75
|
-
return
|
|
75
|
+
return spiceypy.et2utc(et, fmt, prec)
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
@ensure_spice(time_kernels_only=True)
|
|
@@ -101,7 +101,7 @@ def test_ensure_spice_emus_mk_path(func, use_test_metakernel):
|
|
|
101
101
|
@pytest.mark.usefixtures("_unset_metakernel_path")
|
|
102
102
|
def test_ensure_spice_time_kernels():
|
|
103
103
|
"""Test functionality of ensure spice with timekernels set"""
|
|
104
|
-
wrapped = ensure_spice(
|
|
104
|
+
wrapped = ensure_spice(spiceypy.et2utc, time_kernels_only=True)
|
|
105
105
|
# TODO: Update/remove this test when a decision has been made about
|
|
106
106
|
# whether IMAP will use the time_kernels_only functionality and the
|
|
107
107
|
# ensure_spice decorator has been update.
|
|
@@ -113,7 +113,7 @@ def test_ensure_spice_time_kernels():
|
|
|
113
113
|
@pytest.mark.usefixtures("_unset_metakernel_path")
|
|
114
114
|
def test_ensure_spice_key_error():
|
|
115
115
|
"""Test functionality of ensure spice when all branches fail"""
|
|
116
|
-
wrapped = ensure_spice(
|
|
116
|
+
wrapped = ensure_spice(spiceypy.et2utc)
|
|
117
117
|
# The ensure_spice decorator should raise a SpiceyError when all attempts to
|
|
118
118
|
# furnish a set of kernels with sufficient coverage for the spiceypy
|
|
119
119
|
# functions that it decorates.
|
|
@@ -123,7 +123,7 @@ def test_ensure_spice_key_error():
|
|
|
123
123
|
|
|
124
124
|
def test_average_quaternions(et_times, pointing_frame_kernels):
|
|
125
125
|
"""Tests average_quaternions function."""
|
|
126
|
-
|
|
126
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
127
127
|
q_avg = _average_quaternions(et_times)
|
|
128
128
|
|
|
129
129
|
# Generated from MATLAB code results
|
|
@@ -133,10 +133,10 @@ def test_average_quaternions(et_times, pointing_frame_kernels):
|
|
|
133
133
|
|
|
134
134
|
def test_create_rotation_matrix(et_times, pointing_frame_kernels):
|
|
135
135
|
"""Tests create_rotation_matrix function."""
|
|
136
|
-
|
|
136
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
137
137
|
rotation_matrix = _create_rotation_matrix(et_times)
|
|
138
138
|
q_avg = _average_quaternions(et_times)
|
|
139
|
-
z_avg =
|
|
139
|
+
z_avg = spiceypy.q2m(list(q_avg))[:, 2]
|
|
140
140
|
|
|
141
141
|
rotation_matrix_expected = np.array(
|
|
142
142
|
[[0.0000, 0.0000, 1.0000], [0.9104, -0.4136, 0.0000], [0.4136, 0.9104, 0.0000]]
|
|
@@ -151,8 +151,8 @@ def test_create_pointing_frame(
|
|
|
151
151
|
spice_test_data_path, pointing_frame_kernels, tmp_path, et_times
|
|
152
152
|
):
|
|
153
153
|
"""Tests create_pointing_frame function."""
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
spiceypy.kclear()
|
|
155
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
156
156
|
create_pointing_frame(
|
|
157
157
|
pointing_frame_path=tmp_path / "imap_dps.bc",
|
|
158
158
|
ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
@@ -161,9 +161,9 @@ def test_create_pointing_frame(
|
|
|
161
161
|
# After imap_dps.bc has been created.
|
|
162
162
|
dps_kernel = str(tmp_path / "imap_dps.bc")
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
rotation_matrix_1 =
|
|
166
|
-
rotation_matrix_2 =
|
|
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
167
|
|
|
168
168
|
# All the rotation matrices should be the same.
|
|
169
169
|
assert np.array_equal(rotation_matrix_1, rotation_matrix_2)
|
|
@@ -178,7 +178,7 @@ def test_create_pointing_frame(
|
|
|
178
178
|
assert (tmp_path / "imap_dps.bc").exists()
|
|
179
179
|
|
|
180
180
|
# Tests error handling when incorrect kernel is loaded.
|
|
181
|
-
|
|
181
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
182
182
|
with pytest.raises(
|
|
183
183
|
ValueError, match="Error: Expected CK kernel badname_kernel.bc"
|
|
184
184
|
): # Replace match string with expected error message
|
|
@@ -189,11 +189,11 @@ def test_create_pointing_frame(
|
|
|
189
189
|
|
|
190
190
|
def test_et_times(pointing_frame_kernels):
|
|
191
191
|
"""Tests get_et_times function."""
|
|
192
|
-
|
|
192
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
193
193
|
|
|
194
|
-
ck_kernel, _, _, _ =
|
|
195
|
-
ck_cover =
|
|
196
|
-
et_start, et_end =
|
|
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
197
|
et_times = _get_et_times(et_start, et_end)
|
|
198
198
|
|
|
199
199
|
assert et_times[0] == et_start
|
|
@@ -204,7 +204,7 @@ def test_et_times(pointing_frame_kernels):
|
|
|
204
204
|
|
|
205
205
|
def test_multiple_attempts(pointing_frame_kernels, tmp_path, spice_test_data_path):
|
|
206
206
|
"""Tests create_pointing_frame function with multiple pointing kernels."""
|
|
207
|
-
|
|
207
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
208
208
|
|
|
209
209
|
# Check that a single segment is added regardless of how many times
|
|
210
210
|
# create_pointing_frame is called.
|
|
@@ -212,32 +212,32 @@ def test_multiple_attempts(pointing_frame_kernels, tmp_path, spice_test_data_pat
|
|
|
212
212
|
pointing_frame_path=tmp_path / "imap_dps.bc",
|
|
213
213
|
ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
214
214
|
)
|
|
215
|
-
ck_cover =
|
|
215
|
+
ck_cover = spiceypy.ckcov(
|
|
216
216
|
str(tmp_path / "imap_dps.bc"), -43901, True, "INTERVAL", 0, "TDB"
|
|
217
217
|
)
|
|
218
|
-
num_intervals =
|
|
218
|
+
num_intervals = spiceypy.wncard(ck_cover)
|
|
219
219
|
assert num_intervals == 1
|
|
220
220
|
|
|
221
221
|
create_pointing_frame(
|
|
222
222
|
pointing_frame_path=tmp_path / "imap_dps.bc",
|
|
223
223
|
ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
224
224
|
)
|
|
225
|
-
ck_cover =
|
|
225
|
+
ck_cover = spiceypy.ckcov(
|
|
226
226
|
str(tmp_path / "imap_dps.bc"), -43901, True, "INTERVAL", 0, "TDB"
|
|
227
227
|
)
|
|
228
|
-
num_intervals =
|
|
228
|
+
num_intervals = spiceypy.wncard(ck_cover)
|
|
229
229
|
assert num_intervals == 1
|
|
230
230
|
|
|
231
231
|
|
|
232
232
|
def test_multiple_pointings(pointing_frame_kernels, spice_test_data_path, tmp_path):
|
|
233
233
|
"""Tests create_pointing_frame function with multiple pointing kernels."""
|
|
234
|
-
|
|
234
|
+
spiceypy.furnsh(pointing_frame_kernels)
|
|
235
235
|
|
|
236
236
|
create_pointing_frame(
|
|
237
237
|
pointing_frame_path=tmp_path / "imap_pointing_frame.bc",
|
|
238
238
|
ck_path=spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc",
|
|
239
239
|
)
|
|
240
|
-
ck_cover_pointing =
|
|
240
|
+
ck_cover_pointing = spiceypy.ckcov(
|
|
241
241
|
str(tmp_path / "imap_pointing_frame.bc"),
|
|
242
242
|
-43901,
|
|
243
243
|
True,
|
|
@@ -245,10 +245,10 @@ def test_multiple_pointings(pointing_frame_kernels, spice_test_data_path, tmp_pa
|
|
|
245
245
|
0,
|
|
246
246
|
"TDB",
|
|
247
247
|
)
|
|
248
|
-
num_intervals =
|
|
249
|
-
et_start_pointing, et_end_pointing =
|
|
248
|
+
num_intervals = spiceypy.wncard(ck_cover_pointing)
|
|
249
|
+
et_start_pointing, et_end_pointing = spiceypy.wnfetd(ck_cover_pointing, 0)
|
|
250
250
|
|
|
251
|
-
ck_cover =
|
|
251
|
+
ck_cover = spiceypy.ckcov(
|
|
252
252
|
str(spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc"),
|
|
253
253
|
-43000,
|
|
254
254
|
True,
|
|
@@ -256,8 +256,8 @@ def test_multiple_pointings(pointing_frame_kernels, spice_test_data_path, tmp_pa
|
|
|
256
256
|
0,
|
|
257
257
|
"TDB",
|
|
258
258
|
)
|
|
259
|
-
num_intervals_expected =
|
|
260
|
-
et_start_expected, et_end_expected =
|
|
259
|
+
num_intervals_expected = spiceypy.wncard(ck_cover)
|
|
260
|
+
et_start_expected, et_end_expected = spiceypy.wnfetd(ck_cover, 0)
|
|
261
261
|
|
|
262
262
|
assert num_intervals == num_intervals_expected
|
|
263
263
|
assert et_start_pointing == et_start_expected
|
|
@@ -265,8 +265,8 @@ def test_multiple_pointings(pointing_frame_kernels, spice_test_data_path, tmp_pa
|
|
|
265
265
|
|
|
266
266
|
et_times = _get_et_times(et_start_pointing, et_end_pointing)
|
|
267
267
|
|
|
268
|
-
|
|
269
|
-
rotation_matrix_1 =
|
|
270
|
-
rotation_matrix_2 =
|
|
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
271
|
|
|
272
272
|
assert np.array_equal(rotation_matrix_1, rotation_matrix_2)
|