imap-processing 0.12.0__py3-none-any.whl → 0.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of imap-processing might be problematic. Click here for more details.
- imap_processing/__init__.py +1 -0
- imap_processing/_version.py +2 -2
- imap_processing/ccsds/ccsds_data.py +1 -2
- imap_processing/ccsds/excel_to_xtce.py +1 -2
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +18 -12
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +569 -0
- imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +5 -5
- imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +20 -1
- imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +6 -4
- imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +3 -3
- imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +15 -0
- imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
- imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +16 -0
- imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +178 -5
- imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +33 -19
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +8 -48
- imap_processing/cdf/utils.py +41 -33
- imap_processing/cli.py +463 -234
- imap_processing/codice/codice_l1a.py +260 -47
- imap_processing/codice/codice_l1b.py +51 -152
- imap_processing/codice/constants.py +38 -1
- imap_processing/ena_maps/ena_maps.py +658 -65
- imap_processing/ena_maps/utils/coordinates.py +1 -1
- imap_processing/ena_maps/utils/spatial_utils.py +10 -5
- imap_processing/glows/l1a/glows_l1a.py +28 -99
- imap_processing/glows/l1a/glows_l1a_data.py +2 -2
- imap_processing/glows/l1b/glows_l1b.py +1 -4
- imap_processing/glows/l1b/glows_l1b_data.py +1 -3
- imap_processing/glows/l2/glows_l2.py +2 -5
- imap_processing/hi/l1a/hi_l1a.py +31 -12
- imap_processing/hi/l1b/hi_l1b.py +80 -43
- imap_processing/hi/l1c/hi_l1c.py +12 -16
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
- imap_processing/hit/hit_utils.py +93 -35
- imap_processing/hit/l0/decom_hit.py +3 -1
- imap_processing/hit/l1a/hit_l1a.py +30 -25
- imap_processing/hit/l1b/constants.py +6 -2
- imap_processing/hit/l1b/hit_l1b.py +279 -318
- imap_processing/hit/l2/constants.py +37 -0
- imap_processing/hit/l2/hit_l2.py +373 -264
- imap_processing/ialirt/l0/parse_mag.py +138 -10
- imap_processing/ialirt/l0/process_swapi.py +69 -0
- imap_processing/ialirt/l0/process_swe.py +318 -22
- imap_processing/ialirt/packet_definitions/ialirt.xml +216 -212
- imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +1 -1
- imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +1 -1
- imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
- imap_processing/ialirt/utils/grouping.py +1 -1
- imap_processing/idex/idex_constants.py +9 -1
- imap_processing/idex/idex_l0.py +22 -8
- imap_processing/idex/idex_l1a.py +75 -44
- imap_processing/idex/idex_l1b.py +9 -8
- imap_processing/idex/idex_l2a.py +79 -45
- imap_processing/idex/idex_l2b.py +120 -0
- imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -39
- imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
- imap_processing/lo/l0/lo_science.py +1 -2
- imap_processing/lo/l1a/lo_l1a.py +1 -4
- imap_processing/lo/l1b/lo_l1b.py +527 -6
- imap_processing/lo/l1b/tof_conversions.py +11 -0
- imap_processing/lo/l1c/lo_l1c.py +1 -4
- imap_processing/mag/constants.py +43 -0
- imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
- imap_processing/mag/l1a/mag_l1a.py +2 -9
- imap_processing/mag/l1a/mag_l1a_data.py +10 -10
- imap_processing/mag/l1b/mag_l1b.py +84 -17
- imap_processing/mag/l1c/interpolation_methods.py +180 -3
- imap_processing/mag/l1c/mag_l1c.py +236 -70
- imap_processing/mag/l2/mag_l2.py +140 -0
- imap_processing/mag/l2/mag_l2_data.py +288 -0
- imap_processing/spacecraft/quaternions.py +1 -3
- imap_processing/spice/geometry.py +3 -3
- imap_processing/spice/kernels.py +0 -276
- imap_processing/spice/pointing_frame.py +257 -0
- imap_processing/spice/repoint.py +48 -19
- imap_processing/spice/spin.py +38 -33
- imap_processing/spice/time.py +24 -0
- imap_processing/swapi/l1/swapi_l1.py +16 -12
- imap_processing/swapi/l2/swapi_l2.py +116 -4
- imap_processing/swapi/swapi_utils.py +32 -0
- imap_processing/swe/l1a/swe_l1a.py +2 -9
- imap_processing/swe/l1a/swe_science.py +8 -11
- imap_processing/swe/l1b/swe_l1b.py +898 -23
- imap_processing/swe/l2/swe_l2.py +21 -77
- imap_processing/swe/utils/swe_constants.py +1 -0
- imap_processing/tests/ccsds/test_excel_to_xtce.py +1 -1
- imap_processing/tests/cdf/test_utils.py +14 -16
- imap_processing/tests/codice/conftest.py +44 -33
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/test_codice_l1a.py +20 -11
- imap_processing/tests/codice/test_codice_l1b.py +6 -7
- imap_processing/tests/conftest.py +78 -22
- imap_processing/tests/ena_maps/test_ena_maps.py +462 -33
- imap_processing/tests/ena_maps/test_spatial_utils.py +1 -1
- imap_processing/tests/glows/conftest.py +10 -14
- imap_processing/tests/glows/test_glows_decom.py +4 -4
- imap_processing/tests/glows/test_glows_l1a_cdf.py +6 -27
- imap_processing/tests/glows/test_glows_l1a_data.py +6 -8
- imap_processing/tests/glows/test_glows_l1b.py +11 -11
- imap_processing/tests/glows/test_glows_l1b_data.py +5 -5
- imap_processing/tests/glows/test_glows_l2.py +2 -8
- imap_processing/tests/hi/conftest.py +1 -1
- imap_processing/tests/hi/test_hi_l1b.py +10 -12
- imap_processing/tests/hi/test_hi_l1c.py +27 -24
- imap_processing/tests/hi/test_l1a.py +7 -9
- imap_processing/tests/hi/test_science_direct_event.py +2 -2
- imap_processing/tests/hit/helpers/l1_validation.py +44 -43
- imap_processing/tests/hit/test_decom_hit.py +1 -1
- imap_processing/tests/hit/test_hit_l1a.py +9 -9
- imap_processing/tests/hit/test_hit_l1b.py +172 -217
- imap_processing/tests/hit/test_hit_l2.py +380 -118
- imap_processing/tests/hit/test_hit_utils.py +122 -55
- imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
- imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
- imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
- imap_processing/tests/ialirt/unit/test_grouping.py +2 -2
- imap_processing/tests/ialirt/unit/test_parse_mag.py +71 -16
- imap_processing/tests/ialirt/unit/test_process_codicehi.py +3 -3
- imap_processing/tests/ialirt/unit/test_process_codicelo.py +3 -10
- imap_processing/tests/ialirt/unit/test_process_ephemeris.py +4 -4
- imap_processing/tests/ialirt/unit/test_process_hit.py +3 -3
- imap_processing/tests/ialirt/unit/test_process_swapi.py +24 -16
- imap_processing/tests/ialirt/unit/test_process_swe.py +115 -7
- imap_processing/tests/idex/conftest.py +72 -7
- imap_processing/tests/idex/test_data/imap_idex_l0_raw_20241206_v001.pkts +0 -0
- imap_processing/tests/idex/test_data/imap_idex_l0_raw_20250108_v001.pkts +0 -0
- imap_processing/tests/idex/test_idex_l0.py +33 -11
- imap_processing/tests/idex/test_idex_l1a.py +50 -23
- imap_processing/tests/idex/test_idex_l1b.py +104 -25
- imap_processing/tests/idex/test_idex_l2a.py +48 -32
- imap_processing/tests/idex/test_idex_l2b.py +93 -0
- imap_processing/tests/lo/test_lo_l1a.py +3 -3
- imap_processing/tests/lo/test_lo_l1b.py +371 -6
- imap_processing/tests/lo/test_lo_l1c.py +1 -1
- imap_processing/tests/lo/test_lo_science.py +6 -7
- imap_processing/tests/lo/test_star_sensor.py +1 -1
- imap_processing/tests/mag/conftest.py +58 -9
- imap_processing/tests/mag/test_mag_decom.py +4 -3
- imap_processing/tests/mag/test_mag_l1a.py +13 -7
- imap_processing/tests/mag/test_mag_l1b.py +9 -9
- imap_processing/tests/mag/test_mag_l1c.py +151 -47
- imap_processing/tests/mag/test_mag_l2.py +130 -0
- imap_processing/tests/mag/test_mag_validation.py +144 -7
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-out.csv +1857 -0
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-out.csv +1857 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-out.csv +1793 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-out.csv +1793 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-burst-in.csv +2561 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-in.csv +961 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-out.csv +1539 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-in.csv +1921 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-out.csv +2499 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-in.csv +865 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv +1196 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-in.csv +1729 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv +3053 -0
- imap_processing/tests/mag/validation/L2/imap_mag_l1b_norm-mago_20251017_v002.cdf +0 -0
- imap_processing/tests/mag/validation/calibration/imap_mag_l2-calibration-matrices_20251017_v004.cdf +0 -0
- imap_processing/tests/mag/validation/calibration/imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf +0 -0
- imap_processing/tests/spacecraft/test_quaternions.py +1 -1
- imap_processing/tests/spice/test_data/fake_repoint_data.csv +4 -4
- imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
- imap_processing/tests/spice/test_geometry.py +3 -3
- imap_processing/tests/spice/test_kernels.py +1 -200
- imap_processing/tests/spice/test_pointing_frame.py +185 -0
- imap_processing/tests/spice/test_repoint.py +20 -10
- imap_processing/tests/spice/test_spin.py +50 -9
- imap_processing/tests/spice/test_time.py +14 -0
- imap_processing/tests/swapi/lut/imap_swapi_esa-unit-conversion_20250211_v000.csv +73 -0
- imap_processing/tests/swapi/lut/imap_swapi_lut-notes_20250211_v000.csv +1025 -0
- imap_processing/tests/swapi/test_swapi_l1.py +7 -9
- imap_processing/tests/swapi/test_swapi_l2.py +180 -8
- imap_processing/tests/swe/lut/checker-board-indices.csv +24 -0
- imap_processing/tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv +385 -0
- imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv +3 -0
- imap_processing/tests/swe/test_swe_l1a.py +6 -6
- imap_processing/tests/swe/test_swe_l1a_science.py +3 -3
- imap_processing/tests/swe/test_swe_l1b.py +162 -24
- imap_processing/tests/swe/test_swe_l2.py +82 -102
- imap_processing/tests/test_cli.py +171 -88
- imap_processing/tests/test_utils.py +2 -1
- imap_processing/tests/ultra/data/mock_data.py +49 -21
- imap_processing/tests/ultra/unit/conftest.py +53 -70
- imap_processing/tests/ultra/unit/test_badtimes.py +2 -4
- imap_processing/tests/ultra/unit/test_cullingmask.py +4 -6
- imap_processing/tests/ultra/unit/test_de.py +3 -10
- imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
- imap_processing/tests/ultra/unit/test_decom_apid_881.py +15 -16
- imap_processing/tests/ultra/unit/test_decom_apid_883.py +12 -10
- imap_processing/tests/ultra/unit/test_decom_apid_896.py +202 -55
- imap_processing/tests/ultra/unit/test_lookup_utils.py +23 -1
- imap_processing/tests/ultra/unit/test_spacecraft_pset.py +3 -4
- imap_processing/tests/ultra/unit/test_ultra_l1a.py +84 -307
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +30 -12
- imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
- imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +4 -1
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +163 -29
- imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +32 -43
- imap_processing/tests/ultra/unit/test_ultra_l2.py +230 -0
- imap_processing/ultra/constants.py +1 -1
- imap_processing/ultra/l0/decom_tools.py +21 -34
- imap_processing/ultra/l0/decom_ultra.py +168 -204
- imap_processing/ultra/l0/ultra_utils.py +152 -136
- imap_processing/ultra/l1a/ultra_l1a.py +55 -243
- imap_processing/ultra/l1b/badtimes.py +1 -4
- imap_processing/ultra/l1b/cullingmask.py +2 -6
- imap_processing/ultra/l1b/de.py +62 -47
- imap_processing/ultra/l1b/extendedspin.py +8 -4
- imap_processing/ultra/l1b/lookup_utils.py +72 -9
- imap_processing/ultra/l1b/ultra_l1b.py +3 -8
- imap_processing/ultra/l1b/ultra_l1b_culling.py +4 -4
- imap_processing/ultra/l1b/ultra_l1b_extended.py +236 -78
- imap_processing/ultra/l1c/histogram.py +2 -6
- imap_processing/ultra/l1c/spacecraft_pset.py +2 -4
- imap_processing/ultra/l1c/ultra_l1c.py +1 -5
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +107 -60
- imap_processing/ultra/l2/ultra_l2.py +299 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -2
- imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
- imap_processing/ultra/packet_definitions/README.md +38 -0
- imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +15302 -482
- imap_processing/ultra/utils/ultra_l1_utils.py +13 -12
- imap_processing/utils.py +1 -1
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +3 -2
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/RECORD +264 -225
- imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
- imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +0 -6
- imap_processing/mag/l1b/__init__.py +0 -0
- imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
- imap_processing/swe/l1b/swe_l1b_science.py +0 -699
- imap_processing/tests/swe/test_swe_l1b_science.py +0 -103
- imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
- imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
- /imap_processing/idex/packet_definitions/{idex_packet_definition.xml → idex_science_packet_definition.xml} +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971383-404.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971384-405.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971385-406.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971386-407.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971387-408.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971388-409.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971389-410.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971390-411.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971391-412.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/IALiRT Raw Packet Telemetry.txt +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/apid01152.tlm +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/eu_SWP_IAL_20240826_152033.csv +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/hi_fsw_view_1_ccsds.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.ccsds +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.csv +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/sample_decoded_i-alirt_data.csv +0 -0
- /imap_processing/tests/mag/validation/{imap_calibration_mag_20240229_v01.cdf → calibration/imap_mag_l1b-calibration_20240229_v001.cdf} +0 -0
- /imap_processing/{swe/l1b/engineering_unit_convert_table.csv → tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv} +0 -0
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""File describing configuration changes that are not expected to change often."""
|
|
2
|
+
|
|
3
|
+
# interpolation method used in L1C processing
|
|
4
|
+
L1C_INTERPOLATION_METHOD = "linear_filtered"
|
|
5
|
+
|
|
6
|
+
# Setting for L2 output
|
|
7
|
+
# if this setting is updated, the dependency settings for L2 will also need to change.
|
|
8
|
+
ALWAYS_OUTPUT_MAGO = True
|
|
@@ -24,7 +24,7 @@ from imap_processing.spice.time import (
|
|
|
24
24
|
logger = logging.getLogger(__name__)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def mag_l1a(packet_filepath: Path
|
|
27
|
+
def mag_l1a(packet_filepath: Path) -> list[xr.Dataset]:
|
|
28
28
|
"""
|
|
29
29
|
Will process MAG L0 data into L1A CDF files at cdf_filepath.
|
|
30
30
|
|
|
@@ -32,8 +32,6 @@ def mag_l1a(packet_filepath: Path, data_version: str) -> list[xr.Dataset]:
|
|
|
32
32
|
----------
|
|
33
33
|
packet_filepath : pathlib.Path
|
|
34
34
|
Packet files for processing.
|
|
35
|
-
data_version : str
|
|
36
|
-
Data version to write to CDF files.
|
|
37
35
|
|
|
38
36
|
Returns
|
|
39
37
|
-------
|
|
@@ -51,8 +49,6 @@ def mag_l1a(packet_filepath: Path, data_version: str) -> list[xr.Dataset]:
|
|
|
51
49
|
attribute_manager = ImapCdfAttributes()
|
|
52
50
|
attribute_manager.add_instrument_global_attrs("mag")
|
|
53
51
|
attribute_manager.add_instrument_variable_attrs("mag", "l1a")
|
|
54
|
-
|
|
55
|
-
attribute_manager.add_global_attribute("Data_version", data_version)
|
|
56
52
|
attribute_manager.add_global_attribute("Input_files", str(input_files))
|
|
57
53
|
attribute_manager.add_global_attribute(
|
|
58
54
|
"Generation_date",
|
|
@@ -179,7 +175,7 @@ def process_packets(
|
|
|
179
175
|
# each sensor, we can calculate how much data is in this packet and where the
|
|
180
176
|
# byte boundaries are.
|
|
181
177
|
primary_vectors, secondary_vectors = MagL1a.process_vector_data(
|
|
182
|
-
mag_l0.VECTORS,
|
|
178
|
+
mag_l0.VECTORS,
|
|
183
179
|
primary_packet_properties.total_vectors,
|
|
184
180
|
secondary_packet_data.total_vectors,
|
|
185
181
|
mag_l0.COMPRESSION,
|
|
@@ -297,8 +293,6 @@ def generate_dataset(
|
|
|
297
293
|
),
|
|
298
294
|
)
|
|
299
295
|
|
|
300
|
-
# TODO: Epoch here refers to the start of the sample. Confirm that this is
|
|
301
|
-
# what mag is expecting, and if it is, CATDESC needs to be updated.
|
|
302
296
|
epoch_time = xr.DataArray(
|
|
303
297
|
time_data,
|
|
304
298
|
name="epoch",
|
|
@@ -338,7 +332,6 @@ def generate_dataset(
|
|
|
338
332
|
),
|
|
339
333
|
)
|
|
340
334
|
global_attributes = attribute_manager.get_global_attributes(logical_file_id)
|
|
341
|
-
# TODO: this method won't work because these values are not in the schema.
|
|
342
335
|
global_attributes["is_mago"] = str(bool(single_file_l1a.is_mago))
|
|
343
336
|
global_attributes["is_active"] = str(bool(single_file_l1a.is_active))
|
|
344
337
|
global_attributes["vectors_per_second"] = (
|
|
@@ -368,7 +368,7 @@ class MagL1a:
|
|
|
368
368
|
|
|
369
369
|
@staticmethod
|
|
370
370
|
def process_vector_data(
|
|
371
|
-
vector_data: np.ndarray,
|
|
371
|
+
vector_data: np.ndarray | bytes,
|
|
372
372
|
primary_count: int,
|
|
373
373
|
secondary_count: int,
|
|
374
374
|
compression: int,
|
|
@@ -679,10 +679,9 @@ class MagL1a:
|
|
|
679
679
|
primary_boundaries[-1] - primary_boundaries[-4]
|
|
680
680
|
> MAX_COMPRESSED_VECTOR_BITS
|
|
681
681
|
)
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
)
|
|
682
|
+
) or (
|
|
683
|
+
vector_count == 2
|
|
684
|
+
and primary_boundaries[-1] > MAX_COMPRESSED_VECTOR_BITS
|
|
686
685
|
):
|
|
687
686
|
# Since we know how long each uncompressed vector is,
|
|
688
687
|
# we can determine the end of the primary vectors.
|
|
@@ -792,7 +791,7 @@ class MagL1a:
|
|
|
792
791
|
return primary_vectors, secondary_vectors
|
|
793
792
|
|
|
794
793
|
@staticmethod
|
|
795
|
-
def _process_vector_section(
|
|
794
|
+
def _process_vector_section(
|
|
796
795
|
vector_bits: np.ndarray,
|
|
797
796
|
split_bits: list,
|
|
798
797
|
last_index: int,
|
|
@@ -998,7 +997,7 @@ class MagL1a:
|
|
|
998
997
|
"""
|
|
999
998
|
if np.any(vector_data > 1):
|
|
1000
999
|
raise ValueError(
|
|
1001
|
-
"unpack_one_vector method is expecting an array of bits as
|
|
1000
|
+
"unpack_one_vector method is expecting an array of bits as input."
|
|
1002
1001
|
)
|
|
1003
1002
|
|
|
1004
1003
|
if len(vector_data) != width * AXIS_COUNT + RANGE_BIT_WIDTH * has_range:
|
|
@@ -1107,13 +1106,14 @@ class MagL1a:
|
|
|
1107
1106
|
"""
|
|
1108
1107
|
output_str = ""
|
|
1109
1108
|
last_vectors_per_second = None
|
|
1110
|
-
for
|
|
1109
|
+
for _, packet in self.packet_definitions.items():
|
|
1111
1110
|
vecsec = packet.vectors_per_second
|
|
1111
|
+
time: np.int64 = packet.start_time.to_j2000ns().astype(np.int64)
|
|
1112
1112
|
if vecsec != last_vectors_per_second:
|
|
1113
1113
|
if output_str == "":
|
|
1114
|
-
output_str = f"{
|
|
1114
|
+
output_str = f"{time}:{vecsec}"
|
|
1115
1115
|
else:
|
|
1116
|
-
output_str += f",{
|
|
1116
|
+
output_str += f",{time}:{vecsec}"
|
|
1117
1117
|
last_vectors_per_second = vecsec
|
|
1118
1118
|
|
|
1119
1119
|
return output_str
|
|
@@ -9,12 +9,13 @@ from xarray import Dataset
|
|
|
9
9
|
|
|
10
10
|
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
11
11
|
from imap_processing.cdf.utils import load_cdf
|
|
12
|
+
from imap_processing.mag.constants import vectors_per_second_from_string
|
|
12
13
|
|
|
13
14
|
logger = logging.getLogger(__name__)
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def mag_l1b(
|
|
17
|
-
input_dataset: xr.Dataset,
|
|
18
|
+
input_dataset: xr.Dataset, calibration_dataset: xr.Dataset = None
|
|
18
19
|
) -> Dataset:
|
|
19
20
|
"""
|
|
20
21
|
Will process MAG L1B data from L1A data.
|
|
@@ -23,8 +24,6 @@ def mag_l1b(
|
|
|
23
24
|
----------
|
|
24
25
|
input_dataset : xr.Dataset
|
|
25
26
|
The input dataset to process.
|
|
26
|
-
version : str
|
|
27
|
-
The version of the output data.
|
|
28
27
|
calibration_dataset : xr.Dataset
|
|
29
28
|
The calibration dataset containing calibration matrices and timeshift values for
|
|
30
29
|
mago and magi.
|
|
@@ -56,7 +55,6 @@ def mag_l1b(
|
|
|
56
55
|
mag_attributes = ImapCdfAttributes()
|
|
57
56
|
mag_attributes.add_instrument_global_attrs("mag")
|
|
58
57
|
mag_attributes.add_instrument_variable_attrs("mag", "l1b")
|
|
59
|
-
mag_attributes.add_global_attribute("Data_version", version)
|
|
60
58
|
source = source.replace("l1a", "l1b")
|
|
61
59
|
|
|
62
60
|
output_dataset = mag_l1b_processing(
|
|
@@ -100,15 +98,10 @@ def mag_l1b_processing(
|
|
|
100
98
|
output_dataset : xr.Dataset
|
|
101
99
|
L1b dataset.
|
|
102
100
|
"""
|
|
103
|
-
dims = [["direction"], ["compression"]]
|
|
104
|
-
new_dims = [["direction"], ["compression"]]
|
|
105
|
-
|
|
106
101
|
if "mago" in logical_source:
|
|
107
|
-
|
|
108
|
-
time_shift = calibration_dataset["OTS"]
|
|
102
|
+
is_mago = True
|
|
109
103
|
elif "magi" in logical_source:
|
|
110
|
-
|
|
111
|
-
time_shift = calibration_dataset["ITS"]
|
|
104
|
+
is_mago = False
|
|
112
105
|
else:
|
|
113
106
|
raise ValueError(
|
|
114
107
|
f"Calibration matrix not found, invalid logical source "
|
|
@@ -116,6 +109,12 @@ def mag_l1b_processing(
|
|
|
116
109
|
)
|
|
117
110
|
|
|
118
111
|
# TODO: Check validity of time range for calibration
|
|
112
|
+
calibration_matrix, time_shift = retrieve_matrix_from_l1b_calibration(
|
|
113
|
+
calibration_dataset, is_mago
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
dims = [["direction"], ["compression"]]
|
|
117
|
+
new_dims = [["direction"], ["compression"]]
|
|
119
118
|
|
|
120
119
|
l1b_fields = xr.apply_ufunc(
|
|
121
120
|
update_vector,
|
|
@@ -129,6 +128,8 @@ def mag_l1b_processing(
|
|
|
129
128
|
)
|
|
130
129
|
|
|
131
130
|
epoch_time = shift_time(input_dataset["epoch"], time_shift)
|
|
131
|
+
|
|
132
|
+
# Update attributes and assemble dataset
|
|
132
133
|
epoch_time.attrs = mag_attributes.get_variable_attributes("epoch")
|
|
133
134
|
|
|
134
135
|
direction = xr.DataArray(
|
|
@@ -171,9 +172,9 @@ def mag_l1b_processing(
|
|
|
171
172
|
try:
|
|
172
173
|
global_attributes["is_mago"] = input_dataset.attrs["is_mago"]
|
|
173
174
|
global_attributes["is_active"] = input_dataset.attrs["is_active"]
|
|
174
|
-
global_attributes["vectors_per_second"] =
|
|
175
|
-
"vectors_per_second"
|
|
176
|
-
|
|
175
|
+
global_attributes["vectors_per_second"] = timeshift_vectors_per_second(
|
|
176
|
+
input_dataset.attrs["vectors_per_second"], time_shift
|
|
177
|
+
)
|
|
177
178
|
global_attributes["missing_sequences"] = input_dataset.attrs[
|
|
178
179
|
"missing_sequences"
|
|
179
180
|
]
|
|
@@ -210,6 +211,37 @@ def mag_l1b_processing(
|
|
|
210
211
|
return output_dataset
|
|
211
212
|
|
|
212
213
|
|
|
214
|
+
def retrieve_matrix_from_l1b_calibration(
|
|
215
|
+
calibration_dataset: xr.Dataset, is_mago: bool = True
|
|
216
|
+
) -> tuple[xr.DataArray, xr.DataArray]:
|
|
217
|
+
"""
|
|
218
|
+
Retrieve the calibration matrix and time shift from the calibration dataset.
|
|
219
|
+
|
|
220
|
+
Parameters
|
|
221
|
+
----------
|
|
222
|
+
calibration_dataset : xarray.Dataset
|
|
223
|
+
The calibration dataset containing the calibration matrices and time shift.
|
|
224
|
+
is_mago : bool
|
|
225
|
+
Whether the calibration is for mago or magi. If True, it retrieves the mago
|
|
226
|
+
calibration matrix and time shift. If False, it retrieves the magi calibration
|
|
227
|
+
matrix and time shift.
|
|
228
|
+
|
|
229
|
+
Returns
|
|
230
|
+
-------
|
|
231
|
+
tuple[xr.DataArray, xr.DataArray]
|
|
232
|
+
The calibration matrix and time shift. These can be passed directly into
|
|
233
|
+
update_vector, calibrate_vector, and shift_time.
|
|
234
|
+
"""
|
|
235
|
+
if is_mago:
|
|
236
|
+
calibration_matrix = calibration_dataset["MFOTOURFO"]
|
|
237
|
+
time_shift = calibration_dataset["OTS"]
|
|
238
|
+
else:
|
|
239
|
+
calibration_matrix = calibration_dataset["MFITOURFI"]
|
|
240
|
+
time_shift = calibration_dataset["ITS"]
|
|
241
|
+
|
|
242
|
+
return calibration_matrix, time_shift
|
|
243
|
+
|
|
244
|
+
|
|
213
245
|
def update_vector(
|
|
214
246
|
input_vector: np.ndarray,
|
|
215
247
|
input_compression: np.ndarray,
|
|
@@ -302,13 +334,14 @@ def calibrate_vector(
|
|
|
302
334
|
updated_vector : numpy.ndarray
|
|
303
335
|
Calibrated vector.
|
|
304
336
|
"""
|
|
305
|
-
updated_vector: np.ndarray = input_vector.copy()
|
|
337
|
+
updated_vector: np.ndarray = input_vector.copy().astype(np.float64)
|
|
306
338
|
if input_vector[3] % 1 != 0:
|
|
307
339
|
raise ValueError("Range must be an integer.")
|
|
308
340
|
|
|
309
341
|
range = int(input_vector[3])
|
|
310
|
-
x_y_z =
|
|
342
|
+
x_y_z = updated_vector[:3]
|
|
311
343
|
updated_vector[:3] = np.dot(calibration_matrix.values[:, :, range], x_y_z)
|
|
344
|
+
|
|
312
345
|
return updated_vector
|
|
313
346
|
|
|
314
347
|
|
|
@@ -336,7 +369,7 @@ def shift_time(epoch_times: xr.DataArray, time_shift: xr.DataArray) -> xr.DataAr
|
|
|
336
369
|
Parameters
|
|
337
370
|
----------
|
|
338
371
|
epoch_times : xr.DataArray
|
|
339
|
-
The input epoch times, in J2000 ns.
|
|
372
|
+
The input epoch times, in TT J2000 ns.
|
|
340
373
|
time_shift : xr.DataArray
|
|
341
374
|
The time shift to apply for the given sensor. This should be one value and is
|
|
342
375
|
in seconds.
|
|
@@ -353,3 +386,37 @@ def shift_time(epoch_times: xr.DataArray, time_shift: xr.DataArray) -> xr.DataAr
|
|
|
353
386
|
time_shift_ns = time_shift.data * 1e9
|
|
354
387
|
|
|
355
388
|
return epoch_times + time_shift_ns
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def timeshift_vectors_per_second(
|
|
392
|
+
vectors_per_second: str, time_shift: xr.DataArray
|
|
393
|
+
) -> str:
|
|
394
|
+
"""
|
|
395
|
+
Shift the vectors per second attribute by the time shift value.
|
|
396
|
+
|
|
397
|
+
This ensures that the vectors per second attribute is aligned with the epoch values
|
|
398
|
+
if the time is shifted.
|
|
399
|
+
|
|
400
|
+
Parameters
|
|
401
|
+
----------
|
|
402
|
+
vectors_per_second : str
|
|
403
|
+
The vectors per second attribute from the input dataset, in the format
|
|
404
|
+
"timestamp:rate,timestamp:rate".
|
|
405
|
+
time_shift : xr.DataArray
|
|
406
|
+
The time shift to apply for the given sensor. This should be one value and is
|
|
407
|
+
in seconds.
|
|
408
|
+
|
|
409
|
+
Returns
|
|
410
|
+
-------
|
|
411
|
+
str
|
|
412
|
+
The updated vectors per second attribute.
|
|
413
|
+
"""
|
|
414
|
+
time_shift_ns = time_shift.data * 1e9
|
|
415
|
+
|
|
416
|
+
vecsec = vectors_per_second_from_string(vectors_per_second)
|
|
417
|
+
new_vecsec = ""
|
|
418
|
+
for time, rate in vecsec.items():
|
|
419
|
+
new_time = time + time_shift_ns
|
|
420
|
+
new_vecsec += f"{new_time.astype(np.int64)}:{rate},"
|
|
421
|
+
|
|
422
|
+
return new_vecsec[:-1]
|
|
@@ -1,16 +1,51 @@
|
|
|
1
1
|
# mypy: ignore-errors
|
|
2
2
|
"""Module containing interpolation methods for MAG L1C."""
|
|
3
3
|
|
|
4
|
+
import logging
|
|
4
5
|
from enum import Enum
|
|
6
|
+
from typing import Optional
|
|
5
7
|
|
|
6
8
|
import numpy as np
|
|
7
9
|
from scipy.interpolate import make_interp_spline
|
|
10
|
+
from scipy.signal import lfilter
|
|
11
|
+
|
|
12
|
+
from imap_processing.mag.constants import POSSIBLE_RATES, VecSec
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def remove_invalid_output_timestamps(
|
|
18
|
+
input_timestamps: np.ndarray, output_timestamps: np.ndarray
|
|
19
|
+
) -> np.ndarray:
|
|
20
|
+
"""
|
|
21
|
+
Remove output timestamps where we don't have input timestamps to interpolate.
|
|
22
|
+
|
|
23
|
+
I.E. We should never create science data outside of the timeline of burst data.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
input_timestamps : numpy.ndarray
|
|
28
|
+
List of input timestamps (from burst data).
|
|
29
|
+
output_timestamps : numpy.ndarray
|
|
30
|
+
List of output timestamps (from norm data) to downsample/interpolate to.
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
numpy.ndarray
|
|
35
|
+
All valid output timestamps where there exists input data.
|
|
36
|
+
"""
|
|
37
|
+
if input_timestamps[0] > output_timestamps[0]:
|
|
38
|
+
# Chop data where we don't have input timestamps to interpolate
|
|
39
|
+
output_timestamps = output_timestamps[output_timestamps >= input_timestamps[0]]
|
|
40
|
+
return output_timestamps
|
|
8
41
|
|
|
9
42
|
|
|
10
43
|
def linear(
|
|
11
44
|
input_vectors: np.ndarray,
|
|
12
45
|
input_timestamps: np.ndarray,
|
|
13
46
|
output_timestamps: np.ndarray,
|
|
47
|
+
input_rate: Optional[VecSec] = None,
|
|
48
|
+
output_rate: Optional[VecSec] = None,
|
|
14
49
|
) -> np.ndarray:
|
|
15
50
|
"""
|
|
16
51
|
Linear interpolation of input vectors to output timestamps.
|
|
@@ -25,6 +60,10 @@ def linear(
|
|
|
25
60
|
vectors.
|
|
26
61
|
output_timestamps : numpy.ndarray
|
|
27
62
|
Output timestamps of shape (m,) to generate interpolated vectors for.
|
|
63
|
+
input_rate : VecSec, optional
|
|
64
|
+
Not required for this interpolation method.
|
|
65
|
+
output_rate : VecSec, optional
|
|
66
|
+
Not required for this interpolation method.
|
|
28
67
|
|
|
29
68
|
Returns
|
|
30
69
|
-------
|
|
@@ -32,6 +71,7 @@ def linear(
|
|
|
32
71
|
Interpolated vectors of shape (m, 3) where m is equal to the number of output
|
|
33
72
|
timestamps. Contains x, y, z components of the vector.
|
|
34
73
|
"""
|
|
74
|
+
# TODO: Remove invalid timestamps using remove_invalid_output_timestamps
|
|
35
75
|
spline = make_interp_spline(input_timestamps, input_vectors, k=1)
|
|
36
76
|
return spline(output_timestamps)
|
|
37
77
|
|
|
@@ -40,6 +80,8 @@ def quadratic(
|
|
|
40
80
|
input_vectors: np.ndarray,
|
|
41
81
|
input_timestamps: np.ndarray,
|
|
42
82
|
output_timestamps: np.ndarray,
|
|
83
|
+
input_rate: Optional[VecSec] = None,
|
|
84
|
+
output_rate: Optional[VecSec] = None,
|
|
43
85
|
) -> np.ndarray:
|
|
44
86
|
"""
|
|
45
87
|
Quadratic interpolation of input vectors to output timestamps.
|
|
@@ -54,6 +96,10 @@ def quadratic(
|
|
|
54
96
|
vectors.
|
|
55
97
|
output_timestamps : numpy.ndarray
|
|
56
98
|
Output timestamps of shape (m,) to generate interpolated vectors for.
|
|
99
|
+
input_rate : VecSec, optional
|
|
100
|
+
Not required for this interpolation method.
|
|
101
|
+
output_rate : VecSec, optional
|
|
102
|
+
Not required for this interpolation method.
|
|
57
103
|
|
|
58
104
|
Returns
|
|
59
105
|
-------
|
|
@@ -69,6 +115,8 @@ def cubic(
|
|
|
69
115
|
input_vectors: np.ndarray,
|
|
70
116
|
input_timestamps: np.ndarray,
|
|
71
117
|
output_timestamps: np.ndarray,
|
|
118
|
+
input_rate: Optional[VecSec] = None,
|
|
119
|
+
output_rate: Optional[VecSec] = None,
|
|
72
120
|
) -> np.ndarray:
|
|
73
121
|
"""
|
|
74
122
|
Cubic interpolation of input vectors to output timestamps.
|
|
@@ -83,6 +131,10 @@ def cubic(
|
|
|
83
131
|
vectors.
|
|
84
132
|
output_timestamps : numpy.ndarray
|
|
85
133
|
Output timestamps of shape (m,) to generate interpolated vectors for.
|
|
134
|
+
input_rate : VecSec, optional
|
|
135
|
+
Not required for this interpolation method.
|
|
136
|
+
output_rate : VecSec, optional
|
|
137
|
+
Not required for this interpolation method.
|
|
86
138
|
|
|
87
139
|
Returns
|
|
88
140
|
-------
|
|
@@ -94,10 +146,104 @@ def cubic(
|
|
|
94
146
|
return spline(output_timestamps)
|
|
95
147
|
|
|
96
148
|
|
|
149
|
+
def estimate_rate(timestamps: np.ndarray) -> VecSec:
|
|
150
|
+
"""
|
|
151
|
+
Given a set of timestamps, estimate the rate of the timestamps.
|
|
152
|
+
|
|
153
|
+
This rate will be one of the defined rates in the VecSec enum. The calculation
|
|
154
|
+
assumes there are no significant gaps in the timestamps.
|
|
155
|
+
|
|
156
|
+
Parameters
|
|
157
|
+
----------
|
|
158
|
+
timestamps : numpy.ndarray
|
|
159
|
+
1D array of timestamps to estimate the rate of.
|
|
160
|
+
|
|
161
|
+
Returns
|
|
162
|
+
-------
|
|
163
|
+
VecSec
|
|
164
|
+
Estimated rate of the timestamps.
|
|
165
|
+
"""
|
|
166
|
+
samples_per_second = timestamps.shape[0] / (timestamps[-1] - timestamps[0]) * 1e9
|
|
167
|
+
per_second = VecSec(
|
|
168
|
+
POSSIBLE_RATES[(np.abs(POSSIBLE_RATES - samples_per_second)).argmin()]
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
return per_second
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def cic_filter(
|
|
175
|
+
input_vectors: np.ndarray,
|
|
176
|
+
input_timestamps: np.ndarray,
|
|
177
|
+
output_timestamps: np.ndarray,
|
|
178
|
+
input_rate: Optional[VecSec],
|
|
179
|
+
output_rate: Optional[VecSec],
|
|
180
|
+
):
|
|
181
|
+
"""
|
|
182
|
+
Apply CIC filter to data before interpolating.
|
|
183
|
+
|
|
184
|
+
The filtering uses a Cascaded integrator-comb (CIC) filter which is used in FSW to
|
|
185
|
+
filter down the raw data to telemetered data.
|
|
186
|
+
|
|
187
|
+
This assumes that the input_vectors and input_timestamps are downsampled to
|
|
188
|
+
the output_timestamps rate. Neither input_timestamps nor output_timestamps should
|
|
189
|
+
have significant gaps.
|
|
190
|
+
|
|
191
|
+
After the CIC filter is applied, the timestamps at the beginning and end of the
|
|
192
|
+
output are invalid. Therefore, we must pass in extra values and remove them after
|
|
193
|
+
applying the filter. This needs about double the input values to work.
|
|
194
|
+
|
|
195
|
+
Parameters
|
|
196
|
+
----------
|
|
197
|
+
input_vectors : numpy.ndarray
|
|
198
|
+
Input vectors of shape (n, 3) where n is equal to the number of input
|
|
199
|
+
timestamps. Contains x, y, z components of the vector.
|
|
200
|
+
input_timestamps : numpy.ndarray
|
|
201
|
+
Input timestamps of shape (n,) which correspond to the timestamps of the input
|
|
202
|
+
vectors.
|
|
203
|
+
output_timestamps : numpy.ndarray
|
|
204
|
+
Output timestamps of shape (m,) to generate interpolated vectors for.
|
|
205
|
+
input_rate : VecSec, optional
|
|
206
|
+
Expected rate of input timestamps.
|
|
207
|
+
output_rate : VecSec, optional
|
|
208
|
+
Expected rate of output timestamps.
|
|
209
|
+
|
|
210
|
+
Returns
|
|
211
|
+
-------
|
|
212
|
+
input_filtered, vectors_filtered : tuple[numpy.ndarray]
|
|
213
|
+
Filtered input timestamps and filtered input vectors.
|
|
214
|
+
"""
|
|
215
|
+
# output rate should always be higher
|
|
216
|
+
input_rate = estimate_rate(input_timestamps) if input_rate is None else input_rate
|
|
217
|
+
output_rate = (
|
|
218
|
+
estimate_rate(output_timestamps) if output_rate is None else output_rate
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
if input_rate.value <= output_rate.value:
|
|
222
|
+
raise ValueError(
|
|
223
|
+
f"Burst mode input rate {input_rate} should never be less than "
|
|
224
|
+
f"the normal mode output rate {output_rate}. "
|
|
225
|
+
f"Both rates are required"
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
decimation_factor = int(input_rate.value / output_rate.value)
|
|
229
|
+
cic1 = np.ones(decimation_factor)
|
|
230
|
+
cic1 = cic1 / decimation_factor
|
|
231
|
+
cic2 = np.convolve(cic1, cic1)
|
|
232
|
+
delay = (len(cic2) - 1) // 2
|
|
233
|
+
input_filtered = input_timestamps
|
|
234
|
+
if delay != 0:
|
|
235
|
+
input_filtered = input_timestamps[:-delay]
|
|
236
|
+
|
|
237
|
+
vectors_filtered = lfilter(cic2, 1, input_vectors, axis=0)[delay:]
|
|
238
|
+
return input_filtered, vectors_filtered
|
|
239
|
+
|
|
240
|
+
|
|
97
241
|
def linear_filtered(
|
|
98
242
|
input_vectors: np.ndarray,
|
|
99
243
|
input_timestamps: np.ndarray,
|
|
100
244
|
output_timestamps: np.ndarray,
|
|
245
|
+
input_rate: Optional[VecSec] = None,
|
|
246
|
+
output_rate: Optional[VecSec] = None,
|
|
101
247
|
) -> np.ndarray:
|
|
102
248
|
"""
|
|
103
249
|
Linear filtered interpolation of input vectors to output timestamps.
|
|
@@ -112,6 +258,12 @@ def linear_filtered(
|
|
|
112
258
|
vectors.
|
|
113
259
|
output_timestamps : numpy.ndarray
|
|
114
260
|
Output timestamps of shape (m,) to generate interpolated vectors for.
|
|
261
|
+
input_rate : VecSec, optional
|
|
262
|
+
Expected rate of input timestamps to be passed into the CIC filter. If not
|
|
263
|
+
provided, this will be estimated.
|
|
264
|
+
output_rate : VecSec, optional
|
|
265
|
+
Expected rate of output timestamps to be passed into the CIC filter. If not
|
|
266
|
+
provided, this will be estimated.
|
|
115
267
|
|
|
116
268
|
Returns
|
|
117
269
|
-------
|
|
@@ -119,13 +271,18 @@ def linear_filtered(
|
|
|
119
271
|
Interpolated vectors of shape (m, 3) where m is equal to the number of output
|
|
120
272
|
timestamps. Contains x, y, z components of the vector.
|
|
121
273
|
"""
|
|
122
|
-
|
|
274
|
+
input_filtered, vectors_filtered = cic_filter(
|
|
275
|
+
input_vectors, input_timestamps, output_timestamps, input_rate, output_rate
|
|
276
|
+
)
|
|
277
|
+
return linear(vectors_filtered, input_filtered, output_timestamps)
|
|
123
278
|
|
|
124
279
|
|
|
125
280
|
def quadratic_filtered(
|
|
126
281
|
input_vectors: np.ndarray,
|
|
127
282
|
input_timestamps: np.ndarray,
|
|
128
283
|
output_timestamps: np.ndarray,
|
|
284
|
+
input_rate: Optional[VecSec] = None,
|
|
285
|
+
output_rate: Optional[VecSec] = None,
|
|
129
286
|
) -> np.ndarray:
|
|
130
287
|
"""
|
|
131
288
|
Quadratic filtered interpolation of input vectors to output timestamps.
|
|
@@ -140,6 +297,12 @@ def quadratic_filtered(
|
|
|
140
297
|
vectors.
|
|
141
298
|
output_timestamps : numpy.ndarray
|
|
142
299
|
Output timestamps of shape (m,) to generate interpolated vectors for.
|
|
300
|
+
input_rate : VecSec, optional
|
|
301
|
+
Expected rate of input timestamps to be passed into the CIC filter. If not
|
|
302
|
+
provided, this will be estimated.
|
|
303
|
+
output_rate : VecSec, optional
|
|
304
|
+
Expected rate of output timestamps to be passed into the CIC filter. If not
|
|
305
|
+
provided, this will be estimated.
|
|
143
306
|
|
|
144
307
|
Returns
|
|
145
308
|
-------
|
|
@@ -147,13 +310,18 @@ def quadratic_filtered(
|
|
|
147
310
|
Interpolated vectors of shape (m, 3) where m is equal to the number of output
|
|
148
311
|
timestamps. Contains x, y, z components of the vector.
|
|
149
312
|
"""
|
|
150
|
-
|
|
313
|
+
input_filtered, vectors_filtered = cic_filter(
|
|
314
|
+
input_vectors, input_timestamps, output_timestamps, input_rate, output_rate
|
|
315
|
+
)
|
|
316
|
+
return quadratic(vectors_filtered, input_filtered, output_timestamps)
|
|
151
317
|
|
|
152
318
|
|
|
153
319
|
def cubic_filtered(
|
|
154
320
|
input_vectors: np.ndarray,
|
|
155
321
|
input_timestamps: np.ndarray,
|
|
156
322
|
output_timestamps: np.ndarray,
|
|
323
|
+
input_rate: Optional[VecSec] = None,
|
|
324
|
+
output_rate: Optional[VecSec] = None,
|
|
157
325
|
) -> np.ndarray:
|
|
158
326
|
"""
|
|
159
327
|
Cubic filtered interpolation of input vectors to output timestamps.
|
|
@@ -168,6 +336,12 @@ def cubic_filtered(
|
|
|
168
336
|
vectors.
|
|
169
337
|
output_timestamps : numpy.ndarray
|
|
170
338
|
Output timestamps of shape (m,) to generate interpolated vectors for.
|
|
339
|
+
input_rate : VecSec, optional
|
|
340
|
+
Expected rate of input timestamps to be passed into the CIC filter. If not
|
|
341
|
+
provided, this will be estimated.
|
|
342
|
+
output_rate : VecSec, optional
|
|
343
|
+
Expected rate of output timestamps to be passed into the CIC filter. If not
|
|
344
|
+
provided, this will be estimated.
|
|
171
345
|
|
|
172
346
|
Returns
|
|
173
347
|
-------
|
|
@@ -175,7 +349,10 @@ def cubic_filtered(
|
|
|
175
349
|
Interpolated vectors of shape (m, 3) where m is equal to the number of output
|
|
176
350
|
timestamps. Contains x, y, z components of the vector.
|
|
177
351
|
"""
|
|
178
|
-
|
|
352
|
+
input_filtered, vectors_filtered = cic_filter(
|
|
353
|
+
input_vectors, input_timestamps, output_timestamps, input_rate, output_rate
|
|
354
|
+
)
|
|
355
|
+
return cubic(vectors_filtered, input_filtered, output_timestamps)
|
|
179
356
|
|
|
180
357
|
|
|
181
358
|
class InterpolationFunction(Enum):
|