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,548 @@
|
|
|
1
|
+
"""Functions to support I-ALiRT SWE processing."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import xarray as xr
|
|
8
|
+
from numpy.typing import NDArray
|
|
9
|
+
|
|
10
|
+
from imap_processing.ialirt.utils.grouping import find_groups
|
|
11
|
+
from imap_processing.swe.l1a.swe_science import decompressed_counts
|
|
12
|
+
from imap_processing.swe.l1b.swe_l1b import (
|
|
13
|
+
deadtime_correction,
|
|
14
|
+
read_in_flight_cal_data,
|
|
15
|
+
)
|
|
16
|
+
from imap_processing.swe.utils.swe_constants import (
|
|
17
|
+
ESA_VOLTAGE_ROW_INDEX_DICT,
|
|
18
|
+
GEOMETRIC_FACTORS,
|
|
19
|
+
N_CEMS,
|
|
20
|
+
)
|
|
21
|
+
from imap_processing.swe.utils.swe_utils import combine_acquisition_time
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
# Energy bin lookup table (indexed by quarter cycle)
|
|
26
|
+
ENERGY_BINS = np.array(
|
|
27
|
+
[
|
|
28
|
+
[1, 5, 7, 3], # 0 to 14 (Q1)
|
|
29
|
+
[2, 6, 4, 0], # 15 to 29 (Q2)
|
|
30
|
+
[3, 7, 5, 1], # 30 to 44 (Q3)
|
|
31
|
+
[0, 4, 6, 2], # 45 to 59 (Q4)
|
|
32
|
+
]
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def decompress_counts(raw_counts: NDArray) -> NDArray:
|
|
37
|
+
"""
|
|
38
|
+
Perform decompression of raw counts using a predefined decompression table.
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
raw_counts : np.ndarray
|
|
43
|
+
Array of raw compressed counts with shape (n_energy, n_cem, n_phi).
|
|
44
|
+
|
|
45
|
+
Returns
|
|
46
|
+
-------
|
|
47
|
+
counts : np.ndarray
|
|
48
|
+
Array of decompressed counts with the same shape as raw_counts.
|
|
49
|
+
|
|
50
|
+
Notes
|
|
51
|
+
-----
|
|
52
|
+
CEM is channel electron multiplier.
|
|
53
|
+
"""
|
|
54
|
+
decompression_table = np.array([decompressed_counts(i) for i in range(256)])
|
|
55
|
+
|
|
56
|
+
# Decompress using the precomputed table
|
|
57
|
+
counts = decompression_table[raw_counts]
|
|
58
|
+
|
|
59
|
+
return counts
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def phi_to_bin(phi_values: NDArray) -> NDArray:
|
|
63
|
+
"""
|
|
64
|
+
Convert phi values to corresponding bin indices.
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
phi_values : NDArray
|
|
69
|
+
Array of phi values.
|
|
70
|
+
|
|
71
|
+
Returns
|
|
72
|
+
-------
|
|
73
|
+
bin_indices : NDArray
|
|
74
|
+
Array of bin indices.
|
|
75
|
+
"""
|
|
76
|
+
# Ensure it wraps correctly within 0-29 bins
|
|
77
|
+
return ((phi_values - 12) // 12) % 30
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def prepare_raw_counts(grouped: xr.Dataset, cem_number: int = N_CEMS) -> NDArray:
|
|
81
|
+
"""
|
|
82
|
+
Reformat raw counts into a 3D array binned by phi.
|
|
83
|
+
|
|
84
|
+
Parameters
|
|
85
|
+
----------
|
|
86
|
+
grouped : xr.Dataset
|
|
87
|
+
Dataset containing grouped i-ALiRT packet data for 30 seconds.
|
|
88
|
+
cem_number : int
|
|
89
|
+
Number of CEMs (default 7).
|
|
90
|
+
|
|
91
|
+
Returns
|
|
92
|
+
-------
|
|
93
|
+
raw_counts : NDArray
|
|
94
|
+
Raw counts with shape (8, 7, 30).
|
|
95
|
+
|
|
96
|
+
Notes
|
|
97
|
+
-----
|
|
98
|
+
Array of raw counts with shape (n_energy, n_cem, n_phi), where:
|
|
99
|
+
- 8 corresponds to the 8 energy steps.
|
|
100
|
+
- 7 corresponds to the 7 CEM detectors.
|
|
101
|
+
- 30 corresponds to the 30 phi bins.
|
|
102
|
+
"""
|
|
103
|
+
raw_counts = np.zeros((8, cem_number, 30), dtype=np.uint8)
|
|
104
|
+
|
|
105
|
+
# Compute phi values and their corresponding bins
|
|
106
|
+
# Example: energy steps 0-1 have the same phi;
|
|
107
|
+
# energy steps 2-3 have the same phi, etc.
|
|
108
|
+
# A depiction of this is shown in Figure 7 of the SWE Algorithm Document.
|
|
109
|
+
phi_values = np.array(
|
|
110
|
+
[
|
|
111
|
+
(12 + 24 * grouped["swe_seq"].values) % 360, # Energy steps 0 and 1
|
|
112
|
+
(24 + 24 * grouped["swe_seq"].values) % 360, # Energy steps 2 and 3
|
|
113
|
+
]
|
|
114
|
+
)
|
|
115
|
+
phi_bins = phi_to_bin(phi_values).astype(int) # Get phi bin indices
|
|
116
|
+
|
|
117
|
+
# The first 15 seconds is the first quarter cycle, etc.
|
|
118
|
+
quarter_cycles = np.floor(grouped["swe_seq"] / 15).astype(int)
|
|
119
|
+
e_bins = ENERGY_BINS[quarter_cycles]
|
|
120
|
+
|
|
121
|
+
# Populate raw_counts
|
|
122
|
+
for cem in range(1, cem_number + 1): # 7 CEMs
|
|
123
|
+
e1 = grouped[f"swe_cem{cem}_e1"].values
|
|
124
|
+
e2 = grouped[f"swe_cem{cem}_e2"].values
|
|
125
|
+
e3 = grouped[f"swe_cem{cem}_e3"].values
|
|
126
|
+
e4 = grouped[f"swe_cem{cem}_e4"].values
|
|
127
|
+
|
|
128
|
+
# Phi bins 0, 2...(12, 36, ...)
|
|
129
|
+
raw_counts[e_bins[:, 0], cem - 1, phi_bins[0]] = e1
|
|
130
|
+
raw_counts[e_bins[:, 1], cem - 1, phi_bins[0]] = e2
|
|
131
|
+
# Phi bins 1, 3...(24, 48, ...)
|
|
132
|
+
raw_counts[e_bins[:, 2], cem - 1, phi_bins[1]] = e3
|
|
133
|
+
raw_counts[e_bins[:, 3], cem - 1, phi_bins[1]] = e4
|
|
134
|
+
|
|
135
|
+
return raw_counts
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def get_ialirt_energies() -> list:
|
|
139
|
+
"""
|
|
140
|
+
Get the ESA voltages for I-ALiRT.
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
energy : list
|
|
145
|
+
List of ESA voltage for I-ALiRT.
|
|
146
|
+
|
|
147
|
+
Notes
|
|
148
|
+
-----
|
|
149
|
+
This is a subset of the ESA_VOLTAGE_ROW_INDEX_DICT.
|
|
150
|
+
"""
|
|
151
|
+
energy = [k for k, v in ESA_VOLTAGE_ROW_INDEX_DICT.items() if 11 <= v <= 18]
|
|
152
|
+
|
|
153
|
+
return energy
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def normalize_counts(counts: NDArray, latest_cal: pd.Series) -> NDArray:
|
|
157
|
+
"""
|
|
158
|
+
Normalize the counts using the latest calibration factor.
|
|
159
|
+
|
|
160
|
+
Parameters
|
|
161
|
+
----------
|
|
162
|
+
counts : np.ndarray
|
|
163
|
+
Array of counts.
|
|
164
|
+
latest_cal : pd.Series
|
|
165
|
+
Array of latest calibration factors.
|
|
166
|
+
|
|
167
|
+
Returns
|
|
168
|
+
-------
|
|
169
|
+
norm_counts : np.ndarray
|
|
170
|
+
Array of normalized counts.
|
|
171
|
+
"""
|
|
172
|
+
latest_cal = latest_cal.to_numpy()
|
|
173
|
+
|
|
174
|
+
# Norm counts where counts are non-negative
|
|
175
|
+
norm_counts = counts * (latest_cal / GEOMETRIC_FACTORS)[:, np.newaxis]
|
|
176
|
+
norm_counts[norm_counts < 0] = 0
|
|
177
|
+
|
|
178
|
+
return norm_counts
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def find_bin_offsets(
|
|
182
|
+
peak_bins: NDArray, offsets: tuple[int, int]
|
|
183
|
+
) -> tuple[NDArray, NDArray]:
|
|
184
|
+
"""
|
|
185
|
+
Find the bins with offsets from the peak bins.
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
peak_bins : np.ndarray
|
|
190
|
+
Bins that correspond to the maximum counts at each energy.
|
|
191
|
+
offsets : tuple[int, int]
|
|
192
|
+
Offset values for the bins.
|
|
193
|
+
|
|
194
|
+
Returns
|
|
195
|
+
-------
|
|
196
|
+
bin_0 : np.ndarray
|
|
197
|
+
First bin used for the average.
|
|
198
|
+
bin_1 : np.ndarray
|
|
199
|
+
Second bin used for the average.
|
|
200
|
+
"""
|
|
201
|
+
# Azimuth has 30 values.
|
|
202
|
+
# Therefore, anything greater than 30 should be wrapped around.
|
|
203
|
+
bin_0, bin_1 = (peak_bins + offsets[0]) % 30, (peak_bins + offsets[1]) % 30
|
|
204
|
+
|
|
205
|
+
return bin_0, bin_1
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def average_counts(
|
|
209
|
+
peak_bins: NDArray, summed_half_cycle: NDArray, offsets: tuple[int, int]
|
|
210
|
+
) -> NDArray:
|
|
211
|
+
"""
|
|
212
|
+
Get the counts value for the offset bins at each energy level and average them.
|
|
213
|
+
|
|
214
|
+
Parameters
|
|
215
|
+
----------
|
|
216
|
+
peak_bins : np.ndarray
|
|
217
|
+
Bins that corresponds to the maximum counts at each energy.
|
|
218
|
+
summed_half_cycle : np.ndarray
|
|
219
|
+
Counts summed over the 7 CEM detectors.
|
|
220
|
+
offsets : tuple
|
|
221
|
+
Offset values for the bins.
|
|
222
|
+
Offsets +6 and +8 correspond to +90 degrees.
|
|
223
|
+
Offsets +14 and +16 correspond to 180 degrees.
|
|
224
|
+
Offsets -6 and -8 correspond to -90 degrees.
|
|
225
|
+
|
|
226
|
+
Returns
|
|
227
|
+
-------
|
|
228
|
+
avg_counts : np.ndarray
|
|
229
|
+
Average counts of offset bin.
|
|
230
|
+
"""
|
|
231
|
+
# Find the bins with offsets from the peak bins.
|
|
232
|
+
bin_0, bin_1 = find_bin_offsets(peak_bins, offsets)
|
|
233
|
+
|
|
234
|
+
# Get the counts value for the offset bins at each energy level and average them.
|
|
235
|
+
row_idx = np.arange(len(peak_bins))
|
|
236
|
+
avg_counts = (
|
|
237
|
+
summed_half_cycle[row_idx, bin_0] + summed_half_cycle[row_idx, bin_1]
|
|
238
|
+
) / 2
|
|
239
|
+
|
|
240
|
+
return avg_counts
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def find_min_counts(
|
|
244
|
+
summed_half_cycle: NDArray,
|
|
245
|
+
) -> tuple[NDArray, NDArray, tuple[NDArray, NDArray, NDArray]]:
|
|
246
|
+
"""
|
|
247
|
+
Find min counts (cmin), defined as the minimum of counts_180 and counts_90.
|
|
248
|
+
|
|
249
|
+
Parameters
|
|
250
|
+
----------
|
|
251
|
+
summed_half_cycle : np.ndarray
|
|
252
|
+
Counts summed over the 7 CEM detectors.
|
|
253
|
+
|
|
254
|
+
Returns
|
|
255
|
+
-------
|
|
256
|
+
cpeak : np.ndarray
|
|
257
|
+
Maximum counts for each energy level.
|
|
258
|
+
cmin : np.ndarray
|
|
259
|
+
Minimum of counts_neg_90, counts_90, counts_180.
|
|
260
|
+
counts : tuple[np.ndarray, np.ndarray, np.ndarray]
|
|
261
|
+
Counts at +/- 90 and 180 degrees from peak.
|
|
262
|
+
"""
|
|
263
|
+
# Find the maximum counts for each energy level
|
|
264
|
+
cpeak = np.max(summed_half_cycle, axis=1)
|
|
265
|
+
|
|
266
|
+
# Find the bin that corresponds to the maximum counts at each energy
|
|
267
|
+
peak_bin = np.argmax(summed_half_cycle, axis=1)
|
|
268
|
+
|
|
269
|
+
# Find the counts in each offset bins.
|
|
270
|
+
# Offsets +6 and +8 correspond to +90 degrees.
|
|
271
|
+
counts_90 = average_counts(peak_bin, summed_half_cycle, (6, 8))
|
|
272
|
+
|
|
273
|
+
# Find the counts in each offset bins.
|
|
274
|
+
# Offsets +14 and +16 correspond to 180 degrees.
|
|
275
|
+
counts_180 = average_counts(peak_bin, summed_half_cycle, (14, 16))
|
|
276
|
+
|
|
277
|
+
# Find the counts in each offset bins.
|
|
278
|
+
# Offsets -6 and -8 correspond to -90 degrees.
|
|
279
|
+
counts_neg_90 = average_counts(peak_bin, summed_half_cycle, (-6, -8))
|
|
280
|
+
|
|
281
|
+
counts_stacked = np.hstack(
|
|
282
|
+
[
|
|
283
|
+
counts_90[:, np.newaxis],
|
|
284
|
+
counts_180[:, np.newaxis],
|
|
285
|
+
counts_neg_90[:, np.newaxis],
|
|
286
|
+
]
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
# Find the minimum value for each energy level
|
|
290
|
+
cmin = np.min(counts_stacked, axis=1)
|
|
291
|
+
|
|
292
|
+
return cpeak, cmin, (counts_neg_90, counts_90, counts_180)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def determine_streaming(
|
|
296
|
+
numerator_1: NDArray,
|
|
297
|
+
numerator_2: NDArray,
|
|
298
|
+
denominator: NDArray,
|
|
299
|
+
threshold: float = 1.75,
|
|
300
|
+
) -> NDArray:
|
|
301
|
+
"""
|
|
302
|
+
Determine if any energy level satisfies the bidirectional streaming condition.
|
|
303
|
+
|
|
304
|
+
Parameters
|
|
305
|
+
----------
|
|
306
|
+
numerator_1 : np.ndarray
|
|
307
|
+
For the first streaming check : cpeak.
|
|
308
|
+
For the second streaming check : ccem_1.
|
|
309
|
+
numerator_2 : np.ndarray
|
|
310
|
+
For the first streaming check : counts_180.
|
|
311
|
+
For the second streaming check : ccem_7.
|
|
312
|
+
denominator : np.ndarray
|
|
313
|
+
For both streaming checks: cmin.
|
|
314
|
+
threshold : float (optional)
|
|
315
|
+
Threshold value for the streaming condition.
|
|
316
|
+
|
|
317
|
+
Returns
|
|
318
|
+
-------
|
|
319
|
+
streaming_flag : np.ndarray
|
|
320
|
+
Array of 1s and 0s indicating if the condition is satisfied.
|
|
321
|
+
"""
|
|
322
|
+
ratio_1 = numerator_1 / denominator
|
|
323
|
+
ratio_2 = numerator_2 / denominator
|
|
324
|
+
|
|
325
|
+
return ((ratio_1 > threshold) & (ratio_2 > threshold)).astype(int)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def compute_bidirectional(
|
|
329
|
+
streaming_first_half: NDArray,
|
|
330
|
+
streaming_second_half: NDArray,
|
|
331
|
+
min_esa_steps: int = 3,
|
|
332
|
+
) -> tuple[int, int]:
|
|
333
|
+
"""
|
|
334
|
+
Compute the Bidirectional Electron parameter (BDE).
|
|
335
|
+
|
|
336
|
+
Parameters
|
|
337
|
+
----------
|
|
338
|
+
streaming_first_half : np.ndarray
|
|
339
|
+
Array of 1s and 0s indicating bidirectional streaming for first half-cycle.
|
|
340
|
+
streaming_second_half : np.ndarray
|
|
341
|
+
Array of 1s and 0s indicating bidirectional streaming for second half-cycle.
|
|
342
|
+
min_esa_steps : int (optional)
|
|
343
|
+
Minimum number of ESA steps for bidirectional streaming.
|
|
344
|
+
If either of the half cycles has bidirectional streaming for
|
|
345
|
+
3/8 energies then bde = 1.
|
|
346
|
+
|
|
347
|
+
Returns
|
|
348
|
+
-------
|
|
349
|
+
bde : tuple
|
|
350
|
+
Indicator for counter-streaming.
|
|
351
|
+
"""
|
|
352
|
+
count_first: int = int(np.sum(streaming_first_half))
|
|
353
|
+
count_second: int = int(np.sum(streaming_second_half))
|
|
354
|
+
|
|
355
|
+
return int(count_first >= min_esa_steps), int(count_second >= min_esa_steps)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def azimuthal_check_counterstreaming(
|
|
359
|
+
summed_first_half: NDArray, summed_second_half: NDArray
|
|
360
|
+
) -> tuple[int, int]:
|
|
361
|
+
"""
|
|
362
|
+
Check if counterstreaming is observed in azimuthal angle direction.
|
|
363
|
+
|
|
364
|
+
Parameters
|
|
365
|
+
----------
|
|
366
|
+
summed_first_half : np.ndarray
|
|
367
|
+
Counts summed over the 7 CEM detectors for first half-cycle.
|
|
368
|
+
summed_second_half : np.ndarray
|
|
369
|
+
Counts summed over the 7 CEM detectors for second half-cycle.
|
|
370
|
+
|
|
371
|
+
Returns
|
|
372
|
+
-------
|
|
373
|
+
bde : tuple
|
|
374
|
+
Indicator for counter-streaming.
|
|
375
|
+
"""
|
|
376
|
+
# Find peaks, cmin, counts (-90, 90, 180)
|
|
377
|
+
cpeak_first_half, cmin_first_half, counts_first_half = find_min_counts(
|
|
378
|
+
summed_first_half
|
|
379
|
+
)
|
|
380
|
+
cpeak_second_half, cmin_second_half, counts_second_half = find_min_counts(
|
|
381
|
+
summed_second_half
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
# First search for counter-streaming
|
|
385
|
+
streaming_first_half = determine_streaming(
|
|
386
|
+
cpeak_first_half, counts_first_half[2], cmin_first_half
|
|
387
|
+
)
|
|
388
|
+
streaming_second_half = determine_streaming(
|
|
389
|
+
cpeak_second_half, counts_second_half[2], cmin_second_half
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
# If either of the half cycles has bidirectional streaming
|
|
393
|
+
# for 3/8 energies then bde = 1
|
|
394
|
+
bde_first_search = compute_bidirectional(
|
|
395
|
+
streaming_first_half, streaming_second_half
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
return bde_first_search
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def polar_check_counterstreaming(
|
|
402
|
+
summed_first_half: NDArray, summed_second_half: NDArray
|
|
403
|
+
) -> tuple[int, int]:
|
|
404
|
+
"""
|
|
405
|
+
Check if counterstreaming is observed in the polar angle direction.
|
|
406
|
+
|
|
407
|
+
Parameters
|
|
408
|
+
----------
|
|
409
|
+
summed_first_half : np.ndarray
|
|
410
|
+
Counts summed over the azimuth for first half-cycle.
|
|
411
|
+
summed_second_half : np.ndarray
|
|
412
|
+
Counts summed over the azimuth for second half-cycle.
|
|
413
|
+
|
|
414
|
+
Returns
|
|
415
|
+
-------
|
|
416
|
+
bde : tuple
|
|
417
|
+
Indicator for counter-streaming.
|
|
418
|
+
"""
|
|
419
|
+
# Cmin is the average of the counts in CEMs 3, 4, and 5
|
|
420
|
+
cmin_first_half = summed_first_half[:, 2:5].mean(axis=1)
|
|
421
|
+
cmin_second_half = summed_second_half[:, 2:5].mean(axis=1)
|
|
422
|
+
|
|
423
|
+
# Determine if streaming is observed.
|
|
424
|
+
# Note: Bidirectional electron streaming at a given ESA step
|
|
425
|
+
# is identified if both c_cem1/cmin and c_cem7/cmin are > 1.75.
|
|
426
|
+
streaming_first_half = determine_streaming(
|
|
427
|
+
summed_first_half[:, 0], summed_first_half[:, 6], cmin_first_half
|
|
428
|
+
)
|
|
429
|
+
streaming_second_half = determine_streaming(
|
|
430
|
+
summed_second_half[:, 0], summed_second_half[:, 6], cmin_second_half
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
# If either of the half cycles has bidirectional streaming
|
|
434
|
+
# for 3/8 energies then bde = 1
|
|
435
|
+
bde_second_search = compute_bidirectional(
|
|
436
|
+
streaming_first_half, streaming_second_half
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
return bde_second_search
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def process_swe(accumulated_data: xr.Dataset, in_flight_cal_files: list) -> list[dict]:
|
|
443
|
+
"""
|
|
444
|
+
Create L1 data dictionary.
|
|
445
|
+
|
|
446
|
+
Parameters
|
|
447
|
+
----------
|
|
448
|
+
accumulated_data : xr.Dataset
|
|
449
|
+
Packets dataset accumulated over 1 min.
|
|
450
|
+
in_flight_cal_files : list
|
|
451
|
+
List of path to the in-flight calibration files.
|
|
452
|
+
|
|
453
|
+
Returns
|
|
454
|
+
-------
|
|
455
|
+
swe_data : list[dict]
|
|
456
|
+
Dictionaries of the parsed data product.
|
|
457
|
+
"""
|
|
458
|
+
logger.info("Processing SWE.")
|
|
459
|
+
|
|
460
|
+
# Calculate time in seconds
|
|
461
|
+
time_seconds = combine_acquisition_time(
|
|
462
|
+
accumulated_data["swe_acq_sec"], accumulated_data["swe_acq_sub"]
|
|
463
|
+
)
|
|
464
|
+
accumulated_data["time_seconds"] = time_seconds
|
|
465
|
+
|
|
466
|
+
# Get total full cycle data available for processing.
|
|
467
|
+
# There are 60 packets in a set so (0, 59) is the range.
|
|
468
|
+
grouped_data = find_groups(accumulated_data, (0, 59), "swe_seq", "time_seconds")
|
|
469
|
+
unique_groups = np.unique(grouped_data["group"])
|
|
470
|
+
swe_data: list[dict] = []
|
|
471
|
+
|
|
472
|
+
for group in unique_groups:
|
|
473
|
+
# Sequence values for the group should be 0-59 with no duplicates.
|
|
474
|
+
seq_values = grouped_data["swe_seq"][(grouped_data["group"] == group).values]
|
|
475
|
+
|
|
476
|
+
# Ensure no duplicates and all values from 0 to 59 are present
|
|
477
|
+
if not np.array_equal(seq_values, np.arange(60)):
|
|
478
|
+
logger.info(
|
|
479
|
+
f"Group {group} does not contain all values from 0 to "
|
|
480
|
+
f"59 without duplicates."
|
|
481
|
+
)
|
|
482
|
+
continue
|
|
483
|
+
# Prepare raw counts array just for this group
|
|
484
|
+
# (8 energy steps, 7 CEMs, 30 phi bins)
|
|
485
|
+
group_mask = grouped_data["group"] == group
|
|
486
|
+
grouped = grouped_data.sel(epoch=group_mask)
|
|
487
|
+
|
|
488
|
+
# Split into Q1 & Q2 (swe_seq 0-29) and Q3 & Q4 (swe_seq 30-59)
|
|
489
|
+
first_half = grouped.where(grouped["swe_seq"] < 30, drop=True)
|
|
490
|
+
second_half = grouped.where(grouped["swe_seq"] >= 30, drop=True)
|
|
491
|
+
|
|
492
|
+
# Prepare raw counts separately for both halves
|
|
493
|
+
raw_counts_first_half = prepare_raw_counts(first_half)
|
|
494
|
+
raw_counts_second_half = prepare_raw_counts(second_half)
|
|
495
|
+
|
|
496
|
+
# Decompress the raw counts
|
|
497
|
+
counts_first_half = decompress_counts(raw_counts_first_half)
|
|
498
|
+
counts_second_half = decompress_counts(raw_counts_second_half)
|
|
499
|
+
|
|
500
|
+
# Apply the deadtime correction
|
|
501
|
+
# acq_duration = 80 milliseconds
|
|
502
|
+
corrected_first_half = deadtime_correction(counts_first_half, 80 * 10**3)
|
|
503
|
+
corrected_second_half = deadtime_correction(counts_second_half, 80 * 10**3)
|
|
504
|
+
|
|
505
|
+
# Grab the latest calibration factor
|
|
506
|
+
in_flight_cal_df = read_in_flight_cal_data(in_flight_cal_files)
|
|
507
|
+
latest_cal = in_flight_cal_df.sort_values("met_time").iloc[-1][1::]
|
|
508
|
+
|
|
509
|
+
normalized_first_half = normalize_counts(corrected_first_half, latest_cal)
|
|
510
|
+
normalized_second_half = normalize_counts(corrected_second_half, latest_cal)
|
|
511
|
+
|
|
512
|
+
# Sum over the 7 detectors
|
|
513
|
+
summed_first_half_cem = np.sum(normalized_first_half, axis=1)
|
|
514
|
+
summed_second_half_cem = np.sum(normalized_second_half, axis=1)
|
|
515
|
+
bde_first_search = azimuthal_check_counterstreaming(
|
|
516
|
+
summed_first_half_cem, summed_second_half_cem
|
|
517
|
+
)
|
|
518
|
+
# Sum over azimuth.
|
|
519
|
+
summed_first_half_az = np.sum(normalized_first_half, axis=2)
|
|
520
|
+
summed_second_half_az = np.sum(normalized_second_half, axis=2)
|
|
521
|
+
bde_second_search = polar_check_counterstreaming(
|
|
522
|
+
summed_first_half_az, summed_second_half_az
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
# BDE value
|
|
526
|
+
bde_first_half = max(bde_first_search[0], bde_second_search[0])
|
|
527
|
+
bde_second_half = max(bde_first_search[1], bde_second_search[1])
|
|
528
|
+
|
|
529
|
+
# For normalized counts each ESA step is summed
|
|
530
|
+
# over both azimuthal and polar angles
|
|
531
|
+
# Sum over CEMs (axis=1) and azimuths (axis=2)
|
|
532
|
+
summed_first = normalized_first_half.sum(axis=(1, 2))
|
|
533
|
+
summed_second = normalized_second_half.sum(axis=(1, 2))
|
|
534
|
+
times = np.unique(grouped["time_seconds"].values)
|
|
535
|
+
|
|
536
|
+
swe_data.append(
|
|
537
|
+
{
|
|
538
|
+
# Select times corresponding to energy level.
|
|
539
|
+
"met_first_half_cycle": times[[1, 0] * 4],
|
|
540
|
+
"met_second_half_cycle": times[[3, 2] * 4],
|
|
541
|
+
"normalized_counts_first_half_cycle": summed_first,
|
|
542
|
+
"normalized_counts_second_half_cycle": summed_second,
|
|
543
|
+
"bde_first_half_cycle": np.full(summed_first.shape, bde_first_half),
|
|
544
|
+
"bde_second_half_cycle": np.full(summed_second.shape, bde_second_half),
|
|
545
|
+
}
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
return swe_data
|