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
|
@@ -3,17 +3,20 @@
|
|
|
3
3
|
# TODO: Come back and add in FSW logic.
|
|
4
4
|
import logging
|
|
5
5
|
from enum import Enum
|
|
6
|
-
from typing import ClassVar
|
|
7
6
|
|
|
8
7
|
import numpy as np
|
|
8
|
+
import pandas
|
|
9
9
|
import xarray
|
|
10
10
|
from numpy import ndarray
|
|
11
11
|
from numpy.typing import NDArray
|
|
12
|
+
from scipy.interpolate import LinearNDInterpolator, RegularGridInterpolator
|
|
12
13
|
|
|
13
14
|
from imap_processing.spice.spin import get_spin_data
|
|
14
15
|
from imap_processing.ultra.constants import UltraConstants
|
|
15
16
|
from imap_processing.ultra.l1b.lookup_utils import (
|
|
17
|
+
get_angular_profiles,
|
|
16
18
|
get_back_position,
|
|
19
|
+
get_energy_efficiencies,
|
|
17
20
|
get_energy_norm,
|
|
18
21
|
get_image_params,
|
|
19
22
|
get_norm,
|
|
@@ -35,8 +38,8 @@ class StopType(Enum):
|
|
|
35
38
|
|
|
36
39
|
Top = 1
|
|
37
40
|
Bottom = 2
|
|
38
|
-
PH
|
|
39
|
-
SSD
|
|
41
|
+
PH = [1, 2] # noqa RUF012 mutable class attribute
|
|
42
|
+
SSD = [8, 9, 10, 11, 12, 13, 14, 15] # noqa RUF012 mutable class attribute
|
|
40
43
|
|
|
41
44
|
|
|
42
45
|
class CoinType(Enum):
|
|
@@ -46,14 +49,16 @@ class CoinType(Enum):
|
|
|
46
49
|
Bottom = 2
|
|
47
50
|
|
|
48
51
|
|
|
49
|
-
def get_front_x_position(
|
|
52
|
+
def get_front_x_position(
|
|
53
|
+
start_type: ndarray, start_position_tdc: ndarray, sensor: str
|
|
54
|
+
) -> ndarray:
|
|
50
55
|
"""
|
|
51
56
|
Calculate the front xf position.
|
|
52
57
|
|
|
53
58
|
Converts Start Position Time to Digital Converter (TDC)
|
|
54
59
|
values into units of hundredths of a millimeter using a scale factor and offsets.
|
|
55
60
|
Further description is available on pages 30 of
|
|
56
|
-
IMAP-Ultra Flight Software Specification document
|
|
61
|
+
IMAP-Ultra Flight Software Specification document.
|
|
57
62
|
|
|
58
63
|
Parameters
|
|
59
64
|
----------
|
|
@@ -61,6 +66,8 @@ def get_front_x_position(start_type: ndarray, start_position_tdc: ndarray) -> nd
|
|
|
61
66
|
Start Type: 1=Left, 2=Right.
|
|
62
67
|
start_position_tdc : ndarray
|
|
63
68
|
Start Position Time to Digital Converter (TDC).
|
|
69
|
+
sensor : str
|
|
70
|
+
Sensor name.
|
|
64
71
|
|
|
65
72
|
Returns
|
|
66
73
|
-------
|
|
@@ -70,9 +77,9 @@ def get_front_x_position(start_type: ndarray, start_position_tdc: ndarray) -> nd
|
|
|
70
77
|
# Left and right start types.
|
|
71
78
|
indices = np.nonzero((start_type == 1) | (start_type == 2))
|
|
72
79
|
|
|
73
|
-
xftsc = get_image_params("XFTSC")
|
|
74
|
-
xft_lt_off = get_image_params("XFTLTOFF")
|
|
75
|
-
xft_rt_off = get_image_params("XFTRTOFF")
|
|
80
|
+
xftsc = get_image_params("XFTSC", sensor)
|
|
81
|
+
xft_lt_off = get_image_params("XFTLTOFF", sensor)
|
|
82
|
+
xft_rt_off = get_image_params("XFTRTOFF", sensor)
|
|
76
83
|
xft_off = np.where(start_type[indices] == 1, xft_lt_off, xft_rt_off)
|
|
77
84
|
|
|
78
85
|
# Calculate xf and convert to hundredths of a millimeter
|
|
@@ -158,8 +165,7 @@ def get_ph_tof_and_back_positions(
|
|
|
158
165
|
The Time Of Flight (tof) and the position of the particle at the
|
|
159
166
|
back of the sensor are measured using the timing of the pulses.
|
|
160
167
|
Further description is available on pages 32-33 of
|
|
161
|
-
IMAP-Ultra Flight Software Specification document
|
|
162
|
-
(7523-9009_Rev_-.pdf).
|
|
168
|
+
IMAP-Ultra Flight Software Specification document.
|
|
163
169
|
|
|
164
170
|
Parameters
|
|
165
171
|
----------
|
|
@@ -183,7 +189,7 @@ def get_ph_tof_and_back_positions(
|
|
|
183
189
|
Back positions in y direction (hundredths of a millimeter).
|
|
184
190
|
"""
|
|
185
191
|
indices = np.nonzero(
|
|
186
|
-
np.isin(de_dataset["
|
|
192
|
+
np.isin(de_dataset["stop_type"], [StopType.Top.value, StopType.Bottom.value])
|
|
187
193
|
)[0]
|
|
188
194
|
de_filtered = de_dataset.isel(epoch=indices)
|
|
189
195
|
|
|
@@ -191,10 +197,10 @@ def get_ph_tof_and_back_positions(
|
|
|
191
197
|
|
|
192
198
|
# There are mismatches between the stop TDCs, i.e., SpN, SpS, SpE, and SpW.
|
|
193
199
|
# This normalizes the TDCs
|
|
194
|
-
sp_n_norm = get_norm(de_filtered["
|
|
195
|
-
sp_s_norm = get_norm(de_filtered["
|
|
196
|
-
sp_e_norm = get_norm(de_filtered["
|
|
197
|
-
sp_w_norm = get_norm(de_filtered["
|
|
200
|
+
sp_n_norm = get_norm(de_filtered["stop_north_tdc"].data, "SpN", sensor)
|
|
201
|
+
sp_s_norm = get_norm(de_filtered["stop_south_tdc"].data, "SpS", sensor)
|
|
202
|
+
sp_e_norm = get_norm(de_filtered["stop_east_tdc"].data, "SpE", sensor)
|
|
203
|
+
sp_w_norm = get_norm(de_filtered["stop_west_tdc"].data, "SpW", sensor)
|
|
198
204
|
|
|
199
205
|
# Convert normalized TDC values into units of hundredths of a
|
|
200
206
|
# millimeter using lookup tables.
|
|
@@ -220,20 +226,20 @@ def get_ph_tof_and_back_positions(
|
|
|
220
226
|
# Stop Type: 1=Top, 2=Bottom
|
|
221
227
|
# Convert converts normalized TDC values into units of
|
|
222
228
|
# hundredths of a millimeter using lookup tables.
|
|
223
|
-
stop_type_top = de_filtered["
|
|
229
|
+
stop_type_top = de_filtered["stop_type"].data == StopType.Top.value
|
|
224
230
|
xb[stop_type_top] = get_back_position(xb_index[stop_type_top], "XBkTp", sensor)
|
|
225
231
|
yb[stop_type_top] = get_back_position(yb_index[stop_type_top], "YBkTp", sensor)
|
|
226
232
|
|
|
227
233
|
# Correction for the propagation delay of the start anode and other effects.
|
|
228
|
-
t2[stop_type_top] = get_image_params("TOFSC") * t1[
|
|
234
|
+
t2[stop_type_top] = get_image_params("TOFSC", sensor) * t1[
|
|
229
235
|
stop_type_top
|
|
230
|
-
] + get_image_params("TOFTPOFF")
|
|
236
|
+
] + get_image_params("TOFTPOFF", sensor)
|
|
231
237
|
# Variable xf_ph divided by 10 to convert to mm.
|
|
232
238
|
tof[stop_type_top] = t2[stop_type_top] + xf_ph[
|
|
233
239
|
stop_type_top
|
|
234
|
-
] / 10 * get_image_params("XFTTOF")
|
|
240
|
+
] / 10 * get_image_params("XFTTOF", sensor)
|
|
235
241
|
|
|
236
|
-
stop_type_bottom = de_filtered["
|
|
242
|
+
stop_type_bottom = de_filtered["stop_type"].data == StopType.Bottom.value
|
|
237
243
|
xb[stop_type_bottom] = get_back_position(
|
|
238
244
|
xb_index[stop_type_bottom], "XBkBt", sensor
|
|
239
245
|
)
|
|
@@ -242,14 +248,14 @@ def get_ph_tof_and_back_positions(
|
|
|
242
248
|
)
|
|
243
249
|
|
|
244
250
|
# Correction for the propagation delay of the start anode and other effects.
|
|
245
|
-
t2[stop_type_bottom] = get_image_params("TOFSC") * t1[
|
|
251
|
+
t2[stop_type_bottom] = get_image_params("TOFSC", sensor) * t1[
|
|
246
252
|
stop_type_bottom
|
|
247
|
-
] + get_image_params("TOFBTOFF") # 10*ns
|
|
253
|
+
] + get_image_params("TOFBTOFF", sensor) # 10*ns
|
|
248
254
|
|
|
249
255
|
# Variable xf_ph divided by 10 to convert to mm.
|
|
250
256
|
tof[stop_type_bottom] = t2[stop_type_bottom] + xf_ph[
|
|
251
257
|
stop_type_bottom
|
|
252
|
-
] / 10 * get_image_params("XFTTOF")
|
|
258
|
+
] / 10 * get_image_params("XFTTOF", sensor)
|
|
253
259
|
|
|
254
260
|
return tof, t2, xb, yb
|
|
255
261
|
|
|
@@ -284,7 +290,7 @@ def get_path_length(
|
|
|
284
290
|
|
|
285
291
|
|
|
286
292
|
def get_ssd_back_position_and_tof_offset(
|
|
287
|
-
de_dataset: xarray.Dataset,
|
|
293
|
+
de_dataset: xarray.Dataset, sensor: str
|
|
288
294
|
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
289
295
|
"""
|
|
290
296
|
Lookup the Y SSD positions (yb), TOF Offset, and SSD number.
|
|
@@ -293,6 +299,8 @@ def get_ssd_back_position_and_tof_offset(
|
|
|
293
299
|
----------
|
|
294
300
|
de_dataset : xarray.Dataset
|
|
295
301
|
The input dataset containing STOP_TYPE and SSD_FLAG data.
|
|
302
|
+
sensor : str
|
|
303
|
+
Sensor name.
|
|
296
304
|
|
|
297
305
|
Returns
|
|
298
306
|
-------
|
|
@@ -307,7 +315,7 @@ def get_ssd_back_position_and_tof_offset(
|
|
|
307
315
|
-----
|
|
308
316
|
The X back position (xb) is assumed to be 0 for SSD.
|
|
309
317
|
"""
|
|
310
|
-
indices = np.nonzero(np.isin(de_dataset["
|
|
318
|
+
indices = np.nonzero(np.isin(de_dataset["stop_type"], StopType.SSD.value))[0]
|
|
311
319
|
de_filtered = de_dataset.isel(epoch=indices)
|
|
312
320
|
|
|
313
321
|
yb = np.zeros(len(indices), dtype=np.float64)
|
|
@@ -315,18 +323,18 @@ def get_ssd_back_position_and_tof_offset(
|
|
|
315
323
|
tof_offset = np.zeros(len(indices), dtype=np.float64)
|
|
316
324
|
|
|
317
325
|
for i in range(8):
|
|
318
|
-
ssd_flag_mask = de_filtered[f"
|
|
326
|
+
ssd_flag_mask = de_filtered[f"ssd_flag_{i}"].data == 1
|
|
319
327
|
|
|
320
328
|
# Multiply ybs times 100 to convert to hundredths of a millimeter.
|
|
321
|
-
yb[ssd_flag_mask] = get_image_params(f"YBKSSD{i}") * 100
|
|
329
|
+
yb[ssd_flag_mask] = get_image_params(f"YBKSSD{i}", sensor) * 100
|
|
322
330
|
ssd_number[ssd_flag_mask] = i
|
|
323
331
|
|
|
324
332
|
tof_offset[
|
|
325
|
-
(de_filtered["
|
|
326
|
-
] = get_image_params(f"TOFSSDLTOFF{i}")
|
|
333
|
+
(de_filtered["start_type"] == StartType.Left.value) & ssd_flag_mask
|
|
334
|
+
] = get_image_params(f"TOFSSDLTOFF{i}", sensor)
|
|
327
335
|
tof_offset[
|
|
328
|
-
(de_filtered["
|
|
329
|
-
] = get_image_params(f"TOFSSDRTOFF{i}")
|
|
336
|
+
(de_filtered["start_type"] == StartType.Right.value) & ssd_flag_mask
|
|
337
|
+
] = get_image_params(f"TOFSSDRTOFF{i}", sensor)
|
|
330
338
|
|
|
331
339
|
return yb, tof_offset, ssd_number
|
|
332
340
|
|
|
@@ -357,17 +365,17 @@ def calculate_etof_xc(
|
|
|
357
365
|
X coincidence position (millimeters).
|
|
358
366
|
"""
|
|
359
367
|
# CoinNNorm
|
|
360
|
-
coin_n_norm = get_norm(de_subset["
|
|
368
|
+
coin_n_norm = get_norm(de_subset["coin_north_tdc"], "CoinN", sensor)
|
|
361
369
|
# CoinSNorm
|
|
362
|
-
coin_s_norm = get_norm(de_subset["
|
|
363
|
-
xc = get_image_params(f"XCOIN{location}SC") * (
|
|
370
|
+
coin_s_norm = get_norm(de_subset["coin_south_tdc"], "CoinS", sensor)
|
|
371
|
+
xc = get_image_params(f"XCOIN{location}SC", sensor) * (
|
|
364
372
|
coin_s_norm - coin_n_norm
|
|
365
|
-
) + get_image_params(f"XCOIN{location}OFF") # millimeter
|
|
373
|
+
) + get_image_params(f"XCOIN{location}OFF", sensor) # millimeter
|
|
366
374
|
|
|
367
375
|
# Time for the electrons to travel back to coincidence anode.
|
|
368
|
-
t2 = get_image_params("ETOFSC") * (
|
|
369
|
-
|
|
370
|
-
)
|
|
376
|
+
t2 = get_image_params("ETOFSC", sensor) * (
|
|
377
|
+
coin_n_norm + coin_s_norm
|
|
378
|
+
) + get_image_params(f"ETOF{location}OFF", sensor)
|
|
371
379
|
|
|
372
380
|
# Multiply by 10 to convert to tenths of a nanosecond.
|
|
373
381
|
etof = t2 * 10 - particle_tof
|
|
@@ -389,8 +397,7 @@ def get_coincidence_positions(
|
|
|
389
397
|
back to the coincidence anode.
|
|
390
398
|
|
|
391
399
|
Further description is available on pages 34-35 of
|
|
392
|
-
IMAP-Ultra Flight Software Specification document
|
|
393
|
-
(7523-9009_Rev_-.pdf).
|
|
400
|
+
IMAP-Ultra Flight Software Specification document.
|
|
394
401
|
|
|
395
402
|
Parameters
|
|
396
403
|
----------
|
|
@@ -410,16 +417,16 @@ def get_coincidence_positions(
|
|
|
410
417
|
xc : np.ndarray
|
|
411
418
|
X coincidence position (hundredths of a millimeter).
|
|
412
419
|
"""
|
|
413
|
-
index_top = np.nonzero(np.isin(de_dataset["
|
|
420
|
+
index_top = np.nonzero(np.isin(de_dataset["coin_type"], CoinType.Top.value))[0]
|
|
414
421
|
de_top = de_dataset.isel(epoch=index_top)
|
|
415
422
|
|
|
416
|
-
index_bottom = np.nonzero(np.isin(de_dataset["
|
|
423
|
+
index_bottom = np.nonzero(np.isin(de_dataset["coin_type"], CoinType.Bottom.value))[
|
|
417
424
|
0
|
|
418
425
|
]
|
|
419
426
|
de_bottom = de_dataset.isel(epoch=index_bottom)
|
|
420
427
|
|
|
421
|
-
etof = np.zeros(len(de_dataset["
|
|
422
|
-
xc_array = np.zeros(len(de_dataset["
|
|
428
|
+
etof = np.zeros(len(de_dataset["coin_type"]), dtype=np.float64)
|
|
429
|
+
xc_array = np.zeros(len(de_dataset["coin_type"]), dtype=np.float64)
|
|
423
430
|
|
|
424
431
|
# Normalized TDCs
|
|
425
432
|
# For the stop anode, there are mismatches between the coincidence TDCs,
|
|
@@ -443,7 +450,7 @@ def get_de_velocity(
|
|
|
443
450
|
back_position: tuple[NDArray, NDArray],
|
|
444
451
|
d: np.ndarray,
|
|
445
452
|
tof: np.ndarray,
|
|
446
|
-
) -> NDArray:
|
|
453
|
+
) -> tuple[NDArray, NDArray, NDArray]:
|
|
447
454
|
"""
|
|
448
455
|
Determine the direct event velocity.
|
|
449
456
|
|
|
@@ -462,6 +469,10 @@ def get_de_velocity(
|
|
|
462
469
|
-------
|
|
463
470
|
velocities : np.ndarray
|
|
464
471
|
N x 3 array of velocity components (vx, vy, vz) in km/s.
|
|
472
|
+
v_hat : np.ndarray
|
|
473
|
+
Unit vector in the direction of the velocity.
|
|
474
|
+
r_hat : np.ndarray
|
|
475
|
+
Position vector.
|
|
465
476
|
"""
|
|
466
477
|
if tof[tof < 0].any():
|
|
467
478
|
logger.info("Negative tof values found.")
|
|
@@ -483,10 +494,15 @@ def get_de_velocity(
|
|
|
483
494
|
|
|
484
495
|
velocities = np.vstack((v_x, v_y, v_z)).T
|
|
485
496
|
|
|
486
|
-
|
|
497
|
+
v_hat = velocities / np.linalg.norm(velocities, axis=1)[:, None]
|
|
498
|
+
r_hat = -v_hat
|
|
499
|
+
|
|
500
|
+
return velocities, v_hat, r_hat
|
|
487
501
|
|
|
488
502
|
|
|
489
|
-
def get_ssd_tof(
|
|
503
|
+
def get_ssd_tof(
|
|
504
|
+
de_dataset: xarray.Dataset, xf: np.ndarray, sensor: str
|
|
505
|
+
) -> NDArray[np.float64]:
|
|
490
506
|
"""
|
|
491
507
|
Calculate back xb, yb position for the SSDs.
|
|
492
508
|
|
|
@@ -501,8 +517,7 @@ def get_ssd_tof(de_dataset: xarray.Dataset, xf: np.ndarray) -> NDArray[np.float6
|
|
|
501
517
|
A scale factor and offsets, and a multiplier convert xf to a tof offset.
|
|
502
518
|
|
|
503
519
|
Further description is available on pages 36 of
|
|
504
|
-
IMAP-Ultra Flight Software Specification document
|
|
505
|
-
(7523-9009_Rev_-.pdf).
|
|
520
|
+
IMAP-Ultra Flight Software Specification document.
|
|
506
521
|
|
|
507
522
|
Parameters
|
|
508
523
|
----------
|
|
@@ -510,25 +525,27 @@ def get_ssd_tof(de_dataset: xarray.Dataset, xf: np.ndarray) -> NDArray[np.float6
|
|
|
510
525
|
Data in xarray format.
|
|
511
526
|
xf : np.array
|
|
512
527
|
Front x position (hundredths of a millimeter).
|
|
528
|
+
sensor : str
|
|
529
|
+
Sensor name.
|
|
513
530
|
|
|
514
531
|
Returns
|
|
515
532
|
-------
|
|
516
533
|
tof : np.ndarray
|
|
517
534
|
Time of flight (tenths of a nanosecond).
|
|
518
535
|
"""
|
|
519
|
-
_, tof_offset, ssd_number = get_ssd_back_position_and_tof_offset(de_dataset)
|
|
520
|
-
indices = np.nonzero(np.isin(de_dataset["
|
|
536
|
+
_, tof_offset, ssd_number = get_ssd_back_position_and_tof_offset(de_dataset, sensor)
|
|
537
|
+
indices = np.nonzero(np.isin(de_dataset["stop_type"], [StopType.SSD.value]))[0]
|
|
521
538
|
|
|
522
|
-
de_discrete = de_dataset.isel(epoch=indices)["
|
|
539
|
+
de_discrete = de_dataset.isel(epoch=indices)["coin_discrete_tdc"]
|
|
523
540
|
|
|
524
|
-
time = get_image_params("TOFSSDSC") * de_discrete.values + tof_offset
|
|
541
|
+
time = get_image_params("TOFSSDSC", sensor) * de_discrete.values + tof_offset
|
|
525
542
|
|
|
526
543
|
# The scale factor and offsets, and a multiplier to convert xf to a tof offset.
|
|
527
544
|
# Convert xf to mm by dividing by 100.
|
|
528
545
|
tof = (
|
|
529
546
|
time
|
|
530
|
-
+ get_image_params("TOFSSDTOTOFF")
|
|
531
|
-
+ xf[indices] / 100 * get_image_params("XFTTOF")
|
|
547
|
+
+ get_image_params("TOFSSDTOTOFF", sensor)
|
|
548
|
+
+ xf[indices] / 100 * get_image_params("XFTTOF", sensor)
|
|
532
549
|
) * 10
|
|
533
550
|
|
|
534
551
|
# Convert TOF to tenths of a nanosecond.
|
|
@@ -555,7 +572,7 @@ def get_de_energy_kev(v: np.ndarray, species: np.ndarray) -> NDArray:
|
|
|
555
572
|
# Compute the sum of squares.
|
|
556
573
|
v2 = np.sum(vv**2, axis=1)
|
|
557
574
|
|
|
558
|
-
index_hydrogen = np.where(species ==
|
|
575
|
+
index_hydrogen = np.where(species == 1)
|
|
559
576
|
energy = np.full_like(v2, np.nan)
|
|
560
577
|
|
|
561
578
|
# 1/2 mv^2 in Joules, convert to keV
|
|
@@ -567,7 +584,11 @@ def get_de_energy_kev(v: np.ndarray, species: np.ndarray) -> NDArray:
|
|
|
567
584
|
|
|
568
585
|
|
|
569
586
|
def get_energy_pulse_height(
|
|
570
|
-
stop_type: np.ndarray,
|
|
587
|
+
stop_type: np.ndarray,
|
|
588
|
+
energy: np.ndarray,
|
|
589
|
+
xb: np.ndarray,
|
|
590
|
+
yb: np.ndarray,
|
|
591
|
+
sensor: str,
|
|
571
592
|
) -> NDArray[np.float64]:
|
|
572
593
|
"""
|
|
573
594
|
Calculate the pulse-height energy.
|
|
@@ -576,8 +597,7 @@ def get_energy_pulse_height(
|
|
|
576
597
|
pulse height from the stop anode.
|
|
577
598
|
Lookup tables (lut) are used for corrections.
|
|
578
599
|
Further description is available on pages 40-41 of
|
|
579
|
-
IMAP-Ultra Flight Software Specification document
|
|
580
|
-
(7523-9009_Rev_-.pdf).
|
|
600
|
+
IMAP-Ultra Flight Software Specification document.
|
|
581
601
|
|
|
582
602
|
Parameters
|
|
583
603
|
----------
|
|
@@ -589,6 +609,8 @@ def get_energy_pulse_height(
|
|
|
589
609
|
X back position (hundredths of a millimeter).
|
|
590
610
|
yb : np.ndarray
|
|
591
611
|
Y back position (hundredths of a millimeter).
|
|
612
|
+
sensor : str
|
|
613
|
+
Sensor name.
|
|
592
614
|
|
|
593
615
|
Returns
|
|
594
616
|
-------
|
|
@@ -612,12 +634,12 @@ def get_energy_pulse_height(
|
|
|
612
634
|
|
|
613
635
|
# TODO: waiting on these lookup tables: SpTpPHCorr, SpBtPHCorr
|
|
614
636
|
energy_ph[indices_top] = energy[indices_top] - get_image_params(
|
|
615
|
-
"SPTPPHOFF"
|
|
637
|
+
"SPTPPHOFF", sensor
|
|
616
638
|
) # * SpTpPHCorr[
|
|
617
639
|
# xlut[indices_top], ylut[indices_top]] / 1024
|
|
618
640
|
|
|
619
641
|
energy_ph[indices_bottom] = energy[indices_bottom] - get_image_params(
|
|
620
|
-
"SPBTPHOFF"
|
|
642
|
+
"SPBTPHOFF", sensor
|
|
621
643
|
) # * SpBtPHCorr[
|
|
622
644
|
# xlut[indices_bottom], ylut[indices_bottom]] / 1024
|
|
623
645
|
|
|
@@ -634,8 +656,7 @@ def get_energy_ssd(de_dataset: xarray.Dataset, ssd: np.ndarray) -> NDArray[np.fl
|
|
|
634
656
|
SSD energy and SSD energy pulse width.
|
|
635
657
|
The result is then normalized per SSD via a lookup table.
|
|
636
658
|
Further description is available on pages 41 of
|
|
637
|
-
IMAP-Ultra Flight Software Specification document
|
|
638
|
-
(7523-9009_Rev_-.pdf).
|
|
659
|
+
IMAP-Ultra Flight Software Specification document.
|
|
639
660
|
|
|
640
661
|
Parameters
|
|
641
662
|
----------
|
|
@@ -649,14 +670,14 @@ def get_energy_ssd(de_dataset: xarray.Dataset, ssd: np.ndarray) -> NDArray[np.fl
|
|
|
649
670
|
energy_norm : np.ndarray
|
|
650
671
|
Energy measured using the SSD.
|
|
651
672
|
"""
|
|
652
|
-
ssd_indices = np.
|
|
653
|
-
energy = de_dataset["
|
|
673
|
+
ssd_indices = np.nonzero(np.isin(de_dataset["stop_type"], StopType.SSD.value))[0]
|
|
674
|
+
energy = de_dataset["energy_ph"].data[ssd_indices]
|
|
654
675
|
|
|
655
676
|
composite_energy = np.empty(len(energy), dtype=np.float64)
|
|
656
677
|
|
|
657
678
|
composite_energy[energy >= UltraConstants.COMPOSITE_ENERGY_THRESHOLD] = (
|
|
658
679
|
UltraConstants.COMPOSITE_ENERGY_THRESHOLD
|
|
659
|
-
+ de_dataset["
|
|
680
|
+
+ de_dataset["pulse_width"].data[ssd_indices][
|
|
660
681
|
energy >= UltraConstants.COMPOSITE_ENERGY_THRESHOLD
|
|
661
682
|
]
|
|
662
683
|
)
|
|
@@ -679,8 +700,7 @@ def get_ctof(
|
|
|
679
700
|
to a fixed distance dmin between the front and back detectors.
|
|
680
701
|
The normalized TOF is termed the corrected TOF (ctof).
|
|
681
702
|
Further description is available on pages 42-44 of
|
|
682
|
-
IMAP-Ultra Flight Software Specification document
|
|
683
|
-
(7523-9009_Rev_-.pdf).
|
|
703
|
+
IMAP-Ultra Flight Software Specification document.
|
|
684
704
|
|
|
685
705
|
Parameters
|
|
686
706
|
----------
|
|
@@ -702,9 +722,11 @@ def get_ctof(
|
|
|
702
722
|
|
|
703
723
|
# Multiply times 100 to convert to hundredths of a millimeter.
|
|
704
724
|
ctof = tof * dmin_ctof * 100 / path_length
|
|
725
|
+
magnitude_v = np.full(len(ctof), -1.0e31, dtype=np.float32)
|
|
705
726
|
|
|
706
|
-
# Convert from mm/0.1ns to km/s
|
|
707
|
-
|
|
727
|
+
# Convert from mm/0.1ns to km/s for valid ctof values
|
|
728
|
+
valid_mask = ctof >= 0
|
|
729
|
+
magnitude_v[valid_mask] = dmin_ctof / ctof[valid_mask] * 1e4
|
|
708
730
|
|
|
709
731
|
return ctof, magnitude_v
|
|
710
732
|
|
|
@@ -720,8 +742,7 @@ def determine_species(tof: np.ndarray, path_length: np.ndarray, type: str) -> ND
|
|
|
720
742
|
Particle species are determined from ctof using thresholds.
|
|
721
743
|
|
|
722
744
|
Further description is available on pages 42-44 of
|
|
723
|
-
IMAP-Ultra Flight Software Specification document
|
|
724
|
-
(7523-9009_Rev_-.pdf).
|
|
745
|
+
IMAP-Ultra Flight Software Specification document.
|
|
725
746
|
|
|
726
747
|
Parameters
|
|
727
748
|
----------
|
|
@@ -740,13 +761,13 @@ def determine_species(tof: np.ndarray, path_length: np.ndarray, type: str) -> ND
|
|
|
740
761
|
# Event TOF normalization to Z axis
|
|
741
762
|
ctof, _ = get_ctof(tof, path_length, type)
|
|
742
763
|
# Initialize bin array
|
|
743
|
-
species_bin = np.full(len(ctof),
|
|
764
|
+
species_bin = np.full(len(ctof), 255, dtype=np.uint8)
|
|
744
765
|
|
|
745
|
-
# Assign "H" to bins where cTOF is within the specified range
|
|
766
|
+
# Assign Species 1 ("H") to bins where cTOF is within the specified range
|
|
746
767
|
species_bin[
|
|
747
768
|
(ctof > UltraConstants.CTOF_SPECIES_MIN)
|
|
748
769
|
& (ctof < UltraConstants.CTOF_SPECIES_MAX)
|
|
749
|
-
] =
|
|
770
|
+
] = 1
|
|
750
771
|
|
|
751
772
|
return species_bin
|
|
752
773
|
|
|
@@ -809,14 +830,14 @@ def get_eventtimes(
|
|
|
809
830
|
Notes
|
|
810
831
|
-----
|
|
811
832
|
Equation for event time:
|
|
812
|
-
t = t_(spin start) + t_(spin start sub)/
|
|
833
|
+
t = t_(spin start) + t_(spin start sub)/1e6 +
|
|
813
834
|
t_spin_period_sec * phase_angle/720
|
|
814
835
|
"""
|
|
815
836
|
spin_df = get_spin_data()
|
|
816
837
|
index = np.searchsorted(spin_df["spin_number"].values, spin)
|
|
817
838
|
spin_starts = (
|
|
818
|
-
spin_df["
|
|
819
|
-
+ spin_df["
|
|
839
|
+
spin_df["spin_start_sec_sclk"].values[index]
|
|
840
|
+
+ spin_df["spin_start_subsec_sclk"].values[index] / 1e6
|
|
820
841
|
)
|
|
821
842
|
|
|
822
843
|
spin_period_sec = spin_df["spin_period_sec"].values[index]
|
|
@@ -824,3 +845,140 @@ def get_eventtimes(
|
|
|
824
845
|
event_times = spin_starts + spin_period_sec * (phase_angle / 720)
|
|
825
846
|
|
|
826
847
|
return event_times, spin_starts, spin_period_sec
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
def interpolate_fwhm(
|
|
851
|
+
lookup_table: pandas.DataFrame,
|
|
852
|
+
energy: NDArray,
|
|
853
|
+
phi_inst: NDArray,
|
|
854
|
+
theta_inst: NDArray,
|
|
855
|
+
) -> tuple[NDArray, NDArray]:
|
|
856
|
+
"""
|
|
857
|
+
Interpolate phi and theta FWHM values using lookup tables.
|
|
858
|
+
|
|
859
|
+
Parameters
|
|
860
|
+
----------
|
|
861
|
+
lookup_table : DataFrame
|
|
862
|
+
Angular profile lookup table for a given side and sensor.
|
|
863
|
+
energy : NDArray
|
|
864
|
+
Energy values.
|
|
865
|
+
phi_inst : NDArray
|
|
866
|
+
Instrument-frame azimuth angles.
|
|
867
|
+
theta_inst : NDArray
|
|
868
|
+
Instrument-frame elevation angles.
|
|
869
|
+
|
|
870
|
+
Returns
|
|
871
|
+
-------
|
|
872
|
+
phi_interp : NDArray
|
|
873
|
+
Interpolated phi FWHM.
|
|
874
|
+
theta_interp : NDArray
|
|
875
|
+
Interpolated theta FWHM.
|
|
876
|
+
"""
|
|
877
|
+
interp_phi = LinearNDInterpolator(
|
|
878
|
+
lookup_table[["Energy", "phi_degrees"]].values, lookup_table["phi_fwhm"].values
|
|
879
|
+
)
|
|
880
|
+
|
|
881
|
+
interp_theta = LinearNDInterpolator(
|
|
882
|
+
lookup_table[["Energy", "theta_degrees"]].values,
|
|
883
|
+
lookup_table["theta_fwhm"].values,
|
|
884
|
+
)
|
|
885
|
+
|
|
886
|
+
# Note: will return nan for those out-of-bounds inputs.
|
|
887
|
+
phi_interp = interp_phi((energy, phi_inst))
|
|
888
|
+
theta_interp = interp_theta((energy, theta_inst))
|
|
889
|
+
|
|
890
|
+
return phi_interp, theta_interp
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
def get_fwhm(
|
|
894
|
+
start_type: NDArray,
|
|
895
|
+
sensor: str,
|
|
896
|
+
energy: NDArray,
|
|
897
|
+
phi_inst: NDArray,
|
|
898
|
+
theta_inst: NDArray,
|
|
899
|
+
) -> tuple[NDArray, NDArray]:
|
|
900
|
+
"""
|
|
901
|
+
Interpolate phi and theta FWHM values for each event based on start type.
|
|
902
|
+
|
|
903
|
+
Parameters
|
|
904
|
+
----------
|
|
905
|
+
start_type : NDArray
|
|
906
|
+
Start Type: 1=Left, 2=Right.
|
|
907
|
+
sensor : str
|
|
908
|
+
Sensor name: "ultra45" or "ultra90".
|
|
909
|
+
energy : NDArray
|
|
910
|
+
Energy values for each event.
|
|
911
|
+
phi_inst : NDArray
|
|
912
|
+
Instrument-frame azimuth angle for each event.
|
|
913
|
+
theta_inst : NDArray
|
|
914
|
+
Instrument-frame elevation angle for each event.
|
|
915
|
+
|
|
916
|
+
Returns
|
|
917
|
+
-------
|
|
918
|
+
phi_interp : NDArray
|
|
919
|
+
Interpolated phi FWHM values.
|
|
920
|
+
theta_interp : NDArray
|
|
921
|
+
Interpolated theta FWHM values.
|
|
922
|
+
"""
|
|
923
|
+
phi_interp = np.full_like(phi_inst, np.nan, dtype=np.float64)
|
|
924
|
+
theta_interp = np.full_like(theta_inst, np.nan, dtype=np.float64)
|
|
925
|
+
lt_table = get_angular_profiles("left", sensor)
|
|
926
|
+
rt_table = get_angular_profiles("right", sensor)
|
|
927
|
+
|
|
928
|
+
# Left start type
|
|
929
|
+
idx_left = start_type == StartType.Left.value
|
|
930
|
+
phi_interp[idx_left], theta_interp[idx_left] = interpolate_fwhm(
|
|
931
|
+
lt_table, energy[idx_left], phi_inst[idx_left], theta_inst[idx_left]
|
|
932
|
+
)
|
|
933
|
+
|
|
934
|
+
# Right start type
|
|
935
|
+
idx_right = start_type == StartType.Right.value
|
|
936
|
+
phi_interp[idx_right], theta_interp[idx_right] = interpolate_fwhm(
|
|
937
|
+
rt_table, energy[idx_right], phi_inst[idx_right], theta_inst[idx_right]
|
|
938
|
+
)
|
|
939
|
+
|
|
940
|
+
return phi_interp, theta_interp
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
def get_efficiency(
|
|
944
|
+
energy: NDArray,
|
|
945
|
+
phi_inst: NDArray,
|
|
946
|
+
theta_inst: NDArray,
|
|
947
|
+
) -> NDArray:
|
|
948
|
+
"""
|
|
949
|
+
Interpolate efficiency values for each event.
|
|
950
|
+
|
|
951
|
+
Parameters
|
|
952
|
+
----------
|
|
953
|
+
energy : NDArray
|
|
954
|
+
Energy values for each event.
|
|
955
|
+
phi_inst : NDArray
|
|
956
|
+
Instrument-frame azimuth angle for each event.
|
|
957
|
+
theta_inst : NDArray
|
|
958
|
+
Instrument-frame elevation angle for each event.
|
|
959
|
+
|
|
960
|
+
Returns
|
|
961
|
+
-------
|
|
962
|
+
efficiency : NDArray
|
|
963
|
+
Interpolated efficiency values.
|
|
964
|
+
"""
|
|
965
|
+
lookup_table = get_energy_efficiencies()
|
|
966
|
+
|
|
967
|
+
theta_vals = np.sort(lookup_table["theta (deg)"].unique())
|
|
968
|
+
phi_vals = np.sort(lookup_table["phi (deg)"].unique())
|
|
969
|
+
energy_column_names = lookup_table.columns[2:].tolist()
|
|
970
|
+
energy_vals = [float(col.replace("keV", "")) for col in energy_column_names]
|
|
971
|
+
efficiency_2d = lookup_table[energy_column_names].values
|
|
972
|
+
|
|
973
|
+
efficiency_grid = efficiency_2d.reshape(
|
|
974
|
+
(len(theta_vals), len(phi_vals), len(energy_vals))
|
|
975
|
+
)
|
|
976
|
+
|
|
977
|
+
interpolator = RegularGridInterpolator(
|
|
978
|
+
(theta_vals, phi_vals, energy_vals),
|
|
979
|
+
efficiency_grid,
|
|
980
|
+
bounds_error=False,
|
|
981
|
+
fill_value=np.nan,
|
|
982
|
+
)
|
|
983
|
+
|
|
984
|
+
return interpolator((theta_inst, phi_inst, energy))
|
|
@@ -6,9 +6,7 @@ import xarray as xr
|
|
|
6
6
|
from imap_processing.ultra.utils.ultra_l1_utils import create_dataset
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def calculate_histogram(
|
|
10
|
-
histogram_dataset: xr.Dataset, name: str, data_version: str
|
|
11
|
-
) -> xr.Dataset:
|
|
9
|
+
def calculate_histogram(histogram_dataset: xr.Dataset, name: str) -> xr.Dataset:
|
|
12
10
|
"""
|
|
13
11
|
Create dictionary with defined datatype for Histogram Data.
|
|
14
12
|
|
|
@@ -18,8 +16,6 @@ def calculate_histogram(
|
|
|
18
16
|
Dataset containing histogram data.
|
|
19
17
|
name : str
|
|
20
18
|
Name of dataset.
|
|
21
|
-
data_version : str
|
|
22
|
-
Version of the data.
|
|
23
19
|
|
|
24
20
|
Returns
|
|
25
21
|
-------
|
|
@@ -35,6 +31,6 @@ def calculate_histogram(
|
|
|
35
31
|
histogram_dict["epoch"] = epoch
|
|
36
32
|
histogram_dict["sid"] = np.zeros(len(epoch), dtype=np.uint8)
|
|
37
33
|
|
|
38
|
-
dataset = create_dataset(histogram_dict, name, "l1c"
|
|
34
|
+
dataset = create_dataset(histogram_dict, name, "l1c")
|
|
39
35
|
|
|
40
36
|
return dataset
|
|
@@ -22,7 +22,6 @@ def calculate_spacecraft_pset(
|
|
|
22
22
|
extendedspin_dataset: xr.Dataset,
|
|
23
23
|
cullingmask_dataset: xr.Dataset,
|
|
24
24
|
name: str,
|
|
25
|
-
data_version: str,
|
|
26
25
|
) -> xr.Dataset:
|
|
27
26
|
"""
|
|
28
27
|
Create dictionary with defined datatype for Pointing Set Grid Data.
|
|
@@ -37,8 +36,6 @@ def calculate_spacecraft_pset(
|
|
|
37
36
|
Dataset containing cullingmask data.
|
|
38
37
|
name : str
|
|
39
38
|
Name of the dataset.
|
|
40
|
-
data_version : str
|
|
41
|
-
Version of the data.
|
|
42
39
|
|
|
43
40
|
Returns
|
|
44
41
|
-------
|
|
@@ -80,7 +77,8 @@ def calculate_spacecraft_pset(
|
|
|
80
77
|
pset_dict["background_rates"] = background_rates
|
|
81
78
|
pset_dict["exposure_factor"] = exposure_pointing
|
|
82
79
|
pset_dict["healpix"] = healpix
|
|
80
|
+
pset_dict["energy_bin_delta"] = np.diff(intervals, axis=1).squeeze()
|
|
83
81
|
|
|
84
|
-
dataset = create_dataset(pset_dict, name, "l1c"
|
|
82
|
+
dataset = create_dataset(pset_dict, name, "l1c")
|
|
85
83
|
|
|
86
84
|
return dataset
|