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,723 @@
|
|
|
1
|
+
"""IMAP-HIT L2 data processing."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
import pandas as pd
|
|
8
|
+
import xarray as xr
|
|
9
|
+
|
|
10
|
+
from imap_processing.hit.hit_utils import (
|
|
11
|
+
add_summed_particle_data_to_dataset,
|
|
12
|
+
get_attribute_manager,
|
|
13
|
+
)
|
|
14
|
+
from imap_processing.hit.l2.constants import (
|
|
15
|
+
FILLVAL_FLOAT32,
|
|
16
|
+
L2_SECTORED_ANCILLARY_PATH_PREFIX,
|
|
17
|
+
L2_STANDARD_ANCILLARY_PATH_PREFIX,
|
|
18
|
+
L2_SUMMED_ANCILLARY_PATH_PREFIX,
|
|
19
|
+
N_AZIMUTH,
|
|
20
|
+
SECONDS_PER_10_MIN,
|
|
21
|
+
SECONDS_PER_MIN,
|
|
22
|
+
STANDARD_PARTICLE_ENERGY_RANGE_MAPPING,
|
|
23
|
+
VALID_SECTORED_SPECIES,
|
|
24
|
+
VALID_SPECIES,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
# TODO:
|
|
30
|
+
# - review logging levels to use (debug vs. info)
|
|
31
|
+
# - determine where to pull ancillary data. Storing it locally for now
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def hit_l2(dependency: xr.Dataset) -> list[xr.Dataset]:
|
|
35
|
+
"""
|
|
36
|
+
Will process HIT data to L2.
|
|
37
|
+
|
|
38
|
+
Processes dependencies needed to create L2 data products.
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
dependency : xr.Dataset
|
|
43
|
+
L1B xarray science dataset that is either summed rates
|
|
44
|
+
standard rates or sector rates.
|
|
45
|
+
|
|
46
|
+
Returns
|
|
47
|
+
-------
|
|
48
|
+
processed_data : list[xarray.Dataset]
|
|
49
|
+
List of one L2 dataset.
|
|
50
|
+
"""
|
|
51
|
+
logger.info("Creating HIT L2 science datasets")
|
|
52
|
+
|
|
53
|
+
# Create the attribute manager for this data level
|
|
54
|
+
attr_mgr = get_attribute_manager("l2")
|
|
55
|
+
|
|
56
|
+
l2_datasets: dict = {}
|
|
57
|
+
|
|
58
|
+
# Process science data to L2 datasets
|
|
59
|
+
if "imap_hit_l1b_summed-rates" in dependency.attrs["Logical_source"]:
|
|
60
|
+
l2_datasets["imap_hit_l2_summed-intensity"] = process_summed_intensity_data(
|
|
61
|
+
dependency
|
|
62
|
+
)
|
|
63
|
+
logger.info("HIT L2 summed intensity dataset created")
|
|
64
|
+
|
|
65
|
+
if "imap_hit_l1b_standard-rates" in dependency.attrs["Logical_source"]:
|
|
66
|
+
l2_datasets["imap_hit_l2_standard-intensity"] = process_standard_intensity_data(
|
|
67
|
+
dependency
|
|
68
|
+
)
|
|
69
|
+
logger.info("HIT L2 standard intensity dataset created")
|
|
70
|
+
|
|
71
|
+
if "imap_hit_l1b_sectored-rates" in dependency.attrs["Logical_source"]:
|
|
72
|
+
l2_datasets["imap_hit_l2_macropixel-intensity"] = (
|
|
73
|
+
process_sectored_intensity_data(dependency)
|
|
74
|
+
)
|
|
75
|
+
logger.info("HIT L2 macropixel intensity dataset created")
|
|
76
|
+
|
|
77
|
+
# Update attributes and dimensions
|
|
78
|
+
for logical_source, dataset in l2_datasets.items():
|
|
79
|
+
dataset.attrs = attr_mgr.get_global_attributes(logical_source)
|
|
80
|
+
|
|
81
|
+
# TODO: Add CDF attributes to yaml once they're defined for L2 science data
|
|
82
|
+
# consider moving attribute handling to hit_utils.py
|
|
83
|
+
# Assign attributes and dimensions to each data array in the Dataset
|
|
84
|
+
for field in dataset.data_vars.keys():
|
|
85
|
+
try:
|
|
86
|
+
# Create a dict of dimensions using the DEPEND_I keys in the
|
|
87
|
+
# attributes
|
|
88
|
+
dims = {
|
|
89
|
+
key: value
|
|
90
|
+
for key, value in attr_mgr.get_variable_attributes(field).items()
|
|
91
|
+
if "DEPEND" in key
|
|
92
|
+
}
|
|
93
|
+
dataset[field].attrs = attr_mgr.get_variable_attributes(field)
|
|
94
|
+
dataset[field].assign_coords(dims)
|
|
95
|
+
except KeyError:
|
|
96
|
+
# TODO: consider raising an error after L2 attributes are defined.
|
|
97
|
+
# Until then, continue with processing and log warning
|
|
98
|
+
logger.warning(f"Field {field} not found in attribute manager.")
|
|
99
|
+
|
|
100
|
+
# Skip schema check for epoch to prevent attr_mgr from adding the
|
|
101
|
+
# DEPEND_0 attribute which isn't required for epoch
|
|
102
|
+
dataset.epoch.attrs = attr_mgr.get_variable_attributes(
|
|
103
|
+
"epoch", check_schema=False
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
logger.info(f"HIT L2 dataset created for {logical_source}")
|
|
107
|
+
|
|
108
|
+
return list(l2_datasets.values())
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def calculate_intensities(
|
|
112
|
+
rates: xr.DataArray,
|
|
113
|
+
factors: xr.Dataset,
|
|
114
|
+
) -> xr.DataArray:
|
|
115
|
+
"""
|
|
116
|
+
Calculate the intensities for given rates and equation factors.
|
|
117
|
+
|
|
118
|
+
Uses vectorization to calculate the intensities for an array of rates
|
|
119
|
+
for all epochs.
|
|
120
|
+
|
|
121
|
+
This function uses equation 9 and 12 from the HIT algorithm document:
|
|
122
|
+
((Summed L1B Rates) / (Delta Time * Delta E * Geometry Factor * Efficiency)) - b
|
|
123
|
+
|
|
124
|
+
Parameters
|
|
125
|
+
----------
|
|
126
|
+
rates : xr.DataArray
|
|
127
|
+
The L1B rates to be converted to intensities.
|
|
128
|
+
factors : xr.Dataset
|
|
129
|
+
The ancillary data factors needed to calculate the intensity.
|
|
130
|
+
This includes delta_e, geometry_factor, efficiency, and b.
|
|
131
|
+
|
|
132
|
+
Returns
|
|
133
|
+
-------
|
|
134
|
+
xr.DataArray
|
|
135
|
+
The calculated intensities for all epochs.
|
|
136
|
+
"""
|
|
137
|
+
# Calculate the intensity using vectorized operations
|
|
138
|
+
intensity = (
|
|
139
|
+
rates
|
|
140
|
+
/ (
|
|
141
|
+
factors.delta_time
|
|
142
|
+
* factors.delta_e
|
|
143
|
+
* factors.geometry_factor
|
|
144
|
+
* factors.efficiency
|
|
145
|
+
)
|
|
146
|
+
) - factors.b
|
|
147
|
+
|
|
148
|
+
# Apply intensity where rates are not equal to the fill value
|
|
149
|
+
intensity = xr.where(rates == FILLVAL_FLOAT32, FILLVAL_FLOAT32, intensity)
|
|
150
|
+
|
|
151
|
+
return intensity
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def reshape_for_sectored(arr: np.ndarray) -> np.ndarray:
|
|
155
|
+
"""
|
|
156
|
+
Reshape the ancillary data for sectored rates.
|
|
157
|
+
|
|
158
|
+
Reshape the 3D arrays (epoch, energy, declination) to 4D arrays
|
|
159
|
+
(epoch, energy, azimuth, declination) by repeating the data
|
|
160
|
+
along the azimuth dimension. This is done to match the dimensions
|
|
161
|
+
of the sectored rates data to allow for proper calculation of
|
|
162
|
+
intensities.
|
|
163
|
+
|
|
164
|
+
Parameters
|
|
165
|
+
----------
|
|
166
|
+
arr : np.ndarray
|
|
167
|
+
The ancillary data array to reshape.
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
np.ndarray
|
|
172
|
+
The reshaped array.
|
|
173
|
+
"""
|
|
174
|
+
return np.repeat(
|
|
175
|
+
arr.reshape((arr.shape[0], arr.shape[1], arr.shape[2]))[:, :, np.newaxis, :],
|
|
176
|
+
N_AZIMUTH,
|
|
177
|
+
axis=2,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def build_ancillary_dataset(
|
|
182
|
+
delta_e: np.ndarray,
|
|
183
|
+
geometry_factors: np.ndarray,
|
|
184
|
+
efficiencies: np.ndarray,
|
|
185
|
+
b: np.ndarray,
|
|
186
|
+
species_array: xr.DataArray,
|
|
187
|
+
) -> xr.Dataset:
|
|
188
|
+
"""
|
|
189
|
+
Build a xarray Dataset containing ancillary data for calculating intensity.
|
|
190
|
+
|
|
191
|
+
This function builds a dataset containing the factors needed for calculating
|
|
192
|
+
intensity for a given species. The dataset is built based on the dimensions
|
|
193
|
+
and coordinates of the species data to align data along the epoch dimension.
|
|
194
|
+
|
|
195
|
+
Parameters
|
|
196
|
+
----------
|
|
197
|
+
delta_e : np.ndarray
|
|
198
|
+
Delta E values which are energy bin widths.
|
|
199
|
+
geometry_factors : np.ndarray
|
|
200
|
+
Geometry factor values.
|
|
201
|
+
efficiencies : np.ndarray
|
|
202
|
+
Efficiency values.
|
|
203
|
+
b : np.ndarray
|
|
204
|
+
Background intensity values.
|
|
205
|
+
species_array : xr.Dataset
|
|
206
|
+
Data array for the species to extract coordinates from.
|
|
207
|
+
|
|
208
|
+
Returns
|
|
209
|
+
-------
|
|
210
|
+
ancillary_ds : xr.Dataset
|
|
211
|
+
A dataset containing all ancillary data variables and coordinates that
|
|
212
|
+
align with the L2 dataset.
|
|
213
|
+
"""
|
|
214
|
+
data_vars = {}
|
|
215
|
+
|
|
216
|
+
# Check if this is sectored data (i.e., has azimuth and declination dims)
|
|
217
|
+
is_sectored = (
|
|
218
|
+
"declination" in species_array.dims or "declination" in species_array.coords
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Build variables
|
|
222
|
+
data_vars["delta_e"] = (species_array.dims, delta_e)
|
|
223
|
+
data_vars["geometry_factor"] = (
|
|
224
|
+
species_array.dims,
|
|
225
|
+
geometry_factors,
|
|
226
|
+
)
|
|
227
|
+
data_vars["efficiency"] = (
|
|
228
|
+
species_array.dims,
|
|
229
|
+
efficiencies,
|
|
230
|
+
)
|
|
231
|
+
data_vars["b"] = (species_array.dims, b)
|
|
232
|
+
data_vars["delta_time"] = (
|
|
233
|
+
["epoch"],
|
|
234
|
+
np.full(
|
|
235
|
+
len(species_array.epoch),
|
|
236
|
+
SECONDS_PER_10_MIN if is_sectored else SECONDS_PER_MIN,
|
|
237
|
+
),
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
return xr.Dataset(data_vars, coords=species_array.coords)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def calculate_intensities_for_a_species(
|
|
244
|
+
species_variable: str, l2_dataset: xr.Dataset, ancillary_data_frames: dict
|
|
245
|
+
) -> xr.Dataset:
|
|
246
|
+
"""
|
|
247
|
+
Calculate the intensity for a given species in the dataset.
|
|
248
|
+
|
|
249
|
+
This function orchestrates calculating the intensity for a given species
|
|
250
|
+
in the L2 dataset using ancillary data determined by the dynamic threshold
|
|
251
|
+
state (0-3).
|
|
252
|
+
|
|
253
|
+
The intensity is calculated using the equation:
|
|
254
|
+
(L1B Rates) / (Delta Time * Delta E * Geometry Factor * Efficiency) - b
|
|
255
|
+
|
|
256
|
+
where the equation factors are retrieved from the ancillary data for
|
|
257
|
+
the given species and dynamic threshold states.
|
|
258
|
+
|
|
259
|
+
Parameters
|
|
260
|
+
----------
|
|
261
|
+
species_variable : str
|
|
262
|
+
The species variable to calculate the intensity for, which is either the species
|
|
263
|
+
or a statistical uncertainty.
|
|
264
|
+
(i.e. "h", "h_stat_uncert_minus", or "h_stat_uncert_plus").
|
|
265
|
+
l2_dataset : xr.Dataset
|
|
266
|
+
The L2 dataset containing the L1B rates needed to calculate the intensity.
|
|
267
|
+
ancillary_data_frames : dict
|
|
268
|
+
Dictionary containing ancillary data for each dynamic threshold state where
|
|
269
|
+
the key is the dynamic threshold state and the value is a pandas DataFrame
|
|
270
|
+
containing the ancillary data for all species.
|
|
271
|
+
|
|
272
|
+
Returns
|
|
273
|
+
-------
|
|
274
|
+
updated_ds : xr.Dataset
|
|
275
|
+
The updated dataset with intensities calculated for the given species.
|
|
276
|
+
"""
|
|
277
|
+
updated_ds = l2_dataset.copy()
|
|
278
|
+
dynamic_threshold_states = updated_ds["dynamic_threshold_state"].values
|
|
279
|
+
unique_states = np.unique(dynamic_threshold_states)
|
|
280
|
+
species_name = (
|
|
281
|
+
species_variable.split("_")[0]
|
|
282
|
+
if "_uncert_" in species_variable
|
|
283
|
+
else species_variable
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# Subset ancillary data for this species
|
|
287
|
+
species_ancillary_by_state = {
|
|
288
|
+
state: get_species_ancillary_data(state, ancillary_data_frames, species_name)
|
|
289
|
+
for state in unique_states
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
# Extract parameters - 3D arrays (num_states, energy bins, values)
|
|
293
|
+
delta_e = np.stack(
|
|
294
|
+
[
|
|
295
|
+
species_ancillary_by_state[state]["delta_e"]
|
|
296
|
+
for state in dynamic_threshold_states
|
|
297
|
+
]
|
|
298
|
+
)
|
|
299
|
+
geometry_factors = np.stack(
|
|
300
|
+
[
|
|
301
|
+
species_ancillary_by_state[state]["geometry_factor"]
|
|
302
|
+
for state in dynamic_threshold_states
|
|
303
|
+
]
|
|
304
|
+
)
|
|
305
|
+
efficiencies = np.stack(
|
|
306
|
+
[
|
|
307
|
+
species_ancillary_by_state[state]["efficiency"]
|
|
308
|
+
for state in dynamic_threshold_states
|
|
309
|
+
]
|
|
310
|
+
)
|
|
311
|
+
b = np.stack(
|
|
312
|
+
[species_ancillary_by_state[state]["b"] for state in dynamic_threshold_states]
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
# Reshape parameters for sectored rates to 4D arrays
|
|
316
|
+
if "declination" in updated_ds[species_variable].dims:
|
|
317
|
+
delta_e = reshape_for_sectored(delta_e)
|
|
318
|
+
geometry_factors = reshape_for_sectored(geometry_factors)
|
|
319
|
+
efficiencies = reshape_for_sectored(efficiencies)
|
|
320
|
+
b = reshape_for_sectored(b)
|
|
321
|
+
|
|
322
|
+
# Reshape parameters for summed and standard rates to 2D arrays
|
|
323
|
+
# by removing last dimension of size one, (n, n, 1)
|
|
324
|
+
else:
|
|
325
|
+
delta_e = np.squeeze(delta_e, axis=-1)
|
|
326
|
+
geometry_factors = np.squeeze(geometry_factors, axis=-1)
|
|
327
|
+
efficiencies = np.squeeze(efficiencies, axis=-1)
|
|
328
|
+
b = np.squeeze(b, axis=-1)
|
|
329
|
+
|
|
330
|
+
# Build ancillary xarray dataset
|
|
331
|
+
ancillary_ds = build_ancillary_dataset(
|
|
332
|
+
delta_e, geometry_factors, efficiencies, b, l2_dataset[species_name]
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
# Calculate intensities
|
|
336
|
+
updated_ds[species_variable] = calculate_intensities(
|
|
337
|
+
updated_ds[species_variable], ancillary_ds
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
return updated_ds
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def calculate_intensities_for_all_species(
|
|
344
|
+
l2_dataset: xr.Dataset, ancillary_data_frames: dict, valid_data_variables: list
|
|
345
|
+
) -> xr.Dataset:
|
|
346
|
+
"""
|
|
347
|
+
Calculate the intensity for each species in the dataset.
|
|
348
|
+
|
|
349
|
+
Parameters
|
|
350
|
+
----------
|
|
351
|
+
l2_dataset : xr.Dataset
|
|
352
|
+
The L2 dataset.
|
|
353
|
+
ancillary_data_frames : dict
|
|
354
|
+
Dictionary containing ancillary data for each dynamic threshold state
|
|
355
|
+
where the key is the dynamic threshold state and the value is a pandas
|
|
356
|
+
DataFrame containing the ancillary data.
|
|
357
|
+
valid_data_variables : list
|
|
358
|
+
A list of valid data variables to calculate intensity for.
|
|
359
|
+
|
|
360
|
+
Returns
|
|
361
|
+
-------
|
|
362
|
+
updated_ds : xr.Dataset
|
|
363
|
+
The updated dataset with the intensity calculated for each species.
|
|
364
|
+
"""
|
|
365
|
+
updated_ds = l2_dataset.copy()
|
|
366
|
+
|
|
367
|
+
# Add statistical uncertainty variables to the list of valid variables
|
|
368
|
+
data_variables = (
|
|
369
|
+
valid_data_variables
|
|
370
|
+
+ [f"{var}_stat_uncert_minus" for var in valid_data_variables]
|
|
371
|
+
+ [f"{var}_stat_uncert_plus" for var in valid_data_variables]
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
# Calculate the intensity for each valid data variable
|
|
375
|
+
for species_variable in data_variables:
|
|
376
|
+
if species_variable in updated_ds.data_vars:
|
|
377
|
+
updated_ds = calculate_intensities_for_a_species(
|
|
378
|
+
species_variable, updated_ds, ancillary_data_frames
|
|
379
|
+
)
|
|
380
|
+
else:
|
|
381
|
+
logger.warning(
|
|
382
|
+
f"Variable {species_variable} not found in dataset. "
|
|
383
|
+
f"Skipping intensity calculation."
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
return updated_ds
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def add_systematic_uncertainties(dataset: xr.Dataset, particle: str) -> xr.Dataset:
|
|
390
|
+
"""
|
|
391
|
+
Add systematic uncertainties to the dataset.
|
|
392
|
+
|
|
393
|
+
Add systematic uncertainties to the dataset. Just zeros for now.
|
|
394
|
+
To change if/when HIT determines there are systematic uncertainties.
|
|
395
|
+
|
|
396
|
+
Parameters
|
|
397
|
+
----------
|
|
398
|
+
dataset : xr.Dataset
|
|
399
|
+
The dataset to add the systematic uncertainties to
|
|
400
|
+
which contain the particle data variables.
|
|
401
|
+
particle : str
|
|
402
|
+
The particle name.
|
|
403
|
+
|
|
404
|
+
Returns
|
|
405
|
+
-------
|
|
406
|
+
updated_ds : xr.Dataset
|
|
407
|
+
The dataset with the systematic uncertainties added.
|
|
408
|
+
"""
|
|
409
|
+
updated_ds = dataset.copy()
|
|
410
|
+
|
|
411
|
+
updated_ds[f"{particle}_sys_err_minus"] = xr.DataArray(
|
|
412
|
+
data=np.zeros(updated_ds[particle].shape, dtype=np.float32),
|
|
413
|
+
dims=updated_ds[particle].dims,
|
|
414
|
+
name=f"{particle}_sys_err_minus",
|
|
415
|
+
)
|
|
416
|
+
updated_ds[f"{particle}_sys_err_plus"] = xr.DataArray(
|
|
417
|
+
data=np.zeros(updated_ds[particle].shape, dtype=np.float32),
|
|
418
|
+
dims=updated_ds[particle].dims,
|
|
419
|
+
name=f"{particle}_sys_err_plus",
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
return updated_ds
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def add_total_uncertainties(dataset: xr.Dataset, particle: str) -> xr.Dataset:
|
|
426
|
+
"""
|
|
427
|
+
Add total uncertainties to the dataset.
|
|
428
|
+
|
|
429
|
+
This function calculates the total uncertainties for a given particle
|
|
430
|
+
by combining the statistical uncertainties and systematic uncertainties.
|
|
431
|
+
|
|
432
|
+
The total uncertainties are calculated as the square root of the sum
|
|
433
|
+
of the squares of the statistical and systematic uncertainties.
|
|
434
|
+
|
|
435
|
+
Parameters
|
|
436
|
+
----------
|
|
437
|
+
dataset : xr.Dataset
|
|
438
|
+
The dataset to add the total uncertainties to.
|
|
439
|
+
particle : str
|
|
440
|
+
The particle name.
|
|
441
|
+
|
|
442
|
+
Returns
|
|
443
|
+
-------
|
|
444
|
+
updated_ds : xr.Dataset
|
|
445
|
+
The dataset with the total uncertainties added.
|
|
446
|
+
"""
|
|
447
|
+
updated_ds = dataset.copy()
|
|
448
|
+
|
|
449
|
+
# Calculate the total uncertainties
|
|
450
|
+
total_minus = np.sqrt(
|
|
451
|
+
np.square(updated_ds[f"{particle}_stat_uncert_minus"])
|
|
452
|
+
+ np.square(updated_ds[f"{particle}_sys_err_minus"])
|
|
453
|
+
)
|
|
454
|
+
total_plus = np.sqrt(
|
|
455
|
+
np.square(updated_ds[f"{particle}_stat_uncert_plus"])
|
|
456
|
+
+ np.square(updated_ds[f"{particle}_sys_err_plus"])
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
updated_ds[f"{particle}_total_uncert_minus"] = xr.DataArray(
|
|
460
|
+
data=total_minus.astype(np.float32),
|
|
461
|
+
dims=updated_ds[particle].dims,
|
|
462
|
+
name=f"{particle}_total_uncert_minus",
|
|
463
|
+
)
|
|
464
|
+
updated_ds[f"{particle}_total_uncert_plus"] = xr.DataArray(
|
|
465
|
+
data=total_plus.astype(np.float32),
|
|
466
|
+
dims=updated_ds[particle].dims,
|
|
467
|
+
name=f"{particle}_total_uncert_plus",
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
return updated_ds
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def get_species_ancillary_data(
|
|
474
|
+
dynamic_threshold_state: int, ancillary_data_frames: dict, species: str
|
|
475
|
+
) -> dict:
|
|
476
|
+
"""
|
|
477
|
+
Get the ancillary data for a given species and dynamic threshold state.
|
|
478
|
+
|
|
479
|
+
Parameters
|
|
480
|
+
----------
|
|
481
|
+
dynamic_threshold_state : int
|
|
482
|
+
The dynamic threshold state for the ancillary data (0-3).
|
|
483
|
+
ancillary_data_frames : dict
|
|
484
|
+
Dictionary containing ancillary data for each dynamic threshold state
|
|
485
|
+
where the key is the dynamic threshold state and the value is a pandas
|
|
486
|
+
DataFrame containing the ancillary data.
|
|
487
|
+
species : str
|
|
488
|
+
The species to get the ancillary data for.
|
|
489
|
+
|
|
490
|
+
Returns
|
|
491
|
+
-------
|
|
492
|
+
dict
|
|
493
|
+
The ancillary data for the species and dynamic threshold state.
|
|
494
|
+
"""
|
|
495
|
+
ancillary_df = ancillary_data_frames[dynamic_threshold_state]
|
|
496
|
+
|
|
497
|
+
# Remove any trailing spaces from all values in the DataFrame
|
|
498
|
+
ancillary_df = ancillary_df.map(lambda x: x.strip() if isinstance(x, str) else x)
|
|
499
|
+
|
|
500
|
+
# Get the ancillary data for the species and group by lower energy
|
|
501
|
+
species_ancillary_df = ancillary_df[ancillary_df["species"] == species]
|
|
502
|
+
grouped = species_ancillary_df.groupby("lower energy (mev)")
|
|
503
|
+
return {
|
|
504
|
+
"delta_e": np.array(grouped["delta e (mev)"].apply(list).tolist()),
|
|
505
|
+
"geometry_factor": np.array(
|
|
506
|
+
grouped["geometry factor (cm2 sr)"].apply(list).tolist()
|
|
507
|
+
),
|
|
508
|
+
"efficiency": np.array(grouped["efficiency"].apply(list).tolist()),
|
|
509
|
+
"b": np.array(grouped["b"].apply(list).tolist()),
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
def load_ancillary_data(dynamic_threshold_states: set, path_prefix: Path) -> dict:
|
|
514
|
+
"""
|
|
515
|
+
Load ancillary data based on the dynamic threshold state.
|
|
516
|
+
|
|
517
|
+
The dynamic threshold state (0-3) determines which ancillary file to use.
|
|
518
|
+
This function returns a dictionary with ancillary data for each state in
|
|
519
|
+
the dataset.
|
|
520
|
+
|
|
521
|
+
Parameters
|
|
522
|
+
----------
|
|
523
|
+
dynamic_threshold_states : set
|
|
524
|
+
A set of dynamic threshold states in the L2 dataset.
|
|
525
|
+
path_prefix : Path
|
|
526
|
+
The path prefix for ancillary data files.
|
|
527
|
+
|
|
528
|
+
Returns
|
|
529
|
+
-------
|
|
530
|
+
dict
|
|
531
|
+
A dictionary with ancillary data for each dynamic threshold state.
|
|
532
|
+
"""
|
|
533
|
+
# Load ancillary data
|
|
534
|
+
ancillary_data_frames = {
|
|
535
|
+
int(state): pd.read_csv(f"{path_prefix}{state}-factors_20250219_v002.csv")
|
|
536
|
+
for state in dynamic_threshold_states
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
# Convert column names and species values to lowercase
|
|
540
|
+
for df in ancillary_data_frames.values():
|
|
541
|
+
df.columns = df.columns.str.lower().str.strip()
|
|
542
|
+
df["species"] = df["species"].str.lower()
|
|
543
|
+
|
|
544
|
+
return ancillary_data_frames
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def process_summed_intensity_data(l1b_summed_rates_dataset: xr.Dataset) -> xr.Dataset:
|
|
548
|
+
"""
|
|
549
|
+
Will process L2 HIT summed intensity data from L1B summed rates.
|
|
550
|
+
|
|
551
|
+
This function converts the L1B summed rates to L2 summed intensities
|
|
552
|
+
using ancillary tables containing factors needed to calculate the
|
|
553
|
+
intensity (energy bin width, geometry factor, efficiency, and b).
|
|
554
|
+
|
|
555
|
+
Equation 12 from the HIT algorithm document:
|
|
556
|
+
Summed Intensity = (L1B Summed Rate) /
|
|
557
|
+
(60 * Delta E * Geometry Factor * Efficiency) - b
|
|
558
|
+
|
|
559
|
+
Parameters
|
|
560
|
+
----------
|
|
561
|
+
l1b_summed_rates_dataset : xarray.Dataset
|
|
562
|
+
HIT L1B summed rates dataset.
|
|
563
|
+
|
|
564
|
+
Returns
|
|
565
|
+
-------
|
|
566
|
+
xr.Dataset
|
|
567
|
+
The processed L2 summed intensity dataset.
|
|
568
|
+
"""
|
|
569
|
+
# Create a new dataset to store the L2 summed intensity data
|
|
570
|
+
l2_summed_intensity_dataset = l1b_summed_rates_dataset.copy(deep=True)
|
|
571
|
+
|
|
572
|
+
# Load ancillary data for each dynamic threshold state into a dictionary
|
|
573
|
+
ancillary_data_frames = load_ancillary_data(
|
|
574
|
+
set(l2_summed_intensity_dataset["dynamic_threshold_state"].values),
|
|
575
|
+
L2_SUMMED_ANCILLARY_PATH_PREFIX,
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
# Calculate the intensity for each species
|
|
579
|
+
l2_summed_intensity_dataset = calculate_intensities_for_all_species(
|
|
580
|
+
l2_summed_intensity_dataset, ancillary_data_frames, VALID_SPECIES
|
|
581
|
+
)
|
|
582
|
+
|
|
583
|
+
# Add total and systematic uncertainties to the dataset
|
|
584
|
+
for var in l2_summed_intensity_dataset.data_vars:
|
|
585
|
+
if var in VALID_SPECIES:
|
|
586
|
+
l2_summed_intensity_dataset = add_systematic_uncertainties(
|
|
587
|
+
l2_summed_intensity_dataset, var
|
|
588
|
+
)
|
|
589
|
+
l2_summed_intensity_dataset = add_total_uncertainties(
|
|
590
|
+
l2_summed_intensity_dataset, var
|
|
591
|
+
)
|
|
592
|
+
|
|
593
|
+
return l2_summed_intensity_dataset
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
def process_standard_intensity_data(
|
|
597
|
+
l1b_standard_rates_dataset: xr.Dataset,
|
|
598
|
+
) -> xr.Dataset:
|
|
599
|
+
"""
|
|
600
|
+
Will process L2 standard intensity data from L1B standard rates data.
|
|
601
|
+
|
|
602
|
+
This function converts L1B standard rates to L2 standard intensities for each
|
|
603
|
+
particle type and energy range using ancillary tables containing factors
|
|
604
|
+
needed to calculate the intensity (energy bin width, geometry factor, efficiency
|
|
605
|
+
and b).
|
|
606
|
+
|
|
607
|
+
First, rates from the l2fgrates, l3fgrates, and penfgrates data variables
|
|
608
|
+
in the L1B standard rates data are summed. These variables represent rates
|
|
609
|
+
for different detector penetration ranges (Range 2, Range 3, and Range 4
|
|
610
|
+
respectively). Only the energy ranges specified in the
|
|
611
|
+
STANDARD_PARTICLE_ENERGY_RANGE_MAPPING dictionary are included in this
|
|
612
|
+
product.
|
|
613
|
+
|
|
614
|
+
Intensity is then calculated from the summed standard rates:
|
|
615
|
+
|
|
616
|
+
Equation 9 from the HIT algorithm document:
|
|
617
|
+
Standard Intensity = (Summed L1B Standard Rates) /
|
|
618
|
+
(60 * Delta E * Geometry Factor * Efficiency) - b
|
|
619
|
+
|
|
620
|
+
Parameters
|
|
621
|
+
----------
|
|
622
|
+
l1b_standard_rates_dataset : xr.Dataset
|
|
623
|
+
The L1B standard rates dataset.
|
|
624
|
+
|
|
625
|
+
Returns
|
|
626
|
+
-------
|
|
627
|
+
xr.Dataset
|
|
628
|
+
The L2 standard intensity dataset.
|
|
629
|
+
"""
|
|
630
|
+
# Create a new dataset to store the L2 standard intensity data
|
|
631
|
+
l2_standard_intensity_dataset = xr.Dataset()
|
|
632
|
+
|
|
633
|
+
# Assign the epoch coordinate from the l1B dataset
|
|
634
|
+
l2_standard_intensity_dataset = l2_standard_intensity_dataset.assign_coords(
|
|
635
|
+
{"epoch": l1b_standard_rates_dataset.coords["epoch"]}
|
|
636
|
+
)
|
|
637
|
+
|
|
638
|
+
# Add dynamic threshold state to the dataset
|
|
639
|
+
l2_standard_intensity_dataset["dynamic_threshold_state"] = (
|
|
640
|
+
l1b_standard_rates_dataset["dynamic_threshold_state"]
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
# Load ancillary data for each dynamic threshold state into a dictionary
|
|
644
|
+
ancillary_data_frames = load_ancillary_data(
|
|
645
|
+
set(l2_standard_intensity_dataset["dynamic_threshold_state"].values),
|
|
646
|
+
L2_STANDARD_ANCILLARY_PATH_PREFIX,
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
# Process each particle type and add rates and uncertainties to the dataset
|
|
650
|
+
for particle, energy_ranges in STANDARD_PARTICLE_ENERGY_RANGE_MAPPING.items():
|
|
651
|
+
# Add standard particle rates and statistical uncertainties to the dataset
|
|
652
|
+
l2_standard_intensity_dataset = add_summed_particle_data_to_dataset(
|
|
653
|
+
l2_standard_intensity_dataset,
|
|
654
|
+
l1b_standard_rates_dataset,
|
|
655
|
+
particle,
|
|
656
|
+
energy_ranges,
|
|
657
|
+
)
|
|
658
|
+
|
|
659
|
+
l2_standard_intensity_dataset = calculate_intensities_for_all_species(
|
|
660
|
+
l2_standard_intensity_dataset, ancillary_data_frames, VALID_SPECIES
|
|
661
|
+
)
|
|
662
|
+
|
|
663
|
+
# Add total and systematic uncertainties to the dataset
|
|
664
|
+
for particle in STANDARD_PARTICLE_ENERGY_RANGE_MAPPING.keys():
|
|
665
|
+
l2_standard_intensity_dataset = add_systematic_uncertainties(
|
|
666
|
+
l2_standard_intensity_dataset, particle
|
|
667
|
+
)
|
|
668
|
+
l2_standard_intensity_dataset = add_total_uncertainties(
|
|
669
|
+
l2_standard_intensity_dataset, particle
|
|
670
|
+
)
|
|
671
|
+
|
|
672
|
+
return l2_standard_intensity_dataset
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
def process_sectored_intensity_data(
|
|
676
|
+
l1b_sectored_rates_dataset: xr.Dataset,
|
|
677
|
+
) -> xr.Dataset:
|
|
678
|
+
"""
|
|
679
|
+
Will process L2 HIT sectored intensity data from L1B sectored rates data.
|
|
680
|
+
|
|
681
|
+
This function converts the L1B sectored rates to L2 sectored intensities
|
|
682
|
+
using ancillary tables containing factors needed to calculate the
|
|
683
|
+
intensity (energy bin width, geometry factor, efficiency, and b).
|
|
684
|
+
|
|
685
|
+
Equation 12 from the HIT algorithm document:
|
|
686
|
+
Sectored Intensity = (Summed L1B Sectored Rates) /
|
|
687
|
+
(600 * Delta E * Geometry Factor * Efficiency) - b
|
|
688
|
+
|
|
689
|
+
Parameters
|
|
690
|
+
----------
|
|
691
|
+
l1b_sectored_rates_dataset : xr.Dataset
|
|
692
|
+
The L1B sectored rates dataset.
|
|
693
|
+
|
|
694
|
+
Returns
|
|
695
|
+
-------
|
|
696
|
+
xr.Dataset
|
|
697
|
+
The processed L2 sectored intensity dataset.
|
|
698
|
+
"""
|
|
699
|
+
# Create a new dataset to store the L2 sectored intensity data
|
|
700
|
+
l2_sectored_intensity_dataset = l1b_sectored_rates_dataset.copy(deep=True)
|
|
701
|
+
|
|
702
|
+
# Load ancillary data for each dynamic threshold state into a dictionary
|
|
703
|
+
ancillary_data_frames = load_ancillary_data(
|
|
704
|
+
set(l2_sectored_intensity_dataset["dynamic_threshold_state"].values),
|
|
705
|
+
L2_SECTORED_ANCILLARY_PATH_PREFIX,
|
|
706
|
+
)
|
|
707
|
+
|
|
708
|
+
# Calculate the intensity for each species
|
|
709
|
+
l2_sectored_intensity_dataset = calculate_intensities_for_all_species(
|
|
710
|
+
l2_sectored_intensity_dataset, ancillary_data_frames, VALID_SECTORED_SPECIES
|
|
711
|
+
)
|
|
712
|
+
|
|
713
|
+
# Add total and systematic uncertainties to the dataset
|
|
714
|
+
for var in l2_sectored_intensity_dataset.data_vars:
|
|
715
|
+
if var in VALID_SECTORED_SPECIES:
|
|
716
|
+
l2_sectored_intensity_dataset = add_systematic_uncertainties(
|
|
717
|
+
l2_sectored_intensity_dataset, var
|
|
718
|
+
)
|
|
719
|
+
l2_sectored_intensity_dataset = add_total_uncertainties(
|
|
720
|
+
l2_sectored_intensity_dataset, var
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
return l2_sectored_intensity_dataset
|