imap-processing 0.11.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 +11 -11
- imap_processing/_version.py +2 -2
- imap_processing/ccsds/ccsds_data.py +1 -2
- imap_processing/ccsds/excel_to_xtce.py +66 -18
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +24 -40
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +934 -42
- imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
- imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +0 -5
- imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +10 -11
- imap_processing/cdf/config/imap_hi_variable_attrs.yaml +17 -19
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +27 -14
- imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +106 -116
- imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +120 -145
- imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +14 -0
- imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +25 -9
- 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_lo_global_cdf_attrs.yaml +0 -12
- imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +1 -1
- imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +23 -20
- imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml +361 -0
- imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml +160 -0
- imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +160 -0
- imap_processing/cdf/config/imap_spacecraft_global_cdf_attrs.yaml +18 -0
- imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml +40 -0
- imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +1 -5
- imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
- imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +12 -4
- imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +16 -2
- imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +64 -52
- imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +71 -47
- imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +180 -19
- imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +80 -17
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +32 -57
- imap_processing/cdf/utils.py +52 -38
- imap_processing/cli.py +477 -233
- imap_processing/codice/codice_l1a.py +466 -131
- imap_processing/codice/codice_l1b.py +51 -152
- imap_processing/codice/constants.py +1360 -569
- imap_processing/codice/decompress.py +2 -6
- imap_processing/ena_maps/ena_maps.py +1103 -146
- imap_processing/ena_maps/utils/coordinates.py +19 -0
- imap_processing/ena_maps/utils/map_utils.py +14 -17
- imap_processing/ena_maps/utils/spatial_utils.py +55 -52
- 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 +54 -29
- imap_processing/hi/l1a/histogram.py +0 -1
- imap_processing/hi/l1a/science_direct_event.py +6 -8
- imap_processing/hi/l1b/hi_l1b.py +111 -82
- imap_processing/hi/l1c/hi_l1c.py +416 -32
- imap_processing/hi/utils.py +58 -12
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt0-factors_20250219_v002.csv +205 -0
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt1-factors_20250219_v002.csv +205 -0
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt2-factors_20250219_v002.csv +205 -0
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt3-factors_20250219_v002.csv +205 -0
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-summed-dt0-factors_20250219_v002.csv +68 -0
- imap_processing/hit/hit_utils.py +235 -5
- imap_processing/hit/l0/constants.py +20 -11
- imap_processing/hit/l0/decom_hit.py +21 -5
- imap_processing/hit/l1a/hit_l1a.py +71 -75
- imap_processing/hit/l1b/constants.py +321 -0
- imap_processing/hit/l1b/hit_l1b.py +377 -67
- imap_processing/hit/l2/constants.py +318 -0
- imap_processing/hit/l2/hit_l2.py +723 -0
- imap_processing/hit/packet_definitions/hit_packet_definitions.xml +1323 -71
- imap_processing/ialirt/l0/mag_l0_ialirt_data.py +155 -0
- imap_processing/ialirt/l0/parse_mag.py +374 -0
- imap_processing/ialirt/l0/process_swapi.py +69 -0
- imap_processing/ialirt/l0/process_swe.py +548 -0
- imap_processing/ialirt/packet_definitions/ialirt.xml +216 -208
- 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_mag.xml +115 -0
- imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
- imap_processing/ialirt/utils/grouping.py +114 -0
- imap_processing/ialirt/utils/time.py +29 -0
- imap_processing/idex/atomic_masses.csv +22 -0
- imap_processing/idex/decode.py +2 -2
- imap_processing/idex/idex_constants.py +33 -0
- imap_processing/idex/idex_l0.py +22 -8
- imap_processing/idex/idex_l1a.py +81 -51
- imap_processing/idex/idex_l1b.py +13 -39
- imap_processing/idex/idex_l2a.py +823 -0
- imap_processing/idex/idex_l2b.py +120 -0
- imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +11 -11
- imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
- imap_processing/lo/l0/lo_science.py +7 -2
- imap_processing/lo/l1a/lo_l1a.py +1 -5
- imap_processing/lo/l1b/lo_l1b.py +702 -29
- imap_processing/lo/l1b/tof_conversions.py +11 -0
- imap_processing/lo/l1c/lo_l1c.py +1 -4
- imap_processing/mag/constants.py +51 -0
- imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
- imap_processing/mag/l0/decom_mag.py +10 -3
- imap_processing/mag/l1a/mag_l1a.py +23 -19
- imap_processing/mag/l1a/mag_l1a_data.py +35 -10
- imap_processing/mag/l1b/mag_l1b.py +259 -50
- imap_processing/mag/l1c/interpolation_methods.py +388 -0
- imap_processing/mag/l1c/mag_l1c.py +621 -17
- imap_processing/mag/l2/mag_l2.py +140 -0
- imap_processing/mag/l2/mag_l2_data.py +288 -0
- imap_processing/quality_flags.py +1 -0
- imap_processing/spacecraft/packet_definitions/scid_x252.xml +538 -0
- imap_processing/spacecraft/quaternions.py +121 -0
- imap_processing/spice/geometry.py +19 -22
- imap_processing/spice/kernels.py +0 -276
- imap_processing/spice/pointing_frame.py +257 -0
- imap_processing/spice/repoint.py +149 -0
- imap_processing/spice/spin.py +38 -33
- imap_processing/spice/time.py +24 -0
- imap_processing/swapi/l1/swapi_l1.py +20 -12
- imap_processing/swapi/l2/swapi_l2.py +116 -5
- imap_processing/swapi/swapi_utils.py +32 -0
- imap_processing/swe/l1a/swe_l1a.py +44 -12
- imap_processing/swe/l1a/swe_science.py +13 -13
- imap_processing/swe/l1b/swe_l1b.py +898 -23
- imap_processing/swe/l2/swe_l2.py +75 -136
- imap_processing/swe/packet_definitions/swe_packet_definition.xml +1121 -1
- imap_processing/swe/utils/swe_constants.py +64 -0
- imap_processing/swe/utils/swe_utils.py +85 -28
- imap_processing/tests/ccsds/test_data/expected_output.xml +40 -1
- imap_processing/tests/ccsds/test_excel_to_xtce.py +24 -21
- imap_processing/tests/cdf/test_data/imap_instrument2_global_cdf_attrs.yaml +0 -2
- 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-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-singles_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-ialirt_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-omni_20241110193700_v0.0.0.cdf +0 -0
- 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_hi-priorities_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-sectored_20241110193700_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-ialirt_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-pha_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_l1a.py +126 -53
- imap_processing/tests/codice/test_codice_l1b.py +6 -7
- imap_processing/tests/codice/test_decompress.py +4 -4
- imap_processing/tests/conftest.py +239 -27
- imap_processing/tests/ena_maps/conftest.py +51 -0
- imap_processing/tests/ena_maps/test_ena_maps.py +1068 -110
- imap_processing/tests/ena_maps/test_map_utils.py +66 -43
- imap_processing/tests/ena_maps/test_spatial_utils.py +17 -21
- 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/data/l0/H45_diag_fee_20250208.bin +0 -0
- imap_processing/tests/hi/data/l0/H45_diag_fee_20250208_verify.csv +205 -0
- imap_processing/tests/hi/test_hi_l1b.py +22 -27
- imap_processing/tests/hi/test_hi_l1c.py +249 -18
- imap_processing/tests/hi/test_l1a.py +35 -7
- imap_processing/tests/hi/test_science_direct_event.py +3 -3
- imap_processing/tests/hi/test_utils.py +24 -2
- imap_processing/tests/hit/helpers/l1_validation.py +74 -73
- imap_processing/tests/hit/test_data/hskp_sample.ccsds +0 -0
- imap_processing/tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts +0 -0
- imap_processing/tests/hit/test_decom_hit.py +5 -1
- imap_processing/tests/hit/test_hit_l1a.py +32 -36
- imap_processing/tests/hit/test_hit_l1b.py +300 -81
- imap_processing/tests/hit/test_hit_l2.py +716 -0
- imap_processing/tests/hit/test_hit_utils.py +184 -7
- imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
- imap_processing/tests/hit/validation_data/hskp_sample_eu_3_6_2025.csv +89 -0
- imap_processing/tests/hit/validation_data/hskp_sample_raw.csv +89 -88
- imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
- imap_processing/tests/ialirt/data/l0/461971383-404.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971384-405.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971385-406.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971386-407.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971387-408.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971388-409.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971389-410.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971390-411.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971391-412.bin +0 -0
- imap_processing/tests/ialirt/data/l0/sample_decoded_i-alirt_data.csv +383 -0
- imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
- imap_processing/tests/ialirt/unit/test_grouping.py +81 -0
- imap_processing/tests/ialirt/unit/test_parse_mag.py +223 -0
- 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 +319 -6
- imap_processing/tests/ialirt/unit/test_time.py +16 -0
- imap_processing/tests/idex/conftest.py +127 -6
- imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231218_v001.pkts +0 -0
- 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_data/impact_14_tof_high_data.txt +4508 -4508
- imap_processing/tests/idex/test_idex_l0.py +33 -11
- imap_processing/tests/idex/test_idex_l1a.py +92 -21
- imap_processing/tests/idex/test_idex_l1b.py +106 -27
- imap_processing/tests/idex/test_idex_l2a.py +399 -0
- imap_processing/tests/idex/test_idex_l2b.py +93 -0
- imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20241022_v002.cdf +0 -0
- imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20241022_v002.cdf +0 -0
- imap_processing/tests/lo/test_lo_l1a.py +3 -3
- imap_processing/tests/lo/test_lo_l1b.py +515 -6
- imap_processing/tests/lo/test_lo_l1c.py +1 -1
- imap_processing/tests/lo/test_lo_science.py +7 -7
- imap_processing/tests/lo/test_star_sensor.py +1 -1
- imap_processing/tests/mag/conftest.py +120 -2
- imap_processing/tests/mag/test_mag_decom.py +5 -4
- imap_processing/tests/mag/test_mag_l1a.py +51 -7
- imap_processing/tests/mag/test_mag_l1b.py +40 -59
- imap_processing/tests/mag/test_mag_l1c.py +354 -19
- imap_processing/tests/mag/test_mag_l2.py +130 -0
- imap_processing/tests/mag/test_mag_validation.py +247 -26
- imap_processing/tests/mag/validation/L1b/T009/MAGScience-normal-(2,2)-8s-20250204-16h39.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-magi-out.csv +16 -16
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-mago-out.csv +16 -16
- imap_processing/tests/mag/validation/L1b/T010/MAGScience-normal-(2,2)-8s-20250206-12h05.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-magi-out.csv +16 -16
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-mago-out.csv +16 -16
- imap_processing/tests/mag/validation/L1b/T012/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T012/data.bin +0 -0
- imap_processing/tests/mag/validation/L1b/T012/field_like_all_ranges.txt +19200 -0
- imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-cal.cdf +0 -0
- imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-in.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-magi-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-mago-out.csv +17 -0
- 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_l1b-calibration_20240229_v001.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/data/SSR_2024_190_20_08_12_0483851794_2_DA_apid0594_1packet.pkts +0 -0
- imap_processing/tests/spacecraft/test_quaternions.py +71 -0
- imap_processing/tests/spice/test_data/fake_repoint_data.csv +5 -0
- imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
- imap_processing/tests/spice/test_geometry.py +9 -12
- 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 +121 -0
- 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 +13 -11
- imap_processing/tests/swapi/test_swapi_l2.py +180 -8
- imap_processing/tests/swe/l0_data/2024051010_SWE_HK_packet.bin +0 -0
- imap_processing/tests/swe/l0_data/2024051011_SWE_CEM_RAW_packet.bin +0 -0
- imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_APP_HK_20240510_092742.csv +49 -0
- imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_CEM_RAW_20240510_092742.csv +593 -0
- 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 +20 -2
- imap_processing/tests/swe/test_swe_l1a_cem_raw.py +52 -0
- imap_processing/tests/swe/test_swe_l1a_hk.py +68 -0
- 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 +153 -91
- imap_processing/tests/test_cli.py +171 -88
- imap_processing/tests/test_utils.py +140 -17
- imap_processing/tests/ultra/data/l0/FM45_UltraFM45_Functional_2024-01-22T0105_20240122T010548.CCSDS +0 -0
- imap_processing/tests/ultra/data/l0/ultra45_raw_sc_ultraimgrates_20220530_00.csv +164 -0
- imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3243 -3243
- imap_processing/tests/ultra/data/mock_data.py +369 -0
- imap_processing/tests/ultra/unit/conftest.py +115 -89
- imap_processing/tests/ultra/unit/test_badtimes.py +4 -4
- imap_processing/tests/ultra/unit/test_cullingmask.py +8 -6
- imap_processing/tests/ultra/unit/test_de.py +14 -13
- imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
- imap_processing/tests/ultra/unit/test_decom_apid_881.py +54 -11
- 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 +77 -0
- imap_processing/tests/ultra/unit/test_ultra_l1a.py +98 -305
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +60 -14
- imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
- imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +26 -27
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +239 -70
- imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +114 -83
- 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 +27 -39
- 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 -271
- imap_processing/ultra/l1b/badtimes.py +1 -4
- imap_processing/ultra/l1b/cullingmask.py +2 -6
- imap_processing/ultra/l1b/de.py +116 -57
- imap_processing/ultra/l1b/extendedspin.py +20 -18
- imap_processing/ultra/l1b/lookup_utils.py +72 -9
- imap_processing/ultra/l1b/ultra_l1b.py +36 -16
- imap_processing/ultra/l1b/ultra_l1b_culling.py +66 -30
- imap_processing/ultra/l1b/ultra_l1b_extended.py +297 -94
- imap_processing/ultra/l1c/histogram.py +2 -6
- imap_processing/ultra/l1c/spacecraft_pset.py +84 -0
- imap_processing/ultra/l1c/ultra_l1c.py +8 -9
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +206 -108
- 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 +31 -12
- imap_processing/utils.py +69 -29
- {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +10 -6
- imap_processing-0.13.0.dist-info/RECORD +578 -0
- imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +0 -237
- imap_processing/hi/l1a/housekeeping.py +0 -27
- imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
- imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
- imap_processing/swe/l1b/swe_l1b_science.py +0 -652
- 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/hi/data/l1/imap_hi_l1b_45sensor-de_20250415_v999.cdf +0 -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/validation_data/hskp_sample_eu.csv +0 -89
- imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +0 -29
- imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231214_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/swe/test_swe_l1b_science.py +0 -84
- imap_processing/tests/ultra/test_data/mock_data.py +0 -161
- imap_processing/ultra/l1c/pset.py +0 -40
- imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
- imap_processing-0.11.0.dist-info/RECORD +0 -488
- /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/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/{mag/l1b → tests/spacecraft}/__init__.py +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/tests/ultra/{test_data → data}/l0/FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00_20240207T102740.CCSDS +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/FM45_7P_Phi0.0_BeamCal_LinearScan_phi0.04_theta-0.01_20230821T121304.CCSDS +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.CCSDS +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.CCSDS +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_auxdata_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_enaphxtofhangimg_FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.csv +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultraimgrates_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimgevent_FM45_7P_Phi00_BeamCal_LinearScan_phi004_theta-001_20230821T121304.csv +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E1.cdf +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E12.cdf +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E24.cdf +0 -0
- {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Spacecraft quaternion processing."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import xarray as xr
|
|
7
|
+
|
|
8
|
+
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
9
|
+
from imap_processing.spice.time import met_to_ttj2000ns
|
|
10
|
+
from imap_processing.utils import packet_file_to_datasets
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def load_quaternion_packets(packet_file: Path | str) -> xr.Dataset:
|
|
14
|
+
"""
|
|
15
|
+
Load the raw quaternion packets from the packet file.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
packet_file : Path
|
|
20
|
+
Path to the packet file containing the quaternions in apid 594.
|
|
21
|
+
|
|
22
|
+
Returns
|
|
23
|
+
-------
|
|
24
|
+
xarray.Dataset
|
|
25
|
+
Dataset containing the raw quaternion packets.
|
|
26
|
+
"""
|
|
27
|
+
xtce_packet_definition = Path(__file__).parent / "packet_definitions/scid_x252.xml"
|
|
28
|
+
datasets_by_apid = packet_file_to_datasets(
|
|
29
|
+
packet_file=packet_file, xtce_packet_definition=xtce_packet_definition
|
|
30
|
+
)
|
|
31
|
+
return datasets_by_apid[0x252]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def assemble_quaternions(ds: xr.Dataset) -> xr.Dataset:
|
|
35
|
+
"""
|
|
36
|
+
Assemble quaternions from the l1a dataset.
|
|
37
|
+
|
|
38
|
+
The quaternions are stored in separate variables for each component (x, y, z, s)
|
|
39
|
+
and for each 10 Hz sample of the 1s packet. i.e. there are 4 * 10 = 40 variables
|
|
40
|
+
in the initial dataset that we want to turn into 4 variables with a continuous
|
|
41
|
+
10 Hz sampling period.
|
|
42
|
+
|
|
43
|
+
The output dataset will have a single dimension "epoch" that will be the time
|
|
44
|
+
associated with each of the 10 Hz samples. There are 4 data variables: "quat_x",
|
|
45
|
+
"quat_y", "quat_z", "quat_s".
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
ds : xarray.Dataset
|
|
50
|
+
Input dataset containing the 10Hz quaternions from packet 0x252 (APID 594).
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
xarray.Dataset
|
|
55
|
+
Output dataset with the quaternions assembled into 4 variables with a
|
|
56
|
+
continuous 10 Hz sampling period.
|
|
57
|
+
"""
|
|
58
|
+
# Our time is only given for the first timestamp
|
|
59
|
+
# We then add to it 0.1 increments and ravel the array to associate a specific time
|
|
60
|
+
# with each of the 10 samples
|
|
61
|
+
time = (
|
|
62
|
+
ds["SCIENCEDATA1HZ_QUAT_10_HZ_TIME".lower()].values[:, np.newaxis]
|
|
63
|
+
+ np.arange(0, 1, 0.1)
|
|
64
|
+
).ravel()
|
|
65
|
+
output_ds = xr.Dataset(coords={"epoch": time})
|
|
66
|
+
base_name = "FSW_ACS_QUAT_10_HZ_BUFFERED".lower()
|
|
67
|
+
for quat_i, label in enumerate(["x", "y", "z", "s"]):
|
|
68
|
+
# 0, 1, 2, .. 9 // 10, 11, 12, .. 19 // 20, 21, 22, .. 29 // 30, 31, 32, .. 39
|
|
69
|
+
names = [f"{base_name}_{i + quat_i * 10}" for i in range(10)]
|
|
70
|
+
quat = np.stack([ds[name] for name in names], axis=1).ravel()
|
|
71
|
+
output_ds[f"quat_{label}"] = ("epoch", quat)
|
|
72
|
+
return output_ds
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def process_quaternions(packet_file: Path | str) -> tuple[xr.Dataset, xr.Dataset]:
|
|
76
|
+
"""
|
|
77
|
+
Generate l1a and l1b datasets from a packet file containing the raw quaternions.
|
|
78
|
+
|
|
79
|
+
This produces two CDF files: one for the l1a quaternions and one for the l1b
|
|
80
|
+
quaternions. The l1b quaternions are assembled into 4 variables: "quat_x",
|
|
81
|
+
"quat_y", "quat_z", "quat_s".
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
packet_file : Path
|
|
86
|
+
Path to the packet file containing the quaternions in apid 594.
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
xarray.Dataset
|
|
91
|
+
Dataset containing the l1a quaternions.
|
|
92
|
+
xarray.Dataset
|
|
93
|
+
Dataset containing the l1b quaternions.
|
|
94
|
+
"""
|
|
95
|
+
l1a_ds = load_quaternion_packets(packet_file)
|
|
96
|
+
|
|
97
|
+
# Assemble the quaternions into the correct components
|
|
98
|
+
l1b_ds = assemble_quaternions(l1a_ds)
|
|
99
|
+
|
|
100
|
+
# Update dataset global attributes
|
|
101
|
+
attr_mgr = ImapCdfAttributes()
|
|
102
|
+
attr_mgr.add_instrument_global_attrs("spacecraft")
|
|
103
|
+
attr_mgr.add_instrument_variable_attrs(instrument="spacecraft", level=None)
|
|
104
|
+
|
|
105
|
+
l1a_ds.attrs.update(
|
|
106
|
+
attr_mgr.get_global_attributes("imap_spacecraft_l1a_quaternions")
|
|
107
|
+
)
|
|
108
|
+
l1b_ds.attrs.update(
|
|
109
|
+
attr_mgr.get_global_attributes("imap_spacecraft_l1b_quaternions")
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Update the epoch attribute
|
|
113
|
+
l1b_ds["epoch"] = met_to_ttj2000ns(l1b_ds["epoch"])
|
|
114
|
+
# check_schema=False keeps DEPEND_0 = '' from being auto added
|
|
115
|
+
epoch_attrs = attr_mgr.get_variable_attributes("epoch", check_schema=False)
|
|
116
|
+
l1b_ds["epoch"].attrs.update(epoch_attrs)
|
|
117
|
+
|
|
118
|
+
for var in ["quat_x", "quat_y", "quat_z", "quat_s"]:
|
|
119
|
+
l1b_ds[var].attrs.update(attr_mgr.get_variable_attributes(var))
|
|
120
|
+
|
|
121
|
+
return l1a_ds, l1b_ds
|
|
@@ -63,7 +63,7 @@ class SpiceFrame(IntEnum):
|
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
BORESIGHT_LOOKUP = {
|
|
66
|
-
SpiceFrame.
|
|
66
|
+
SpiceFrame.IMAP_LO_BASE: np.array([0, -1, 0]),
|
|
67
67
|
SpiceFrame.IMAP_HI_45: np.array([0, 1, 0]),
|
|
68
68
|
SpiceFrame.IMAP_HI_90: np.array([0, 1, 0]),
|
|
69
69
|
SpiceFrame.IMAP_ULTRA_45: np.array([0, 0, 1]),
|
|
@@ -136,7 +136,7 @@ def get_spacecraft_to_instrument_spin_phase_offset(instrument: SpiceFrame) -> fl
|
|
|
136
136
|
"""
|
|
137
137
|
# TODO: Implement retrieval from SPICE?
|
|
138
138
|
offset_lookup = {
|
|
139
|
-
SpiceFrame.
|
|
139
|
+
SpiceFrame.IMAP_LO_BASE: 330 / 360,
|
|
140
140
|
SpiceFrame.IMAP_HI_45: 255 / 360,
|
|
141
141
|
SpiceFrame.IMAP_HI_90: 285 / 360,
|
|
142
142
|
SpiceFrame.IMAP_ULTRA_45: 33 / 360,
|
|
@@ -268,7 +268,7 @@ def frame_transform_az_el(
|
|
|
268
268
|
spherical_coords_in = np.array(
|
|
269
269
|
[np.ones_like(az_el[..., 0]), az_el[..., 0], az_el[..., 1]]
|
|
270
270
|
).T
|
|
271
|
-
from_frame_cartesian = spherical_to_cartesian(spherical_coords_in
|
|
271
|
+
from_frame_cartesian = spherical_to_cartesian(spherical_coords_in)
|
|
272
272
|
# Transform to to_frame
|
|
273
273
|
to_frame_cartesian = frame_transform(et, from_frame_cartesian, from_frame, to_frame)
|
|
274
274
|
# Convert to spherical and extract azimuth/elevation
|
|
@@ -325,7 +325,7 @@ def instrument_pointing(
|
|
|
325
325
|
"""
|
|
326
326
|
Compute the instrument pointing at the specified times.
|
|
327
327
|
|
|
328
|
-
By default, the coordinates returned are
|
|
328
|
+
By default, the coordinates returned are (Longitude, Latitude) coordinates in
|
|
329
329
|
the reference frame `to_frame`. Cartesian coordinates can be returned if
|
|
330
330
|
desired by setting `cartesian=True`.
|
|
331
331
|
|
|
@@ -425,14 +425,14 @@ def cartesian_to_spherical(
|
|
|
425
425
|
- r : Distance of the point from the origin.
|
|
426
426
|
- azimuth : angle in the xy-plane
|
|
427
427
|
In degrees if degrees parameter is True (by default):
|
|
428
|
-
output range=[0, 360
|
|
428
|
+
output range=[0, 360) degrees,
|
|
429
429
|
otherwise in radians if degrees parameter is False:
|
|
430
|
-
output range=[0, 2*pi
|
|
430
|
+
output range=[0, 2*pi) radians.
|
|
431
431
|
- elevation : angle from the xy-plane
|
|
432
432
|
In degrees if degrees parameter is True (by default):
|
|
433
|
-
output range=[
|
|
433
|
+
output range=[-90, 90) degrees,
|
|
434
434
|
otherwise in radians if degrees parameter is False:
|
|
435
|
-
output range=[-pi/2, pi/2
|
|
435
|
+
output range=[-pi/2, pi/2) radians.
|
|
436
436
|
"""
|
|
437
437
|
# Magnitude of the velocity vector
|
|
438
438
|
magnitude_v = np.linalg.norm(v, axis=-1, keepdims=True)
|
|
@@ -457,9 +457,9 @@ def cartesian_to_spherical(
|
|
|
457
457
|
return spherical_coords
|
|
458
458
|
|
|
459
459
|
|
|
460
|
-
def spherical_to_cartesian(spherical_coords: NDArray
|
|
460
|
+
def spherical_to_cartesian(spherical_coords: NDArray) -> NDArray:
|
|
461
461
|
"""
|
|
462
|
-
Convert spherical coordinates to Cartesian coordinates.
|
|
462
|
+
Convert spherical coordinates (angles in degrees) to Cartesian coordinates.
|
|
463
463
|
|
|
464
464
|
Parameters
|
|
465
465
|
----------
|
|
@@ -468,11 +468,8 @@ def spherical_to_cartesian(spherical_coords: NDArray, degrees: bool = False) ->
|
|
|
468
468
|
the spherical coordinates (r, azimuth, elevation):
|
|
469
469
|
|
|
470
470
|
- r : Distance of the point from the origin.
|
|
471
|
-
- azimuth : angle in the xy-plane in
|
|
472
|
-
- elevation : angle from the xy-plane in
|
|
473
|
-
degrees : bool
|
|
474
|
-
Set to True if input azimuth and elevation angles are in degrees.
|
|
475
|
-
Defaults to False.
|
|
471
|
+
- azimuth : angle in the xy-plane in degrees. Range is [0, 360) degrees.
|
|
472
|
+
- elevation : angle from the xy-plane in degrees. Range is [-90, 90) degrees.
|
|
476
473
|
|
|
477
474
|
Returns
|
|
478
475
|
-------
|
|
@@ -483,9 +480,9 @@ def spherical_to_cartesian(spherical_coords: NDArray, degrees: bool = False) ->
|
|
|
483
480
|
azimuth = spherical_coords[..., 1]
|
|
484
481
|
elevation = spherical_coords[..., 2]
|
|
485
482
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
483
|
+
# Convert to radians for numpy trigonometric operations
|
|
484
|
+
azimuth = np.deg2rad(azimuth)
|
|
485
|
+
elevation = np.deg2rad(elevation)
|
|
489
486
|
|
|
490
487
|
x = r * np.cos(elevation) * np.cos(azimuth)
|
|
491
488
|
y = r * np.cos(elevation) * np.sin(azimuth)
|
|
@@ -496,7 +493,7 @@ def spherical_to_cartesian(spherical_coords: NDArray, degrees: bool = False) ->
|
|
|
496
493
|
return cartesian_coords
|
|
497
494
|
|
|
498
495
|
|
|
499
|
-
def cartesian_to_latitudinal(coords: NDArray, degrees: bool =
|
|
496
|
+
def cartesian_to_latitudinal(coords: NDArray, degrees: bool = True) -> NDArray:
|
|
500
497
|
"""
|
|
501
498
|
Convert cartesian coordinates to latitudinal coordinates in radians.
|
|
502
499
|
|
|
@@ -511,7 +508,7 @@ def cartesian_to_latitudinal(coords: NDArray, degrees: bool = False) -> NDArray:
|
|
|
511
508
|
with x, y, z-components.
|
|
512
509
|
degrees : bool
|
|
513
510
|
If True, the longitude and latitude coords are returned in degrees.
|
|
514
|
-
Defaults to
|
|
511
|
+
Defaults to True.
|
|
515
512
|
|
|
516
513
|
Returns
|
|
517
514
|
-------
|
|
@@ -532,7 +529,7 @@ def cartesian_to_latitudinal(coords: NDArray, degrees: bool = False) -> NDArray:
|
|
|
532
529
|
|
|
533
530
|
def solar_longitude(
|
|
534
531
|
et: Union[np.ndarray, float],
|
|
535
|
-
degrees: bool =
|
|
532
|
+
degrees: bool = True,
|
|
536
533
|
) -> Union[float, npt.NDArray]:
|
|
537
534
|
"""
|
|
538
535
|
Compute the solar longitude of the Imap Spacecraft.
|
|
@@ -543,7 +540,7 @@ def solar_longitude(
|
|
|
543
540
|
Ephemeris time(s) to at which to compute solar longitude.
|
|
544
541
|
degrees : bool
|
|
545
542
|
If True, the longitude is returned in degrees.
|
|
546
|
-
Defaults to
|
|
543
|
+
Defaults to True.
|
|
547
544
|
|
|
548
545
|
Returns
|
|
549
546
|
-------
|
imap_processing/spice/kernels.py
CHANGED
|
@@ -3,14 +3,9 @@
|
|
|
3
3
|
import functools
|
|
4
4
|
import logging
|
|
5
5
|
import os
|
|
6
|
-
from collections.abc import Generator
|
|
7
|
-
from contextlib import contextmanager
|
|
8
|
-
from pathlib import Path
|
|
9
6
|
from typing import Any, Callable, Optional, Union, overload
|
|
10
7
|
|
|
11
|
-
import numpy as np
|
|
12
8
|
import spiceypy
|
|
13
|
-
from numpy.typing import NDArray
|
|
14
9
|
from spiceypy.utils.exceptions import SpiceyError
|
|
15
10
|
|
|
16
11
|
from imap_processing import imap_module_directory
|
|
@@ -181,277 +176,6 @@ def ensure_spice(
|
|
|
181
176
|
return _decorator
|
|
182
177
|
|
|
183
178
|
|
|
184
|
-
@contextmanager
|
|
185
|
-
def open_spice_ck_file(pointing_frame_path: Path) -> Generator[int, None, None]:
|
|
186
|
-
"""
|
|
187
|
-
Context manager for handling SPICE CK files.
|
|
188
|
-
|
|
189
|
-
Parameters
|
|
190
|
-
----------
|
|
191
|
-
pointing_frame_path : str
|
|
192
|
-
Path to the CK file.
|
|
193
|
-
|
|
194
|
-
Yields
|
|
195
|
-
------
|
|
196
|
-
handle : int
|
|
197
|
-
Handle to the opened CK file.
|
|
198
|
-
"""
|
|
199
|
-
# TODO: We will need to figure out if ck kernel changes
|
|
200
|
-
# and how that will affect appending to the pointing
|
|
201
|
-
# frame kernel.
|
|
202
|
-
if pointing_frame_path.exists():
|
|
203
|
-
handle = spiceypy.dafopw(str(pointing_frame_path))
|
|
204
|
-
else:
|
|
205
|
-
handle = spiceypy.ckopn(str(pointing_frame_path), "CK", 0)
|
|
206
|
-
try:
|
|
207
|
-
yield handle
|
|
208
|
-
finally:
|
|
209
|
-
spiceypy.ckcls(handle)
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
@ensure_spice
|
|
213
|
-
def create_pointing_frame(pointing_frame_path: Path, ck_path: Path) -> None:
|
|
214
|
-
"""
|
|
215
|
-
Create the pointing frame.
|
|
216
|
-
|
|
217
|
-
Parameters
|
|
218
|
-
----------
|
|
219
|
-
pointing_frame_path : pathlib.Path
|
|
220
|
-
Location of pointing frame kernel.
|
|
221
|
-
ck_path : pathlib.Path
|
|
222
|
-
Location of the CK kernel.
|
|
223
|
-
|
|
224
|
-
Notes
|
|
225
|
-
-----
|
|
226
|
-
Kernels required to be furnished:
|
|
227
|
-
"imap_science_0001.tf",
|
|
228
|
-
"imap_sclk_0000.tsc",
|
|
229
|
-
"imap_sim_ck_2hr_2secsampling_with_nutation.bc" or
|
|
230
|
-
"sim_1yr_imap_attitude.bc",
|
|
231
|
-
"imap_wkcp.tf",
|
|
232
|
-
"naif0012.tls"
|
|
233
|
-
|
|
234
|
-
Assumptions:
|
|
235
|
-
- The MOC has removed timeframe in which nutation/procession are present.
|
|
236
|
-
TODO: We may come back and have a check for this.
|
|
237
|
-
- We will continue to append to the pointing frame kernel.
|
|
238
|
-
TODO: Figure out how we want to handle the file size becoming too large.
|
|
239
|
-
- For now we can only furnish a single ck kernel.
|
|
240
|
-
TODO: This will not be the case once we add the ability to query the .csv.
|
|
241
|
-
|
|
242
|
-
References
|
|
243
|
-
----------
|
|
244
|
-
https://numpydoc.readthedocs.io/en/latest/format.html#references
|
|
245
|
-
"""
|
|
246
|
-
# Get IDs.
|
|
247
|
-
# https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.gipool
|
|
248
|
-
id_imap_dps = spiceypy.gipool("FRAME_IMAP_DPS", 0, 1)
|
|
249
|
-
id_imap_sclk = spiceypy.gipool("CK_-43000_SCLK", 0, 1)
|
|
250
|
-
|
|
251
|
-
# Verify that only ck_path kernel is loaded.
|
|
252
|
-
count = spiceypy.ktotal("ck")
|
|
253
|
-
loaded_ck_kernel, _, _, _ = spiceypy.kdata(count - 1, "ck")
|
|
254
|
-
|
|
255
|
-
if count != 1 or str(ck_path) != loaded_ck_kernel:
|
|
256
|
-
raise ValueError(f"Error: Expected CK kernel {ck_path}")
|
|
257
|
-
|
|
258
|
-
# If the pointing frame kernel already exists, find the last time.
|
|
259
|
-
if pointing_frame_path.exists():
|
|
260
|
-
# Get the last time in the pointing frame kernel.
|
|
261
|
-
pointing_cover = spiceypy.ckcov(
|
|
262
|
-
str(pointing_frame_path), int(id_imap_dps), True, "SEGMENT", 0, "TDB"
|
|
263
|
-
)
|
|
264
|
-
num_segments = spiceypy.wncard(pointing_cover)
|
|
265
|
-
_, et_end_pointing_frame = spiceypy.wnfetd(pointing_cover, num_segments - 1)
|
|
266
|
-
else:
|
|
267
|
-
et_end_pointing_frame = None
|
|
268
|
-
|
|
269
|
-
# TODO: Query for .csv file to get the pointing start and end times.
|
|
270
|
-
# TODO: Remove next four lines once query is added.
|
|
271
|
-
id_imap_spacecraft = spiceypy.gipool("FRAME_IMAP_SPACECRAFT", 0, 1)
|
|
272
|
-
ck_cover = spiceypy.ckcov(
|
|
273
|
-
str(ck_path), int(id_imap_spacecraft), True, "INTERVAL", 0, "TDB"
|
|
274
|
-
)
|
|
275
|
-
num_intervals = spiceypy.wncard(ck_cover)
|
|
276
|
-
|
|
277
|
-
with open_spice_ck_file(pointing_frame_path) as handle:
|
|
278
|
-
# TODO: this will change to the number of pointings.
|
|
279
|
-
for i in range(num_intervals):
|
|
280
|
-
# Get the coverage window
|
|
281
|
-
# TODO: this will change to pointing start and end time.
|
|
282
|
-
et_start, et_end = spiceypy.wnfetd(ck_cover, i)
|
|
283
|
-
et_times = _get_et_times(et_start, et_end)
|
|
284
|
-
|
|
285
|
-
# TODO: remove after query is added.
|
|
286
|
-
if (
|
|
287
|
-
et_end_pointing_frame is not None
|
|
288
|
-
and et_times[0] < et_end_pointing_frame
|
|
289
|
-
):
|
|
290
|
-
break
|
|
291
|
-
|
|
292
|
-
# Create a rotation matrix
|
|
293
|
-
rotation_matrix = _create_rotation_matrix(et_times)
|
|
294
|
-
|
|
295
|
-
# Convert the rotation matrix to a quaternion.
|
|
296
|
-
# https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.m2q
|
|
297
|
-
q_avg = spiceypy.m2q(rotation_matrix)
|
|
298
|
-
|
|
299
|
-
# https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.sce2c
|
|
300
|
-
# Convert start and end times to SCLK.
|
|
301
|
-
sclk_begtim = spiceypy.sce2c(int(id_imap_sclk), et_times[0])
|
|
302
|
-
sclk_endtim = spiceypy.sce2c(int(id_imap_sclk), et_times[-1])
|
|
303
|
-
|
|
304
|
-
# Create the pointing frame kernel.
|
|
305
|
-
# https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.ckw02
|
|
306
|
-
spiceypy.ckw02(
|
|
307
|
-
# Handle of an open CK file.
|
|
308
|
-
handle,
|
|
309
|
-
# Start time of the segment.
|
|
310
|
-
sclk_begtim,
|
|
311
|
-
# End time of the segment.
|
|
312
|
-
sclk_endtim,
|
|
313
|
-
# Pointing frame ID.
|
|
314
|
-
int(id_imap_dps),
|
|
315
|
-
# Reference frame.
|
|
316
|
-
"ECLIPJ2000", # Reference frame
|
|
317
|
-
# Identifier.
|
|
318
|
-
"IMAP_DPS",
|
|
319
|
-
# Number of pointing intervals.
|
|
320
|
-
1,
|
|
321
|
-
# Start times of individual pointing records within segment.
|
|
322
|
-
# Since there is only a single record this is equal to sclk_begtim.
|
|
323
|
-
np.array([sclk_begtim]),
|
|
324
|
-
# End times of individual pointing records within segment.
|
|
325
|
-
# Since there is only a single record this is equal to sclk_endtim.
|
|
326
|
-
np.array([sclk_endtim]), # Single stop time
|
|
327
|
-
# Average quaternion.
|
|
328
|
-
q_avg,
|
|
329
|
-
# 0.0 Angular rotation terms.
|
|
330
|
-
np.array([0.0, 0.0, 0.0]),
|
|
331
|
-
# Rates (seconds per tick) at which the quaternion and
|
|
332
|
-
# angular velocity change.
|
|
333
|
-
np.array([1.0]),
|
|
334
|
-
)
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
def _get_et_times(et_start: float, et_end: float) -> NDArray[np.float64]:
|
|
338
|
-
"""
|
|
339
|
-
Get times for pointing start and stop.
|
|
340
|
-
|
|
341
|
-
Parameters
|
|
342
|
-
----------
|
|
343
|
-
et_start : float
|
|
344
|
-
Pointing start time.
|
|
345
|
-
et_end : float
|
|
346
|
-
Pointing end time.
|
|
347
|
-
|
|
348
|
-
Returns
|
|
349
|
-
-------
|
|
350
|
-
et_times : numpy.ndarray
|
|
351
|
-
Array of times between et_start and et_end.
|
|
352
|
-
"""
|
|
353
|
-
# TODO: Queried pointing start and stop times here.
|
|
354
|
-
# TODO removing the @ensure_spice decorator when using the repointing table.
|
|
355
|
-
|
|
356
|
-
# 1 spin/15 seconds; 10 quaternions / spin.
|
|
357
|
-
num_samples = (et_end - et_start) / 15 * 10
|
|
358
|
-
# There were rounding errors when using spiceypy.pxform so np.ceil and np.floor
|
|
359
|
-
# were used to ensure the start and end times were included in the array.
|
|
360
|
-
et_times = np.linspace(
|
|
361
|
-
np.ceil(et_start * 1e6) / 1e6, np.floor(et_end * 1e6) / 1e6, int(num_samples)
|
|
362
|
-
)
|
|
363
|
-
|
|
364
|
-
return et_times
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
@ensure_spice
|
|
368
|
-
def _average_quaternions(et_times: np.ndarray) -> NDArray:
|
|
369
|
-
"""
|
|
370
|
-
Average the quaternions.
|
|
371
|
-
|
|
372
|
-
Parameters
|
|
373
|
-
----------
|
|
374
|
-
et_times : numpy.ndarray
|
|
375
|
-
Array of times between et_start and et_end.
|
|
376
|
-
|
|
377
|
-
Returns
|
|
378
|
-
-------
|
|
379
|
-
q_avg : np.ndarray
|
|
380
|
-
Average quaternion.
|
|
381
|
-
"""
|
|
382
|
-
aggregate = np.zeros((4, 4))
|
|
383
|
-
for tdb in et_times:
|
|
384
|
-
# we use a quick and dirty method here for grabbing the quaternions
|
|
385
|
-
# from the attitude kernel. Depending on how well the kernel input
|
|
386
|
-
# data is built and sampled, there may or may not be aliasing with this
|
|
387
|
-
# approach. If it turns out that we need to pull the quaternions
|
|
388
|
-
# directly from the CK there are several routines that exist to do this
|
|
389
|
-
# but it's not straight forward. We'll revisit this if needed.
|
|
390
|
-
|
|
391
|
-
# Rotation matrix from IMAP spacecraft frame to ECLIPJ2000.
|
|
392
|
-
# https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.pxform
|
|
393
|
-
body_rots = spiceypy.pxform("IMAP_SPACECRAFT", "ECLIPJ2000", tdb)
|
|
394
|
-
# Convert rotation matrix to quaternion.
|
|
395
|
-
# https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.m2q
|
|
396
|
-
body_quat = spiceypy.m2q(body_rots)
|
|
397
|
-
|
|
398
|
-
# Standardize the quaternion so that they may be compared.
|
|
399
|
-
body_quat = body_quat * np.sign(body_quat[0])
|
|
400
|
-
# Aggregate quaternions into a single matrix.
|
|
401
|
-
aggregate += np.outer(body_quat, body_quat)
|
|
402
|
-
|
|
403
|
-
# Reference: "On Averaging Rotations".
|
|
404
|
-
# Link: https://link.springer.com/content/pdf/10.1023/A:1011129215388.pdf
|
|
405
|
-
aggregate /= len(et_times)
|
|
406
|
-
|
|
407
|
-
# Compute eigen values and vectors of the matrix A
|
|
408
|
-
# Eigenvalues tell you how much "influence" each
|
|
409
|
-
# direction (eigenvector) has.
|
|
410
|
-
# The largest eigenvalue corresponds to the direction
|
|
411
|
-
# that has the most influence.
|
|
412
|
-
# The eigenvector corresponding to the largest
|
|
413
|
-
# eigenvalue points in the direction that has the most
|
|
414
|
-
# combined rotation influence.
|
|
415
|
-
eigvals, eigvecs = np.linalg.eig(aggregate)
|
|
416
|
-
# q0: The scalar part of the quaternion.
|
|
417
|
-
# q1, q2, q3: The vector part of the quaternion.
|
|
418
|
-
q_avg = eigvecs[:, np.argmax(eigvals)]
|
|
419
|
-
|
|
420
|
-
return q_avg
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
def _create_rotation_matrix(et_times: np.ndarray) -> NDArray:
|
|
424
|
-
"""
|
|
425
|
-
Create a rotation matrix.
|
|
426
|
-
|
|
427
|
-
Parameters
|
|
428
|
-
----------
|
|
429
|
-
et_times : numpy.ndarray
|
|
430
|
-
Array of times between et_start and et_end.
|
|
431
|
-
|
|
432
|
-
Returns
|
|
433
|
-
-------
|
|
434
|
-
rotation_matrix : np.ndarray
|
|
435
|
-
Rotation matrix.
|
|
436
|
-
"""
|
|
437
|
-
# Averaged quaternions.
|
|
438
|
-
q_avg = _average_quaternions(et_times)
|
|
439
|
-
|
|
440
|
-
# Converts the averaged quaternion (q_avg) into a rotation matrix
|
|
441
|
-
# and get inertial z axis.
|
|
442
|
-
# https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.q2m
|
|
443
|
-
z_avg = spiceypy.q2m(list(q_avg))[:, 2]
|
|
444
|
-
# y_avg is perpendicular to both z_avg and the standard Z-axis.
|
|
445
|
-
y_avg = np.cross(z_avg, [0, 0, 1])
|
|
446
|
-
# x_avg is perpendicular to y_avg and z_avg.
|
|
447
|
-
x_avg = np.cross(y_avg, z_avg)
|
|
448
|
-
|
|
449
|
-
# Construct the rotation matrix from x_avg, y_avg, z_avg
|
|
450
|
-
rotation_matrix = np.asarray([x_avg, y_avg, z_avg])
|
|
451
|
-
|
|
452
|
-
return rotation_matrix
|
|
453
|
-
|
|
454
|
-
|
|
455
179
|
def furnish_time_kernel() -> None:
|
|
456
180
|
"""Furnish the time kernels."""
|
|
457
181
|
spice_test_data_path = imap_module_directory / "tests/spice/test_data"
|