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
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
"Tests pointing sets"
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import astropy_healpix.healpy as hp
|
|
4
4
|
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
5
6
|
import pytest
|
|
6
|
-
from cdflib import CDF
|
|
7
7
|
|
|
8
8
|
from imap_processing import imap_module_directory
|
|
9
|
-
from imap_processing.ena_maps.utils.spatial_utils import build_spatial_bins
|
|
10
9
|
from imap_processing.ultra.l1c.ultra_l1c_pset_bins import (
|
|
11
10
|
build_energy_bins,
|
|
11
|
+
get_background_rates,
|
|
12
12
|
get_helio_exposure_times,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
get_spacecraft_exposure_times,
|
|
14
|
+
get_spacecraft_histogram,
|
|
15
|
+
get_spacecraft_sensitivity,
|
|
16
|
+
grid_sensitivity,
|
|
16
17
|
)
|
|
17
18
|
|
|
18
19
|
BASE_PATH = imap_module_directory / "ultra" / "lookup_tables"
|
|
20
|
+
TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1"
|
|
19
21
|
|
|
20
22
|
|
|
21
|
-
@pytest.fixture
|
|
23
|
+
@pytest.fixture
|
|
22
24
|
def test_data():
|
|
23
25
|
"""Test data fixture."""
|
|
24
26
|
vx_sc = np.array([-186.5575, 508.5697, 508.5697, 508.5697])
|
|
25
27
|
vy_sc = np.array([-707.5707, -516.0282, -516.0282, -516.0282])
|
|
26
28
|
vz_sc = np.array([618.0569, 892.6931, 892.6931, 892.6931])
|
|
27
|
-
energy = np.array([3.384, 3.385,
|
|
29
|
+
energy = np.array([3.384, 3.385, 4.138, 4.138])
|
|
28
30
|
v = np.column_stack((vx_sc, vy_sc, vz_sc))
|
|
29
31
|
|
|
30
32
|
return v, energy
|
|
@@ -32,13 +34,13 @@ def test_data():
|
|
|
32
34
|
|
|
33
35
|
def test_build_energy_bins():
|
|
34
36
|
"""Tests build_energy_bins function."""
|
|
35
|
-
|
|
36
|
-
energy_bin_start = [interval[0] for interval in
|
|
37
|
-
energy_bin_end = [interval[1] for interval in
|
|
37
|
+
intervals, energy_midpoints, energy_bin_geometric_means = build_energy_bins()
|
|
38
|
+
energy_bin_start = [interval[0] for interval in intervals]
|
|
39
|
+
energy_bin_end = [interval[1] for interval in intervals]
|
|
38
40
|
|
|
39
41
|
assert energy_bin_start[0] == 0
|
|
40
42
|
assert energy_bin_start[1] == 3.385
|
|
41
|
-
assert len(
|
|
43
|
+
assert len(intervals) == 24
|
|
42
44
|
assert energy_midpoints[0] == (energy_bin_start[0] + energy_bin_end[0]) / 2
|
|
43
45
|
|
|
44
46
|
# Comparison to expected values.
|
|
@@ -46,107 +48,136 @@ def test_build_energy_bins():
|
|
|
46
48
|
np.testing.assert_allclose(energy_bin_start[-1], 279.810, atol=1e-4)
|
|
47
49
|
np.testing.assert_allclose(energy_bin_end[-1], 341.989, atol=1e-4)
|
|
48
50
|
|
|
51
|
+
expected_geometric_means = np.sqrt(
|
|
52
|
+
np.array(energy_bin_start) * np.array(energy_bin_end)
|
|
53
|
+
)
|
|
54
|
+
np.testing.assert_allclose(
|
|
55
|
+
energy_bin_geometric_means, expected_geometric_means, atol=1e-4
|
|
56
|
+
)
|
|
57
|
+
|
|
49
58
|
|
|
50
|
-
def
|
|
59
|
+
def test_get_spacecraft_histogram(test_data):
|
|
51
60
|
"""Tests get_histogram function."""
|
|
52
61
|
v, energy = test_data
|
|
53
62
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
)
|
|
57
|
-
energy_bin_edges, _ = build_energy_bins()
|
|
58
|
-
|
|
59
|
-
hist = get_histogram(v, energy, az_bin_edges, el_bin_edges, energy_bin_edges)
|
|
63
|
+
energy_bin_edges, _, _ = build_energy_bins()
|
|
64
|
+
subset_energy_bin_edges = energy_bin_edges[:3]
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
len(el_bin_edges) - 1,
|
|
64
|
-
len(energy_bin_edges),
|
|
66
|
+
hist, latitude, longitude, n_pix = get_spacecraft_histogram(
|
|
67
|
+
v, energy, subset_energy_bin_edges, nside=1
|
|
65
68
|
)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
assert hist.shape == (len(subset_energy_bin_edges), hp.nside2npix(1))
|
|
70
|
+
assert n_pix == hp.nside2npix(1)
|
|
71
|
+
assert latitude.shape == (n_pix,)
|
|
72
|
+
assert longitude.shape == (n_pix,)
|
|
73
|
+
|
|
74
|
+
# Spot check that 2 counts are in the third energy bin
|
|
75
|
+
assert np.sum(hist[2, :]) == 2
|
|
76
|
+
|
|
77
|
+
# Test overlapping energy bins
|
|
78
|
+
overlapping_bins = [
|
|
79
|
+
(0.0, 3.385),
|
|
80
|
+
(2.5, 4.137),
|
|
81
|
+
(3.385, 5.057),
|
|
82
|
+
]
|
|
83
|
+
hist, latitude, longitude, n_pix = get_spacecraft_histogram(
|
|
84
|
+
v, energy, overlapping_bins, nside=1
|
|
75
85
|
)
|
|
76
|
-
|
|
77
|
-
assert
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
assert
|
|
81
|
-
|
|
86
|
+
# Spot check that 3 counts are in the third energy bin
|
|
87
|
+
assert np.sum(hist[2, :]) == 3
|
|
88
|
+
assert n_pix == hp.nside2npix(1)
|
|
89
|
+
assert latitude.shape == (n_pix,)
|
|
90
|
+
assert longitude.shape == (n_pix,)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_get_background_rates():
|
|
94
|
+
"""Tests get_background_rates function."""
|
|
95
|
+
background_rates = get_background_rates(nside=128)
|
|
96
|
+
assert background_rates.shape == hp.nside2npix(128)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@pytest.mark.external_test_data
|
|
100
|
+
def test_get_spacecraft_exposure_times():
|
|
101
|
+
"""Test get_spacecraft_exposure_times function."""
|
|
102
|
+
constant_exposure = TEST_PATH / "ultra_90_dps_exposure.csv"
|
|
103
|
+
df_exposure = pd.read_csv(constant_exposure)
|
|
104
|
+
exposure_pointing = get_spacecraft_exposure_times(df_exposure)
|
|
105
|
+
assert exposure_pointing.shape == (196608,)
|
|
106
|
+
|
|
107
|
+
np.testing.assert_allclose(
|
|
108
|
+
exposure_pointing.values[22684:22686],
|
|
109
|
+
np.array([1.035, 1.035]) * 5760,
|
|
110
|
+
atol=1e-6,
|
|
82
111
|
)
|
|
83
|
-
# Assert that the exposure time at the lowest azimuth is 0 (no exposure).
|
|
84
|
-
assert np.array_equal(exposure[:, 0], np.full_like(exposure[:, 359], 0.0))
|
|
85
112
|
|
|
86
113
|
|
|
87
|
-
@pytest.mark.external_kernel
|
|
114
|
+
@pytest.mark.external_kernel
|
|
88
115
|
@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
|
|
89
116
|
def test_get_helio_exposure_times():
|
|
90
117
|
"""Tests get_helio_exposure_times function."""
|
|
91
118
|
|
|
92
|
-
constant_exposure = BASE_PATH / "dps_grid45_compressed.cdf"
|
|
93
119
|
start_time = 829485054.185627
|
|
94
120
|
end_time = 829567884.185627
|
|
121
|
+
|
|
95
122
|
mid_time = np.average([start_time, end_time])
|
|
96
123
|
|
|
97
|
-
|
|
98
|
-
|
|
124
|
+
constant_exposure = TEST_PATH / "ultra_90_dps_exposure.csv"
|
|
125
|
+
df_exposure = pd.read_csv(constant_exposure)
|
|
99
126
|
|
|
100
|
-
|
|
127
|
+
helio_exposure = get_helio_exposure_times(mid_time, df_exposure)
|
|
101
128
|
|
|
102
|
-
|
|
103
|
-
az_bin_edges, el_bin_edges, az_bin_midpoints, el_bin_midpoints = (
|
|
104
|
-
np.rad2deg(angle_radians) for angle_radians in (build_spatial_bins())
|
|
105
|
-
)
|
|
129
|
+
_, energy_midpoints, _ = build_energy_bins()
|
|
106
130
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
len(energy_midpoints),
|
|
111
|
-
)
|
|
131
|
+
nside = 128
|
|
132
|
+
npix = hp.nside2npix(nside)
|
|
133
|
+
assert helio_exposure.shape == (npix, len(energy_midpoints))
|
|
112
134
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
("dps_exposure_helio_45_E12.cdf", "dps_exposure_helio_45_E12"),
|
|
116
|
-
("dps_exposure_helio_45_E24.cdf", "dps_exposure_helio_45_E24"),
|
|
117
|
-
]
|
|
135
|
+
total_input = np.sum(df_exposure["Exposure Time"].values)
|
|
136
|
+
total_output = np.sum(helio_exposure[:, 23])
|
|
118
137
|
|
|
119
|
-
|
|
138
|
+
assert np.allclose(total_input, total_output, atol=1e-6)
|
|
120
139
|
|
|
121
|
-
exposures = []
|
|
122
140
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
141
|
+
@pytest.mark.external_test_data
|
|
142
|
+
def test_get_spacecraft_sensitivity():
|
|
143
|
+
"""Tests get_spacecraft_sensitivity function."""
|
|
144
|
+
# TODO: remove below here with lookup table aux api
|
|
145
|
+
efficiencies = TEST_PATH / "Ultra_90_DPS_efficiencies_all.csv"
|
|
146
|
+
geometric_function = TEST_PATH / "ultra_90_dps_gf.csv"
|
|
129
147
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
assert np.array_equal(np.squeeze(exposures[2]), exposure_3d[:, :, 23])
|
|
148
|
+
df_efficiencies = pd.read_csv(efficiencies)
|
|
149
|
+
df_geometric_function = pd.read_csv(geometric_function)
|
|
133
150
|
|
|
151
|
+
sensitivity, energy_vals, right_ascension, declination = get_spacecraft_sensitivity(
|
|
152
|
+
df_efficiencies, df_geometric_function
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
assert sensitivity.shape == (df_efficiencies.shape[0], df_efficiencies.shape[1] - 2)
|
|
156
|
+
assert np.array_equal(energy_vals, np.arange(3.0, 80.5, 0.5))
|
|
134
157
|
|
|
135
|
-
|
|
136
|
-
|
|
158
|
+
df_efficiencies_test = pd.DataFrame(
|
|
159
|
+
{"3.0keV": [1.0, 2.0], "3.5keV": [3.0, 4.0], "4.0keV": [5.0, 6.0]}
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
df_geometric_function_test = pd.DataFrame({"Response": [0.1, 0.2]})
|
|
163
|
+
|
|
164
|
+
df_sensitivity_test = df_efficiencies_test.mul(
|
|
165
|
+
df_geometric_function_test["Response"], axis=0
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
expected_sensitivity = pd.DataFrame(
|
|
169
|
+
{"3.0keV": [0.1, 0.4], "3.5keV": [0.3, 0.8], "4.0keV": [0.5, 1.2]}
|
|
170
|
+
)
|
|
137
171
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
spins_per_pointing = 5760
|
|
141
|
-
sensitivity = get_pointing_frame_sensitivity(
|
|
142
|
-
constant_sensitivity,
|
|
143
|
-
spins_per_pointing,
|
|
144
|
-
"45",
|
|
172
|
+
assert np.allclose(
|
|
173
|
+
df_sensitivity_test.to_numpy(), expected_sensitivity.to_numpy(), atol=1e-6
|
|
145
174
|
)
|
|
146
175
|
|
|
147
|
-
|
|
176
|
+
expected_result = sensitivity["3.0keV"].values
|
|
177
|
+
result = grid_sensitivity(df_efficiencies, df_geometric_function, 3.0)
|
|
148
178
|
|
|
149
|
-
|
|
150
|
-
expected_sensitivity = cdf_file.varget("dps_sensitivity45") * spins_per_pointing
|
|
179
|
+
assert np.allclose(result, expected_result, atol=1e-5)
|
|
151
180
|
|
|
152
|
-
|
|
181
|
+
# Check that out-of-bounds energy returns all NaNs
|
|
182
|
+
result = grid_sensitivity(df_efficiencies, df_geometric_function, 2.5)
|
|
183
|
+
assert np.isnan(result).all()
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
from unittest.mock import patch
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from imap_processing.ena_maps import ena_maps
|
|
7
|
+
from imap_processing.ena_maps.utils.coordinates import CoordNames
|
|
8
|
+
from imap_processing.tests.ultra.data.mock_data import mock_l1c_pset_product_healpix
|
|
9
|
+
from imap_processing.ultra.l2 import ultra_l2
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestUltraL2:
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def _setup_spice_kernels_list(self, spice_test_data_path, furnish_kernels):
|
|
15
|
+
self.required_kernel_names = [
|
|
16
|
+
"imap_science_0001.tf",
|
|
17
|
+
"imap_sclk_0000.tsc",
|
|
18
|
+
"sim_1yr_imap_attitude.bc",
|
|
19
|
+
"sim_1yr_imap_pointing_frame.bc",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
@pytest.fixture
|
|
23
|
+
def _mock_single_pset(self, _setup_spice_kernels_list, furnish_kernels):
|
|
24
|
+
with furnish_kernels(self.required_kernel_names):
|
|
25
|
+
self.ultra_pset = mock_l1c_pset_product_healpix(
|
|
26
|
+
nside=128, stripe_center_lat=0, timestr="2025-05-15T12:00:00"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
@pytest.fixture
|
|
30
|
+
def _mock_multiple_psets(self, _setup_spice_kernels_list, furnish_kernels):
|
|
31
|
+
with furnish_kernels(self.required_kernel_names):
|
|
32
|
+
self.ultra_psets = [
|
|
33
|
+
mock_l1c_pset_product_healpix(
|
|
34
|
+
nside=128,
|
|
35
|
+
stripe_center_lat=mid_latitude,
|
|
36
|
+
width_scale=5,
|
|
37
|
+
counts_scaling_params=(50, 0.5),
|
|
38
|
+
peak_exposure=1000,
|
|
39
|
+
timestr=f"2025-05-{4 * i + 1:02d}T12:00:00",
|
|
40
|
+
head=("90"),
|
|
41
|
+
)
|
|
42
|
+
for i, mid_latitude in enumerate(
|
|
43
|
+
np.arange(
|
|
44
|
+
22.5,
|
|
45
|
+
180,
|
|
46
|
+
45,
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
self.psets_total_counts = np.sum(
|
|
52
|
+
[pset["counts"].values.sum() for pset in self.ultra_psets]
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
@pytest.fixture
|
|
56
|
+
def mock_data_dict(self, _mock_multiple_psets):
|
|
57
|
+
return {pset.attrs["Logical_file_id"]: pset for pset in self.ultra_psets}
|
|
58
|
+
|
|
59
|
+
@pytest.mark.parametrize(
|
|
60
|
+
["map_frame", "rtol"],
|
|
61
|
+
[
|
|
62
|
+
# Tight tolerance when 'projecting' to the same frame
|
|
63
|
+
("IMAP_DPS", 1e-8),
|
|
64
|
+
# Loose tolerance of 30% error vs naive flux estimate with real projection.
|
|
65
|
+
# TODO: Ideally this tolerance will tighten if we can fix the issue with
|
|
66
|
+
# the exposure time for uneven numbers of pixels from each PointingSet.
|
|
67
|
+
("ECLIPJ2000", 3e-1),
|
|
68
|
+
],
|
|
69
|
+
)
|
|
70
|
+
@pytest.mark.usefixtures("_mock_single_pset", "_setup_spice_kernels_list")
|
|
71
|
+
def test_generate_ultra_healpix_skymap_single_pset(
|
|
72
|
+
self, map_frame, rtol, furnish_kernels
|
|
73
|
+
):
|
|
74
|
+
# Avoid modifying the original pset
|
|
75
|
+
pset = self.ultra_pset.copy(deep=True)
|
|
76
|
+
|
|
77
|
+
# Set the values in the single input PSET for easy calculation
|
|
78
|
+
# of the expected flux and flux uncertainty
|
|
79
|
+
pset["counts"].values = np.full_like(pset["counts"].values, 10)
|
|
80
|
+
pset["exposure_factor"].values = np.ones_like(pset["exposure_factor"].values)
|
|
81
|
+
pset["background_rates"].values = np.ones_like(pset["background_rates"].values)
|
|
82
|
+
pset["sensitivity"].values = np.ones_like(pset["sensitivity"].values)
|
|
83
|
+
pset["energy_bin_delta"].values = np.ones_like(pset["energy_bin_delta"].values)
|
|
84
|
+
|
|
85
|
+
# Create the Healpix skymap in the desired frame.
|
|
86
|
+
with furnish_kernels(self.required_kernel_names):
|
|
87
|
+
hp_skymap = ultra_l2.generate_ultra_healpix_skymap(
|
|
88
|
+
ultra_l1c_psets=[
|
|
89
|
+
pset,
|
|
90
|
+
],
|
|
91
|
+
output_map_structure=ena_maps.AbstractSkyMap.from_dict(
|
|
92
|
+
{
|
|
93
|
+
"sky_tiling_type": "HEALPIX",
|
|
94
|
+
"spice_reference_frame": map_frame,
|
|
95
|
+
"projection_method_and_values": {
|
|
96
|
+
"PUSH": [
|
|
97
|
+
"counts",
|
|
98
|
+
"exposure_factor",
|
|
99
|
+
"sensitivity",
|
|
100
|
+
"background_rates",
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
"nside": 32,
|
|
104
|
+
"nested": False,
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
assert hp_skymap.nside == 32
|
|
110
|
+
assert hp_skymap.nested is False
|
|
111
|
+
|
|
112
|
+
# Check that required variables are present, and dropped variables are not
|
|
113
|
+
expected_vars = [
|
|
114
|
+
"flux",
|
|
115
|
+
"flux_uncertainty",
|
|
116
|
+
"exposure_factor",
|
|
117
|
+
"observation_time",
|
|
118
|
+
]
|
|
119
|
+
for var in expected_vars:
|
|
120
|
+
assert var in hp_skymap.data_1d.data_vars
|
|
121
|
+
unexpected_vars = ultra_l2.VARIABLES_TO_DROP_AFTER_FLUX_CALCULATION
|
|
122
|
+
for var in unexpected_vars:
|
|
123
|
+
assert var not in hp_skymap.data_1d.data_vars
|
|
124
|
+
|
|
125
|
+
# The ratio of the solid angle of a map's pixel to the solid angle of a
|
|
126
|
+
# pointing set's pixel. Counts will scale up by this ratio.
|
|
127
|
+
solid_angle_ratio_map_to_pset = (
|
|
128
|
+
hp_skymap.solid_angle / ena_maps.UltraPointingSet(pset).solid_angle
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Estimate the expected flux and flux uncertainty
|
|
132
|
+
expected_flux = (
|
|
133
|
+
(10 * solid_angle_ratio_map_to_pset / 1) - 1 * solid_angle_ratio_map_to_pset
|
|
134
|
+
) / (1 * hp_skymap.solid_angle * 1)
|
|
135
|
+
expected_flux_unc = ((10 * solid_angle_ratio_map_to_pset) ** 0.5 / 1) / (
|
|
136
|
+
1 * hp_skymap.solid_angle * 1
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
np.testing.assert_allclose(
|
|
140
|
+
hp_skymap.data_1d["flux"].values,
|
|
141
|
+
expected_flux,
|
|
142
|
+
rtol=rtol,
|
|
143
|
+
)
|
|
144
|
+
np.testing.assert_allclose(
|
|
145
|
+
hp_skymap.data_1d["flux_uncertainty"].values,
|
|
146
|
+
expected_flux_unc,
|
|
147
|
+
rtol=rtol,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
@pytest.mark.usefixtures("_mock_multiple_psets", "_setup_spice_kernels_list")
|
|
151
|
+
def test_generate_ultra_healpix_skymap_multiple_psets(self, furnish_kernels):
|
|
152
|
+
with patch(
|
|
153
|
+
"imap_processing.ultra.l2.ultra_l2.VARIABLES_TO_DROP_AFTER_FLUX_CALCULATION",
|
|
154
|
+
[],
|
|
155
|
+
):
|
|
156
|
+
with furnish_kernels(self.required_kernel_names):
|
|
157
|
+
hp_skymap = ultra_l2.generate_ultra_healpix_skymap(
|
|
158
|
+
ultra_l1c_psets=self.ultra_psets,
|
|
159
|
+
output_map_structure=ena_maps.AbstractSkyMap.from_dict(
|
|
160
|
+
{
|
|
161
|
+
"sky_tiling_type": "RECTANGULAR",
|
|
162
|
+
"spice_reference_frame": "ECLIPJ2000",
|
|
163
|
+
"projection_method_and_values": {
|
|
164
|
+
"PUSH": [
|
|
165
|
+
"counts",
|
|
166
|
+
"exposure_factor",
|
|
167
|
+
"sensitivity",
|
|
168
|
+
"background_rates",
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
"spacing_deg": 2.0,
|
|
172
|
+
}
|
|
173
|
+
),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
assert hp_skymap.nside == ultra_l2.DEFAULT_L2_HEALPIX_NSIDE
|
|
177
|
+
assert hp_skymap.nested == ultra_l2.DEFAULT_L2_HEALPIX_NESTED
|
|
178
|
+
|
|
179
|
+
# The total counts in the skymap should be equal to the sum of the counts
|
|
180
|
+
# in the individual psets
|
|
181
|
+
np.testing.assert_allclose(
|
|
182
|
+
hp_skymap.data_1d["counts"].sum(),
|
|
183
|
+
self.psets_total_counts,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# The map should contain the following variables,
|
|
187
|
+
# because we did not drop any variables
|
|
188
|
+
expected_vars = (
|
|
189
|
+
ultra_l2.REQUIRED_L1C_VARIABLES
|
|
190
|
+
+ ultra_l2.VARIABLES_TO_DROP_AFTER_FLUX_CALCULATION
|
|
191
|
+
+ ["flux", "flux_uncertainty"]
|
|
192
|
+
)
|
|
193
|
+
for var in expected_vars:
|
|
194
|
+
assert var in hp_skymap.data_1d.data_vars
|
|
195
|
+
|
|
196
|
+
# Check the dims of the key variables
|
|
197
|
+
counts_dims = (
|
|
198
|
+
CoordNames.TIME.value,
|
|
199
|
+
CoordNames.ENERGY_ULTRA.value,
|
|
200
|
+
CoordNames.GENERIC_PIXEL.value,
|
|
201
|
+
)
|
|
202
|
+
assert hp_skymap.data_1d["counts"].dims == counts_dims
|
|
203
|
+
assert hp_skymap.data_1d["flux"].dims == counts_dims
|
|
204
|
+
assert hp_skymap.data_1d["flux_uncertainty"].dims == counts_dims
|
|
205
|
+
assert hp_skymap.data_1d["exposure_factor"].dims == counts_dims[-1:]
|
|
206
|
+
|
|
207
|
+
@pytest.mark.usefixtures("_setup_spice_kernels_list")
|
|
208
|
+
def test_ultra_l2_output_unbinned_healpix(self, mock_data_dict, furnish_kernels):
|
|
209
|
+
map_structure = ena_maps.AbstractSkyMap.from_dict(
|
|
210
|
+
{
|
|
211
|
+
"sky_tiling_type": "HEALPIX",
|
|
212
|
+
"spice_reference_frame": "ECLIPJ2000",
|
|
213
|
+
"projection_method_and_values": {
|
|
214
|
+
"PUSH": ["counts", "exposure_factor", "sensitivity"],
|
|
215
|
+
},
|
|
216
|
+
"nside": 16,
|
|
217
|
+
"nested": True,
|
|
218
|
+
}
|
|
219
|
+
)
|
|
220
|
+
with furnish_kernels(self.required_kernel_names):
|
|
221
|
+
[
|
|
222
|
+
map_dataset,
|
|
223
|
+
] = ultra_l2.ultra_l2(
|
|
224
|
+
data_dict=mock_data_dict,
|
|
225
|
+
data_version="001",
|
|
226
|
+
output_map_structure=map_structure,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
assert map_dataset.attrs["HEALPix_nside"] == map_structure.nside
|
|
230
|
+
assert map_dataset.attrs["HEALPix_nest"] == map_structure.nested
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
"""Ultra Decompression Tools."""
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
|
-
|
|
5
|
-
import space_packet_parser
|
|
4
|
+
from numpy.typing import NDArray
|
|
6
5
|
|
|
7
6
|
from imap_processing.ultra.l0.ultra_utils import (
|
|
8
|
-
EVENT_FIELD_RANGES,
|
|
9
|
-
append_fillval,
|
|
10
7
|
parse_event,
|
|
11
8
|
)
|
|
12
9
|
from imap_processing.utils import convert_to_binary_string
|
|
@@ -130,14 +127,15 @@ def decompress_binary(
|
|
|
130
127
|
current_position = 0
|
|
131
128
|
decompressed_values: list = []
|
|
132
129
|
|
|
133
|
-
while current_position < len(binary):
|
|
130
|
+
while current_position < len(binary) and len(decompressed_values) < array_length:
|
|
134
131
|
# Read the width of the block
|
|
135
132
|
width, current_position = read_and_advance(binary, width_bit, current_position)
|
|
136
|
-
# If width is 0
|
|
137
|
-
if width
|
|
138
|
-
|
|
133
|
+
# If width is 0, add 'block' number of zeroes and continue
|
|
134
|
+
if width == 0:
|
|
135
|
+
decompressed_values.extend([0] * block)
|
|
136
|
+
continue
|
|
139
137
|
|
|
140
|
-
# For each block, read
|
|
138
|
+
# For each block, read 'block' values of the given width
|
|
141
139
|
for _ in range(block):
|
|
142
140
|
# Ensure there are enough bits left to read the width
|
|
143
141
|
if len(binary) - current_position < width:
|
|
@@ -156,7 +154,7 @@ def decompress_image(
|
|
|
156
154
|
binary_data: str,
|
|
157
155
|
width_bit: int,
|
|
158
156
|
mantissa_bit_length: int,
|
|
159
|
-
) ->
|
|
157
|
+
) -> NDArray:
|
|
160
158
|
"""
|
|
161
159
|
Will decompress a binary string representing an image into a matrix of pixel values.
|
|
162
160
|
|
|
@@ -177,14 +175,14 @@ def decompress_image(
|
|
|
177
175
|
|
|
178
176
|
Returns
|
|
179
177
|
-------
|
|
180
|
-
p_decom :
|
|
178
|
+
p_decom : NDArray
|
|
181
179
|
A 2D numpy array representing pixel values.
|
|
182
180
|
Each pixel is stored as an unsigned 16-bit integer (uint16).
|
|
183
181
|
|
|
184
182
|
Notes
|
|
185
183
|
-----
|
|
186
184
|
This process is described starting on page 168 in IMAP-Ultra Flight
|
|
187
|
-
Software Specification document
|
|
185
|
+
Software Specification document.
|
|
188
186
|
"""
|
|
189
187
|
rows = 54
|
|
190
188
|
cols = 180
|
|
@@ -239,44 +237,34 @@ def decompress_image(
|
|
|
239
237
|
|
|
240
238
|
|
|
241
239
|
def read_image_raw_events_binary(
|
|
242
|
-
|
|
243
|
-
|
|
240
|
+
event_data: bytes,
|
|
241
|
+
count: int,
|
|
242
|
+
) -> NDArray:
|
|
244
243
|
"""
|
|
245
244
|
Convert contents of binary string 'EVENTDATA' into values.
|
|
246
245
|
|
|
247
246
|
Parameters
|
|
248
247
|
----------
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
248
|
+
event_data : bytes
|
|
249
|
+
Event data.
|
|
250
|
+
count : int
|
|
251
|
+
Number of events.
|
|
253
252
|
|
|
254
253
|
Returns
|
|
255
254
|
-------
|
|
256
|
-
|
|
257
|
-
|
|
255
|
+
event_data : NDArray
|
|
256
|
+
Event data.
|
|
258
257
|
"""
|
|
259
|
-
binary = convert_to_binary_string(
|
|
260
|
-
count = packet["COUNT"]
|
|
258
|
+
binary = convert_to_binary_string(event_data)
|
|
261
259
|
# 166 bits per event
|
|
262
260
|
event_length = 166 if count else 0
|
|
263
|
-
|
|
264
|
-
# Uses fill value for all packets that do not contain event data.
|
|
265
|
-
if count == 0:
|
|
266
|
-
# if decom_data is empty, append fill values to all fields
|
|
267
|
-
if not decom_data:
|
|
268
|
-
for field in EVENT_FIELD_RANGES.keys():
|
|
269
|
-
decom_data[field] = []
|
|
270
|
-
append_fillval(decom_data, packet)
|
|
261
|
+
event_data_list = []
|
|
271
262
|
|
|
272
263
|
# For all packets with event data, parses the binary string
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
for key, value in event_data.items():
|
|
280
|
-
decom_data[key].append(value)
|
|
264
|
+
for i in range(count):
|
|
265
|
+
start_index = i * event_length
|
|
266
|
+
event_binary = binary[start_index : start_index + event_length]
|
|
267
|
+
parsed_event = parse_event(event_binary)
|
|
268
|
+
event_data_list.append(parsed_event)
|
|
281
269
|
|
|
282
|
-
return
|
|
270
|
+
return np.array(event_data_list)
|