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
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
from unittest.mock import patch
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from imap_processing.ena_maps import ena_maps
|
|
7
|
+
from imap_processing.ena_maps.utils.coordinates import CoordNames
|
|
8
|
+
from imap_processing.tests.ultra.data.mock_data import mock_l1c_pset_product_healpix
|
|
9
|
+
from imap_processing.ultra.l2 import ultra_l2
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestUltraL2:
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def _setup_spice_kernels_list(self, spice_test_data_path, furnish_kernels):
|
|
15
|
+
self.required_kernel_names = [
|
|
16
|
+
"imap_science_0001.tf",
|
|
17
|
+
"imap_sclk_0000.tsc",
|
|
18
|
+
"sim_1yr_imap_attitude.bc",
|
|
19
|
+
"sim_1yr_imap_pointing_frame.bc",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
@pytest.fixture
|
|
23
|
+
def _mock_single_pset(self, _setup_spice_kernels_list, furnish_kernels):
|
|
24
|
+
with furnish_kernels(self.required_kernel_names):
|
|
25
|
+
self.ultra_pset = mock_l1c_pset_product_healpix(
|
|
26
|
+
nside=128, stripe_center_lat=0, timestr="2025-05-15T12:00:00"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
@pytest.fixture
|
|
30
|
+
def _mock_multiple_psets(self, _setup_spice_kernels_list, furnish_kernels):
|
|
31
|
+
with furnish_kernels(self.required_kernel_names):
|
|
32
|
+
self.ultra_psets = [
|
|
33
|
+
mock_l1c_pset_product_healpix(
|
|
34
|
+
nside=128,
|
|
35
|
+
stripe_center_lat=mid_latitude,
|
|
36
|
+
width_scale=5,
|
|
37
|
+
counts_scaling_params=(50, 0.5),
|
|
38
|
+
peak_exposure=1000,
|
|
39
|
+
timestr=f"2025-05-{4 * i + 1:02d}T12:00:00",
|
|
40
|
+
head=("90"),
|
|
41
|
+
)
|
|
42
|
+
for i, mid_latitude in enumerate(
|
|
43
|
+
np.arange(
|
|
44
|
+
22.5,
|
|
45
|
+
180,
|
|
46
|
+
45,
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
self.psets_total_counts = np.sum(
|
|
52
|
+
[pset["counts"].values.sum() for pset in self.ultra_psets]
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
@pytest.fixture
|
|
56
|
+
def mock_data_dict(self, _mock_multiple_psets):
|
|
57
|
+
return {pset.attrs["Logical_file_id"]: pset for pset in self.ultra_psets}
|
|
58
|
+
|
|
59
|
+
@pytest.mark.parametrize(
|
|
60
|
+
["map_frame", "rtol"],
|
|
61
|
+
[
|
|
62
|
+
# Tight tolerance when 'projecting' to the same frame
|
|
63
|
+
("IMAP_DPS", 1e-8),
|
|
64
|
+
# Loose tolerance of 30% error vs naive flux estimate with real projection.
|
|
65
|
+
# TODO: Ideally this tolerance will tighten if we can fix the issue with
|
|
66
|
+
# the exposure time for uneven numbers of pixels from each PointingSet.
|
|
67
|
+
("ECLIPJ2000", 3e-1),
|
|
68
|
+
],
|
|
69
|
+
)
|
|
70
|
+
@pytest.mark.usefixtures("_mock_single_pset", "_setup_spice_kernels_list")
|
|
71
|
+
def test_generate_ultra_healpix_skymap_single_pset(
|
|
72
|
+
self, map_frame, rtol, furnish_kernels
|
|
73
|
+
):
|
|
74
|
+
# Avoid modifying the original pset
|
|
75
|
+
pset = self.ultra_pset.copy(deep=True)
|
|
76
|
+
|
|
77
|
+
# Set the values in the single input PSET for easy calculation
|
|
78
|
+
# of the expected flux and flux uncertainty
|
|
79
|
+
pset["counts"].values = np.full_like(pset["counts"].values, 10)
|
|
80
|
+
pset["exposure_factor"].values = np.ones_like(pset["exposure_factor"].values)
|
|
81
|
+
pset["background_rates"].values = np.ones_like(pset["background_rates"].values)
|
|
82
|
+
pset["sensitivity"].values = np.ones_like(pset["sensitivity"].values)
|
|
83
|
+
pset["energy_bin_delta"].values = np.ones_like(pset["energy_bin_delta"].values)
|
|
84
|
+
|
|
85
|
+
# Create the Healpix skymap in the desired frame.
|
|
86
|
+
with furnish_kernels(self.required_kernel_names):
|
|
87
|
+
hp_skymap = ultra_l2.generate_ultra_healpix_skymap(
|
|
88
|
+
ultra_l1c_psets=[
|
|
89
|
+
pset,
|
|
90
|
+
],
|
|
91
|
+
output_map_structure=ena_maps.AbstractSkyMap.from_dict(
|
|
92
|
+
{
|
|
93
|
+
"sky_tiling_type": "HEALPIX",
|
|
94
|
+
"spice_reference_frame": map_frame,
|
|
95
|
+
"projection_method_and_values": {
|
|
96
|
+
"PUSH": [
|
|
97
|
+
"counts",
|
|
98
|
+
"exposure_factor",
|
|
99
|
+
"sensitivity",
|
|
100
|
+
"background_rates",
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
"nside": 32,
|
|
104
|
+
"nested": False,
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
assert hp_skymap.nside == 32
|
|
110
|
+
assert hp_skymap.nested is False
|
|
111
|
+
|
|
112
|
+
# Check that required variables are present, and dropped variables are not
|
|
113
|
+
expected_vars = [
|
|
114
|
+
"flux",
|
|
115
|
+
"flux_uncertainty",
|
|
116
|
+
"exposure_factor",
|
|
117
|
+
"observation_time",
|
|
118
|
+
]
|
|
119
|
+
for var in expected_vars:
|
|
120
|
+
assert var in hp_skymap.data_1d.data_vars
|
|
121
|
+
unexpected_vars = ultra_l2.VARIABLES_TO_DROP_AFTER_FLUX_CALCULATION
|
|
122
|
+
for var in unexpected_vars:
|
|
123
|
+
assert var not in hp_skymap.data_1d.data_vars
|
|
124
|
+
|
|
125
|
+
# The ratio of the solid angle of a map's pixel to the solid angle of a
|
|
126
|
+
# pointing set's pixel. Counts will scale up by this ratio.
|
|
127
|
+
solid_angle_ratio_map_to_pset = (
|
|
128
|
+
hp_skymap.solid_angle / ena_maps.UltraPointingSet(pset).solid_angle
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Estimate the expected flux and flux uncertainty
|
|
132
|
+
expected_flux = (
|
|
133
|
+
(10 * solid_angle_ratio_map_to_pset / 1) - 1 * solid_angle_ratio_map_to_pset
|
|
134
|
+
) / (1 * hp_skymap.solid_angle * 1)
|
|
135
|
+
expected_flux_unc = ((10 * solid_angle_ratio_map_to_pset) ** 0.5 / 1) / (
|
|
136
|
+
1 * hp_skymap.solid_angle * 1
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
np.testing.assert_allclose(
|
|
140
|
+
hp_skymap.data_1d["flux"].values,
|
|
141
|
+
expected_flux,
|
|
142
|
+
rtol=rtol,
|
|
143
|
+
)
|
|
144
|
+
np.testing.assert_allclose(
|
|
145
|
+
hp_skymap.data_1d["flux_uncertainty"].values,
|
|
146
|
+
expected_flux_unc,
|
|
147
|
+
rtol=rtol,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
@pytest.mark.usefixtures("_mock_multiple_psets", "_setup_spice_kernels_list")
|
|
151
|
+
def test_generate_ultra_healpix_skymap_multiple_psets(self, furnish_kernels):
|
|
152
|
+
with patch(
|
|
153
|
+
"imap_processing.ultra.l2.ultra_l2.VARIABLES_TO_DROP_AFTER_FLUX_CALCULATION",
|
|
154
|
+
[],
|
|
155
|
+
):
|
|
156
|
+
with furnish_kernels(self.required_kernel_names):
|
|
157
|
+
hp_skymap = ultra_l2.generate_ultra_healpix_skymap(
|
|
158
|
+
ultra_l1c_psets=self.ultra_psets,
|
|
159
|
+
output_map_structure=ena_maps.AbstractSkyMap.from_dict(
|
|
160
|
+
{
|
|
161
|
+
"sky_tiling_type": "RECTANGULAR",
|
|
162
|
+
"spice_reference_frame": "ECLIPJ2000",
|
|
163
|
+
"projection_method_and_values": {
|
|
164
|
+
"PUSH": [
|
|
165
|
+
"counts",
|
|
166
|
+
"exposure_factor",
|
|
167
|
+
"sensitivity",
|
|
168
|
+
"background_rates",
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
"spacing_deg": 2.0,
|
|
172
|
+
}
|
|
173
|
+
),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
assert hp_skymap.nside == ultra_l2.DEFAULT_L2_HEALPIX_NSIDE
|
|
177
|
+
assert hp_skymap.nested == ultra_l2.DEFAULT_L2_HEALPIX_NESTED
|
|
178
|
+
|
|
179
|
+
# The total counts in the skymap should be equal to the sum of the counts
|
|
180
|
+
# in the individual psets
|
|
181
|
+
np.testing.assert_allclose(
|
|
182
|
+
hp_skymap.data_1d["counts"].sum(),
|
|
183
|
+
self.psets_total_counts,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# The map should contain the following variables,
|
|
187
|
+
# because we did not drop any variables
|
|
188
|
+
expected_vars = (
|
|
189
|
+
ultra_l2.REQUIRED_L1C_VARIABLES
|
|
190
|
+
+ ultra_l2.VARIABLES_TO_DROP_AFTER_FLUX_CALCULATION
|
|
191
|
+
+ ["flux", "flux_uncertainty"]
|
|
192
|
+
)
|
|
193
|
+
for var in expected_vars:
|
|
194
|
+
assert var in hp_skymap.data_1d.data_vars
|
|
195
|
+
|
|
196
|
+
# Check the dims of the key variables
|
|
197
|
+
counts_dims = (
|
|
198
|
+
CoordNames.TIME.value,
|
|
199
|
+
CoordNames.ENERGY_ULTRA.value,
|
|
200
|
+
CoordNames.GENERIC_PIXEL.value,
|
|
201
|
+
)
|
|
202
|
+
assert hp_skymap.data_1d["counts"].dims == counts_dims
|
|
203
|
+
assert hp_skymap.data_1d["flux"].dims == counts_dims
|
|
204
|
+
assert hp_skymap.data_1d["flux_uncertainty"].dims == counts_dims
|
|
205
|
+
assert hp_skymap.data_1d["exposure_factor"].dims == counts_dims[-1:]
|
|
206
|
+
|
|
207
|
+
@pytest.mark.usefixtures("_setup_spice_kernels_list")
|
|
208
|
+
def test_ultra_l2_output_unbinned_healpix(self, mock_data_dict, furnish_kernels):
|
|
209
|
+
map_structure = ena_maps.AbstractSkyMap.from_dict(
|
|
210
|
+
{
|
|
211
|
+
"sky_tiling_type": "HEALPIX",
|
|
212
|
+
"spice_reference_frame": "ECLIPJ2000",
|
|
213
|
+
"projection_method_and_values": {
|
|
214
|
+
"PUSH": ["counts", "exposure_factor", "sensitivity"],
|
|
215
|
+
},
|
|
216
|
+
"nside": 16,
|
|
217
|
+
"nested": True,
|
|
218
|
+
}
|
|
219
|
+
)
|
|
220
|
+
with furnish_kernels(self.required_kernel_names):
|
|
221
|
+
[
|
|
222
|
+
map_dataset,
|
|
223
|
+
] = ultra_l2.ultra_l2(
|
|
224
|
+
data_dict=mock_data_dict,
|
|
225
|
+
data_version="001",
|
|
226
|
+
output_map_structure=map_structure,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
assert map_dataset.attrs["HEALPix_nside"] == map_structure.nside
|
|
230
|
+
assert map_dataset.attrs["HEALPix_nest"] == map_structure.nested
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
"""Ultra Decompression Tools."""
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
|
-
|
|
5
|
-
import space_packet_parser
|
|
4
|
+
from numpy.typing import NDArray
|
|
6
5
|
|
|
7
6
|
from imap_processing.ultra.l0.ultra_utils import (
|
|
8
|
-
EVENT_FIELD_RANGES,
|
|
9
|
-
append_fillval,
|
|
10
7
|
parse_event,
|
|
11
8
|
)
|
|
12
9
|
from imap_processing.utils import convert_to_binary_string
|
|
@@ -157,7 +154,7 @@ def decompress_image(
|
|
|
157
154
|
binary_data: str,
|
|
158
155
|
width_bit: int,
|
|
159
156
|
mantissa_bit_length: int,
|
|
160
|
-
) ->
|
|
157
|
+
) -> NDArray:
|
|
161
158
|
"""
|
|
162
159
|
Will decompress a binary string representing an image into a matrix of pixel values.
|
|
163
160
|
|
|
@@ -178,14 +175,14 @@ def decompress_image(
|
|
|
178
175
|
|
|
179
176
|
Returns
|
|
180
177
|
-------
|
|
181
|
-
p_decom :
|
|
178
|
+
p_decom : NDArray
|
|
182
179
|
A 2D numpy array representing pixel values.
|
|
183
180
|
Each pixel is stored as an unsigned 16-bit integer (uint16).
|
|
184
181
|
|
|
185
182
|
Notes
|
|
186
183
|
-----
|
|
187
184
|
This process is described starting on page 168 in IMAP-Ultra Flight
|
|
188
|
-
Software Specification document
|
|
185
|
+
Software Specification document.
|
|
189
186
|
"""
|
|
190
187
|
rows = 54
|
|
191
188
|
cols = 180
|
|
@@ -240,44 +237,34 @@ def decompress_image(
|
|
|
240
237
|
|
|
241
238
|
|
|
242
239
|
def read_image_raw_events_binary(
|
|
243
|
-
|
|
244
|
-
|
|
240
|
+
event_data: bytes,
|
|
241
|
+
count: int,
|
|
242
|
+
) -> NDArray:
|
|
245
243
|
"""
|
|
246
244
|
Convert contents of binary string 'EVENTDATA' into values.
|
|
247
245
|
|
|
248
246
|
Parameters
|
|
249
247
|
----------
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
248
|
+
event_data : bytes
|
|
249
|
+
Event data.
|
|
250
|
+
count : int
|
|
251
|
+
Number of events.
|
|
254
252
|
|
|
255
253
|
Returns
|
|
256
254
|
-------
|
|
257
|
-
|
|
258
|
-
|
|
255
|
+
event_data : NDArray
|
|
256
|
+
Event data.
|
|
259
257
|
"""
|
|
260
|
-
binary = convert_to_binary_string(
|
|
261
|
-
count = packet["COUNT"]
|
|
258
|
+
binary = convert_to_binary_string(event_data)
|
|
262
259
|
# 166 bits per event
|
|
263
260
|
event_length = 166 if count else 0
|
|
264
|
-
|
|
265
|
-
# Uses fill value for all packets that do not contain event data.
|
|
266
|
-
if count == 0:
|
|
267
|
-
# if decom_data is empty, append fill values to all fields
|
|
268
|
-
if not decom_data:
|
|
269
|
-
for field in EVENT_FIELD_RANGES.keys():
|
|
270
|
-
decom_data[field] = []
|
|
271
|
-
append_fillval(decom_data, packet)
|
|
261
|
+
event_data_list = []
|
|
272
262
|
|
|
273
263
|
# For all packets with event data, parses the binary string
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
for key, value in event_data.items():
|
|
281
|
-
decom_data[key].append(value)
|
|
264
|
+
for i in range(count):
|
|
265
|
+
start_index = i * event_length
|
|
266
|
+
event_binary = binary[start_index : start_index + event_length]
|
|
267
|
+
parsed_event = parse_event(event_binary)
|
|
268
|
+
event_data_list.append(parsed_event)
|
|
282
269
|
|
|
283
|
-
return
|
|
270
|
+
return np.array(event_data_list)
|