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
|
@@ -8,7 +8,16 @@ from imap_processing.hit.hit_utils import (
|
|
|
8
8
|
HitAPID,
|
|
9
9
|
get_datasets_by_apid,
|
|
10
10
|
)
|
|
11
|
-
from imap_processing.hit.l1a.hit_l1a import
|
|
11
|
+
from imap_processing.hit.l1a.hit_l1a import (
|
|
12
|
+
calculate_uncertainties,
|
|
13
|
+
decom_hit,
|
|
14
|
+
hit_l1a,
|
|
15
|
+
subcom_sectorates,
|
|
16
|
+
)
|
|
17
|
+
from imap_processing.tests.hit.helpers.l1_validation import (
|
|
18
|
+
compare_data,
|
|
19
|
+
prepare_counts_validation_data,
|
|
20
|
+
)
|
|
12
21
|
|
|
13
22
|
# TODO: Packet files are per apid at the moment so the tests currently
|
|
14
23
|
# reflect this. Eventually, HIT will provide a packet file with all apids
|
|
@@ -26,7 +35,97 @@ def hk_packet_filepath():
|
|
|
26
35
|
@pytest.fixture(scope="module")
|
|
27
36
|
def sci_packet_filepath():
|
|
28
37
|
"""Set path to test data file"""
|
|
29
|
-
return imap_module_directory / "tests/hit/test_data/
|
|
38
|
+
return imap_module_directory / "tests/hit/test_data/sci_sample.ccsds"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@pytest.fixture(scope="module")
|
|
42
|
+
def validation_data():
|
|
43
|
+
"""Load validation data from CSV file."""
|
|
44
|
+
validation_file = (
|
|
45
|
+
imap_module_directory / "tests/hit/validation_data/sci_sample_raw.csv"
|
|
46
|
+
)
|
|
47
|
+
validation_data = pd.read_csv(validation_file)
|
|
48
|
+
return validation_data
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# <=== TESTS ===>
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_subcom_sectorates(sci_packet_filepath):
|
|
55
|
+
"""Test the subcom_sectorates function.
|
|
56
|
+
|
|
57
|
+
This function organizes the sector rates data
|
|
58
|
+
by species and adds the data as new variables
|
|
59
|
+
to the dataset.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
# Unpack and decompress ccsds file to xarray datasets
|
|
63
|
+
sci_dataset = get_datasets_by_apid(sci_packet_filepath)[HitAPID.HIT_SCIENCE]
|
|
64
|
+
sci_dataset = decom_hit(sci_dataset)
|
|
65
|
+
|
|
66
|
+
# Call the function to be tested
|
|
67
|
+
subcom_sectorates(sci_dataset)
|
|
68
|
+
|
|
69
|
+
# Number of science frames in the dataset
|
|
70
|
+
frames = sci_dataset["epoch"].shape[0]
|
|
71
|
+
|
|
72
|
+
# Check if the dataset has the expected new variables
|
|
73
|
+
for species in ["h", "he4", "cno", "nemgsi", "fe"]:
|
|
74
|
+
assert f"{species}_counts_sectored" in sci_dataset
|
|
75
|
+
assert f"{species}_energy_min" in sci_dataset
|
|
76
|
+
assert f"{species}_energy_max" in sci_dataset
|
|
77
|
+
|
|
78
|
+
# Check the shape of the new data variables
|
|
79
|
+
if species == "h":
|
|
80
|
+
assert sci_dataset[f"{species}_counts_sectored"].shape == (frames, 3, 8, 15)
|
|
81
|
+
assert sci_dataset[f"{species}_energy_min"].shape == (3,)
|
|
82
|
+
elif species in ("4he", "cno", "nemgsi"):
|
|
83
|
+
assert sci_dataset[f"{species}_counts_sectored"].shape == (frames, 2, 8, 15)
|
|
84
|
+
assert sci_dataset[f"{species}_energy_min"].shape == (2,)
|
|
85
|
+
elif species == "fe":
|
|
86
|
+
assert sci_dataset[f"{species}_counts_sectored"].shape == (frames, 1, 8, 15)
|
|
87
|
+
assert sci_dataset[f"{species}_energy_min"].shape == (1,)
|
|
88
|
+
assert (
|
|
89
|
+
sci_dataset[f"{species}_energy_max"].shape
|
|
90
|
+
== sci_dataset[f"{species}_energy_min"].shape
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_calculate_uncertainties():
|
|
95
|
+
"""Test the calculate_uncertainties function.
|
|
96
|
+
|
|
97
|
+
This function calculates the uncertainties for the counts data.
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
# Create a sample dataset
|
|
101
|
+
data = {
|
|
102
|
+
"counts": (("epoch", "index"), np.array([[10, 20], [0, 1]])),
|
|
103
|
+
"version": (("epoch",), np.array([1, 1])),
|
|
104
|
+
}
|
|
105
|
+
dataset = xr.Dataset(data)
|
|
106
|
+
|
|
107
|
+
# Calculate uncertainties
|
|
108
|
+
result = calculate_uncertainties(dataset)
|
|
109
|
+
|
|
110
|
+
# Expected uncertainties
|
|
111
|
+
# DELTA_PLUS = sqrt(counts + 1) + 1
|
|
112
|
+
# DELTA_MINUS = sqrt(counts)
|
|
113
|
+
expected_delta_plus = np.array(
|
|
114
|
+
[[np.sqrt(11) + 1, np.sqrt(21) + 1], [np.sqrt(1) + 1, np.sqrt(2) + 1]]
|
|
115
|
+
)
|
|
116
|
+
expected_delta_minus = np.array(
|
|
117
|
+
[[np.sqrt(10), np.sqrt(20)], [np.sqrt(0), np.sqrt(1)]]
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Assertions
|
|
121
|
+
np.testing.assert_array_almost_equal(
|
|
122
|
+
result["counts_delta_plus"].values, expected_delta_plus
|
|
123
|
+
)
|
|
124
|
+
np.testing.assert_array_almost_equal(
|
|
125
|
+
result["counts_delta_minus"].values, expected_delta_minus
|
|
126
|
+
)
|
|
127
|
+
assert "version_delta_plus" not in result
|
|
128
|
+
assert "version_delta_minus" not in result
|
|
30
129
|
|
|
31
130
|
|
|
32
131
|
def test_validate_l1a_housekeeping_data(hk_packet_filepath):
|
|
@@ -107,191 +206,36 @@ def test_validate_l1a_housekeeping_data(hk_packet_filepath):
|
|
|
107
206
|
)
|
|
108
207
|
|
|
109
208
|
|
|
110
|
-
def
|
|
111
|
-
"""Test the subcom_sectorates function.
|
|
112
|
-
|
|
113
|
-
This function organizes the sector rates data
|
|
114
|
-
by species and adds the data as new variables
|
|
115
|
-
to the dataset.
|
|
116
|
-
"""
|
|
117
|
-
|
|
118
|
-
# Unpack and decompress ccsds file to xarray datasets
|
|
119
|
-
sci_dataset = get_datasets_by_apid(sci_packet_filepath)[HitAPID.HIT_SCIENCE]
|
|
120
|
-
sci_dataset = decom_hit(sci_dataset)
|
|
121
|
-
|
|
122
|
-
# Call the function to be tested
|
|
123
|
-
subcom_sectorates(sci_dataset)
|
|
124
|
-
|
|
125
|
-
# Number of science frames in the dataset
|
|
126
|
-
frames = sci_dataset["epoch"].shape[0]
|
|
127
|
-
|
|
128
|
-
# Check if the dataset has the expected new variables
|
|
129
|
-
for species in ["h", "he4", "cno", "nemgsi", "fe"]:
|
|
130
|
-
assert f"{species}_counts_sectored" in sci_dataset
|
|
131
|
-
assert f"{species}_energy_min" in sci_dataset
|
|
132
|
-
assert f"{species}_energy_max" in sci_dataset
|
|
133
|
-
|
|
134
|
-
# Check the shape of the new data variables
|
|
135
|
-
if species == "h":
|
|
136
|
-
assert sci_dataset[f"{species}_counts_sectored"].shape == (frames, 3, 8, 15)
|
|
137
|
-
assert sci_dataset[f"{species}_energy_min"].shape == (3,)
|
|
138
|
-
elif species in ("4he", "cno", "nemgsi"):
|
|
139
|
-
assert sci_dataset[f"{species}_counts_sectored"].shape == (frames, 2, 8, 15)
|
|
140
|
-
assert sci_dataset[f"{species}_energy_min"].shape == (2,)
|
|
141
|
-
elif species == "fe":
|
|
142
|
-
assert sci_dataset[f"{species}_counts_sectored"].shape == (frames, 1, 8, 15)
|
|
143
|
-
assert sci_dataset[f"{species}_energy_min"].shape == (1,)
|
|
144
|
-
assert (
|
|
145
|
-
sci_dataset[f"{species}_energy_max"].shape
|
|
146
|
-
== sci_dataset[f"{species}_energy_min"].shape
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
def test_validate_l1a_counts_data(sci_packet_filepath):
|
|
209
|
+
def test_validate_l1a_counts_data(sci_packet_filepath, validation_data):
|
|
151
210
|
"""Compare the output of the L1A processing to the validation data.
|
|
152
211
|
|
|
153
212
|
This test compares the counts data product with the validation data.
|
|
154
213
|
The PHA data product is not validated since it's not being decommutated.
|
|
155
214
|
|
|
215
|
+
Since the validation data is structured differently than the processed data,
|
|
216
|
+
This test prepares the validation data for comparison by calling helper
|
|
217
|
+
functions to consolidate the data into arrays and rename columns to match
|
|
218
|
+
the processed data.
|
|
219
|
+
|
|
156
220
|
Parameters
|
|
157
221
|
----------
|
|
158
222
|
sci_packet_filepath : str
|
|
159
223
|
Path to ccsds file for science data
|
|
224
|
+
validation_data : pd.DataFrame
|
|
225
|
+
Preloaded validation data
|
|
160
226
|
"""
|
|
227
|
+
|
|
161
228
|
# Process the sample data
|
|
162
229
|
processed_datasets = hit_l1a(sci_packet_filepath, "001")
|
|
163
230
|
l1a_counts_data = processed_datasets[0]
|
|
164
231
|
|
|
165
|
-
# Read in the validation data
|
|
166
|
-
validation_data = pd.read_csv(
|
|
167
|
-
imap_module_directory / "tests/hit/validation_data/sci_sample_raw1.csv"
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
# Helper functions for this test
|
|
171
|
-
def consolidate_rate_columns(data, rate_columns):
|
|
172
|
-
# The validation data isn't organized by arrays.
|
|
173
|
-
# Each value is in a separate column.
|
|
174
|
-
# Aggregate related data into arrays.
|
|
175
|
-
for new_col, prefix in rate_columns.items():
|
|
176
|
-
columns = [col for col in data.columns if prefix in col]
|
|
177
|
-
data[new_col] = data[columns].apply(lambda row: row.values, axis=1)
|
|
178
|
-
if new_col == "sectorates":
|
|
179
|
-
# Differentiate between the sectorate columns with three and
|
|
180
|
-
# five digits in the name. Those with three digits contain the
|
|
181
|
-
# sectorate value for the science frame and those with five digits
|
|
182
|
-
# are the sectorate values with the mod value appended to the end.
|
|
183
|
-
# The mod value determines the species and energy range for that
|
|
184
|
-
# science frame
|
|
185
|
-
sectorates_three_digits = data.filter(
|
|
186
|
-
regex=r"^SECTORATES_\d{3}$"
|
|
187
|
-
).columns
|
|
188
|
-
sectorates_five_digits = data.filter(
|
|
189
|
-
regex=r"^SECTORATES_\d{3}_\d{1}$"
|
|
190
|
-
).columns
|
|
191
|
-
data["sectorates"] = data[sectorates_three_digits].apply(
|
|
192
|
-
lambda row: row.values.reshape(8, 15), axis=1
|
|
193
|
-
)
|
|
194
|
-
data["sectorates_by_mod_val"] = data[sectorates_five_digits].apply(
|
|
195
|
-
lambda row: row.values, axis=1
|
|
196
|
-
)
|
|
197
|
-
data.drop(columns=columns, inplace=True)
|
|
198
|
-
return data
|
|
199
|
-
|
|
200
|
-
def process_single_rates(data):
|
|
201
|
-
# Combine the single rates for high and low gain into a 2D array
|
|
202
|
-
data["sngrates"] = data.apply(
|
|
203
|
-
lambda row: np.array([row["sngrates_hg"], row["sngrates_lg"]]), axis=1
|
|
204
|
-
)
|
|
205
|
-
data.drop(columns=["sngrates_hg", "sngrates_lg"], inplace=True)
|
|
206
|
-
return data
|
|
207
|
-
|
|
208
|
-
def process_sectorates(data):
|
|
209
|
-
# Add species and energy index to the data frame for each science frame
|
|
210
|
-
# First find the mod value for each science frame which equals the first index
|
|
211
|
-
# in the sectorates_by_mod_val array that has a value instead of a blank space
|
|
212
|
-
data["mod_10"] = data["sectorates_by_mod_val"].apply(
|
|
213
|
-
lambda row: next((i for i, value in enumerate(row) if value != " "), None)
|
|
214
|
-
)
|
|
215
|
-
# Mapping of mod value to species and energy index
|
|
216
|
-
species_energy = {
|
|
217
|
-
0: {"species": "H", "energy_idx": 0},
|
|
218
|
-
1: {"species": "H", "energy_idx": 1},
|
|
219
|
-
2: {"species": "H", "energy_idx": 2},
|
|
220
|
-
3: {"species": "He4", "energy_idx": 0},
|
|
221
|
-
4: {"species": "He4", "energy_idx": 1},
|
|
222
|
-
5: {"species": "CNO", "energy_idx": 0},
|
|
223
|
-
6: {"species": "CNO", "energy_idx": 1},
|
|
224
|
-
7: {"species": "NeMgSi", "energy_idx": 0},
|
|
225
|
-
8: {"species": "NeMgSi", "energy_idx": 1},
|
|
226
|
-
9: {"species": "Fe", "energy_idx": 0},
|
|
227
|
-
}
|
|
228
|
-
# Use the mod 10 value to determine the species and energy index
|
|
229
|
-
# for each science frame and add this information to the data frame
|
|
230
|
-
data["species"] = data["mod_10"].apply(
|
|
231
|
-
lambda row: species_energy[row]["species"].lower()
|
|
232
|
-
if row is not None
|
|
233
|
-
else None
|
|
234
|
-
)
|
|
235
|
-
data["energy_idx"] = data["mod_10"].apply(
|
|
236
|
-
lambda row: species_energy[row]["energy_idx"] if row is not None else None
|
|
237
|
-
)
|
|
238
|
-
data.drop(columns=["sectorates_by_mod_val", "mod_10"], inplace=True)
|
|
239
|
-
return data
|
|
240
|
-
|
|
241
|
-
def compare_data(expected_data, actual_data, skip):
|
|
242
|
-
# Compare the processed data to the validation data
|
|
243
|
-
for field in expected_data.columns:
|
|
244
|
-
if field not in [
|
|
245
|
-
"sc_tick",
|
|
246
|
-
"hdr_status_bits",
|
|
247
|
-
"species",
|
|
248
|
-
"energy_idx",
|
|
249
|
-
]:
|
|
250
|
-
assert field in l1a_counts_data.data_vars.keys()
|
|
251
|
-
if field not in ignore:
|
|
252
|
-
for frame in range(expected_data.shape[0]):
|
|
253
|
-
if field == "species":
|
|
254
|
-
species = expected_data[field][frame]
|
|
255
|
-
energy_idx = expected_data["energy_idx"][frame]
|
|
256
|
-
assert np.array_equal(
|
|
257
|
-
actual_data[f"{species}_counts_sectored"][frame][
|
|
258
|
-
energy_idx
|
|
259
|
-
].data,
|
|
260
|
-
expected_data["sectorates"][frame],
|
|
261
|
-
)
|
|
262
|
-
else:
|
|
263
|
-
assert np.array_equal(
|
|
264
|
-
actual_data[field][frame].data, expected_data[field][frame]
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
rate_columns = {
|
|
268
|
-
"coinrates": "COINRATES_",
|
|
269
|
-
"bufrates": "BUFRATES_",
|
|
270
|
-
"l2fgrates": "L2FGRATES_",
|
|
271
|
-
"l2bgrates": "L2BGRATES_",
|
|
272
|
-
"l3fgrates": "L3FGRATES_",
|
|
273
|
-
"l3bgrates": "L3BGRATES_",
|
|
274
|
-
"penfgrates": "PENFGRATES_",
|
|
275
|
-
"penbgrates": "PENBGRATES_",
|
|
276
|
-
"sectorates": "SECTORATES_",
|
|
277
|
-
"l4fgrates": "L4FGRATES_",
|
|
278
|
-
"l4bgrates": "L4BGRATES_",
|
|
279
|
-
"ialirtrates": "IALIRTRATES_",
|
|
280
|
-
"sngrates_hg": "SNGRATES_HG_",
|
|
281
|
-
"sngrates_lg": "SNGRATES_LG_",
|
|
282
|
-
}
|
|
283
|
-
|
|
284
232
|
# Prepare validation data for comparison with processed data
|
|
285
|
-
validation_data
|
|
286
|
-
validation_data = consolidate_rate_columns(validation_data, rate_columns)
|
|
287
|
-
validation_data = process_single_rates(validation_data)
|
|
288
|
-
validation_data = process_sectorates(validation_data)
|
|
233
|
+
validation_data = prepare_counts_validation_data(validation_data)
|
|
289
234
|
|
|
290
|
-
# Fields to skip in comparison. CCSDS headers plus a few others
|
|
291
|
-
# relevant to the comparison.
|
|
235
|
+
# Fields to skip in comparison. CCSDS headers plus a few others.
|
|
292
236
|
# The CCSDS header fields contain data per packet in the dataset, but the
|
|
293
|
-
# validation data has
|
|
294
|
-
|
|
237
|
+
# validation data has one value per science frame.
|
|
238
|
+
skip_fields = [
|
|
295
239
|
"version",
|
|
296
240
|
"type",
|
|
297
241
|
"sec_hdr_flg",
|
|
@@ -299,20 +243,13 @@ def test_validate_l1a_counts_data(sci_packet_filepath):
|
|
|
299
243
|
"seq_flgs",
|
|
300
244
|
"src_seq_ctr",
|
|
301
245
|
"pkt_len",
|
|
302
|
-
"sc_tick",
|
|
303
|
-
"hdr_status_bits",
|
|
304
246
|
"energy_idx",
|
|
305
247
|
]
|
|
306
248
|
|
|
307
249
|
# Compare processed data to validation data
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
# TODO: add validation for hdr_status_bits once validation data has been updated
|
|
312
|
-
# to include this field broken out into its subfields
|
|
313
|
-
|
|
314
|
-
# TODO: add validation for CCSDS fields? currently validation data only has
|
|
315
|
-
# one value per frame and the processed data has one value per packet.
|
|
250
|
+
compare_data(
|
|
251
|
+
expected_data=validation_data, actual_data=l1a_counts_data, skip=skip_fields
|
|
252
|
+
)
|
|
316
253
|
|
|
317
254
|
|
|
318
255
|
def test_hit_l1a(hk_packet_filepath, sci_packet_filepath):
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import numpy as np
|
|
1
2
|
import pandas as pd
|
|
2
3
|
import pytest
|
|
3
4
|
import xarray as xr
|
|
@@ -5,30 +6,47 @@ import xarray as xr
|
|
|
5
6
|
from imap_processing import imap_module_directory
|
|
6
7
|
from imap_processing.hit.l1a import hit_l1a
|
|
7
8
|
from imap_processing.hit.l1b import hit_l1b
|
|
9
|
+
from imap_processing.tests.hit.helpers.l1_validation import (
|
|
10
|
+
prepare_standard_rates_validation_data,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
# TODO: Packet files are per apid at the moment so the tests currently
|
|
14
|
+
# reflect this. Eventually, HIT will provide a packet file with all apids
|
|
15
|
+
# and the tests will need to be updated.
|
|
8
16
|
|
|
9
17
|
|
|
10
18
|
@pytest.fixture(scope="module")
|
|
11
19
|
def packet_filepath():
|
|
12
20
|
"""Set path to test data file"""
|
|
21
|
+
# TODO: Update this path when HIT provides a packet file with all apids.
|
|
22
|
+
# Current test file only has the housekeeping apid is available.
|
|
13
23
|
return (
|
|
14
24
|
imap_module_directory / "tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts"
|
|
15
25
|
)
|
|
16
26
|
|
|
17
27
|
|
|
28
|
+
@pytest.fixture(scope="module")
|
|
29
|
+
def sci_packet_filepath():
|
|
30
|
+
"""Set path to test data file"""
|
|
31
|
+
return imap_module_directory / "tests/hit/test_data/sci_sample.ccsds"
|
|
32
|
+
|
|
33
|
+
|
|
18
34
|
@pytest.fixture()
|
|
19
|
-
def dependencies(packet_filepath):
|
|
35
|
+
def dependencies(packet_filepath, sci_packet_filepath):
|
|
20
36
|
"""Get dependencies for L1B processing"""
|
|
21
37
|
# Create dictionary of dependencies and add CCSDS packet file
|
|
22
38
|
data_dict = {"imap_hit_l0_raw": packet_filepath}
|
|
23
39
|
# Add L1A datasets
|
|
24
40
|
l1a_datasets = hit_l1a.hit_l1a(packet_filepath, "001")
|
|
41
|
+
# TODO: Remove this when HIT provides a packet file with all apids.
|
|
42
|
+
l1a_datasets.extend(hit_l1a.hit_l1a(sci_packet_filepath, "001"))
|
|
25
43
|
for dataset in l1a_datasets:
|
|
26
44
|
data_dict[dataset.attrs["Logical_source"]] = dataset
|
|
27
45
|
return data_dict
|
|
28
46
|
|
|
29
47
|
|
|
30
48
|
@pytest.fixture()
|
|
31
|
-
def
|
|
49
|
+
def l1b_hk_dataset(dependencies):
|
|
32
50
|
"""Get the housekeeping dataset"""
|
|
33
51
|
datasets = hit_l1b.hit_l1b(dependencies, "001")
|
|
34
52
|
for dataset in datasets:
|
|
@@ -36,7 +54,100 @@ def hk_dataset(dependencies):
|
|
|
36
54
|
return dataset
|
|
37
55
|
|
|
38
56
|
|
|
39
|
-
|
|
57
|
+
@pytest.fixture()
|
|
58
|
+
def l1b_standard_rates_dataset(dependencies):
|
|
59
|
+
"""Get the standard rates dataset"""
|
|
60
|
+
# TODO: use this fixture in future unit test to validate the standard rates dataset
|
|
61
|
+
datasets = hit_l1b.hit_l1b(dependencies, "001")
|
|
62
|
+
for dataset in datasets:
|
|
63
|
+
if dataset.attrs["Logical_source"] == "imap_hit_l1b_standard-rates":
|
|
64
|
+
return dataset
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@pytest.fixture()
|
|
68
|
+
def l1a_counts_dataset(sci_packet_filepath):
|
|
69
|
+
"""Get L1A counts dataset to test l1b processing functions"""
|
|
70
|
+
l1a_datasets = hit_l1a.hit_l1a(sci_packet_filepath, "001")
|
|
71
|
+
for dataset in l1a_datasets:
|
|
72
|
+
if dataset.attrs["Logical_source"] == "imap_hit_l1a_count-rates":
|
|
73
|
+
return dataset
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_process_standard_rates_data(l1a_counts_dataset):
|
|
77
|
+
"""Test function for processing standard rates data"""
|
|
78
|
+
l1b_standard_rates_dataset = hit_l1b.process_standard_rates_data(l1a_counts_dataset)
|
|
79
|
+
|
|
80
|
+
# Check that a xarray dataset with the correct logical source is returned
|
|
81
|
+
assert isinstance(l1b_standard_rates_dataset, xr.Dataset)
|
|
82
|
+
|
|
83
|
+
# Define the data variables that should be present in the dataset
|
|
84
|
+
valid_data_vars = {
|
|
85
|
+
"sngrates",
|
|
86
|
+
"coinrates",
|
|
87
|
+
"pbufrates",
|
|
88
|
+
"l2fgrates",
|
|
89
|
+
"l2bgrates",
|
|
90
|
+
"l3fgrates",
|
|
91
|
+
"l3bgrates",
|
|
92
|
+
"penfgrates",
|
|
93
|
+
"penbgrates",
|
|
94
|
+
"ialirtrates",
|
|
95
|
+
"l4fgrates",
|
|
96
|
+
"l4bgrates",
|
|
97
|
+
"sngrates_delta_plus",
|
|
98
|
+
"coinrates_delta_plus",
|
|
99
|
+
"pbufrates_delta_plus",
|
|
100
|
+
"l2fgrates_delta_plus",
|
|
101
|
+
"l2bgrates_delta_plus",
|
|
102
|
+
"l3fgrates_delta_plus",
|
|
103
|
+
"l3bgrates_delta_plus",
|
|
104
|
+
"penfgrates_delta_plus",
|
|
105
|
+
"penbgrates_delta_plus",
|
|
106
|
+
"ialirtrates_delta_plus",
|
|
107
|
+
"l4fgrates_delta_plus",
|
|
108
|
+
"l4bgrates_delta_plus",
|
|
109
|
+
"sngrates_delta_minus",
|
|
110
|
+
"coinrates_delta_minus",
|
|
111
|
+
"pbufrates_delta_minus",
|
|
112
|
+
"l2fgrates_delta_minus",
|
|
113
|
+
"l2bgrates_delta_minus",
|
|
114
|
+
"l3fgrates_delta_minus",
|
|
115
|
+
"l3bgrates_delta_minus",
|
|
116
|
+
"penfgrates_delta_minus",
|
|
117
|
+
"penbgrates_delta_minus",
|
|
118
|
+
"ialirtrates_delta_minus",
|
|
119
|
+
"l4fgrates_delta_minus",
|
|
120
|
+
"l4bgrates_delta_minus",
|
|
121
|
+
"dynamic_threshold_state",
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
valid_coords = [
|
|
125
|
+
"epoch",
|
|
126
|
+
"gain",
|
|
127
|
+
"sngrates_index",
|
|
128
|
+
"coinrates_index",
|
|
129
|
+
"pbufrates_index",
|
|
130
|
+
"l2fgrates_index",
|
|
131
|
+
"l2bgrates_index",
|
|
132
|
+
"l3fgrates_index",
|
|
133
|
+
"l3bgrates_index",
|
|
134
|
+
"penfgrates_index",
|
|
135
|
+
"penbgrates_index",
|
|
136
|
+
"ialirtrates_index",
|
|
137
|
+
"l4fgrates_index",
|
|
138
|
+
"l4bgrates_index",
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
# Check that the dataset has the correct variables
|
|
142
|
+
assert valid_data_vars == set(
|
|
143
|
+
l1b_standard_rates_dataset.data_vars.keys()
|
|
144
|
+
), "Data variables mismatch"
|
|
145
|
+
assert valid_coords == list(
|
|
146
|
+
l1b_standard_rates_dataset.coords
|
|
147
|
+
), "Coordinates mismatch"
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def test_hit_l1b_hk_dataset_variables(l1b_hk_dataset):
|
|
40
151
|
"""Test the variables in the housekeeping dataset"""
|
|
41
152
|
# Define the keys that should have dropped from the housekeeping dataset
|
|
42
153
|
dropped_keys = {
|
|
@@ -113,61 +224,18 @@ def test_hit_l1b_hk_dataset_variables(hk_dataset):
|
|
|
113
224
|
"mode",
|
|
114
225
|
}
|
|
115
226
|
# Check that the dataset has the correct variables
|
|
116
|
-
assert valid_keys == set(
|
|
117
|
-
assert set(dropped_keys).isdisjoint(set(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def test_hit_l1b_hk_dataset_attributes(hk_dataset):
|
|
121
|
-
"""Test the attributes, dims, and coords in the housekeeping dataset"""
|
|
122
|
-
# TODO consider removing this test since it may be hard to upkeep if
|
|
123
|
-
# attributes change
|
|
124
|
-
# Define the housekeeping dataset attributes
|
|
125
|
-
dataset_attrs = {
|
|
126
|
-
"Acknowledgement": "Please acknowledge the IMAP Mission Principal "
|
|
127
|
-
"Investigator, Prof. David J. McComas of Princeton "
|
|
128
|
-
"University.\n",
|
|
129
|
-
"Data_level": "1B",
|
|
130
|
-
"Data_type": "L1B_HK>Level-1B Housekeeping",
|
|
131
|
-
"Data_version": "001",
|
|
132
|
-
"Descriptor": "HIT>IMAP High-energy Ion Telescope",
|
|
133
|
-
"Discipline": "Solar Physics>Heliospheric Physics",
|
|
134
|
-
"File_naming_convention": "source_descriptor_datatype_yyyyMMdd_vNNN",
|
|
135
|
-
"HTTP_LINK": "https://imap.princeton.edu/",
|
|
136
|
-
"Instrument_type": "Particles (space)",
|
|
137
|
-
"LINK_TITLE": "IMAP The Interstellar Mapping and Acceleration Probe",
|
|
138
|
-
"Logical_file_id": None,
|
|
139
|
-
"Logical_source": "imap_hit_l1b_hk",
|
|
140
|
-
"Logical_source_description": "IMAP Mission HIT Instrument Level-1B "
|
|
141
|
-
"Housekeeping Data.",
|
|
142
|
-
"Mission_group": "IMAP",
|
|
143
|
-
"PI_affiliation": "Princeton University",
|
|
144
|
-
"PI_name": "Prof. David J. McComas",
|
|
145
|
-
"Project": "STP>Solar Terrestrial Probes",
|
|
146
|
-
"Rules_of_use": "All IMAP data products are publicly released and citable for "
|
|
147
|
-
"use in publications. Please consult the IMAP team "
|
|
148
|
-
"publications and personnel for further details on "
|
|
149
|
-
"production, processing, and usage of these data.\n",
|
|
150
|
-
"Source_name": "IMAP>Interstellar Mapping and Acceleration Probe",
|
|
151
|
-
"TEXT": "The High-energy Ion Telescope (HIT) measures the elemental "
|
|
152
|
-
"composition, energy spectra, angle distributions, and arrival "
|
|
153
|
-
"times of high-energy ions. HIT delivers full-sky coverage from "
|
|
154
|
-
"a wide instrument field-of-view (FOV) to enable a high resolution "
|
|
155
|
-
"of ion measurements, such as observing shock-accelerated ions, "
|
|
156
|
-
"determining the origin of the solar energetic particles (SEPs) "
|
|
157
|
-
"spectra, and resolving particle transport in the heliosphere. "
|
|
158
|
-
"See https://imap.princeton.edu/instruments/hit for more details.\n",
|
|
159
|
-
}
|
|
227
|
+
assert valid_keys == set(l1b_hk_dataset.data_vars.keys())
|
|
228
|
+
assert set(dropped_keys).isdisjoint(set(l1b_hk_dataset.data_vars.keys()))
|
|
160
229
|
|
|
161
230
|
# Define the coordinates and dimensions. Both have equivalent values
|
|
162
231
|
dataset_coords_dims = {"epoch", "adc_channels", "adc_channels_label"}
|
|
163
232
|
|
|
164
|
-
# Check that the dataset has the correct
|
|
165
|
-
assert
|
|
166
|
-
assert hk_dataset.coords.keys() == dataset_coords_dims
|
|
233
|
+
# Check that the dataset has the correct coordinates, and dimensions
|
|
234
|
+
assert l1b_hk_dataset.coords.keys() == dataset_coords_dims
|
|
167
235
|
|
|
168
236
|
|
|
169
|
-
def
|
|
170
|
-
"""
|
|
237
|
+
def test_validate_l1b_hk_data(l1b_hk_dataset):
|
|
238
|
+
"""Test to validate the housekeeping dataset created by the L1B processing.
|
|
171
239
|
|
|
172
240
|
Parameters
|
|
173
241
|
----------
|
|
@@ -214,7 +282,7 @@ def test_validate_l1b_housekeeping_data(hk_dataset):
|
|
|
214
282
|
}
|
|
215
283
|
|
|
216
284
|
# Check that dropped variables are not in the dataset
|
|
217
|
-
assert set(dropped_fields).isdisjoint(set(
|
|
285
|
+
assert set(dropped_fields).isdisjoint(set(l1b_hk_dataset.data_vars.keys()))
|
|
218
286
|
|
|
219
287
|
# TODO: uncomment block after new validation data is provided
|
|
220
288
|
# Define the keys that should be ignored in the validation
|
|
@@ -241,6 +309,30 @@ def test_validate_l1b_housekeeping_data(hk_dataset):
|
|
|
241
309
|
# )
|
|
242
310
|
|
|
243
311
|
|
|
312
|
+
def test_validate_l1b_standard_rates_data(l1b_standard_rates_dataset):
|
|
313
|
+
"""A test to validate the standard rates dataset created by the L1B processing."""
|
|
314
|
+
|
|
315
|
+
validation_data = pd.read_csv(
|
|
316
|
+
imap_module_directory
|
|
317
|
+
/ "tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv"
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
validation_data = prepare_standard_rates_validation_data(validation_data)
|
|
321
|
+
|
|
322
|
+
for field in validation_data.columns:
|
|
323
|
+
assert (
|
|
324
|
+
field in l1b_standard_rates_dataset.data_vars.keys()
|
|
325
|
+
), f"Field {field} not found in actual data variables"
|
|
326
|
+
for frame in range(validation_data.shape[0]):
|
|
327
|
+
np.testing.assert_allclose(
|
|
328
|
+
l1b_standard_rates_dataset[field][frame].data,
|
|
329
|
+
validation_data[field][frame],
|
|
330
|
+
rtol=1e-7,
|
|
331
|
+
atol=1e-3,
|
|
332
|
+
err_msg=f"Mismatch in {field} at frame {frame}",
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
|
|
244
336
|
def test_hit_l1b(dependencies):
|
|
245
337
|
"""Test creating L1B CDF files
|
|
246
338
|
|
|
@@ -254,6 +346,8 @@ def test_hit_l1b(dependencies):
|
|
|
254
346
|
# TODO: update assertions after science data processing is completed
|
|
255
347
|
datasets = hit_l1b.hit_l1b(dependencies, "001")
|
|
256
348
|
|
|
257
|
-
assert len(datasets) ==
|
|
258
|
-
|
|
349
|
+
assert len(datasets) == 2
|
|
350
|
+
for dataset in datasets:
|
|
351
|
+
assert isinstance(dataset, xr.Dataset)
|
|
259
352
|
assert datasets[0].attrs["Logical_source"] == "imap_hit_l1b_hk"
|
|
353
|
+
assert datasets[1].attrs["Logical_source"] == "imap_hit_l1b_standard-rates"
|