imap-processing 0.12.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 +1 -0
- imap_processing/_version.py +2 -2
- imap_processing/ccsds/ccsds_data.py +1 -2
- imap_processing/ccsds/excel_to_xtce.py +1 -2
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +18 -12
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +569 -0
- imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +5 -5
- imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +20 -1
- 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_mag_global_cdf_attrs.yaml +15 -0
- imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
- imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +16 -0
- imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +178 -5
- imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +33 -19
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +8 -48
- imap_processing/cdf/utils.py +41 -33
- imap_processing/cli.py +463 -234
- imap_processing/codice/codice_l1a.py +260 -47
- imap_processing/codice/codice_l1b.py +51 -152
- imap_processing/codice/constants.py +38 -1
- imap_processing/ena_maps/ena_maps.py +658 -65
- imap_processing/ena_maps/utils/coordinates.py +1 -1
- imap_processing/ena_maps/utils/spatial_utils.py +10 -5
- 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 +31 -12
- imap_processing/hi/l1b/hi_l1b.py +80 -43
- imap_processing/hi/l1c/hi_l1c.py +12 -16
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
- imap_processing/hit/hit_utils.py +93 -35
- imap_processing/hit/l0/decom_hit.py +3 -1
- imap_processing/hit/l1a/hit_l1a.py +30 -25
- imap_processing/hit/l1b/constants.py +6 -2
- imap_processing/hit/l1b/hit_l1b.py +279 -318
- imap_processing/hit/l2/constants.py +37 -0
- imap_processing/hit/l2/hit_l2.py +373 -264
- imap_processing/ialirt/l0/parse_mag.py +138 -10
- imap_processing/ialirt/l0/process_swapi.py +69 -0
- imap_processing/ialirt/l0/process_swe.py +318 -22
- imap_processing/ialirt/packet_definitions/ialirt.xml +216 -212
- 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_swapi.xml +14 -14
- imap_processing/ialirt/utils/grouping.py +1 -1
- imap_processing/idex/idex_constants.py +9 -1
- imap_processing/idex/idex_l0.py +22 -8
- imap_processing/idex/idex_l1a.py +75 -44
- imap_processing/idex/idex_l1b.py +9 -8
- imap_processing/idex/idex_l2a.py +79 -45
- imap_processing/idex/idex_l2b.py +120 -0
- imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -39
- imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
- imap_processing/lo/l0/lo_science.py +1 -2
- imap_processing/lo/l1a/lo_l1a.py +1 -4
- imap_processing/lo/l1b/lo_l1b.py +527 -6
- imap_processing/lo/l1b/tof_conversions.py +11 -0
- imap_processing/lo/l1c/lo_l1c.py +1 -4
- imap_processing/mag/constants.py +43 -0
- imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
- imap_processing/mag/l1a/mag_l1a.py +2 -9
- imap_processing/mag/l1a/mag_l1a_data.py +10 -10
- imap_processing/mag/l1b/mag_l1b.py +84 -17
- imap_processing/mag/l1c/interpolation_methods.py +180 -3
- imap_processing/mag/l1c/mag_l1c.py +236 -70
- imap_processing/mag/l2/mag_l2.py +140 -0
- imap_processing/mag/l2/mag_l2_data.py +288 -0
- imap_processing/spacecraft/quaternions.py +1 -3
- imap_processing/spice/geometry.py +3 -3
- imap_processing/spice/kernels.py +0 -276
- imap_processing/spice/pointing_frame.py +257 -0
- imap_processing/spice/repoint.py +48 -19
- imap_processing/spice/spin.py +38 -33
- imap_processing/spice/time.py +24 -0
- imap_processing/swapi/l1/swapi_l1.py +16 -12
- imap_processing/swapi/l2/swapi_l2.py +116 -4
- imap_processing/swapi/swapi_utils.py +32 -0
- imap_processing/swe/l1a/swe_l1a.py +2 -9
- imap_processing/swe/l1a/swe_science.py +8 -11
- imap_processing/swe/l1b/swe_l1b.py +898 -23
- imap_processing/swe/l2/swe_l2.py +21 -77
- imap_processing/swe/utils/swe_constants.py +1 -0
- imap_processing/tests/ccsds/test_excel_to_xtce.py +1 -1
- 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-pha_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/test_codice_l1a.py +20 -11
- imap_processing/tests/codice/test_codice_l1b.py +6 -7
- imap_processing/tests/conftest.py +78 -22
- imap_processing/tests/ena_maps/test_ena_maps.py +462 -33
- imap_processing/tests/ena_maps/test_spatial_utils.py +1 -1
- 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/test_hi_l1b.py +10 -12
- imap_processing/tests/hi/test_hi_l1c.py +27 -24
- imap_processing/tests/hi/test_l1a.py +7 -9
- imap_processing/tests/hi/test_science_direct_event.py +2 -2
- imap_processing/tests/hit/helpers/l1_validation.py +44 -43
- imap_processing/tests/hit/test_decom_hit.py +1 -1
- imap_processing/tests/hit/test_hit_l1a.py +9 -9
- imap_processing/tests/hit/test_hit_l1b.py +172 -217
- imap_processing/tests/hit/test_hit_l2.py +380 -118
- imap_processing/tests/hit/test_hit_utils.py +122 -55
- imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
- imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
- imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
- imap_processing/tests/ialirt/unit/test_grouping.py +2 -2
- imap_processing/tests/ialirt/unit/test_parse_mag.py +71 -16
- 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 +115 -7
- imap_processing/tests/idex/conftest.py +72 -7
- 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_idex_l0.py +33 -11
- imap_processing/tests/idex/test_idex_l1a.py +50 -23
- imap_processing/tests/idex/test_idex_l1b.py +104 -25
- imap_processing/tests/idex/test_idex_l2a.py +48 -32
- imap_processing/tests/idex/test_idex_l2b.py +93 -0
- imap_processing/tests/lo/test_lo_l1a.py +3 -3
- imap_processing/tests/lo/test_lo_l1b.py +371 -6
- imap_processing/tests/lo/test_lo_l1c.py +1 -1
- imap_processing/tests/lo/test_lo_science.py +6 -7
- imap_processing/tests/lo/test_star_sensor.py +1 -1
- imap_processing/tests/mag/conftest.py +58 -9
- imap_processing/tests/mag/test_mag_decom.py +4 -3
- imap_processing/tests/mag/test_mag_l1a.py +13 -7
- imap_processing/tests/mag/test_mag_l1b.py +9 -9
- imap_processing/tests/mag/test_mag_l1c.py +151 -47
- imap_processing/tests/mag/test_mag_l2.py +130 -0
- imap_processing/tests/mag/test_mag_validation.py +144 -7
- 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_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/test_quaternions.py +1 -1
- imap_processing/tests/spice/test_data/fake_repoint_data.csv +4 -4
- imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
- imap_processing/tests/spice/test_geometry.py +3 -3
- 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 +20 -10
- 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 +7 -9
- imap_processing/tests/swapi/test_swapi_l2.py +180 -8
- 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 +6 -6
- 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 +82 -102
- imap_processing/tests/test_cli.py +171 -88
- imap_processing/tests/test_utils.py +2 -1
- imap_processing/tests/ultra/data/mock_data.py +49 -21
- imap_processing/tests/ultra/unit/conftest.py +53 -70
- imap_processing/tests/ultra/unit/test_badtimes.py +2 -4
- imap_processing/tests/ultra/unit/test_cullingmask.py +4 -6
- imap_processing/tests/ultra/unit/test_de.py +3 -10
- imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
- imap_processing/tests/ultra/unit/test_decom_apid_881.py +15 -16
- 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 +3 -4
- imap_processing/tests/ultra/unit/test_ultra_l1a.py +84 -307
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +30 -12
- imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
- imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +4 -1
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +163 -29
- imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +32 -43
- 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 +21 -34
- 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 -243
- imap_processing/ultra/l1b/badtimes.py +1 -4
- imap_processing/ultra/l1b/cullingmask.py +2 -6
- imap_processing/ultra/l1b/de.py +62 -47
- imap_processing/ultra/l1b/extendedspin.py +8 -4
- imap_processing/ultra/l1b/lookup_utils.py +72 -9
- imap_processing/ultra/l1b/ultra_l1b.py +3 -8
- imap_processing/ultra/l1b/ultra_l1b_culling.py +4 -4
- imap_processing/ultra/l1b/ultra_l1b_extended.py +236 -78
- imap_processing/ultra/l1c/histogram.py +2 -6
- imap_processing/ultra/l1c/spacecraft_pset.py +2 -4
- imap_processing/ultra/l1c/ultra_l1c.py +1 -5
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +107 -60
- 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 +13 -12
- imap_processing/utils.py +1 -1
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +3 -2
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/RECORD +264 -225
- imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
- imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +0 -6
- imap_processing/mag/l1b/__init__.py +0 -0
- imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
- imap_processing/swe/l1b/swe_l1b_science.py +0 -699
- imap_processing/tests/swe/test_swe_l1b_science.py +0 -103
- imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
- imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
- /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/461971383-404.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971384-405.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971385-406.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971386-407.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971387-408.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971388-409.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971389-410.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971390-411.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971391-412.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/tests/ialirt/{test_data → data}/l0/sample_decoded_i-alirt_data.csv +0 -0
- /imap_processing/tests/mag/validation/{imap_calibration_mag_20240229_v01.cdf → calibration/imap_mag_l1b-calibration_20240229_v001.cdf} +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-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""IMAP-HIT L1B data processing."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from typing import NamedTuple
|
|
5
4
|
|
|
6
5
|
import numpy as np
|
|
7
6
|
import xarray as xr
|
|
@@ -9,13 +8,16 @@ import xarray as xr
|
|
|
9
8
|
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
10
9
|
from imap_processing.hit.hit_utils import (
|
|
11
10
|
HitAPID,
|
|
11
|
+
add_summed_particle_data_to_dataset,
|
|
12
12
|
get_attribute_manager,
|
|
13
13
|
get_datasets_by_apid,
|
|
14
14
|
process_housekeeping_data,
|
|
15
15
|
)
|
|
16
16
|
from imap_processing.hit.l1b.constants import (
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
FILLVAL_FLOAT32,
|
|
18
|
+
FILLVAL_INT64,
|
|
19
|
+
LIVESTIM_PULSES,
|
|
20
|
+
SUMMED_PARTICLE_ENERGY_RANGE_MAPPING,
|
|
19
21
|
)
|
|
20
22
|
|
|
21
23
|
logger = logging.getLogger(__name__)
|
|
@@ -23,7 +25,7 @@ logger = logging.getLogger(__name__)
|
|
|
23
25
|
# TODO review logging levels to use (debug vs. info)
|
|
24
26
|
|
|
25
27
|
|
|
26
|
-
def hit_l1b(dependencies: dict
|
|
28
|
+
def hit_l1b(dependencies: dict) -> list[xr.Dataset]:
|
|
27
29
|
"""
|
|
28
30
|
Will process HIT data to L1B.
|
|
29
31
|
|
|
@@ -35,8 +37,6 @@ def hit_l1b(dependencies: dict, data_version: str) -> list[xr.Dataset]:
|
|
|
35
37
|
Dictionary of dependencies that are L1A xarray datasets
|
|
36
38
|
for science data and a file path string to an L0 file
|
|
37
39
|
for housekeeping data.
|
|
38
|
-
data_version : str
|
|
39
|
-
Version of the data product being created.
|
|
40
40
|
|
|
41
41
|
Returns
|
|
42
42
|
-------
|
|
@@ -44,7 +44,7 @@ def hit_l1b(dependencies: dict, data_version: str) -> list[xr.Dataset]:
|
|
|
44
44
|
List of four L1B datasets.
|
|
45
45
|
"""
|
|
46
46
|
# Create the attribute manager for this data level
|
|
47
|
-
attr_mgr = get_attribute_manager(
|
|
47
|
+
attr_mgr = get_attribute_manager("l1b")
|
|
48
48
|
|
|
49
49
|
# Create L1B datasets
|
|
50
50
|
l1b_datasets: list = []
|
|
@@ -72,7 +72,7 @@ def hit_l1b(dependencies: dict, data_version: str) -> list[xr.Dataset]:
|
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
def process_science_data(
|
|
75
|
-
|
|
75
|
+
l1a_counts_dataset: xr.Dataset, attr_mgr: ImapCdfAttributes
|
|
76
76
|
) -> list[xr.Dataset]:
|
|
77
77
|
"""
|
|
78
78
|
Will create L1B science datasets for CDF products.
|
|
@@ -86,7 +86,7 @@ def process_science_data(
|
|
|
86
86
|
|
|
87
87
|
Parameters
|
|
88
88
|
----------
|
|
89
|
-
|
|
89
|
+
l1a_counts_dataset : xr.Dataset
|
|
90
90
|
The L1A counts dataset.
|
|
91
91
|
attr_mgr : AttributeManager
|
|
92
92
|
The attribute manager for the L1B data level.
|
|
@@ -98,28 +98,27 @@ def process_science_data(
|
|
|
98
98
|
"""
|
|
99
99
|
logger.info("Creating HIT L1B science datasets")
|
|
100
100
|
|
|
101
|
-
# Logical sources for the three L1B science products.
|
|
102
|
-
# TODO: add logical sources for other l1b products once processing functions
|
|
103
|
-
# are written. ""imap_hit_l1b_sectored-rates"
|
|
104
|
-
logical_sources = ["imap_hit_l1b_standard-rates", "imap_hit_l1b_summed-rates"]
|
|
105
|
-
|
|
106
101
|
# TODO: Write functions to create the following datasets
|
|
107
102
|
# Process sectored rates dataset
|
|
108
103
|
|
|
109
104
|
# Calculate fractional livetime from the livetime counter
|
|
110
|
-
livetime =
|
|
111
|
-
|
|
112
|
-
# Create a standard rates dataset
|
|
113
|
-
standard_rates_dataset = process_standard_rates_data(raw_counts_dataset, livetime)
|
|
105
|
+
livetime = l1a_counts_dataset["livetime_counter"] / LIVESTIM_PULSES
|
|
106
|
+
livetime = livetime.rename("livetime")
|
|
114
107
|
|
|
115
|
-
#
|
|
116
|
-
|
|
108
|
+
# Process counts data to L1B datasets
|
|
109
|
+
l1b_datasets: dict = {}
|
|
110
|
+
l1b_datasets["imap_hit_l1b_standard-rates"] = process_standard_rates_data(
|
|
111
|
+
l1a_counts_dataset, livetime
|
|
112
|
+
)
|
|
113
|
+
l1b_datasets["imap_hit_l1b_summed-rates"] = process_summed_rates_data(
|
|
114
|
+
l1a_counts_dataset, livetime
|
|
115
|
+
)
|
|
116
|
+
l1b_datasets["imap_hit_l1b_sectored-rates"] = process_sectored_rates_data(
|
|
117
|
+
l1a_counts_dataset, livetime
|
|
118
|
+
)
|
|
117
119
|
|
|
118
|
-
l1b_science_datasets = []
|
|
119
120
|
# Update attributes and dimensions
|
|
120
|
-
for
|
|
121
|
-
[standard_rates_dataset, summed_rates_dataset], logical_sources
|
|
122
|
-
):
|
|
121
|
+
for logical_source, dataset in l1b_datasets.items():
|
|
123
122
|
dataset.attrs = attr_mgr.get_global_attributes(logical_source)
|
|
124
123
|
|
|
125
124
|
# TODO: Add CDF attributes to yaml once they're defined for L1B science data
|
|
@@ -145,22 +144,48 @@ def process_science_data(
|
|
|
145
144
|
"epoch", check_schema=False
|
|
146
145
|
)
|
|
147
146
|
|
|
148
|
-
l1b_science_datasets.append(dataset)
|
|
149
|
-
|
|
150
147
|
logger.info(f"HIT L1B dataset created for {logical_source}")
|
|
151
148
|
|
|
152
|
-
return
|
|
149
|
+
return list(l1b_datasets.values())
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def initialize_l1b_dataset(l1a_counts_dataset: xr.Dataset, coords: list) -> xr.Dataset:
|
|
153
|
+
"""
|
|
154
|
+
Initialize the L1B dataset.
|
|
155
|
+
|
|
156
|
+
Create a dataset and add coordinates and the dynamic threshold state data array
|
|
157
|
+
from the L1A counts dataset.
|
|
158
|
+
|
|
159
|
+
Parameters
|
|
160
|
+
----------
|
|
161
|
+
l1a_counts_dataset : xr.Dataset
|
|
162
|
+
The L1A counts dataset.
|
|
163
|
+
coords : list
|
|
164
|
+
A list of coordinates to assign to the L1B dataset.
|
|
165
|
+
|
|
166
|
+
Returns
|
|
167
|
+
-------
|
|
168
|
+
l1b_dataset : xr.Dataset
|
|
169
|
+
An L1B dataset with coordinates and dynamic threshold state.
|
|
170
|
+
"""
|
|
171
|
+
l1b_dataset = xr.Dataset(
|
|
172
|
+
coords={coord: l1a_counts_dataset.coords[coord] for coord in coords}
|
|
173
|
+
)
|
|
174
|
+
l1b_dataset["dynamic_threshold_state"] = l1a_counts_dataset[
|
|
175
|
+
"hdr_dynamic_threshold_state"
|
|
176
|
+
]
|
|
177
|
+
return l1b_dataset
|
|
153
178
|
|
|
154
179
|
|
|
155
180
|
def process_standard_rates_data(
|
|
156
|
-
|
|
181
|
+
l1a_counts_dataset: xr.Dataset, livetime: xr.DataArray
|
|
157
182
|
) -> xr.Dataset:
|
|
158
183
|
"""
|
|
159
|
-
Will process L1B standard rates data from raw
|
|
184
|
+
Will process L1B standard rates data from L1A raw counts data.
|
|
160
185
|
|
|
161
186
|
Parameters
|
|
162
187
|
----------
|
|
163
|
-
|
|
188
|
+
l1a_counts_dataset : xr.Dataset
|
|
164
189
|
The L1A counts dataset.
|
|
165
190
|
|
|
166
191
|
livetime : xr.DataArray
|
|
@@ -172,37 +197,26 @@ def process_standard_rates_data(
|
|
|
172
197
|
xr.Dataset
|
|
173
198
|
The processed L1B standard rates dataset.
|
|
174
199
|
"""
|
|
175
|
-
#
|
|
176
|
-
l1b_standard_rates_dataset =
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
]
|
|
193
|
-
l1b_standard_rates_dataset = l1b_standard_rates_dataset.assign_coords(
|
|
194
|
-
{coord: raw_counts_dataset.coords[coord] for coord in coords}
|
|
200
|
+
# Initialize the L1B standard rates dataset with coordinates from the L1A dataset
|
|
201
|
+
l1b_standard_rates_dataset = initialize_l1b_dataset(
|
|
202
|
+
l1a_counts_dataset,
|
|
203
|
+
coords=[
|
|
204
|
+
"epoch",
|
|
205
|
+
"gain",
|
|
206
|
+
"sngrates_index",
|
|
207
|
+
"coinrates_index",
|
|
208
|
+
"pbufrates_index",
|
|
209
|
+
"l2fgrates_index",
|
|
210
|
+
"l2bgrates_index",
|
|
211
|
+
"l3fgrates_index",
|
|
212
|
+
"l3bgrates_index",
|
|
213
|
+
"penfgrates_index",
|
|
214
|
+
"penbgrates_index",
|
|
215
|
+
"ialirtrates_index",
|
|
216
|
+
],
|
|
195
217
|
)
|
|
196
218
|
|
|
197
|
-
#
|
|
198
|
-
l1b_standard_rates_dataset["dynamic_threshold_state"] = raw_counts_dataset[
|
|
199
|
-
"hdr_dynamic_threshold_state"
|
|
200
|
-
]
|
|
201
|
-
l1b_standard_rates_dataset["dynamic_threshold_state"].attrs = raw_counts_dataset[
|
|
202
|
-
"hdr_dynamic_threshold_state"
|
|
203
|
-
].attrs
|
|
204
|
-
|
|
205
|
-
# Define fields from the raw_counts_dataset to calculate standard rates from
|
|
219
|
+
# Define fields from the L1A counts dataset to calculate standard rates from
|
|
206
220
|
standard_rate_fields = [
|
|
207
221
|
"sngrates",
|
|
208
222
|
"coinrates",
|
|
@@ -218,274 +232,204 @@ def process_standard_rates_data(
|
|
|
218
232
|
"l4bgrates",
|
|
219
233
|
]
|
|
220
234
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
235
|
+
for var in standard_rate_fields:
|
|
236
|
+
# Add counts and uncertainty data to the dataset
|
|
237
|
+
l1b_standard_rates_dataset[var] = l1a_counts_dataset[var]
|
|
238
|
+
l1b_standard_rates_dataset[f"{var}_stat_uncert_minus"] = l1a_counts_dataset[
|
|
239
|
+
f"{var}_stat_uncert_minus"
|
|
240
|
+
]
|
|
241
|
+
l1b_standard_rates_dataset[f"{var}_stat_uncert_plus"] = l1a_counts_dataset[
|
|
242
|
+
f"{var}_stat_uncert_plus"
|
|
243
|
+
]
|
|
244
|
+
# Calculate rates using livetime
|
|
245
|
+
l1b_standard_rates_dataset = calculate_rates(
|
|
246
|
+
l1b_standard_rates_dataset, var, livetime
|
|
247
|
+
)
|
|
229
248
|
|
|
230
249
|
return l1b_standard_rates_dataset
|
|
231
250
|
|
|
232
251
|
|
|
233
|
-
def
|
|
252
|
+
def calculate_rates(
|
|
234
253
|
dataset: xr.Dataset,
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
epoch_size: int,
|
|
254
|
+
var: str,
|
|
255
|
+
livetime: xr.DataArray,
|
|
238
256
|
) -> xr.Dataset:
|
|
239
257
|
"""
|
|
240
|
-
|
|
258
|
+
Calculate rates by dividing counts by livetime.
|
|
241
259
|
|
|
242
260
|
Parameters
|
|
243
261
|
----------
|
|
244
262
|
dataset : xr.Dataset
|
|
245
|
-
The dataset
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
he4
|
|
252
|
-
he
|
|
253
|
-
c
|
|
254
|
-
n
|
|
255
|
-
o
|
|
256
|
-
ne
|
|
257
|
-
na
|
|
258
|
-
mg
|
|
259
|
-
al
|
|
260
|
-
si
|
|
261
|
-
s
|
|
262
|
-
ar
|
|
263
|
-
ca
|
|
264
|
-
fe
|
|
265
|
-
ni
|
|
266
|
-
|
|
267
|
-
num_energy_ranges : int
|
|
268
|
-
Number of energy ranges for the particle.
|
|
269
|
-
Used to define the shape of the data arrays.
|
|
270
|
-
|
|
271
|
-
epoch_size : int
|
|
272
|
-
Used to define the shape of the data arrays.
|
|
263
|
+
The L1B dataset containing counts data.
|
|
264
|
+
var : str
|
|
265
|
+
The name of the variable to calculate rates for.
|
|
266
|
+
livetime : xr.DataArray
|
|
267
|
+
1D array of livetime values. Shape equals the
|
|
268
|
+
number of epochs in the dataset.
|
|
273
269
|
|
|
274
270
|
Returns
|
|
275
271
|
-------
|
|
276
|
-
|
|
277
|
-
The dataset with
|
|
272
|
+
xr.Dataset
|
|
273
|
+
The dataset with rates.
|
|
278
274
|
"""
|
|
279
|
-
dataset[f"{
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
name=f"{particle}_delta_minus",
|
|
288
|
-
)
|
|
289
|
-
dataset[f"{particle}_delta_plus"] = xr.DataArray(
|
|
290
|
-
data=np.zeros((epoch_size, num_energy_ranges), dtype=np.float32),
|
|
291
|
-
dims=["epoch", f"{particle}_energy_index"],
|
|
292
|
-
name=f"{particle}_delta_plus",
|
|
293
|
-
)
|
|
294
|
-
dataset.coords[f"{particle}_energy_index"] = xr.DataArray(
|
|
295
|
-
np.arange(num_energy_ranges, dtype=np.int8),
|
|
296
|
-
dims=[f"{particle}_energy_index"],
|
|
297
|
-
name=f"{particle}_energy_index",
|
|
298
|
-
)
|
|
275
|
+
dataset[f"{var}"] = (dataset[f"{var}"] / livetime).astype(np.float32)
|
|
276
|
+
dataset[f"{var}_stat_uncert_minus"] = (
|
|
277
|
+
dataset[f"{var}_stat_uncert_minus"] / livetime
|
|
278
|
+
).astype(np.float32)
|
|
279
|
+
dataset[f"{var}_stat_uncert_plus"] = (
|
|
280
|
+
dataset[f"{var}_stat_uncert_plus"] / livetime
|
|
281
|
+
).astype(np.float32)
|
|
282
|
+
|
|
299
283
|
return dataset
|
|
300
284
|
|
|
301
285
|
|
|
302
|
-
def
|
|
303
|
-
raw_counts_dataset: xr.Dataset, count_indices: dict
|
|
304
|
-
) -> tuple[xr.DataArray, xr.DataArray, xr.DataArray]:
|
|
286
|
+
def sum_livetime_10min(livetime: xr.DataArray) -> xr.DataArray:
|
|
305
287
|
"""
|
|
306
|
-
|
|
288
|
+
Sum livetime values in 10-minute intervals.
|
|
307
289
|
|
|
308
290
|
Parameters
|
|
309
291
|
----------
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
and penfgrates data variables with the particle counts data
|
|
313
|
-
needed for the calculation.
|
|
314
|
-
|
|
315
|
-
count_indices : dict
|
|
316
|
-
A dictionary containing the indices for particle counts to sum for a given
|
|
317
|
-
energy range.
|
|
318
|
-
R2=Indices for L2FGRATES, R3=Indices for L3FGRATES, R4=Indices for PENFGRATES.
|
|
292
|
+
livetime : xr.DataArray
|
|
293
|
+
1D array of livetime values. Shape equals the number of epochs in the dataset.
|
|
319
294
|
|
|
320
295
|
Returns
|
|
321
296
|
-------
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
The summed counts for delta minus uncertainty.
|
|
327
|
-
|
|
328
|
-
summed_counts_delta_plus : xr.DataArray
|
|
329
|
-
The summed counts for delta plus uncertainty.
|
|
297
|
+
xr.DataArray
|
|
298
|
+
Livetime summed over 10-minute intervals. Values repeated for each epoch in the
|
|
299
|
+
10-minute intervals to match the original livetime array shape.
|
|
300
|
+
[5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7].
|
|
330
301
|
"""
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
)
|
|
336
|
-
|
|
337
|
-
summed_counts_delta_minus = (
|
|
338
|
-
raw_counts_dataset["l2fgrates_delta_minus"][:, count_indices["R2"]].sum(axis=1)
|
|
339
|
-
+ raw_counts_dataset["l3fgrates_delta_minus"][:, count_indices["R3"]].sum(
|
|
340
|
-
axis=1
|
|
341
|
-
)
|
|
342
|
-
+ raw_counts_dataset["penfgrates_delta_minus"][:, count_indices["R4"]].sum(
|
|
343
|
-
axis=1
|
|
344
|
-
)
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
summed_counts_delta_plus = (
|
|
348
|
-
raw_counts_dataset["l2fgrates_delta_plus"][:, count_indices["R2"]].sum(axis=1)
|
|
349
|
-
+ raw_counts_dataset["l3fgrates_delta_plus"][:, count_indices["R3"]].sum(axis=1)
|
|
350
|
-
+ raw_counts_dataset["penfgrates_delta_plus"][:, count_indices["R4"]].sum(
|
|
351
|
-
axis=1
|
|
352
|
-
)
|
|
353
|
-
)
|
|
354
|
-
|
|
355
|
-
return summed_counts, summed_counts_delta_minus, summed_counts_delta_plus
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
class SummedCounts(NamedTuple):
|
|
359
|
-
"""A namedtuple to store summed counts and uncertainties."""
|
|
360
|
-
|
|
361
|
-
summed_counts: xr.DataArray
|
|
362
|
-
summed_counts_delta_minus: xr.DataArray
|
|
363
|
-
summed_counts_delta_plus: xr.DataArray
|
|
302
|
+
livetime_10min_sum = [
|
|
303
|
+
livetime[i : i + 10].sum().item() for i in range(0, len(livetime) - 9, 10)
|
|
304
|
+
]
|
|
305
|
+
livetime_expanded = np.repeat(livetime_10min_sum, 10)
|
|
306
|
+
return xr.DataArray(livetime_expanded, dims=livetime.dims, coords=livetime.coords)
|
|
364
307
|
|
|
365
308
|
|
|
366
|
-
def
|
|
367
|
-
|
|
368
|
-
particle: str,
|
|
369
|
-
index: int,
|
|
370
|
-
summed_counts: SummedCounts,
|
|
371
|
-
livetime: xr.DataArray,
|
|
309
|
+
def process_summed_rates_data(
|
|
310
|
+
l1a_counts_dataset: xr.Dataset, livetime: xr.DataArray
|
|
372
311
|
) -> xr.Dataset:
|
|
373
312
|
"""
|
|
374
|
-
|
|
313
|
+
Will process L1B summed rates data from L1A raw counts data.
|
|
314
|
+
|
|
315
|
+
This function calculates summed rates for each particle type and energy range.
|
|
316
|
+
The counts that are summed come from the l2fgrates, l3fgrates, and penfgrates
|
|
317
|
+
data variables in the L1A counts data. These variables represent counts
|
|
318
|
+
of different detector penetration ranges (Range 2, Range 3, and Range 4
|
|
319
|
+
respectively). Only the energy ranges specified in the
|
|
320
|
+
SUMMED_PARTICLE_ENERGY_RANGE_MAPPING dictionary are included in this product.
|
|
375
321
|
|
|
376
|
-
|
|
377
|
-
|
|
322
|
+
The summed rates are calculated by summing the counts for each energy range and
|
|
323
|
+
dividing by the livetime.
|
|
378
324
|
|
|
379
325
|
Parameters
|
|
380
326
|
----------
|
|
381
|
-
|
|
382
|
-
The
|
|
383
|
-
|
|
384
|
-
particle : str
|
|
385
|
-
The abbreviated particle name. Valid names are:
|
|
386
|
-
h
|
|
387
|
-
he3
|
|
388
|
-
he4
|
|
389
|
-
he
|
|
390
|
-
c
|
|
391
|
-
n
|
|
392
|
-
o
|
|
393
|
-
ne
|
|
394
|
-
na
|
|
395
|
-
mg
|
|
396
|
-
al
|
|
397
|
-
si
|
|
398
|
-
s
|
|
399
|
-
ar
|
|
400
|
-
ca
|
|
401
|
-
fe
|
|
402
|
-
ni
|
|
403
|
-
|
|
404
|
-
index : int
|
|
405
|
-
The index of the energy range.
|
|
406
|
-
|
|
407
|
-
summed_counts : namedtuple
|
|
408
|
-
A namedtuple containing the summed counts.
|
|
409
|
-
SummedCounts(summed_counts, summed_counts_delta_minus,
|
|
410
|
-
summed_counts_delta_plus).
|
|
327
|
+
l1a_counts_dataset : xr.Dataset
|
|
328
|
+
The L1A counts dataset.
|
|
411
329
|
|
|
412
330
|
livetime : xr.DataArray
|
|
413
|
-
1D array of livetime values
|
|
331
|
+
1D array of livetime values calculated from the livetime counter.
|
|
332
|
+
Shape equals the number of epochs in the dataset.
|
|
414
333
|
|
|
415
334
|
Returns
|
|
416
335
|
-------
|
|
417
|
-
|
|
418
|
-
The
|
|
336
|
+
xr.Dataset
|
|
337
|
+
The processed L1B summed rates dataset.
|
|
419
338
|
"""
|
|
420
|
-
dataset
|
|
421
|
-
|
|
339
|
+
# Initialize the L1B summed rates dataset with coordinates from the L1A dataset
|
|
340
|
+
l1b_summed_rates_dataset = initialize_l1b_dataset(
|
|
341
|
+
l1a_counts_dataset, coords=["epoch"]
|
|
422
342
|
)
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
343
|
+
|
|
344
|
+
for particle, energy_ranges in SUMMED_PARTICLE_ENERGY_RANGE_MAPPING.items():
|
|
345
|
+
# Sum counts for each energy range and add to dataset
|
|
346
|
+
l1b_summed_rates_dataset = add_summed_particle_data_to_dataset(
|
|
347
|
+
l1b_summed_rates_dataset,
|
|
348
|
+
l1a_counts_dataset,
|
|
349
|
+
particle,
|
|
350
|
+
energy_ranges,
|
|
351
|
+
)
|
|
352
|
+
# Calculate rates using livetime
|
|
353
|
+
l1b_summed_rates_dataset = calculate_rates(
|
|
354
|
+
l1b_summed_rates_dataset, particle, livetime
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
return l1b_summed_rates_dataset
|
|
430
358
|
|
|
431
359
|
|
|
432
|
-
def
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
energy_min_values: np.ndarray,
|
|
436
|
-
energy_max_values: np.ndarray,
|
|
437
|
-
) -> xr.Dataset:
|
|
360
|
+
def subset_data_for_sectored_counts(
|
|
361
|
+
l1a_counts_dataset: xr.Dataset, livetime: xr.DataArray
|
|
362
|
+
) -> tuple[xr.Dataset, xr.DataArray]:
|
|
438
363
|
"""
|
|
439
|
-
|
|
364
|
+
Subset data for complete sets of sectored counts and corresponding livetime values.
|
|
365
|
+
|
|
366
|
+
A set of sectored data starts with hydrogen and ends with iron and correspond to
|
|
367
|
+
the mod 10 values 0-9. The livetime values from the previous 10 minutes are used
|
|
368
|
+
to calculate the rates for each set since those counts are transmitted 10 minutes
|
|
369
|
+
after they were collected.
|
|
440
370
|
|
|
441
371
|
Parameters
|
|
442
372
|
----------
|
|
443
|
-
|
|
444
|
-
The
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
energy_min_values : np.ndarray
|
|
448
|
-
The minimum energy values for each energy range.
|
|
449
|
-
energy_max_values : np.ndarray
|
|
450
|
-
The maximum energy values for each energy range.
|
|
373
|
+
l1a_counts_dataset : xr.Dataset
|
|
374
|
+
The L1A counts dataset.
|
|
375
|
+
livetime : xr.DataArray
|
|
376
|
+
1D array of livetime values calculated from the livetime counter.
|
|
451
377
|
|
|
452
378
|
Returns
|
|
453
379
|
-------
|
|
454
|
-
xr.Dataset
|
|
455
|
-
|
|
380
|
+
tuple[xr.Dataset, xr.DataArray]
|
|
381
|
+
Subsetted L1A counts dataset and corresponding livetime values.
|
|
456
382
|
"""
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
name=f"{particle}_energy_max",
|
|
383
|
+
# Identify 10-minute intervals of complete sectored counts.
|
|
384
|
+
bin_size = 10
|
|
385
|
+
mod_10 = l1a_counts_dataset.hdr_minute_cnt.values % 10
|
|
386
|
+
pattern = np.arange(bin_size)
|
|
387
|
+
|
|
388
|
+
# Use sliding windows to find pattern matches
|
|
389
|
+
matches = np.all(
|
|
390
|
+
np.lib.stride_tricks.sliding_window_view(mod_10, bin_size) == pattern, axis=1
|
|
466
391
|
)
|
|
467
|
-
|
|
392
|
+
start_indices = np.where(matches)[0]
|
|
468
393
|
|
|
394
|
+
# Filter out start indices that are less than or equal to the bin size
|
|
395
|
+
# since the previous 10 minutes are needed
|
|
396
|
+
start_indices = start_indices[start_indices > bin_size]
|
|
397
|
+
data_slice = slice(start_indices[0], start_indices[-1] + bin_size)
|
|
469
398
|
|
|
470
|
-
|
|
471
|
-
|
|
399
|
+
# Subset data to include only complete sets of sectored counts
|
|
400
|
+
l1b_sectored_rates_dataset = l1a_counts_dataset.isel(epoch=data_slice)
|
|
401
|
+
|
|
402
|
+
# Subset livetime staggered from sectored counts by 10 minutes
|
|
403
|
+
livetime_slice = slice(start_indices[0] - bin_size, start_indices[-1])
|
|
404
|
+
livetime = livetime[livetime_slice]
|
|
405
|
+
|
|
406
|
+
return l1b_sectored_rates_dataset, livetime
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def process_sectored_rates_data(
|
|
410
|
+
l1a_counts_dataset: xr.Dataset, livetime: xr.DataArray
|
|
472
411
|
) -> xr.Dataset:
|
|
473
412
|
"""
|
|
474
|
-
Will process L1B
|
|
413
|
+
Will process L1B sectored rates data from L1A raw counts data.
|
|
475
414
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
data variables in the L1A counts data. These variables represent counts
|
|
479
|
-
of different detector penetration ranges (Range 2, Range 3, and Range 4
|
|
480
|
-
respectively). Only the energy ranges specified in the
|
|
481
|
-
PARTICLE_ENERGY_RANGE_MAPPING dictionary are included in this product.
|
|
415
|
+
A complete set of sectored counts is taken over 10 science frames (10 minutes)
|
|
416
|
+
where each science frame contains counts for one species and energy range.
|
|
482
417
|
|
|
483
|
-
|
|
484
|
-
|
|
418
|
+
Species and energy ranges are as follows:
|
|
419
|
+
|
|
420
|
+
H 1.8 - 3.6 MeV, 4.0 - 6.0 MeV, 6.0 - 10 MeV
|
|
421
|
+
4He 4.0 - 6.0 MeV, 6.0 - 12.0 MeV
|
|
422
|
+
CNO 4.0 - 6.0 MeV, 6.0 - 12.0 MeV
|
|
423
|
+
NeMgSi 4.0 - 6.0 MeV, 6.0 - 12.0 MeV
|
|
424
|
+
Fe 4.0 - 12.0 MeV
|
|
425
|
+
|
|
426
|
+
Sectored counts data is transmitted 10 minutes after they are collected.
|
|
427
|
+
To calculate rates, the sectored counts over 10 minutes need to be divided by
|
|
428
|
+
the sum of livetime values from the previous 10 minutes.
|
|
485
429
|
|
|
486
430
|
Parameters
|
|
487
431
|
----------
|
|
488
|
-
|
|
432
|
+
l1a_counts_dataset : xr.Dataset
|
|
489
433
|
The L1A counts dataset.
|
|
490
434
|
|
|
491
435
|
livetime : xr.DataArray
|
|
@@ -495,63 +439,80 @@ def process_summed_rates_data(
|
|
|
495
439
|
Returns
|
|
496
440
|
-------
|
|
497
441
|
xr.Dataset
|
|
498
|
-
The processed L1B
|
|
442
|
+
The processed L1B sectored rates dataset.
|
|
499
443
|
"""
|
|
500
|
-
#
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
#
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
#
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
"
|
|
444
|
+
# TODO
|
|
445
|
+
# -filter by epoch values in day being processed.
|
|
446
|
+
# middle epoch (or mod 5 value for 6th frame)
|
|
447
|
+
# -consider refactoring calculate_rates function to handle sectored rates
|
|
448
|
+
|
|
449
|
+
# Define particles and coordinates
|
|
450
|
+
particles = ["h", "he4", "cno", "nemgsi", "fe"]
|
|
451
|
+
|
|
452
|
+
# Extract relevant data variable names that start with a particle name
|
|
453
|
+
data_vars = [
|
|
454
|
+
str(var)
|
|
455
|
+
for var in l1a_counts_dataset.data_vars
|
|
456
|
+
if any(str(var).startswith(f"{p}_") for p in particles)
|
|
513
457
|
]
|
|
514
|
-
l1b_summed_rates_dataset["dynamic_threshold_state"].attrs = raw_counts_dataset[
|
|
515
|
-
"hdr_dynamic_threshold_state"
|
|
516
|
-
].attrs
|
|
517
|
-
|
|
518
|
-
# Calculate summed rates for each particle and add them to the dataset
|
|
519
|
-
for particle, energy_ranges in PARTICLE_ENERGY_RANGE_MAPPING.items():
|
|
520
|
-
l1b_summed_rates_dataset = create_particle_data_arrays(
|
|
521
|
-
l1b_summed_rates_dataset,
|
|
522
|
-
particle,
|
|
523
|
-
len(energy_ranges),
|
|
524
|
-
raw_counts_dataset.sizes["epoch"],
|
|
525
|
-
)
|
|
526
458
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
for i, energy_range in enumerate(energy_ranges):
|
|
532
|
-
summed_counts, summed_counts_delta_minus, summed_counts_delta_plus = (
|
|
533
|
-
calculate_summed_counts(raw_counts_dataset, energy_range)
|
|
534
|
-
)
|
|
459
|
+
# Subset data for complete sets of sectored counts and corresponding livetime values
|
|
460
|
+
l1a_counts_dataset, livetime = subset_data_for_sectored_counts(
|
|
461
|
+
l1a_counts_dataset, livetime
|
|
462
|
+
)
|
|
535
463
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
464
|
+
# Sum livetime over 10 minute intervals
|
|
465
|
+
livetime_10min = sum_livetime_10min(livetime)
|
|
466
|
+
|
|
467
|
+
# Initialize the L1B dataset with coordinates from the subset L1A dataset
|
|
468
|
+
l1b_sectored_rates_dataset = initialize_l1b_dataset(
|
|
469
|
+
l1a_counts_dataset,
|
|
470
|
+
coords=[
|
|
471
|
+
"epoch",
|
|
472
|
+
"declination",
|
|
473
|
+
"azimuth",
|
|
474
|
+
"h_energy_mean",
|
|
475
|
+
"he4_energy_mean",
|
|
476
|
+
"cno_energy_mean",
|
|
477
|
+
"nemgsi_energy_mean",
|
|
478
|
+
"fe_energy_mean",
|
|
479
|
+
],
|
|
480
|
+
)
|
|
540
481
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
482
|
+
# Dictionary to store variable rename mappings for L1B dataset
|
|
483
|
+
rename_map = {}
|
|
484
|
+
|
|
485
|
+
# # Compute rates, skipping fill values, and add to the L1B dataset
|
|
486
|
+
for var in data_vars:
|
|
487
|
+
if "sectored_counts" in var:
|
|
488
|
+
# Determine the new variable name for the L1B dataset
|
|
489
|
+
if "_sectored_counts" in var:
|
|
490
|
+
new_var = var.replace("_sectored_counts", "")
|
|
491
|
+
else:
|
|
492
|
+
new_var = None
|
|
493
|
+
if new_var:
|
|
494
|
+
rename_map[var] = new_var
|
|
495
|
+
|
|
496
|
+
# Since epoch times don't align, convert xarray data arrays to numpy arrays
|
|
497
|
+
# to avoid rates being calculated along the epoch dimension.
|
|
498
|
+
# Reshape livetime to match 4D shape of counts.
|
|
499
|
+
counts = l1a_counts_dataset[var].values
|
|
500
|
+
livetime_10min_reshaped = livetime_10min.values[:, None, None, None]
|
|
501
|
+
rates = xr.DataArray(
|
|
502
|
+
np.where(
|
|
503
|
+
counts != FILLVAL_INT64,
|
|
504
|
+
(counts / livetime_10min_reshaped).astype(np.float32),
|
|
505
|
+
FILLVAL_FLOAT32,
|
|
506
|
+
),
|
|
507
|
+
dims=l1a_counts_dataset[var].dims,
|
|
551
508
|
)
|
|
509
|
+
l1b_sectored_rates_dataset[var] = rates
|
|
510
|
+
else:
|
|
511
|
+
# Add other data variables to the dataset
|
|
512
|
+
l1b_sectored_rates_dataset[var] = l1a_counts_dataset[var]
|
|
552
513
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
)
|
|
514
|
+
# Rename variables in L1B dataset
|
|
515
|
+
if rename_map:
|
|
516
|
+
l1b_sectored_rates_dataset = l1b_sectored_rates_dataset.rename(rename_map)
|
|
556
517
|
|
|
557
|
-
return
|
|
518
|
+
return l1b_sectored_rates_dataset
|