imap-processing 0.9.0__py3-none-any.whl → 0.11.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/_version.py +2 -2
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +749 -442
- imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +7 -0
- imap_processing/cdf/config/imap_glows_l1a_variable_attrs.yaml +8 -2
- imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +0 -1
- imap_processing/cdf/config/imap_glows_l2_variable_attrs.yaml +358 -0
- imap_processing/cdf/config/imap_hi_variable_attrs.yaml +59 -25
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +22 -0
- imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +32 -8
- imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +94 -5
- imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +65 -37
- imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +16 -1
- imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +7 -0
- imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +14 -14
- imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +25 -24
- imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +238 -0
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +100 -92
- imap_processing/cdf/utils.py +2 -2
- imap_processing/cli.py +45 -9
- imap_processing/codice/codice_l1a.py +104 -58
- imap_processing/codice/constants.py +111 -155
- imap_processing/codice/data/esa_sweep_values.csv +256 -256
- imap_processing/codice/data/lo_stepping_values.csv +128 -128
- imap_processing/ena_maps/ena_maps.py +519 -0
- imap_processing/ena_maps/utils/map_utils.py +145 -0
- imap_processing/ena_maps/utils/spatial_utils.py +226 -0
- imap_processing/glows/__init__.py +3 -0
- imap_processing/glows/ancillary/imap_glows_pipeline_settings_v001.json +52 -0
- imap_processing/glows/l1a/glows_l1a.py +72 -14
- imap_processing/glows/l1b/glows_l1b.py +2 -1
- imap_processing/glows/l1b/glows_l1b_data.py +25 -1
- imap_processing/glows/l2/glows_l2.py +324 -0
- imap_processing/glows/l2/glows_l2_data.py +156 -51
- imap_processing/hi/l1a/science_direct_event.py +57 -51
- imap_processing/hi/l1b/hi_l1b.py +43 -28
- imap_processing/hi/l1c/hi_l1c.py +225 -42
- imap_processing/hi/utils.py +20 -3
- imap_processing/hit/l0/constants.py +2 -2
- imap_processing/hit/l0/decom_hit.py +1 -1
- imap_processing/hit/l1a/hit_l1a.py +94 -13
- imap_processing/hit/l1b/hit_l1b.py +158 -9
- imap_processing/ialirt/l0/process_codicehi.py +156 -0
- imap_processing/ialirt/l0/process_codicelo.py +5 -2
- imap_processing/ialirt/packet_definitions/ialirt.xml +28 -20
- imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +241 -0
- imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +170 -0
- imap_processing/ialirt/packet_definitions/ialirt_swe.xml +258 -0
- imap_processing/ialirt/process_ephemeris.py +72 -40
- imap_processing/idex/decode.py +241 -0
- imap_processing/idex/idex_l1a.py +143 -81
- imap_processing/idex/idex_l1b.py +244 -10
- imap_processing/lo/l0/lo_science.py +61 -0
- imap_processing/lo/l1a/lo_l1a.py +98 -10
- imap_processing/lo/l1b/lo_l1b.py +2 -2
- imap_processing/lo/l1c/lo_l1c.py +2 -2
- imap_processing/lo/packet_definitions/lo_xtce.xml +1082 -9178
- imap_processing/mag/l0/decom_mag.py +2 -2
- imap_processing/mag/l1a/mag_l1a.py +7 -7
- imap_processing/mag/l1a/mag_l1a_data.py +62 -30
- imap_processing/mag/l1b/mag_l1b.py +11 -6
- imap_processing/quality_flags.py +18 -3
- imap_processing/spice/geometry.py +149 -177
- imap_processing/spice/kernels.py +26 -26
- imap_processing/spice/spin.py +233 -0
- imap_processing/spice/time.py +96 -31
- imap_processing/swapi/l1/swapi_l1.py +60 -31
- imap_processing/swapi/packet_definitions/swapi_packet_definition.xml +363 -384
- imap_processing/swe/l1a/swe_l1a.py +8 -3
- imap_processing/swe/l1a/swe_science.py +24 -24
- imap_processing/swe/l1b/swe_l1b.py +2 -1
- imap_processing/swe/l1b/swe_l1b_science.py +181 -122
- imap_processing/swe/l2/swe_l2.py +337 -70
- imap_processing/swe/utils/swe_utils.py +28 -0
- imap_processing/tests/cdf/test_utils.py +2 -2
- imap_processing/tests/codice/conftest.py +20 -17
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hskp_20241110193622_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-counters-singles_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-angular_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-priority_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-nsw-species_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-angular_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-priority_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-sw-species_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/test_codice_l0.py +55 -121
- imap_processing/tests/codice/test_codice_l1a.py +147 -59
- imap_processing/tests/conftest.py +81 -22
- imap_processing/tests/ena_maps/test_ena_maps.py +309 -0
- imap_processing/tests/ena_maps/test_map_utils.py +286 -0
- imap_processing/tests/ena_maps/test_spatial_utils.py +161 -0
- imap_processing/tests/glows/conftest.py +7 -1
- imap_processing/tests/glows/test_glows_l1a_cdf.py +3 -7
- imap_processing/tests/glows/test_glows_l1a_data.py +34 -6
- imap_processing/tests/glows/test_glows_l1b_data.py +29 -17
- imap_processing/tests/glows/test_glows_l2.py +101 -0
- imap_processing/tests/hi/conftest.py +3 -3
- imap_processing/tests/hi/data/l1/imap_hi_l1b_45sensor-de_20250415_v999.cdf +0 -0
- imap_processing/tests/hi/data/l1/imap_his_pset-calibration-prod-config_20240101_v001.csv +31 -0
- imap_processing/tests/hi/test_hi_l1b.py +14 -9
- imap_processing/tests/hi/test_hi_l1c.py +136 -36
- imap_processing/tests/hi/test_l1a.py +0 -2
- imap_processing/tests/hi/test_science_direct_event.py +18 -14
- imap_processing/tests/hi/test_utils.py +16 -11
- imap_processing/tests/hit/helpers/__init__.py +0 -0
- imap_processing/tests/hit/helpers/l1_validation.py +405 -0
- imap_processing/tests/hit/test_data/sci_sample.ccsds +0 -0
- imap_processing/tests/hit/test_decom_hit.py +8 -10
- imap_processing/tests/hit/test_hit_l1a.py +117 -180
- imap_processing/tests/hit/test_hit_l1b.py +149 -55
- imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -0
- imap_processing/tests/hit/validation_data/sci_sample_raw.csv +62 -0
- imap_processing/tests/ialirt/test_data/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/eu_SWP_IAL_20240826_152033.csv +644 -0
- imap_processing/tests/ialirt/test_data/l0/hi_fsw_view_1_ccsds.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +914 -0
- imap_processing/tests/ialirt/test_data/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
- imap_processing/tests/ialirt/unit/test_process_codicehi.py +106 -0
- imap_processing/tests/ialirt/unit/test_process_ephemeris.py +33 -5
- imap_processing/tests/ialirt/unit/test_process_swapi.py +85 -0
- imap_processing/tests/ialirt/unit/test_process_swe.py +106 -0
- imap_processing/tests/idex/conftest.py +29 -1
- imap_processing/tests/idex/test_data/compressed_2023_102_14_24_55.pkts +0 -0
- imap_processing/tests/idex/test_data/non_compressed_2023_102_14_22_26.pkts +0 -0
- imap_processing/tests/idex/test_idex_l0.py +6 -3
- imap_processing/tests/idex/test_idex_l1a.py +151 -1
- imap_processing/tests/idex/test_idex_l1b.py +124 -2
- imap_processing/tests/lo/test_lo_l1a.py +62 -2
- imap_processing/tests/lo/test_lo_science.py +85 -0
- imap_processing/tests/lo/validation_data/Instrument_FM1_T104_R129_20240803_ILO_SPIN_EU.csv +2 -0
- imap_processing/tests/mag/conftest.py +16 -0
- imap_processing/tests/mag/test_mag_decom.py +6 -4
- imap_processing/tests/mag/test_mag_l1a.py +36 -7
- imap_processing/tests/mag/test_mag_l1b.py +55 -4
- imap_processing/tests/mag/test_mag_validation.py +148 -0
- imap_processing/tests/mag/validation/L1a/T001/all_p_ones.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T001/mag-l0-l1a-t001-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T001/mag-l0-l1a-t001-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T002/all_n_ones.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T002/mag-l0-l1a-t002-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T002/mag-l0-l1a-t002-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T003/field_like.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T003/mag-l0-l1a-t003-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T003/mag-l0-l1a-t003-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T004/field_like.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T004/mag-l0-l1a-t004-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T004/mag-l0-l1a-t004-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T005/field_like_range_change.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T005/mag-l0-l1a-t005-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T005/mag-l0-l1a-t005-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T006/hdr_field.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T006/mag-l0-l1a-t006-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T006/mag-l0-l1a-t006-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T007/hdr_field_and_range_change.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T007/mag-l0-l1a-t007-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T007/mag-l0-l1a-t007-out.csv +17 -0
- imap_processing/tests/mag/validation/L1a/T008/field_like_range_change.txt +19200 -0
- imap_processing/tests/mag/validation/L1a/T008/mag-l0-l1a-t008-in.bin +0 -0
- imap_processing/tests/mag/validation/L1a/T008/mag-l0-l1a-t008-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T009/data.bin +0 -0
- imap_processing/tests/mag/validation/L1b/T009/field_like_all_ranges.txt +19200 -0
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-in.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-magi-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-mago-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T010/data.bin +0 -0
- imap_processing/tests/mag/validation/L1b/T010/field_like_all_ranges.txt +19200 -0
- imap_processing/tests/mag/validation/L1b/T010/mag-l1a-l1b-t010-in.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T010/mag-l1a-l1b-t010-magi-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T010/mag-l1a-l1b-t010-mago-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/data.bin +0 -0
- imap_processing/tests/mag/validation/L1b/T011/field_like_all_ranges.txt +19200 -0
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-in.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-magi-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-mago-out.csv +17 -0
- imap_processing/tests/spice/test_geometry.py +128 -133
- imap_processing/tests/spice/test_kernels.py +37 -37
- imap_processing/tests/spice/test_spin.py +184 -0
- imap_processing/tests/spice/test_time.py +43 -20
- imap_processing/tests/swapi/test_swapi_l1.py +11 -10
- imap_processing/tests/swapi/test_swapi_l2.py +13 -3
- imap_processing/tests/swe/test_swe_l1a.py +1 -1
- imap_processing/tests/swe/test_swe_l1b.py +20 -3
- imap_processing/tests/swe/test_swe_l1b_science.py +54 -35
- imap_processing/tests/swe/test_swe_l2.py +148 -5
- imap_processing/tests/test_cli.py +39 -7
- imap_processing/tests/test_quality_flags.py +19 -19
- imap_processing/tests/test_utils.py +3 -2
- imap_processing/tests/ultra/test_data/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3314 -3314
- imap_processing/tests/ultra/test_data/mock_data.py +161 -0
- imap_processing/tests/ultra/unit/conftest.py +73 -0
- imap_processing/tests/ultra/unit/test_badtimes.py +58 -0
- imap_processing/tests/ultra/unit/test_cullingmask.py +87 -0
- imap_processing/tests/ultra/unit/test_de.py +61 -60
- imap_processing/tests/ultra/unit/test_ultra_l1a.py +3 -3
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +51 -77
- imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +5 -5
- imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +114 -0
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +86 -26
- imap_processing/tests/ultra/unit/test_ultra_l1c.py +1 -1
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +3 -3
- imap_processing/ultra/constants.py +11 -1
- imap_processing/ultra/l1a/ultra_l1a.py +2 -2
- imap_processing/ultra/l1b/badtimes.py +22 -5
- imap_processing/ultra/l1b/cullingmask.py +31 -5
- imap_processing/ultra/l1b/de.py +32 -37
- imap_processing/ultra/l1b/extendedspin.py +44 -20
- imap_processing/ultra/l1b/ultra_l1b.py +21 -22
- imap_processing/ultra/l1b/ultra_l1b_culling.py +190 -0
- imap_processing/ultra/l1b/ultra_l1b_extended.py +81 -30
- imap_processing/ultra/l1c/histogram.py +6 -2
- imap_processing/ultra/l1c/pset.py +6 -2
- imap_processing/ultra/l1c/ultra_l1c.py +2 -3
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +4 -3
- imap_processing/ultra/utils/ultra_l1_utils.py +70 -14
- imap_processing/utils.py +2 -2
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/METADATA +7 -2
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/RECORD +235 -152
- imap_processing/tests/codice/data/eu_unit_lookup_table.csv +0 -101
- imap_processing/tests/codice/data/idle_export_eu.COD_NHK_20230822_122700 2.csv +0 -100
- imap_processing/tests/codice/data/idle_export_raw.COD_NHK_20230822_122700.csv +0 -100
- imap_processing/tests/codice/data/imap_codice_l0_raw_20241110_v001.pkts +0 -0
- imap_processing/tests/hi/test_data/l1a/imap_hi_l1a_45sensor-de_20250415_v000.cdf +0 -0
- imap_processing/tests/hit/test_data/sci_sample1.ccsds +0 -0
- imap_processing/tests/ultra/unit/test_spatial_utils.py +0 -125
- imap_processing/ultra/utils/spatial_utils.py +0 -221
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_APP_NHK.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_APP_NHK.csv +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_SCI_CNT.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/20231030_H45_SCI_DE.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/H90_NHK_20241104.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/H90_sci_cnt_20241104.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/H90_sci_de_20241104.bin +0 -0
- /imap_processing/tests/hi/{test_data → data}/l0/README.txt +0 -0
- /imap_processing/tests/idex/{imap_idex_l0_raw_20231214_v001.pkts → test_data/imap_idex_l0_raw_20231214_v001.pkts} +0 -0
- /imap_processing/tests/idex/{impact_14_tof_high_data.txt → test_data/impact_14_tof_high_data.txt} +0 -0
- /imap_processing/tests/mag/{imap_mag_l1a_norm-magi_20251017_v001.cdf → validation/imap_mag_l1a_norm-magi_20251017_v001.cdf} +0 -0
- /imap_processing/tests/mag/{mag_l0_test_data.pkts → validation/mag_l0_test_data.pkts} +0 -0
- /imap_processing/tests/mag/{mag_l0_test_output.csv → validation/mag_l0_test_output.csv} +0 -0
- /imap_processing/tests/mag/{mag_l1_test_data.pkts → validation/mag_l1_test_data.pkts} +0 -0
- /imap_processing/tests/mag/{mag_l1a_test_output.csv → validation/mag_l1a_test_output.csv} +0 -0
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.9.0.dist-info → imap_processing-0.11.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
"""helper functions for HIT L1 unit tests"""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import xarray as xr
|
|
8
|
+
|
|
9
|
+
# <=== CONSTANTS ===>
|
|
10
|
+
|
|
11
|
+
# Dictionary of columns to consolidate
|
|
12
|
+
# key = new column name
|
|
13
|
+
# value = prefix of column names in the validation data
|
|
14
|
+
RATE_COLUMNS = {
|
|
15
|
+
"coinrates": "COINRATES_",
|
|
16
|
+
"pbufrates": "BUFRATES_",
|
|
17
|
+
"l2fgrates": "L2FGRATES_",
|
|
18
|
+
"l2bgrates": "L2BGRATES_",
|
|
19
|
+
"l3fgrates": "L3FGRATES_",
|
|
20
|
+
"l3bgrates": "L3BGRATES_",
|
|
21
|
+
"penfgrates": "PENFGRATES_",
|
|
22
|
+
"penbgrates": "PENBGRATES_",
|
|
23
|
+
"sectorates": "SECTORATES_",
|
|
24
|
+
"l4fgrates": "L4FGRATES_",
|
|
25
|
+
"l4bgrates": "L4BGRATES_",
|
|
26
|
+
"ialirtrates": "IALIRTRATES_",
|
|
27
|
+
"sngrates_hg": "SNGRATES_HG_",
|
|
28
|
+
"sngrates_lg": "SNGRATES_LG_",
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
# Dictionary of columns to rename
|
|
32
|
+
# key = existing column name
|
|
33
|
+
# value = new column name
|
|
34
|
+
RENAME_COLUMNS = {
|
|
35
|
+
"CCSDS_VERSION": "version",
|
|
36
|
+
"CCSDS_TYPE": "type",
|
|
37
|
+
"CCSDS_SEC_HDR_FLAG": "sec_hdr_flg",
|
|
38
|
+
"CCSDS_APPID": "pkt_apid",
|
|
39
|
+
"CCSDS_GRP_FLAG": "seq_flgs",
|
|
40
|
+
"CCSDS_SEQ_CNT": "src_seq_ctr",
|
|
41
|
+
"CCSDS_LENGTH": "pkt_len",
|
|
42
|
+
"SC_TICK": "sc_tick_by_frame",
|
|
43
|
+
"CODE_OK": "hdr_code_ok",
|
|
44
|
+
"HEATER_DUTY_CYCLE": "hdr_heater_duty_cycle",
|
|
45
|
+
"LEAK_CONV": "hdr_leak_conv",
|
|
46
|
+
"DY_TH_STATE": "hdr_dynamic_threshold_state",
|
|
47
|
+
"LIVE_TIME": "livetime_counter",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
MOD_VALUE_TO_SPECIES_ENERGY_MAP = {
|
|
51
|
+
0: {"species": "H", "energy_idx": 0},
|
|
52
|
+
1: {"species": "H", "energy_idx": 1},
|
|
53
|
+
2: {"species": "H", "energy_idx": 2},
|
|
54
|
+
3: {"species": "He4", "energy_idx": 0},
|
|
55
|
+
4: {"species": "He4", "energy_idx": 1},
|
|
56
|
+
5: {"species": "CNO", "energy_idx": 0},
|
|
57
|
+
6: {"species": "CNO", "energy_idx": 1},
|
|
58
|
+
7: {"species": "NeMgSi", "energy_idx": 0},
|
|
59
|
+
8: {"species": "NeMgSi", "energy_idx": 1},
|
|
60
|
+
9: {"species": "Fe", "energy_idx": 0},
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# <=== HELPER FUNCTIONS FOR L1 DATA VALIDATION ===>
|
|
65
|
+
def prepare_counts_validation_data(validation_data: pd.DataFrame) -> pd.DataFrame:
|
|
66
|
+
"""Prepare validation data for comparison with processed data.
|
|
67
|
+
|
|
68
|
+
The L1A counts validation data is organized with each value in a
|
|
69
|
+
separate column. This function consolidates related data into
|
|
70
|
+
arrays to match the processed data. It also renames columns to
|
|
71
|
+
match the processed data.
|
|
72
|
+
|
|
73
|
+
Parameters
|
|
74
|
+
----------
|
|
75
|
+
validation_data : pd.DataFrame
|
|
76
|
+
Validation data extracted from a csv file
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
pd.DataFrame
|
|
81
|
+
Validation data formatted for comparison with processed data
|
|
82
|
+
"""
|
|
83
|
+
validation_data.columns = validation_data.columns.str.strip()
|
|
84
|
+
validation_data.rename(columns=RENAME_COLUMNS, inplace=True)
|
|
85
|
+
validation_data = consolidate_rate_columns(validation_data, RATE_COLUMNS)
|
|
86
|
+
validation_data = process_single_rates(validation_data)
|
|
87
|
+
validation_data = add_species_energy(validation_data)
|
|
88
|
+
validation_data.columns = validation_data.columns.str.lower()
|
|
89
|
+
return validation_data
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def prepare_standard_rates_validation_data(
|
|
93
|
+
validation_data: pd.DataFrame,
|
|
94
|
+
) -> pd.DataFrame:
|
|
95
|
+
"""Prepare validation data for comparison with processed data.
|
|
96
|
+
|
|
97
|
+
The L1B standard rates validation data is organized with each
|
|
98
|
+
value in a separate column. This function consolidates related
|
|
99
|
+
data into arrays that match the processed data.
|
|
100
|
+
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
validation_data : pd.DataFrame
|
|
104
|
+
Validation data extracted from a csv file
|
|
105
|
+
|
|
106
|
+
Returns
|
|
107
|
+
-------
|
|
108
|
+
pd.DataFrame
|
|
109
|
+
Validation data formatted for comparison with processed data
|
|
110
|
+
"""
|
|
111
|
+
validation_data.columns = validation_data.columns.str.strip()
|
|
112
|
+
validation_data = consolidate_rate_columns(
|
|
113
|
+
validation_data, {k: v for k, v in RATE_COLUMNS.items() if k != "sectorates"}
|
|
114
|
+
)
|
|
115
|
+
validation_data = process_single_rates(validation_data)
|
|
116
|
+
validation_data.columns = validation_data.columns.str.lower()
|
|
117
|
+
return validation_data
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def consolidate_rate_columns(
|
|
121
|
+
data: pd.DataFrame, rate_columns: dict[str, str]
|
|
122
|
+
) -> pd.DataFrame:
|
|
123
|
+
"""Consolidate related data into arrays to match processed data.
|
|
124
|
+
|
|
125
|
+
The validation data has each value in a separate column. This
|
|
126
|
+
function aggregates related data into arrays to match processed
|
|
127
|
+
data. Each rate column has a corresponding delta plus and delta
|
|
128
|
+
minus column for uncertainty values.
|
|
129
|
+
|
|
130
|
+
Parameters
|
|
131
|
+
----------
|
|
132
|
+
data : pd.DataFrame
|
|
133
|
+
Validation data
|
|
134
|
+
|
|
135
|
+
rate_columns : dict[str, str]
|
|
136
|
+
Dictionary of columns to consolidate
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
pd.DataFrame
|
|
141
|
+
Validation data with rate columns consolidated into arrays
|
|
142
|
+
"""
|
|
143
|
+
for new_col, prefix in rate_columns.items():
|
|
144
|
+
pattern_rates = re.compile(rf"^{prefix}\d+$")
|
|
145
|
+
pattern_delta_plus = re.compile(rf"^{prefix}\d+_DELTA_PLUS$")
|
|
146
|
+
pattern_delta_minus = re.compile(rf"^{prefix}\d+_DELTA_MINUS$")
|
|
147
|
+
data[new_col] = data.filter(regex=pattern_rates.pattern).apply(
|
|
148
|
+
lambda row: row.values, axis=1
|
|
149
|
+
)
|
|
150
|
+
data[f"{new_col}_delta_plus"] = data.filter(
|
|
151
|
+
regex=pattern_delta_plus.pattern
|
|
152
|
+
).apply(lambda row: row.values, axis=1)
|
|
153
|
+
data[f"{new_col}_delta_minus"] = data.filter(
|
|
154
|
+
regex=pattern_delta_minus.pattern
|
|
155
|
+
).apply(lambda row: row.values, axis=1)
|
|
156
|
+
if new_col == "sectorates":
|
|
157
|
+
data = consolidate_sectorates(data)
|
|
158
|
+
data.drop(
|
|
159
|
+
columns=data.filter(regex=pattern_rates.pattern).columns, inplace=True
|
|
160
|
+
)
|
|
161
|
+
data.drop(
|
|
162
|
+
columns=data.filter(regex=pattern_delta_plus.pattern).columns, inplace=True
|
|
163
|
+
)
|
|
164
|
+
data.drop(
|
|
165
|
+
columns=data.filter(regex=pattern_delta_minus.pattern).columns, inplace=True
|
|
166
|
+
)
|
|
167
|
+
return data
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def consolidate_sectorates(data: pd.DataFrame) -> pd.DataFrame:
|
|
171
|
+
"""Consolidate sector rate data into arrays.
|
|
172
|
+
|
|
173
|
+
This function distinguishes between sector rate columns with three digits
|
|
174
|
+
and those with four digits in their names.
|
|
175
|
+
|
|
176
|
+
SECTORATES_000 SECTORATES_000_0 SECTORATES_000_1 SECTORATES_000_2...SECTORATES_120_9
|
|
177
|
+
0 0
|
|
178
|
+
0 0
|
|
179
|
+
0 0
|
|
180
|
+
:
|
|
181
|
+
|
|
182
|
+
Columns with three digits (e.g., SECTORATE_000) contain sectorate
|
|
183
|
+
values for the science frame, with 120 such columns in the validation
|
|
184
|
+
data. These will be organized into an array named "sectorates".
|
|
185
|
+
|
|
186
|
+
Columns with four digits (e.g., SECTORATES_000_0) include the sectorate
|
|
187
|
+
values with a mod 10 value appended (e.g., 0). The mod 10 value determines
|
|
188
|
+
the species and energy range the sector rates represent in the science frame.
|
|
189
|
+
There are 10 possible species and energy ranges, but only one has data per
|
|
190
|
+
science frame. The validation data has 10 columns per 120 sector rates,
|
|
191
|
+
totaling 1200 columns per science frame. Each set of 10 columns will have
|
|
192
|
+
only one value, resulting in an array that looks like this:
|
|
193
|
+
|
|
194
|
+
[nan, nan, nan, 0, nan, nan, nan, nan, nan, nan...nan, nan, nan, 0, nan...]
|
|
195
|
+
|
|
196
|
+
These will be consolidated into a "sectorates_by_mod_val" column in the
|
|
197
|
+
validation data.
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
data : pd.DataFrame
|
|
202
|
+
Validation data
|
|
203
|
+
|
|
204
|
+
Returns
|
|
205
|
+
-------
|
|
206
|
+
pd.DataFrame
|
|
207
|
+
Validation data with sectorate columns consolidated into arrays
|
|
208
|
+
"""
|
|
209
|
+
sectorates_three_digits = data.filter(regex=r"^SECTORATES_\d{3}$").columns
|
|
210
|
+
sectorates_delta_plus_three_digits = data.filter(
|
|
211
|
+
regex=r"^SECTORATES_\d{3}_DELTA_PLUS$"
|
|
212
|
+
).columns
|
|
213
|
+
sectorates_delta_minus_three_digits = data.filter(
|
|
214
|
+
regex=r"^SECTORATES_\d{3}_DELTA_MINUS$"
|
|
215
|
+
).columns
|
|
216
|
+
|
|
217
|
+
data["sectorates"] = data[sectorates_three_digits].apply(
|
|
218
|
+
lambda row: row.values.reshape(8, 15), axis=1
|
|
219
|
+
)
|
|
220
|
+
data["sectorates_delta_plus"] = data[sectorates_delta_plus_three_digits].apply(
|
|
221
|
+
lambda row: row.values.reshape(8, 15), axis=1
|
|
222
|
+
)
|
|
223
|
+
data["sectorates_delta_minus"] = data[sectorates_delta_minus_three_digits].apply(
|
|
224
|
+
lambda row: row.values.reshape(8, 15), axis=1
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
sectorates_four_digits = data.filter(regex=r"^SECTORATES_\d{3}_\d{1}$").columns
|
|
228
|
+
data["sectorates_by_mod_val"] = data[sectorates_four_digits].apply(
|
|
229
|
+
lambda row: row.values, axis=1
|
|
230
|
+
)
|
|
231
|
+
data.drop(
|
|
232
|
+
columns=data.filter(regex=r"^SECTORATES_\d{3}_\d{1}.*$").columns, inplace=True
|
|
233
|
+
)
|
|
234
|
+
return data
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def process_single_rates(data: pd.DataFrame) -> pd.DataFrame:
|
|
238
|
+
"""Combine the high and low gain single rates into 2D arrays
|
|
239
|
+
|
|
240
|
+
Parameters
|
|
241
|
+
----------
|
|
242
|
+
data : pd.DataFrame
|
|
243
|
+
Validation data
|
|
244
|
+
|
|
245
|
+
Returns
|
|
246
|
+
-------
|
|
247
|
+
pd.DataFrame
|
|
248
|
+
Validation data with single rates combined into 2D arrays
|
|
249
|
+
"""
|
|
250
|
+
data["sngrates"] = data.apply(
|
|
251
|
+
lambda row: np.array([row["sngrates_hg"], row["sngrates_lg"]]), axis=1
|
|
252
|
+
)
|
|
253
|
+
data["sngrates_delta_plus"] = data.apply(
|
|
254
|
+
lambda row: np.array(
|
|
255
|
+
[row["sngrates_hg_delta_plus"], row["sngrates_lg_delta_plus"]]
|
|
256
|
+
),
|
|
257
|
+
axis=1,
|
|
258
|
+
)
|
|
259
|
+
data["sngrates_delta_minus"] = data.apply(
|
|
260
|
+
lambda row: np.array(
|
|
261
|
+
[row["sngrates_hg_delta_minus"], row["sngrates_lg_delta_minus"]]
|
|
262
|
+
),
|
|
263
|
+
axis=1,
|
|
264
|
+
)
|
|
265
|
+
data.drop(
|
|
266
|
+
columns=[
|
|
267
|
+
"sngrates_hg",
|
|
268
|
+
"sngrates_lg",
|
|
269
|
+
"sngrates_hg_delta_plus",
|
|
270
|
+
"sngrates_lg_delta_plus",
|
|
271
|
+
"sngrates_hg_delta_minus",
|
|
272
|
+
"sngrates_lg_delta_minus",
|
|
273
|
+
],
|
|
274
|
+
inplace=True,
|
|
275
|
+
)
|
|
276
|
+
return data
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def add_species_energy(data: pd.DataFrame) -> pd.DataFrame:
|
|
280
|
+
"""Add species and energy index to the validation data.
|
|
281
|
+
|
|
282
|
+
The sector rate data is organized by species and energy index
|
|
283
|
+
in the processed data so this function adds this information
|
|
284
|
+
to each row (i.e. science frame) in the validation data.
|
|
285
|
+
|
|
286
|
+
Parameters
|
|
287
|
+
----------
|
|
288
|
+
data : pd.DataFrame
|
|
289
|
+
Validation data
|
|
290
|
+
|
|
291
|
+
Returns
|
|
292
|
+
-------
|
|
293
|
+
pd.DataFrame
|
|
294
|
+
Validation data with species and energy index added
|
|
295
|
+
"""
|
|
296
|
+
# Find the mod value for each science frame which equals the
|
|
297
|
+
# first index in the sectorates_by_mod_val array that has a value
|
|
298
|
+
# instead of a nan or empty string.
|
|
299
|
+
# Then use the mod 10 value to determine the species and energy index
|
|
300
|
+
# for each science frame and add this information to the data frame
|
|
301
|
+
data["mod_10"] = data["sectorates_by_mod_val"].apply(
|
|
302
|
+
lambda row: next(
|
|
303
|
+
(i for i, value in enumerate(row) if pd.notna(value) and value != " "), None
|
|
304
|
+
)
|
|
305
|
+
)
|
|
306
|
+
data["species"] = data["mod_10"].apply(
|
|
307
|
+
lambda row: MOD_VALUE_TO_SPECIES_ENERGY_MAP[row]["species"].lower()
|
|
308
|
+
if row is not None
|
|
309
|
+
else None
|
|
310
|
+
)
|
|
311
|
+
data["energy_idx"] = data["mod_10"].apply(
|
|
312
|
+
lambda row: MOD_VALUE_TO_SPECIES_ENERGY_MAP[row]["energy_idx"]
|
|
313
|
+
if row is not None
|
|
314
|
+
else None
|
|
315
|
+
)
|
|
316
|
+
data.drop(columns=["sectorates_by_mod_val", "mod_10"], inplace=True)
|
|
317
|
+
return data
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def compare_data(
|
|
321
|
+
expected_data: pd.DataFrame, actual_data: xr.Dataset, skip: list[str]
|
|
322
|
+
) -> None:
|
|
323
|
+
"""Compare the processed L1A counts data with the validation data.
|
|
324
|
+
|
|
325
|
+
Parameters
|
|
326
|
+
----------
|
|
327
|
+
expected_data : pd.DataFrame
|
|
328
|
+
Validation data extracted from a csv file
|
|
329
|
+
and reformatted for comparison
|
|
330
|
+
actual_data : xr.Dataset
|
|
331
|
+
Processed counts data from l1a processing
|
|
332
|
+
skip : list
|
|
333
|
+
Fields to skip in comparison
|
|
334
|
+
"""
|
|
335
|
+
for field in expected_data.columns:
|
|
336
|
+
if field not in [
|
|
337
|
+
"sc_tick_by_frame",
|
|
338
|
+
"species",
|
|
339
|
+
"energy_idx",
|
|
340
|
+
]:
|
|
341
|
+
assert (
|
|
342
|
+
field in actual_data.data_vars.keys()
|
|
343
|
+
), f"Field {field} not found in actual data variables"
|
|
344
|
+
if field not in skip:
|
|
345
|
+
for frame in range(expected_data.shape[0]):
|
|
346
|
+
if field == "species":
|
|
347
|
+
# Compare sector rates data using species and energy index.
|
|
348
|
+
# which are only present in the validation data. In the actual
|
|
349
|
+
# data, sector rates are organized by species in 4D arrays.
|
|
350
|
+
# i.e. h_counts_sectored has shape
|
|
351
|
+
# (epoch, h_energy_index, declination, azimuth).
|
|
352
|
+
# species and energy index are used to find the correct
|
|
353
|
+
# array of sector rate data from the actual data for comparison.
|
|
354
|
+
species = expected_data[field][frame]
|
|
355
|
+
energy_idx = expected_data["energy_idx"][frame]
|
|
356
|
+
if "sectorates_delta_plus" in expected_data.columns:
|
|
357
|
+
np.testing.assert_allclose(
|
|
358
|
+
actual_data[f"{species}_counts_sectored_delta_plus"][frame][
|
|
359
|
+
energy_idx
|
|
360
|
+
].data,
|
|
361
|
+
expected_data["sectorates_delta_plus"][frame],
|
|
362
|
+
rtol=1e-7, # relative tolerance
|
|
363
|
+
atol=1e-8, # absolute tolerance
|
|
364
|
+
err_msg=f"Mismatch in {species}_counts_sectored_delta_"
|
|
365
|
+
f"plus at frame {frame}, energy_idx {energy_idx}",
|
|
366
|
+
)
|
|
367
|
+
if "sectorates_delta_minus" in expected_data.columns:
|
|
368
|
+
np.testing.assert_allclose(
|
|
369
|
+
actual_data[f"{species}_counts_sectored_delta_minus"][
|
|
370
|
+
frame
|
|
371
|
+
][energy_idx].data,
|
|
372
|
+
expected_data["sectorates_delta_minus"][frame],
|
|
373
|
+
rtol=1e-7,
|
|
374
|
+
atol=1e-8,
|
|
375
|
+
err_msg=f"Mismatch in {species}_counts_sectored_delta_"
|
|
376
|
+
f"minus at frame {frame}, energy_idx {energy_idx}",
|
|
377
|
+
)
|
|
378
|
+
else:
|
|
379
|
+
np.testing.assert_allclose(
|
|
380
|
+
actual_data[f"{species}_counts_sectored"][frame][
|
|
381
|
+
energy_idx
|
|
382
|
+
].data,
|
|
383
|
+
expected_data["sectorates"][frame],
|
|
384
|
+
rtol=1e-7,
|
|
385
|
+
atol=1e-8,
|
|
386
|
+
err_msg=f"Mismatch in {species}_counts_sectored at"
|
|
387
|
+
f"frame {frame}, energy_idx {energy_idx}",
|
|
388
|
+
)
|
|
389
|
+
elif field == "sc_tick_by_frame":
|
|
390
|
+
# Get the sc_tick values for each frame in the actual data
|
|
391
|
+
# to compare with the validation data
|
|
392
|
+
sc_tick = actual_data.sc_tick.values
|
|
393
|
+
sc_tick_by_frame = sc_tick[::20]
|
|
394
|
+
assert np.array_equal(
|
|
395
|
+
sc_tick_by_frame[frame], expected_data[field][frame]
|
|
396
|
+
), f"Mismatch in {field} at frame {frame}"
|
|
397
|
+
|
|
398
|
+
else:
|
|
399
|
+
np.testing.assert_allclose(
|
|
400
|
+
actual_data[field][frame].data,
|
|
401
|
+
expected_data[field][frame],
|
|
402
|
+
rtol=1e-7,
|
|
403
|
+
atol=1e-8,
|
|
404
|
+
err_msg=f"Mismatch in {field} at frame {frame}",
|
|
405
|
+
)
|
|
Binary file
|
|
@@ -79,7 +79,7 @@ def test_parse_count_rates(sci_dataset):
|
|
|
79
79
|
"hdr_code_ok",
|
|
80
80
|
"hdr_minute_cnt",
|
|
81
81
|
"spare",
|
|
82
|
-
"
|
|
82
|
+
"livetime_counter",
|
|
83
83
|
"num_trig",
|
|
84
84
|
"num_reject",
|
|
85
85
|
"num_acc_w_pha",
|
|
@@ -107,7 +107,7 @@ def test_parse_count_rates(sci_dataset):
|
|
|
107
107
|
"nerror",
|
|
108
108
|
"nbadtags",
|
|
109
109
|
"coinrates",
|
|
110
|
-
"
|
|
110
|
+
"pbufrates",
|
|
111
111
|
"l2fgrates",
|
|
112
112
|
"l2bgrates",
|
|
113
113
|
"l3fgrates",
|
|
@@ -125,12 +125,10 @@ def test_parse_count_rates(sci_dataset):
|
|
|
125
125
|
|
|
126
126
|
def test_is_sequential():
|
|
127
127
|
"""Test the is_sequential function."""
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if not is_sequential(counters):
|
|
133
|
-
assert True
|
|
128
|
+
assert is_sequential(np.array([0, 1, 2, 3, 4]))
|
|
129
|
+
assert not is_sequential(np.array([0, 2, 3, 4, 5]))
|
|
130
|
+
# Wrap-around case
|
|
131
|
+
assert is_sequential(np.array([16382, 16383, 0, 1, 2]))
|
|
134
132
|
|
|
135
133
|
|
|
136
134
|
def test_get_valid_starting_indices():
|
|
@@ -244,7 +242,7 @@ def test_decom_hit(sci_dataset):
|
|
|
244
242
|
"hdr_heater_duty_cycle",
|
|
245
243
|
"hdr_code_ok",
|
|
246
244
|
"hdr_minute_cnt",
|
|
247
|
-
"
|
|
245
|
+
"livetime_counter",
|
|
248
246
|
"num_trig",
|
|
249
247
|
"num_reject",
|
|
250
248
|
"num_acc_w_pha",
|
|
@@ -272,7 +270,7 @@ def test_decom_hit(sci_dataset):
|
|
|
272
270
|
"nerror",
|
|
273
271
|
"nbadtags",
|
|
274
272
|
"coinrates",
|
|
275
|
-
"
|
|
273
|
+
"pbufrates",
|
|
276
274
|
"l2fgrates",
|
|
277
275
|
"l2bgrates",
|
|
278
276
|
"l3fgrates",
|