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
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from unittest import mock
|
|
2
|
-
|
|
3
1
|
import numpy as np
|
|
4
2
|
import pytest
|
|
5
3
|
import xarray as xr
|
|
@@ -32,45 +30,58 @@ def mock_data_l1a_rates_dict():
|
|
|
32
30
|
|
|
33
31
|
|
|
34
32
|
@pytest.fixture()
|
|
35
|
-
def
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"var": ("epoch", np.zeros(5)),
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
attrs = {
|
|
46
|
-
"Logical_source": "imap_ultra_l1a_45sensor-name",
|
|
47
|
-
"Logical_source_description": "IMAP Mission ULTRA Instrument "
|
|
48
|
-
"Level-1A Single-Sensor Data",
|
|
49
|
-
}
|
|
33
|
+
def mock_data_l1b_de_dict():
|
|
34
|
+
epoch = np.array(
|
|
35
|
+
[760591786368000000, 760591787368000000, 760591788368000000],
|
|
36
|
+
dtype="datetime64[ns]",
|
|
37
|
+
)
|
|
38
|
+
data_dict = {"epoch": epoch, "x_front": np.zeros(3), "y_front": np.zeros(3)}
|
|
39
|
+
return data_dict
|
|
50
40
|
|
|
51
|
-
dataset = xr.Dataset(data_vars, coords={"epoch": epoch}, attrs=attrs)
|
|
52
41
|
|
|
42
|
+
@pytest.fixture()
|
|
43
|
+
def mock_data_l1b_extendedspin_dict():
|
|
44
|
+
spin = np.array(
|
|
45
|
+
[0, 1, 2],
|
|
46
|
+
dtype="uint32",
|
|
47
|
+
)
|
|
48
|
+
energy = np.array(
|
|
49
|
+
[0, 1],
|
|
50
|
+
dtype="int32",
|
|
51
|
+
)
|
|
52
|
+
quality = np.zeros((2, 3), dtype="uint16")
|
|
53
53
|
data_dict = {
|
|
54
|
-
"
|
|
55
|
-
"
|
|
54
|
+
"spin_number": spin,
|
|
55
|
+
"energy_bin_geometric_mean": energy,
|
|
56
|
+
"quality_ena_rates": quality,
|
|
56
57
|
}
|
|
57
|
-
|
|
58
58
|
return data_dict
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
def test_create_extendedspin_dataset(mock_data_l1b_extendedspin_dict):
|
|
62
|
+
"""Tests that dataset is created as expected."""
|
|
63
|
+
dataset = create_dataset(
|
|
64
|
+
mock_data_l1b_extendedspin_dict,
|
|
65
|
+
"imap_ultra_l1b_45sensor-extendedspin",
|
|
66
|
+
"l1b",
|
|
67
|
+
"001",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
assert "spin_number" in dataset.coords
|
|
71
|
+
assert "energy_bin_geometric_mean" in dataset.coords
|
|
72
|
+
assert dataset.coords["spin_number"].dtype == "uint32"
|
|
73
|
+
assert dataset.attrs["Logical_source"] == "imap_ultra_l1b_45sensor-extendedspin"
|
|
74
|
+
assert dataset["quality_ena_rates"].attrs["UNITS"] == " "
|
|
75
|
+
np.testing.assert_array_equal(
|
|
76
|
+
dataset["quality_ena_rates"], np.zeros((2, 3), dtype="uint16")
|
|
66
77
|
)
|
|
67
|
-
data_dict = {"epoch": epoch, "x_front": np.zeros(3), "y_front": np.zeros(3)}
|
|
68
|
-
return data_dict
|
|
69
78
|
|
|
70
79
|
|
|
71
|
-
def
|
|
80
|
+
def test_create_de_dataset(mock_data_l1b_de_dict):
|
|
72
81
|
"""Tests that dataset is created as expected."""
|
|
73
|
-
dataset = create_dataset(
|
|
82
|
+
dataset = create_dataset(
|
|
83
|
+
mock_data_l1b_de_dict, "imap_ultra_l1b_45sensor-de", "l1b", "001"
|
|
84
|
+
)
|
|
74
85
|
|
|
75
86
|
assert "epoch" in dataset.coords
|
|
76
87
|
assert dataset.coords["epoch"].dtype == "datetime64[ns]"
|
|
@@ -79,58 +90,21 @@ def test_create_dataset(mock_data_l1b_dict):
|
|
|
79
90
|
np.testing.assert_array_equal(dataset["x_front"], np.zeros(3))
|
|
80
91
|
|
|
81
92
|
|
|
82
|
-
def
|
|
93
|
+
def test_ultra_l1b(l1b_datasets):
|
|
83
94
|
"""Tests that L1b data is created."""
|
|
84
|
-
output_datasets = ultra_l1b(mock_data_l1a_rates_dict, data_version="001")
|
|
85
95
|
|
|
86
|
-
assert len(
|
|
87
|
-
assert (
|
|
88
|
-
output_datasets[0].attrs["Logical_source"]
|
|
89
|
-
== "imap_ultra_l1b_45sensor-extendedspin"
|
|
90
|
-
)
|
|
91
|
-
assert (
|
|
92
|
-
output_datasets[1].attrs["Logical_source"]
|
|
93
|
-
== "imap_ultra_l1b_45sensor-cullingmask"
|
|
94
|
-
)
|
|
95
|
-
assert (
|
|
96
|
-
output_datasets[2].attrs["Logical_source"] == "imap_ultra_l1b_45sensor-badtimes"
|
|
97
|
-
)
|
|
98
|
-
assert (
|
|
99
|
-
output_datasets[0].attrs["Logical_source_description"]
|
|
100
|
-
== "IMAP-Ultra Instrument Level-1B Extended Spin Data."
|
|
101
|
-
)
|
|
96
|
+
assert len(l1b_datasets) == 4
|
|
102
97
|
|
|
98
|
+
# Define the suffixes and prefix
|
|
99
|
+
prefix = "imap_ultra_l1b_45sensor"
|
|
100
|
+
suffixes = ["de", "extendedspin", "cullingmask", "badtimes"]
|
|
101
|
+
|
|
102
|
+
for i in range(len(suffixes)):
|
|
103
|
+
expected_logical_source = f"{prefix}-{suffixes[i]}"
|
|
104
|
+
assert l1b_datasets[i].attrs["Logical_source"] == expected_logical_source
|
|
103
105
|
|
|
104
|
-
@pytest.mark.external_kernel()
|
|
105
|
-
@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
|
|
106
|
-
@mock.patch("imap_processing.ultra.l1b.de.get_annotated_particle_velocity")
|
|
107
|
-
def test_ultra_l1b_de(mock_get_annotated_particle_velocity, de_dataset):
|
|
108
|
-
"""Tests that L1b data is created."""
|
|
109
|
-
data_dict = {}
|
|
110
|
-
data_dict[de_dataset.attrs["Logical_source"]] = de_dataset
|
|
111
|
-
data_dict["imap_ultra_l1a_45sensor-aux"] = de_dataset
|
|
112
|
-
|
|
113
|
-
# Mock get_annotated_particle_velocity to avoid needing kernels
|
|
114
|
-
def side_effect_func(event_times, position, ultra_frame, dps_frame, sc_frame):
|
|
115
|
-
"""
|
|
116
|
-
Mock behavior of get_annotated_particle_velocity.
|
|
117
|
-
|
|
118
|
-
Returns NaN-filled arrays matching the expected output shape.
|
|
119
|
-
"""
|
|
120
|
-
num_events = event_times.size
|
|
121
|
-
return (
|
|
122
|
-
np.full((num_events, 3), np.nan), # sc_velocity
|
|
123
|
-
np.full((num_events, 3), np.nan), # sc_dps_velocity
|
|
124
|
-
np.full((num_events, 3), np.nan), # helio_velocity
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
mock_get_annotated_particle_velocity.side_effect = side_effect_func
|
|
128
|
-
output_datasets = ultra_l1b(data_dict, data_version="001")
|
|
129
|
-
|
|
130
|
-
assert len(output_datasets) == 1
|
|
131
|
-
assert output_datasets[0].attrs["Logical_source"] == "imap_ultra_l1b_45sensor-de"
|
|
132
106
|
assert (
|
|
133
|
-
|
|
107
|
+
l1b_datasets[0].attrs["Logical_source_description"]
|
|
134
108
|
== "IMAP-Ultra Instrument Level-1B Direct Event Data."
|
|
135
109
|
)
|
|
136
110
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pytest
|
|
5
|
-
import spiceypy
|
|
5
|
+
import spiceypy
|
|
6
6
|
|
|
7
7
|
from imap_processing.spice.geometry import SpiceFrame
|
|
8
8
|
from imap_processing.ultra.l1b.ultra_l1b_annotated import (
|
|
@@ -31,9 +31,9 @@ def kernels(spice_test_data_path):
|
|
|
31
31
|
@pytest.mark.external_kernel()
|
|
32
32
|
def test_get_particle_velocity(spice_test_data_path, kernels):
|
|
33
33
|
"""Tests get_particle_velocity function."""
|
|
34
|
-
|
|
34
|
+
spiceypy.furnsh(kernels)
|
|
35
35
|
|
|
36
|
-
pointing_cover =
|
|
36
|
+
pointing_cover = spiceypy.ckcov(
|
|
37
37
|
str(spice_test_data_path / "sim_1yr_imap_pointing_frame.bc"),
|
|
38
38
|
SpiceFrame.IMAP_DPS.value,
|
|
39
39
|
True,
|
|
@@ -42,7 +42,7 @@ def test_get_particle_velocity(spice_test_data_path, kernels):
|
|
|
42
42
|
"TDB",
|
|
43
43
|
)
|
|
44
44
|
# Get start and end time of first interval
|
|
45
|
-
start, _ =
|
|
45
|
+
start, _ = spiceypy.wnfetd(pointing_cover, 0)
|
|
46
46
|
|
|
47
47
|
times = np.array([start])
|
|
48
48
|
instrument_velocity = np.array([[41.18609, -471.24467, -832.8784]])
|
|
@@ -71,7 +71,7 @@ def test_get_particle_velocity(spice_test_data_path, kernels):
|
|
|
71
71
|
magnitude_sc_90 = np.linalg.norm(sc_velocity_90)
|
|
72
72
|
magnitude_dps_45 = np.linalg.norm(sc_dps_velocity_45)
|
|
73
73
|
magnitude_dps_90 = np.linalg.norm(sc_dps_velocity_90)
|
|
74
|
-
state, lt =
|
|
74
|
+
state, lt = spiceypy.spkezr("IMAP", times, "IMAP_DPS", "NONE", "SUN")
|
|
75
75
|
|
|
76
76
|
assert np.allclose(magnitude_sc_45, magnitude_sc_90, atol=1e-6)
|
|
77
77
|
assert np.allclose(magnitude_dps_45, magnitude_dps_90, atol=1e-6)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Tests Culling for ULTRA L1b."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from imap_processing.quality_flags import ImapAttitudeUltraFlags, ImapRatesUltraFlags
|
|
7
|
+
from imap_processing.ultra.constants import UltraConstants
|
|
8
|
+
from imap_processing.ultra.l1b.ultra_l1b_culling import (
|
|
9
|
+
flag_attitude,
|
|
10
|
+
flag_spin,
|
|
11
|
+
get_energy_histogram,
|
|
12
|
+
get_n_sigma,
|
|
13
|
+
get_spin,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture()
|
|
18
|
+
def test_data(use_fake_spin_data_for_time):
|
|
19
|
+
"""Fixture to compute and return test data."""
|
|
20
|
+
|
|
21
|
+
time = np.arange(0, 32, 2)
|
|
22
|
+
spin_number = np.array([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2])
|
|
23
|
+
energy = np.array([5, 5, 5, 5, 5, 5, 5, 5, 5, 15, 15, 25, -2, -2, -2, 2])
|
|
24
|
+
|
|
25
|
+
use_fake_spin_data_for_time(time[0], time[-1])
|
|
26
|
+
|
|
27
|
+
energy_edges = UltraConstants.CULLING_ENERGY_BIN_EDGES
|
|
28
|
+
unique_spins = np.unique(spin_number)
|
|
29
|
+
expected_counts = np.zeros((len(energy_edges) - 1, len(unique_spins)))
|
|
30
|
+
|
|
31
|
+
for spin_idx, spin in enumerate(unique_spins):
|
|
32
|
+
for energy_idx in range(len(energy_edges) - 1):
|
|
33
|
+
count = np.sum(
|
|
34
|
+
(spin_number == spin)
|
|
35
|
+
& (energy >= energy_edges[energy_idx])
|
|
36
|
+
& (energy < energy_edges[energy_idx + 1])
|
|
37
|
+
)
|
|
38
|
+
expected_counts[energy_idx, spin_idx] = count
|
|
39
|
+
|
|
40
|
+
return time, spin_number, energy, expected_counts
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_get_spin(use_fake_spin_data_for_time):
|
|
44
|
+
"""Tests get_spin function."""
|
|
45
|
+
|
|
46
|
+
nspins = 5
|
|
47
|
+
spin_period = 15
|
|
48
|
+
start = 0
|
|
49
|
+
stop = start + (nspins + 1) * spin_period
|
|
50
|
+
use_fake_spin_data_for_time(start, stop)
|
|
51
|
+
spin_number = get_spin(np.linspace(start, stop, num=20))
|
|
52
|
+
|
|
53
|
+
assert len(spin_number) == len(np.linspace(start, stop, num=20))
|
|
54
|
+
expected_num_spins = np.ceil((stop - start) / 15) + 1
|
|
55
|
+
assert np.array_equal(len(np.unique(spin_number)), expected_num_spins)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_get_energy_histogram(test_data):
|
|
59
|
+
"""Tests get_energy_histogram function."""
|
|
60
|
+
|
|
61
|
+
_, spin_number, energy, expected_counts = test_data
|
|
62
|
+
|
|
63
|
+
hist, _, counts, duration = get_energy_histogram(spin_number, energy)
|
|
64
|
+
|
|
65
|
+
assert np.all(counts == expected_counts)
|
|
66
|
+
assert np.all(hist == expected_counts / 15)
|
|
67
|
+
assert duration == 15
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_flag_attitude(use_fake_spin_data_for_time):
|
|
71
|
+
"""Tests flag_attitude function."""
|
|
72
|
+
|
|
73
|
+
start = 4.45015658e08
|
|
74
|
+
stop = 4.45015873e08
|
|
75
|
+
use_fake_spin_data_for_time(start, stop)
|
|
76
|
+
quality_flags, spin_rates, spin_period, spin_start_time = flag_attitude(
|
|
77
|
+
np.linspace(start, stop, num=20)
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
flag = ImapAttitudeUltraFlags(quality_flags[0])
|
|
81
|
+
assert flag.name == "NONE"
|
|
82
|
+
assert np.all(quality_flags == ImapAttitudeUltraFlags.NONE.value)
|
|
83
|
+
assert np.all(spin_rates == 60 / spin_period)
|
|
84
|
+
assert np.all(np.diff(spin_start_time) == 15)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_get_n_sigma():
|
|
88
|
+
"""Tests get_six_sigma function."""
|
|
89
|
+
|
|
90
|
+
counts = np.array([[16, 4, 1], [0, 0, 0], [1, 1, 1], [2, 0, 5]])
|
|
91
|
+
threshold = get_n_sigma(counts / 15, 15, 6)
|
|
92
|
+
|
|
93
|
+
assert np.all(threshold >= 3 / 15)
|
|
94
|
+
mean = np.mean(counts[0] / 15)
|
|
95
|
+
squared_differences = (counts[0] / 15 - mean) ** 2
|
|
96
|
+
variance = np.mean(squared_differences)
|
|
97
|
+
std_dev = np.sqrt(variance)
|
|
98
|
+
|
|
99
|
+
np.testing.assert_allclose(mean + std_dev * 6, threshold[0], atol=1e-2, rtol=0)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_flag_spin(test_data):
|
|
103
|
+
"""Tests flag_spin function."""
|
|
104
|
+
|
|
105
|
+
time, _, energy, expected_counts = test_data
|
|
106
|
+
quality_flags, spin, energy, _ = flag_spin(time, energy, 1)
|
|
107
|
+
threshold = get_n_sigma(expected_counts / 15, 15, 1)
|
|
108
|
+
|
|
109
|
+
# At the first energy level were the rates > threshold and the counts > threshold?
|
|
110
|
+
assert np.all(
|
|
111
|
+
quality_flags[expected_counts == 0] == ImapRatesUltraFlags.ZEROCOUNTS.value
|
|
112
|
+
)
|
|
113
|
+
high_rates_flag = quality_flags[expected_counts / 15 > threshold[:, np.newaxis]]
|
|
114
|
+
assert np.all(high_rates_flag == ImapRatesUltraFlags.HIGHRATES.value)
|
|
@@ -13,6 +13,9 @@ from imap_processing.ultra.l1b.ultra_l1b_extended import (
|
|
|
13
13
|
determine_species,
|
|
14
14
|
get_coincidence_positions,
|
|
15
15
|
get_ctof,
|
|
16
|
+
get_de_az_el,
|
|
17
|
+
get_de_energy_kev,
|
|
18
|
+
get_de_velocity,
|
|
16
19
|
get_energy_pulse_height,
|
|
17
20
|
get_energy_ssd,
|
|
18
21
|
get_front_x_position,
|
|
@@ -21,7 +24,6 @@ from imap_processing.ultra.l1b.ultra_l1b_extended import (
|
|
|
21
24
|
get_ph_tof_and_back_positions,
|
|
22
25
|
get_ssd_back_position_and_tof_offset,
|
|
23
26
|
get_ssd_tof,
|
|
24
|
-
get_unit_vector,
|
|
25
27
|
)
|
|
26
28
|
|
|
27
29
|
|
|
@@ -213,41 +215,42 @@ def test_calculate_etof_xc(de_dataset, yf_fixture):
|
|
|
213
215
|
)
|
|
214
216
|
|
|
215
217
|
|
|
216
|
-
def
|
|
217
|
-
"""Tests
|
|
218
|
+
def test_get_de_velocity(de_dataset, yf_fixture):
|
|
219
|
+
"""Tests get_de_velocity function."""
|
|
218
220
|
df_filt, _, _ = yf_fixture
|
|
221
|
+
df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])]
|
|
219
222
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
ph_rows = df_filt.iloc[ph_indices]
|
|
225
|
-
test_xf = ph_rows["Xf"].astype("float").values
|
|
226
|
-
test_yf = ph_rows["Yf"].astype("float").values
|
|
227
|
-
test_xb = ph_rows["Xb"].astype("float").values
|
|
228
|
-
test_yb = ph_rows["Yb"].astype("float").values
|
|
229
|
-
test_d = ph_rows["d"].astype("float").values
|
|
230
|
-
test_tof = ph_rows["TOF"].astype("float").values
|
|
223
|
+
test_xf, test_yf, test_xb, test_yb, test_d, test_tof = (
|
|
224
|
+
df_ph[col].astype("float").values
|
|
225
|
+
for col in ["Xf", "Yf", "Xb", "Yb", "d", "TOF"]
|
|
226
|
+
)
|
|
231
227
|
|
|
232
|
-
|
|
228
|
+
v = get_de_velocity(
|
|
233
229
|
(test_xf, test_yf),
|
|
234
230
|
(test_xb, test_yb),
|
|
235
231
|
test_d,
|
|
236
232
|
test_tof,
|
|
237
233
|
)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
234
|
+
|
|
235
|
+
v_x, v_y, v_z = v[:, 0], v[:, 1], v[:, 2]
|
|
236
|
+
|
|
237
|
+
np.testing.assert_allclose(
|
|
238
|
+
v_x[test_tof > 0],
|
|
239
|
+
df_ph["vx"].astype("float").values[test_tof > 0],
|
|
240
|
+
atol=1e-01,
|
|
241
|
+
rtol=0,
|
|
243
242
|
)
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
243
|
+
np.testing.assert_allclose(
|
|
244
|
+
v_y[test_tof > 0],
|
|
245
|
+
df_ph["vy"].astype("float").values[test_tof > 0],
|
|
246
|
+
atol=1e-01,
|
|
247
|
+
rtol=0,
|
|
247
248
|
)
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
249
|
+
np.testing.assert_allclose(
|
|
250
|
+
v_z[test_tof > 0],
|
|
251
|
+
df_ph["vz"].astype("float").values[test_tof > 0],
|
|
252
|
+
atol=1e-01,
|
|
253
|
+
rtol=0,
|
|
251
254
|
)
|
|
252
255
|
|
|
253
256
|
|
|
@@ -264,6 +267,37 @@ def test_get_ssd_tof(de_dataset, yf_fixture):
|
|
|
264
267
|
)
|
|
265
268
|
|
|
266
269
|
|
|
270
|
+
def test_get_de_energy_kev(de_dataset, yf_fixture):
|
|
271
|
+
"""Tests get_de_energy_kev function."""
|
|
272
|
+
df_filt, _, _ = yf_fixture
|
|
273
|
+
df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])]
|
|
274
|
+
df_ph = df_ph[df_ph["energy_revised"].astype("str") != "FILL"]
|
|
275
|
+
|
|
276
|
+
species_bin_ph = determine_species(
|
|
277
|
+
df_ph["TOF"].astype("float").to_numpy(),
|
|
278
|
+
df_ph["r"].astype("float").to_numpy(),
|
|
279
|
+
"PH",
|
|
280
|
+
)
|
|
281
|
+
test_xf, test_yf, test_xb, test_yb, test_d, test_tof = (
|
|
282
|
+
df_ph[col].astype("float").values
|
|
283
|
+
for col in ["Xf", "Yf", "Xb", "Yb", "d", "TOF"]
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
v = get_de_velocity(
|
|
287
|
+
(test_xf, test_yf),
|
|
288
|
+
(test_xb, test_yb),
|
|
289
|
+
test_d,
|
|
290
|
+
test_tof,
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
energy = get_de_energy_kev(v, species_bin_ph)
|
|
294
|
+
index_hydrogen = np.where(species_bin_ph == "H")
|
|
295
|
+
actual_energy = energy[index_hydrogen[0]]
|
|
296
|
+
expected_energy = df_ph["energy_revised"].astype("float")
|
|
297
|
+
|
|
298
|
+
np.testing.assert_allclose(actual_energy, expected_energy, atol=1e-01, rtol=0)
|
|
299
|
+
|
|
300
|
+
|
|
267
301
|
def test_get_energy_ssd(de_dataset, yf_fixture):
|
|
268
302
|
"""Tests get_energy_ssd function."""
|
|
269
303
|
df_filt, _, _ = yf_fixture
|
|
@@ -360,3 +394,29 @@ def test_determine_species(yf_fixture):
|
|
|
360
394
|
|
|
361
395
|
np.testing.assert_array_equal(h_indices_ph, ctof_indices_ph)
|
|
362
396
|
np.testing.assert_array_equal(h_indices_ssd, ctof_indices_ssd)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def test_get_de_az_el(de_dataset, yf_fixture):
|
|
400
|
+
"""Tests get_de_az_el function."""
|
|
401
|
+
df_filt, _, _ = yf_fixture
|
|
402
|
+
df_filt = df_filt[
|
|
403
|
+
(df_filt["event_theta"].astype("str") != "FILL")
|
|
404
|
+
& (df_filt["TOF"].astype("float") >= 0)
|
|
405
|
+
]
|
|
406
|
+
df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])]
|
|
407
|
+
|
|
408
|
+
test_xf, test_yf, test_xb, test_yb, test_d, test_tof = (
|
|
409
|
+
df_ph[col].astype("float").values
|
|
410
|
+
for col in ["Xf", "Yf", "Xb", "Yb", "d", "TOF"]
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
v = get_de_velocity(
|
|
414
|
+
(test_xf, test_yf),
|
|
415
|
+
(test_xb, test_yb),
|
|
416
|
+
test_d,
|
|
417
|
+
test_tof,
|
|
418
|
+
)
|
|
419
|
+
az, _ = get_de_az_el(v)
|
|
420
|
+
expected_phi = df_ph["event_phi"].astype("float")
|
|
421
|
+
|
|
422
|
+
np.testing.assert_allclose(az, expected_phi % (2 * np.pi), atol=1e-03, rtol=0)
|
|
@@ -68,7 +68,7 @@ def mock_data_l1c_dict():
|
|
|
68
68
|
def test_create_dataset(mock_data_l1c_dict):
|
|
69
69
|
"""Tests that dataset is created as expected."""
|
|
70
70
|
dataset = create_dataset(
|
|
71
|
-
mock_data_l1c_dict, "imap_ultra_l1c_45sensor-histogram", "l1c"
|
|
71
|
+
mock_data_l1c_dict, "imap_ultra_l1c_45sensor-histogram", "l1c", "001"
|
|
72
72
|
)
|
|
73
73
|
|
|
74
74
|
assert "epoch" in dataset.coords
|
|
@@ -6,6 +6,7 @@ import pytest
|
|
|
6
6
|
from cdflib import CDF
|
|
7
7
|
|
|
8
8
|
from imap_processing import imap_module_directory
|
|
9
|
+
from imap_processing.ena_maps.utils.spatial_utils import build_spatial_bins
|
|
9
10
|
from imap_processing.ultra.l1c.ultra_l1c_pset_bins import (
|
|
10
11
|
build_energy_bins,
|
|
11
12
|
get_helio_exposure_times,
|
|
@@ -13,7 +14,6 @@ from imap_processing.ultra.l1c.ultra_l1c_pset_bins import (
|
|
|
13
14
|
get_pointing_frame_exposure_times,
|
|
14
15
|
get_pointing_frame_sensitivity,
|
|
15
16
|
)
|
|
16
|
-
from imap_processing.ultra.utils.spatial_utils import build_spatial_bins
|
|
17
17
|
|
|
18
18
|
BASE_PATH = imap_module_directory / "ultra" / "lookup_tables"
|
|
19
19
|
|
|
@@ -52,7 +52,7 @@ def test_get_histogram(test_data):
|
|
|
52
52
|
v, energy = test_data
|
|
53
53
|
|
|
54
54
|
az_bin_edges, el_bin_edges, az_bin_midpoints, el_bin_midpoints = (
|
|
55
|
-
build_spatial_bins()
|
|
55
|
+
np.rad2deg(angle_radians) for angle_radians in (build_spatial_bins())
|
|
56
56
|
)
|
|
57
57
|
energy_bin_edges, _ = build_energy_bins()
|
|
58
58
|
|
|
@@ -101,7 +101,7 @@ def test_get_helio_exposure_times():
|
|
|
101
101
|
|
|
102
102
|
energy_bin_edges, energy_midpoints = build_energy_bins()
|
|
103
103
|
az_bin_edges, el_bin_edges, az_bin_midpoints, el_bin_midpoints = (
|
|
104
|
-
build_spatial_bins()
|
|
104
|
+
np.rad2deg(angle_radians) for angle_radians in (build_spatial_bins())
|
|
105
105
|
)
|
|
106
106
|
|
|
107
107
|
assert exposure_3d.shape == (
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Module for constants and useful shared classes used in Ultra."""
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
+
from typing import ClassVar
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
@dataclass(frozen=True)
|
|
@@ -60,7 +61,8 @@ class UltraConstants:
|
|
|
60
61
|
) # SSD-specific correction to DMIN [mm]
|
|
61
62
|
|
|
62
63
|
# Conversion factors
|
|
63
|
-
KEV_J = 1.
|
|
64
|
+
KEV_J = 1.602177e-16 # keV to joules
|
|
65
|
+
J_KEV = 1 / KEV_J # joules to keV
|
|
64
66
|
MASS_H = 1.6735575e-27 # Mass of a hydrogen atom in kilograms.
|
|
65
67
|
|
|
66
68
|
# Energy bin constants
|
|
@@ -71,3 +73,11 @@ class UltraConstants:
|
|
|
71
73
|
# Constants for species determination based on ctof range.
|
|
72
74
|
CTOF_SPECIES_MIN = 50
|
|
73
75
|
CTOF_SPECIES_MAX = 200
|
|
76
|
+
|
|
77
|
+
# RPMs for the Ultra instrument.
|
|
78
|
+
# TODO: this is a placeholder.
|
|
79
|
+
CULLING_RPM_MIN = 2.0
|
|
80
|
+
CULLING_RPM_MAX = 6.0
|
|
81
|
+
|
|
82
|
+
# Thresholds for culling based on counts.
|
|
83
|
+
CULLING_ENERGY_BIN_EDGES: ClassVar[list] = [-1e5, 0, 10, 20, 1e5]
|
|
@@ -11,7 +11,7 @@ import xarray as xr
|
|
|
11
11
|
|
|
12
12
|
from imap_processing import decom, imap_module_directory
|
|
13
13
|
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
14
|
-
from imap_processing.spice.time import
|
|
14
|
+
from imap_processing.spice.time import met_to_ttj2000ns
|
|
15
15
|
from imap_processing.ultra.l0.decom_ultra import process_ultra_apids
|
|
16
16
|
from imap_processing.ultra.l0.ultra_utils import (
|
|
17
17
|
ULTRA_AUX,
|
|
@@ -69,7 +69,7 @@ def initiate_data_arrays(decom_ultra: dict, apid: int) -> xr.Dataset:
|
|
|
69
69
|
cdf_manager.add_instrument_variable_attrs("ultra", "l1a")
|
|
70
70
|
|
|
71
71
|
epoch_time = xr.DataArray(
|
|
72
|
-
|
|
72
|
+
met_to_ttj2000ns(raw_time),
|
|
73
73
|
name="epoch",
|
|
74
74
|
dims=["epoch"],
|
|
75
75
|
attrs=cdf_manager.get_variable_attributes("epoch"),
|
|
@@ -1,26 +1,43 @@
|
|
|
1
1
|
"""Calculate Badtimes."""
|
|
2
2
|
|
|
3
|
+
import numpy as np
|
|
3
4
|
import xarray as xr
|
|
5
|
+
from numpy.typing import NDArray
|
|
4
6
|
|
|
5
7
|
from imap_processing.ultra.utils.ultra_l1_utils import create_dataset
|
|
6
8
|
|
|
7
9
|
|
|
8
|
-
def calculate_badtimes(
|
|
10
|
+
def calculate_badtimes(
|
|
11
|
+
extendedspin_dataset: xr.Dataset,
|
|
12
|
+
cullingmask_spins: NDArray,
|
|
13
|
+
name: str,
|
|
14
|
+
data_version: str,
|
|
15
|
+
) -> xr.Dataset:
|
|
9
16
|
"""
|
|
10
17
|
Create dataset with defined datatypes for Badtimes Data.
|
|
11
18
|
|
|
12
19
|
Parameters
|
|
13
20
|
----------
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
extendedspin_dataset : xarray.Dataset
|
|
22
|
+
Dataset containing the data.
|
|
23
|
+
cullingmask_spins : np.ndarray
|
|
24
|
+
Dataset containing the culled data.
|
|
16
25
|
name : str
|
|
17
26
|
Name of the dataset.
|
|
27
|
+
data_version : str
|
|
28
|
+
Version of the data.
|
|
18
29
|
|
|
19
30
|
Returns
|
|
20
31
|
-------
|
|
21
32
|
badtimes_dataset : xarray.Dataset
|
|
22
|
-
Dataset containing the data.
|
|
33
|
+
Dataset containing the extendedspin data that has been culled.
|
|
23
34
|
"""
|
|
24
|
-
|
|
35
|
+
culled_spins = np.setdiff1d(
|
|
36
|
+
extendedspin_dataset["spin_number"].values, cullingmask_spins
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
filtered_dataset = extendedspin_dataset.sel(spin_number=culled_spins)
|
|
40
|
+
|
|
41
|
+
badtimes_dataset = create_dataset(filtered_dataset, name, "l1b", data_version)
|
|
25
42
|
|
|
26
43
|
return badtimes_dataset
|
|
@@ -2,25 +2,51 @@
|
|
|
2
2
|
|
|
3
3
|
import xarray as xr
|
|
4
4
|
|
|
5
|
+
from imap_processing.quality_flags import ImapAttitudeUltraFlags, ImapRatesUltraFlags
|
|
5
6
|
from imap_processing.ultra.utils.ultra_l1_utils import create_dataset
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
def calculate_cullingmask(
|
|
9
|
+
def calculate_cullingmask(
|
|
10
|
+
extendedspin_dataset: xr.Dataset, name: str, data_version: str
|
|
11
|
+
) -> xr.Dataset:
|
|
9
12
|
"""
|
|
10
13
|
Create dataset with defined datatype for Culling Mask Data.
|
|
11
14
|
|
|
12
15
|
Parameters
|
|
13
16
|
----------
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
extendedspin_dataset : xarray.Dataset
|
|
18
|
+
Dataset containing the data.
|
|
16
19
|
name : str
|
|
17
20
|
Name of the dataset.
|
|
21
|
+
data_version : str
|
|
22
|
+
Version of the data.
|
|
18
23
|
|
|
19
24
|
Returns
|
|
20
25
|
-------
|
|
21
26
|
cullingmask_dataset : xarray.Dataset
|
|
22
|
-
Dataset containing the data.
|
|
27
|
+
Dataset containing the extendedspin data that remains after culling.
|
|
23
28
|
"""
|
|
24
|
-
|
|
29
|
+
# If the spin rate was too high or low then the spin should be thrown out.
|
|
30
|
+
# If the rates at any energy level are too high then throw out the entire spin.
|
|
31
|
+
good_mask = (
|
|
32
|
+
(
|
|
33
|
+
extendedspin_dataset["quality_attitude"]
|
|
34
|
+
& ImapAttitudeUltraFlags.SPINRATE.value
|
|
35
|
+
)
|
|
36
|
+
== 0
|
|
37
|
+
) & (
|
|
38
|
+
(
|
|
39
|
+
(
|
|
40
|
+
extendedspin_dataset["quality_ena_rates"]
|
|
41
|
+
& ImapRatesUltraFlags.HIGHRATES.value
|
|
42
|
+
)
|
|
43
|
+
== 0
|
|
44
|
+
).all(dim="energy_bin_geometric_mean")
|
|
45
|
+
)
|
|
46
|
+
filtered_dataset = extendedspin_dataset.sel(
|
|
47
|
+
spin_number=extendedspin_dataset["spin_number"][good_mask]
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
cullingmask_dataset = create_dataset(filtered_dataset, name, "l1b", data_version)
|
|
25
51
|
|
|
26
52
|
return cullingmask_dataset
|