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,184 @@
|
|
|
1
|
+
from contextlib import nullcontext as does_not_raise
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from imap_processing.spice.geometry import SpiceFrame
|
|
8
|
+
from imap_processing.spice.spin import (
|
|
9
|
+
get_instrument_spin_phase,
|
|
10
|
+
get_spacecraft_spin_phase,
|
|
11
|
+
get_spin_angle,
|
|
12
|
+
get_spin_data,
|
|
13
|
+
interpolate_spin_data,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture()
|
|
18
|
+
def fake_spin_data(monkeypatch, spice_test_data_path):
|
|
19
|
+
"""Generate fake spin dataframe for testing"""
|
|
20
|
+
fake_spin_path = spice_test_data_path / "fake_spin_data.csv"
|
|
21
|
+
monkeypatch.setenv("SPIN_DATA_FILEPATH", str(fake_spin_path))
|
|
22
|
+
return fake_spin_path
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.mark.parametrize(
|
|
26
|
+
"query_met_times, expected",
|
|
27
|
+
[
|
|
28
|
+
(
|
|
29
|
+
15,
|
|
30
|
+
[[1, 15, 0, 15.0, 1, 1, 0, 0, 15.0, 0.0]],
|
|
31
|
+
), # Scalar test at spin start time
|
|
32
|
+
(
|
|
33
|
+
np.array([15.1, 30.2]),
|
|
34
|
+
[
|
|
35
|
+
[1, 15, 0, 15.0, 1, 1, 0, 0, 15.0, 0.1 / 15],
|
|
36
|
+
[2, 30, 0, 15.0, 1, 1, 0, 0, 30.0, 0.2 / 15],
|
|
37
|
+
],
|
|
38
|
+
), # Array test
|
|
39
|
+
],
|
|
40
|
+
)
|
|
41
|
+
def test_interpolate_spin_data(query_met_times, expected, fake_spin_data):
|
|
42
|
+
"""Test interpolate_spin_data() with generated spin data."""
|
|
43
|
+
# Call the function
|
|
44
|
+
spin_df = interpolate_spin_data(query_met_times=query_met_times)
|
|
45
|
+
|
|
46
|
+
# Test the value
|
|
47
|
+
for i_row, row in enumerate(expected):
|
|
48
|
+
np.testing.assert_array_almost_equal(spin_df.iloc[i_row].tolist(), row)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@pytest.mark.parametrize(
|
|
52
|
+
"query_met_times, expected",
|
|
53
|
+
[
|
|
54
|
+
(15, 0.0), # Scalar test
|
|
55
|
+
(np.array([15.1, 30.1]), np.array([0.1 / 15, 0.1 / 15])), # Array test
|
|
56
|
+
(np.array([50]), np.array([5 / 15])), # Single element array test
|
|
57
|
+
# The first spin has thruster firing set, but should return valid value
|
|
58
|
+
(5.0, 5 / 15),
|
|
59
|
+
# Test invalid spin period flag causes nan
|
|
60
|
+
(106.0, np.nan),
|
|
61
|
+
# Test invalid spin phase flag causes nans
|
|
62
|
+
(np.array([121, 122, 123]), np.full(3, np.nan)),
|
|
63
|
+
# Test that invalid spin period causes nans
|
|
64
|
+
(np.array([110, 111]), np.full(2, np.nan)),
|
|
65
|
+
# Test for time in missing spin
|
|
66
|
+
(65, np.nan),
|
|
67
|
+
(np.array([65.1, 66]), np.full(2, np.nan)),
|
|
68
|
+
# Combined test
|
|
69
|
+
(
|
|
70
|
+
np.array([7.5, 30, 61, 75, 106, 121, 136]),
|
|
71
|
+
np.array([0.5, 0, np.nan, 0, np.nan, np.nan, 1 / 15]),
|
|
72
|
+
),
|
|
73
|
+
# Test that this spin phase range [0, 1) is valid which
|
|
74
|
+
# is same as [0, 360) degree angle. At 15 seconds the spacecraft
|
|
75
|
+
# has completed a full spin
|
|
76
|
+
(np.array([0, 15]), np.zeros(2)),
|
|
77
|
+
],
|
|
78
|
+
)
|
|
79
|
+
def test_get_spacecraft_spin_phase(query_met_times, expected, fake_spin_data):
|
|
80
|
+
"""Test get_spacecraft_spin_phase() with generated spin data."""
|
|
81
|
+
# Call the function
|
|
82
|
+
spin_phases = get_spacecraft_spin_phase(query_met_times=query_met_times)
|
|
83
|
+
|
|
84
|
+
# Test the returned type
|
|
85
|
+
if isinstance(expected, float):
|
|
86
|
+
assert isinstance(spin_phases, float), "Spin phase must be a float."
|
|
87
|
+
elif expected is None:
|
|
88
|
+
assert len(spin_phases) == 0, "Spin phase must be empty."
|
|
89
|
+
else:
|
|
90
|
+
assert spin_phases.shape == expected.shape
|
|
91
|
+
# Test the value
|
|
92
|
+
np.testing.assert_array_almost_equal(spin_phases, expected)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@pytest.mark.parametrize(
|
|
96
|
+
"spin_phases, degrees, expected, context",
|
|
97
|
+
[
|
|
98
|
+
(np.arange(0, 1, 0.1), True, np.arange(0, 1, 0.1) * 360, does_not_raise()),
|
|
99
|
+
(
|
|
100
|
+
np.arange(0, 1, 0.1),
|
|
101
|
+
False,
|
|
102
|
+
np.arange(0, 1, 0.1) * 2 * np.pi,
|
|
103
|
+
does_not_raise(),
|
|
104
|
+
),
|
|
105
|
+
(
|
|
106
|
+
np.array([0, 1]),
|
|
107
|
+
True,
|
|
108
|
+
None,
|
|
109
|
+
pytest.raises(ValueError, match="Spin phases *"),
|
|
110
|
+
),
|
|
111
|
+
(
|
|
112
|
+
np.array([-1, 0]),
|
|
113
|
+
False,
|
|
114
|
+
None,
|
|
115
|
+
pytest.raises(ValueError, match="Spin phases *"),
|
|
116
|
+
),
|
|
117
|
+
],
|
|
118
|
+
)
|
|
119
|
+
def test_get_spin_angle(spin_phases, degrees, expected, context):
|
|
120
|
+
"""Test get_spin_angle() with fake spin phases."""
|
|
121
|
+
with context:
|
|
122
|
+
spin_angles = get_spin_angle(spin_phases, degrees=degrees)
|
|
123
|
+
np.testing.assert_array_equal(spin_angles, expected)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@pytest.mark.parametrize("query_met_times", [-1, 165])
|
|
127
|
+
def test_get_spacecraft_spin_phase_value_error(query_met_times, fake_spin_data):
|
|
128
|
+
"""Test get_spacecraft_spin_phase() for raising ValueError."""
|
|
129
|
+
with pytest.raises(ValueError, match="Query times"):
|
|
130
|
+
_ = get_spacecraft_spin_phase(query_met_times)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@pytest.mark.usefixtures("use_fake_spin_data_for_time")
|
|
134
|
+
def test_get_spin_data(use_fake_spin_data_for_time):
|
|
135
|
+
"""Test get_spin_data() with generated spin data."""
|
|
136
|
+
use_fake_spin_data_for_time(453051323.0 - 56120)
|
|
137
|
+
spin_data = get_spin_data()
|
|
138
|
+
|
|
139
|
+
(
|
|
140
|
+
np.testing.assert_array_equal(spin_data["spin_number"], np.arange(5761)),
|
|
141
|
+
"One day should have 5,761 records of 15 seconds when including end_met.",
|
|
142
|
+
)
|
|
143
|
+
assert isinstance(spin_data, pd.DataFrame), "Return type must be pandas.DataFrame."
|
|
144
|
+
|
|
145
|
+
assert set(spin_data.columns) == {
|
|
146
|
+
"spin_number",
|
|
147
|
+
"spin_start_sec",
|
|
148
|
+
"spin_start_subsec",
|
|
149
|
+
"spin_period_sec",
|
|
150
|
+
"spin_period_valid",
|
|
151
|
+
"spin_phase_valid",
|
|
152
|
+
"spin_period_source",
|
|
153
|
+
"thruster_firing",
|
|
154
|
+
"spin_start_time",
|
|
155
|
+
}, "Spin data must have the specified fields."
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@pytest.mark.parametrize(
|
|
159
|
+
"instrument",
|
|
160
|
+
[
|
|
161
|
+
SpiceFrame.IMAP_LO,
|
|
162
|
+
SpiceFrame.IMAP_HI_45,
|
|
163
|
+
SpiceFrame.IMAP_HI_90,
|
|
164
|
+
SpiceFrame.IMAP_ULTRA_45,
|
|
165
|
+
SpiceFrame.IMAP_ULTRA_90,
|
|
166
|
+
SpiceFrame.IMAP_SWAPI,
|
|
167
|
+
SpiceFrame.IMAP_IDEX,
|
|
168
|
+
SpiceFrame.IMAP_CODICE,
|
|
169
|
+
SpiceFrame.IMAP_HIT,
|
|
170
|
+
SpiceFrame.IMAP_SWE,
|
|
171
|
+
SpiceFrame.IMAP_GLOWS,
|
|
172
|
+
SpiceFrame.IMAP_MAG,
|
|
173
|
+
],
|
|
174
|
+
)
|
|
175
|
+
def test_get_instrument_spin_phase(instrument, fake_spin_data):
|
|
176
|
+
"""Test coverage for get_instrument_spin_phase()"""
|
|
177
|
+
met_times = np.array([7.5, 30, 61, 75, 106, 121, 136])
|
|
178
|
+
expected_nan_mask = np.array([False, False, True, False, True, True, False])
|
|
179
|
+
inst_phase = get_instrument_spin_phase(met_times, instrument)
|
|
180
|
+
assert inst_phase.shape == met_times.shape
|
|
181
|
+
np.testing.assert_array_equal(np.isnan(inst_phase), expected_nan_mask)
|
|
182
|
+
assert np.logical_and(
|
|
183
|
+
0 <= inst_phase[~expected_nan_mask], inst_phase[~expected_nan_mask] < 1
|
|
184
|
+
).all()
|
|
@@ -7,14 +7,15 @@ import spiceypy
|
|
|
7
7
|
from imap_processing.spice import IMAP_SC_ID
|
|
8
8
|
from imap_processing.spice.time import (
|
|
9
9
|
TICK_DURATION,
|
|
10
|
-
_sct2e_wrapper,
|
|
11
10
|
et_to_utc,
|
|
12
|
-
j2000ns_to_j2000s,
|
|
13
11
|
met_to_datetime64,
|
|
14
|
-
met_to_j2000ns,
|
|
15
12
|
met_to_sclkticks,
|
|
13
|
+
met_to_ttj2000ns,
|
|
16
14
|
met_to_utc,
|
|
15
|
+
sct_to_et,
|
|
16
|
+
sct_to_ttj2000s,
|
|
17
17
|
str_to_et,
|
|
18
|
+
ttj2000ns_to_et,
|
|
18
19
|
)
|
|
19
20
|
|
|
20
21
|
|
|
@@ -27,10 +28,11 @@ def test_met_to_sclkticks(met):
|
|
|
27
28
|
np.testing.assert_array_equal(ticks, expected)
|
|
28
29
|
|
|
29
30
|
|
|
30
|
-
def
|
|
31
|
-
"""Test coverage for
|
|
31
|
+
def test_met_to_ttj2000ns(furnish_time_kernels):
|
|
32
|
+
"""Test coverage for met_to_ttj2000ns function."""
|
|
32
33
|
utc = "2026-01-01T00:00:00.125"
|
|
33
34
|
et = spiceypy.str2et(utc)
|
|
35
|
+
spicey_tt = spiceypy.unitim(et, "ET", "TT")
|
|
34
36
|
sclk_str = spiceypy.sce2s(IMAP_SC_ID, et)
|
|
35
37
|
seconds, ticks = sclk_str.split("/")[1].split(":")
|
|
36
38
|
# There is some floating point error calculating tick duration from 1 clock
|
|
@@ -39,26 +41,30 @@ def test_met_to_j2000ns(furnish_time_kernels):
|
|
|
39
41
|
spiceypy.sct2e(IMAP_SC_ID, 1e12) - spiceypy.sct2e(IMAP_SC_ID, 0)
|
|
40
42
|
) / 1e12
|
|
41
43
|
met = float(seconds) + float(ticks) * spice_tick_duration
|
|
42
|
-
|
|
43
|
-
assert
|
|
44
|
-
np.testing.assert_array_equal(
|
|
44
|
+
tt = met_to_ttj2000ns(met)
|
|
45
|
+
assert tt.dtype == np.int64
|
|
46
|
+
np.testing.assert_array_equal(tt, np.array(spicey_tt * 1e9))
|
|
45
47
|
|
|
46
48
|
|
|
47
|
-
def
|
|
48
|
-
"""Test coverage for
|
|
49
|
+
def test_ttj2000ns_to_et(furnish_time_kernels):
|
|
50
|
+
"""Test coverage for ttj2000ns_to_et function."""
|
|
49
51
|
# Use spice to come up with reasonable J2000 values
|
|
50
52
|
utc = "2025-09-23T00:00:00.000"
|
|
51
53
|
# Test single value input
|
|
52
54
|
et = spiceypy.str2et(utc)
|
|
53
|
-
epoch = int(et * 1e9)
|
|
54
|
-
j2000s =
|
|
55
|
+
epoch = int(spiceypy.unitim(et, "ET", "TT") * 1e9)
|
|
56
|
+
j2000s = ttj2000ns_to_et(epoch)
|
|
55
57
|
assert j2000s == et
|
|
58
|
+
# Test for bug when spiceypy tries to iterate over 0-d array returned by
|
|
59
|
+
# np.vectorize for the scalar case
|
|
60
|
+
assert not spiceypy.support_types.is_iterable(et)
|
|
56
61
|
# Test array input
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
j2000s, np.arange(et, et + 10000, 100, dtype=np.float64)
|
|
62
|
+
ets = np.arange(et, et + 10000, 100)
|
|
63
|
+
epoch = np.array([spiceypy.unitim(et, "ET", "TT") * 1e9 for et in ets]).astype(
|
|
64
|
+
np.int64
|
|
61
65
|
)
|
|
66
|
+
j2000s = ttj2000ns_to_et(epoch)
|
|
67
|
+
np.testing.assert_array_equal(j2000s, ets)
|
|
62
68
|
|
|
63
69
|
|
|
64
70
|
@pytest.mark.parametrize(
|
|
@@ -106,26 +112,42 @@ def test_met_to_datetime64(furnish_time_kernels, utc):
|
|
|
106
112
|
et_arr = spiceypy.str2et(utc)
|
|
107
113
|
sclk_ticks = np.array([spiceypy.sce2c(IMAP_SC_ID, et) for et in et_arr])
|
|
108
114
|
else:
|
|
109
|
-
expected_dt64 = np.
|
|
115
|
+
expected_dt64 = np.datetime64(utc)
|
|
110
116
|
et = spiceypy.str2et(utc)
|
|
111
117
|
sclk_ticks = spiceypy.sce2c(IMAP_SC_ID, et)
|
|
112
118
|
met = sclk_ticks * TICK_DURATION
|
|
113
119
|
dt64 = met_to_datetime64(met)
|
|
120
|
+
|
|
121
|
+
if isinstance(utc, list):
|
|
122
|
+
assert isinstance(dt64, np.ndarray)
|
|
123
|
+
assert dt64.dtype.name == "datetime64[ns]"
|
|
124
|
+
else:
|
|
125
|
+
assert isinstance(dt64, np.datetime64)
|
|
114
126
|
np.testing.assert_array_equal(
|
|
115
127
|
dt64.astype("datetime64[us]"), expected_dt64.astype("datetime64[us]")
|
|
116
128
|
)
|
|
117
129
|
|
|
118
130
|
|
|
119
131
|
@pytest.mark.parametrize("sclk_ticks", [0.0, np.arange(10)])
|
|
120
|
-
def
|
|
121
|
-
"""Test for `
|
|
122
|
-
et =
|
|
132
|
+
def test_sct_to_et(sclk_ticks):
|
|
133
|
+
"""Test for `sct_to_et` function."""
|
|
134
|
+
et = sct_to_et(sclk_ticks)
|
|
123
135
|
if isinstance(sclk_ticks, float):
|
|
124
136
|
assert isinstance(et, float)
|
|
125
137
|
else:
|
|
126
138
|
assert len(et) == len(sclk_ticks)
|
|
127
139
|
|
|
128
140
|
|
|
141
|
+
@pytest.mark.parametrize("sclk_ticks", [0.0, np.arange(10)])
|
|
142
|
+
def test_sct_to_ttj2000s(sclk_ticks):
|
|
143
|
+
"""Test for `sct_to_ttj2000s` function."""
|
|
144
|
+
tt = sct_to_ttj2000s(sclk_ticks)
|
|
145
|
+
if isinstance(sclk_ticks, float):
|
|
146
|
+
assert isinstance(tt, float)
|
|
147
|
+
else:
|
|
148
|
+
assert len(tt) == len(sclk_ticks)
|
|
149
|
+
|
|
150
|
+
|
|
129
151
|
def test_str_to_et(furnish_time_kernels):
|
|
130
152
|
"""Test coverage for string to et conversion function."""
|
|
131
153
|
utc = "2017-07-14T19:46:00"
|
|
@@ -133,6 +155,7 @@ def test_str_to_et(furnish_time_kernels):
|
|
|
133
155
|
expected_et = 553333629.1837274
|
|
134
156
|
actual_et = str_to_et(utc)
|
|
135
157
|
assert expected_et == actual_et
|
|
158
|
+
assert isinstance(actual_et, float)
|
|
136
159
|
|
|
137
160
|
# Test list input
|
|
138
161
|
list_of_utc = [
|
|
@@ -4,7 +4,7 @@ import xarray as xr
|
|
|
4
4
|
|
|
5
5
|
from imap_processing import imap_module_directory
|
|
6
6
|
from imap_processing.cdf.utils import write_cdf
|
|
7
|
-
from imap_processing.spice.time import
|
|
7
|
+
from imap_processing.spice.time import met_to_ttj2000ns
|
|
8
8
|
from imap_processing.swapi.l1.swapi_l1 import (
|
|
9
9
|
SWAPIAPID,
|
|
10
10
|
decompress_count,
|
|
@@ -91,7 +91,7 @@ def test_find_sweep_starts():
|
|
|
91
91
|
sequence_number = time % 12
|
|
92
92
|
ds = xr.Dataset(
|
|
93
93
|
{"seq_number": sequence_number, "shcoarse": np.arange(1, 27, 1)},
|
|
94
|
-
coords={"epoch":
|
|
94
|
+
coords={"epoch": met_to_ttj2000ns(time)},
|
|
95
95
|
)
|
|
96
96
|
|
|
97
97
|
start_indices = find_sweep_starts(ds)
|
|
@@ -114,7 +114,7 @@ def test_get_full_indices():
|
|
|
114
114
|
sequence_number = time % 12
|
|
115
115
|
ds = xr.Dataset(
|
|
116
116
|
{"seq_number": sequence_number, "shcoarse": np.arange(1, 27, 1)},
|
|
117
|
-
coords={"epoch":
|
|
117
|
+
coords={"epoch": met_to_ttj2000ns(time)},
|
|
118
118
|
)
|
|
119
119
|
|
|
120
120
|
sweep_indices = get_indices_of_full_sweep(ds)
|
|
@@ -176,7 +176,14 @@ def test_process_swapi_science(decom_test_data):
|
|
|
176
176
|
def test_swapi_l1_cdf(swapi_l0_test_data_path):
|
|
177
177
|
"""Test housekeeping processing and CDF file creation"""
|
|
178
178
|
test_packet_file = swapi_l0_test_data_path / "imap_swapi_l0_raw_20240924_v001.pkts"
|
|
179
|
-
processed_data = swapi_l1(test_packet_file, data_version="v001")
|
|
179
|
+
processed_data = swapi_l1([test_packet_file], data_version="v001")
|
|
180
|
+
# hk cdf file
|
|
181
|
+
hk_cdf_filename = "imap_swapi_l1_hk_20240924_v001.cdf"
|
|
182
|
+
# TODO: how to add ignore ISTP checks for HK data to cli.py
|
|
183
|
+
hk_cdf_path = write_cdf(processed_data[0])
|
|
184
|
+
assert hk_cdf_path.name == hk_cdf_filename
|
|
185
|
+
|
|
186
|
+
processed_data = swapi_l1([test_packet_file, hk_cdf_path], data_version="v001")
|
|
180
187
|
|
|
181
188
|
assert processed_data[0].attrs["Apid"] == f"{SWAPIAPID.SWP_SCI}"
|
|
182
189
|
|
|
@@ -184,9 +191,3 @@ def test_swapi_l1_cdf(swapi_l0_test_data_path):
|
|
|
184
191
|
cdf_filename = "imap_swapi_l1_sci_20240924_v001.cdf"
|
|
185
192
|
cdf_path = write_cdf(processed_data[0])
|
|
186
193
|
assert cdf_path.name == cdf_filename
|
|
187
|
-
|
|
188
|
-
# hk cdf file
|
|
189
|
-
cdf_filename = "imap_swapi_l1_hk_20240924_v001.cdf"
|
|
190
|
-
# Ignore ISTP checks for HK data
|
|
191
|
-
cdf_path = write_cdf(processed_data[1], istp=False)
|
|
192
|
-
assert cdf_path.name == cdf_filename
|
|
@@ -7,10 +7,20 @@ from imap_processing.swapi.l2.swapi_l2 import TIME_PER_BIN, swapi_l2
|
|
|
7
7
|
|
|
8
8
|
def test_swapi_l2_cdf(swapi_l0_test_data_path):
|
|
9
9
|
"""Test housekeeping processing and CDF file creation"""
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
test_packet_file = swapi_l0_test_data_path / "imap_swapi_l0_raw_20240924_v001.pkts"
|
|
11
|
+
# Create HK CDF File
|
|
12
|
+
processed_hk_data = swapi_l1([test_packet_file], data_version="v001")
|
|
13
|
+
hk_cdf_filename = "imap_swapi_l1_hk_20240924_v001.cdf"
|
|
14
|
+
hk_cdf_path = write_cdf(processed_hk_data[0])
|
|
15
|
+
assert hk_cdf_path.name == hk_cdf_filename
|
|
13
16
|
|
|
17
|
+
# Create L1 CDF File
|
|
18
|
+
processed_sci_data = swapi_l1([test_packet_file, hk_cdf_path], data_version="v001")
|
|
19
|
+
cdf_filename = "imap_swapi_l1_sci_20240924_v001.cdf"
|
|
20
|
+
cdf_path = write_cdf(processed_sci_data[0])
|
|
21
|
+
assert cdf_path.name == cdf_filename
|
|
22
|
+
|
|
23
|
+
l1_dataset = processed_sci_data[0]
|
|
14
24
|
l2_dataset = swapi_l2(l1_dataset, data_version="v001")
|
|
15
25
|
l2_cdf = write_cdf(l2_dataset)
|
|
16
26
|
assert l2_cdf.name == "imap_swapi_l2_sci_20240924_v001.cdf"
|
|
@@ -7,6 +7,6 @@ def test_cdf_creation():
|
|
|
7
7
|
test_data_path = "tests/swe/l0_data/2024051010_SWE_SCIENCE_packet.bin"
|
|
8
8
|
processed_data = swe_l1a(imap_module_directory / test_data_path, "001")
|
|
9
9
|
|
|
10
|
-
cem_raw_cdf_filepath = write_cdf(processed_data)
|
|
10
|
+
cem_raw_cdf_filepath = write_cdf(processed_data[0])
|
|
11
11
|
|
|
12
12
|
assert cem_raw_cdf_filepath.name == "imap_swe_l1a_sci_20240510_v001.cdf"
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from unittest.mock import patch
|
|
2
|
+
|
|
1
3
|
import numpy as np
|
|
2
4
|
import pandas as pd
|
|
3
5
|
|
|
@@ -45,14 +47,29 @@ def test_swe_l1b(decom_test_data_derived):
|
|
|
45
47
|
)
|
|
46
48
|
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
@patch(
|
|
51
|
+
"imap_processing.swe.l1b.swe_l1b_science.read_in_flight_cal_data",
|
|
52
|
+
return_value=pd.DataFrame(
|
|
53
|
+
{
|
|
54
|
+
"met_time": [452051300, 454051900],
|
|
55
|
+
"cem1": [1, 1],
|
|
56
|
+
"cem2": [1, 1],
|
|
57
|
+
"cem3": [1, 1],
|
|
58
|
+
"cem4": [1, 1],
|
|
59
|
+
"cem5": [1, 1],
|
|
60
|
+
"cem6": [1, 1],
|
|
61
|
+
"cem7": [1, 1],
|
|
62
|
+
}
|
|
63
|
+
),
|
|
64
|
+
)
|
|
65
|
+
def test_cdf_creation(mock_read_in_flight_cal_data, l1b_validation_df):
|
|
49
66
|
"""Test that CDF file is created and has the correct name."""
|
|
50
67
|
test_data_path = "tests/swe/l0_data/2024051010_SWE_SCIENCE_packet.bin"
|
|
51
68
|
l1a_datasets = swe_l1a(imap_module_directory / test_data_path, "002")
|
|
52
69
|
|
|
53
|
-
l1b_dataset = swe_l1b(l1a_datasets, "002")
|
|
70
|
+
l1b_dataset = swe_l1b(l1a_datasets[0], "002")
|
|
54
71
|
|
|
55
|
-
sci_l1b_filepath = write_cdf(l1b_dataset)
|
|
72
|
+
sci_l1b_filepath = write_cdf(l1b_dataset[0])
|
|
56
73
|
|
|
57
74
|
assert sci_l1b_filepath.name == "imap_swe_l1b_sci_20240510_v002.cdf"
|
|
58
75
|
# load the CDF file and compare the values
|
|
@@ -1,47 +1,21 @@
|
|
|
1
|
+
from unittest.mock import patch
|
|
2
|
+
|
|
1
3
|
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
2
5
|
import pytest
|
|
3
6
|
|
|
4
|
-
from imap_processing import imap_module_directory
|
|
5
7
|
from imap_processing.swe.l1a.swe_science import swe_science
|
|
6
8
|
from imap_processing.swe.l1b.swe_l1b_science import (
|
|
9
|
+
apply_in_flight_calibration,
|
|
7
10
|
get_indices_of_full_cycles,
|
|
8
11
|
)
|
|
9
|
-
from imap_processing.swe.utils.swe_utils import SWEAPID
|
|
10
|
-
from imap_processing.utils import packet_file_to_datasets
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
@pytest.fixture(scope="session")
|
|
14
|
-
def l1a_test_data():
|
|
15
|
-
"""Read test data from file"""
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
# Packet 1 has spin 4's data
|
|
19
|
-
# Packet 2 has spin 1's data
|
|
20
|
-
# Packet 3 has spin 2's data
|
|
21
|
-
# Packet 4 has spin 3's data
|
|
22
|
-
# moved packet 1 to bottom to show data in order.
|
|
23
|
-
packet_files = [
|
|
24
|
-
imap_module_directory
|
|
25
|
-
/ "tests/swe/l0_data/20230927173253_SWE_SCIENCE_packet.bin",
|
|
26
|
-
imap_module_directory
|
|
27
|
-
/ "tests/swe/l0_data/20230927173308_SWE_SCIENCE_packet.bin",
|
|
28
|
-
imap_module_directory
|
|
29
|
-
/ "tests/swe/l0_data/20230927173323_SWE_SCIENCE_packet.bin",
|
|
30
|
-
imap_module_directory
|
|
31
|
-
/ "tests/swe/l0_data/20230927173238_SWE_SCIENCE_packet.bin",
|
|
32
|
-
]
|
|
33
|
-
dataset = packet_file_to_datasets(packet_files[0], use_derived_value=False)[
|
|
34
|
-
SWEAPID.SWE_SCIENCE
|
|
35
|
-
]
|
|
36
|
-
for packet_file in packet_files[1:]:
|
|
37
|
-
dataset.merge(
|
|
38
|
-
packet_file_to_datasets(packet_file, use_derived_value=False)[
|
|
39
|
-
SWEAPID.SWE_SCIENCE
|
|
40
|
-
]
|
|
41
|
-
)
|
|
42
|
-
# Get unpacked science data
|
|
43
|
-
unpacked_data = swe_science(dataset, "001")
|
|
44
|
-
return unpacked_data
|
|
15
|
+
def l1a_test_data(decom_test_data):
|
|
16
|
+
"""Read test data from file and process to l1a"""
|
|
17
|
+
processed_data = swe_science(decom_test_data, "001")
|
|
18
|
+
return processed_data
|
|
45
19
|
|
|
46
20
|
|
|
47
21
|
def test_get_full_cycle_data_indices():
|
|
@@ -62,4 +36,49 @@ def test_get_full_cycle_data_indices():
|
|
|
62
36
|
np.testing.assert_array_equal(filtered_q, np.array([]))
|
|
63
37
|
|
|
64
38
|
|
|
65
|
-
|
|
39
|
+
@patch(
|
|
40
|
+
"imap_processing.swe.l1b.swe_l1b_science.read_in_flight_cal_data",
|
|
41
|
+
return_value=pd.DataFrame(
|
|
42
|
+
{
|
|
43
|
+
"met_time": [453051300, 453051900],
|
|
44
|
+
"cem1": [1, 2],
|
|
45
|
+
"cem2": [1, 2],
|
|
46
|
+
"cem3": [1, 2],
|
|
47
|
+
"cem4": [1, 2],
|
|
48
|
+
"cem5": [1, 2],
|
|
49
|
+
"cem6": [1, 2],
|
|
50
|
+
"cem7": [1, 2],
|
|
51
|
+
}
|
|
52
|
+
),
|
|
53
|
+
)
|
|
54
|
+
def test_in_flight_calibration_factor(mock_read_in_flight_cal_data, l1a_test_data):
|
|
55
|
+
"""Test that the L1B processing is working as expected."""
|
|
56
|
+
# create sample data
|
|
57
|
+
|
|
58
|
+
input_time = 453051355.0
|
|
59
|
+
input_count = 19967
|
|
60
|
+
one_full_cycle_data = np.full((24, 30, 7), input_count)
|
|
61
|
+
acquisition_time = np.full((24, 30), input_time)
|
|
62
|
+
|
|
63
|
+
# Test that calibration factor is within correct range given test data
|
|
64
|
+
expected_cal_factor = 1 + ((2 - 1) / (453051900 - 453051300)) * (
|
|
65
|
+
input_time - 453051300
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
calibrated_count = apply_in_flight_calibration(
|
|
69
|
+
one_full_cycle_data,
|
|
70
|
+
acquisition_time,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
np.testing.assert_allclose(
|
|
74
|
+
calibrated_count,
|
|
75
|
+
np.full((24, 30, 7), input_count * expected_cal_factor),
|
|
76
|
+
rtol=1e-9,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Check for value outside of calibration time range
|
|
80
|
+
input_time = 1.0
|
|
81
|
+
acquisition_time = np.full((24, 30), input_time)
|
|
82
|
+
|
|
83
|
+
with pytest.raises(ValueError, match="Acquisition min/max times: "):
|
|
84
|
+
apply_in_flight_calibration(one_full_cycle_data, acquisition_time)
|