imap-processing 0.11.0__py3-none-any.whl → 0.12.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 +10 -11
- imap_processing/_version.py +2 -2
- imap_processing/ccsds/excel_to_xtce.py +65 -16
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +6 -28
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +365 -42
- imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +0 -5
- imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +10 -11
- imap_processing/cdf/config/imap_hi_variable_attrs.yaml +17 -19
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +26 -13
- imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +106 -116
- imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +120 -145
- imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +14 -0
- imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +6 -9
- imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +1 -1
- imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +0 -12
- imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +1 -1
- imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +9 -21
- imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml +361 -0
- imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml +160 -0
- imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +160 -0
- imap_processing/cdf/config/imap_spacecraft_global_cdf_attrs.yaml +18 -0
- imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml +40 -0
- imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +1 -5
- imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +12 -4
- imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +16 -2
- imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +48 -52
- imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +71 -47
- imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +2 -14
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +51 -2
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +29 -14
- imap_processing/cdf/utils.py +13 -7
- imap_processing/cli.py +23 -8
- imap_processing/codice/codice_l1a.py +207 -85
- imap_processing/codice/constants.py +1322 -568
- imap_processing/codice/decompress.py +2 -6
- imap_processing/ena_maps/ena_maps.py +480 -116
- imap_processing/ena_maps/utils/coordinates.py +19 -0
- imap_processing/ena_maps/utils/map_utils.py +14 -17
- imap_processing/ena_maps/utils/spatial_utils.py +45 -47
- imap_processing/hi/l1a/hi_l1a.py +24 -18
- imap_processing/hi/l1a/histogram.py +0 -1
- imap_processing/hi/l1a/science_direct_event.py +6 -8
- imap_processing/hi/l1b/hi_l1b.py +31 -39
- imap_processing/hi/l1c/hi_l1c.py +405 -17
- imap_processing/hi/utils.py +58 -12
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt0-factors_20250219_v002.csv +205 -0
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt1-factors_20250219_v002.csv +205 -0
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt2-factors_20250219_v002.csv +205 -0
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-standard-dt3-factors_20250219_v002.csv +205 -0
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-summed-dt0-factors_20250219_v002.csv +68 -0
- imap_processing/hit/hit_utils.py +173 -1
- imap_processing/hit/l0/constants.py +20 -11
- imap_processing/hit/l0/decom_hit.py +18 -4
- imap_processing/hit/l1a/hit_l1a.py +45 -54
- imap_processing/hit/l1b/constants.py +317 -0
- imap_processing/hit/l1b/hit_l1b.py +367 -18
- imap_processing/hit/l2/constants.py +281 -0
- imap_processing/hit/l2/hit_l2.py +614 -0
- imap_processing/hit/packet_definitions/hit_packet_definitions.xml +1323 -71
- imap_processing/ialirt/l0/mag_l0_ialirt_data.py +155 -0
- imap_processing/ialirt/l0/parse_mag.py +246 -0
- imap_processing/ialirt/l0/process_swe.py +252 -0
- imap_processing/ialirt/packet_definitions/ialirt.xml +7 -3
- imap_processing/ialirt/packet_definitions/ialirt_mag.xml +115 -0
- imap_processing/ialirt/utils/grouping.py +114 -0
- imap_processing/ialirt/utils/time.py +29 -0
- imap_processing/idex/atomic_masses.csv +22 -0
- imap_processing/idex/decode.py +2 -2
- imap_processing/idex/idex_constants.py +25 -0
- imap_processing/idex/idex_l1a.py +6 -7
- imap_processing/idex/idex_l1b.py +4 -31
- imap_processing/idex/idex_l2a.py +789 -0
- imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +39 -33
- imap_processing/lo/l0/lo_science.py +6 -0
- imap_processing/lo/l1a/lo_l1a.py +0 -1
- imap_processing/lo/l1b/lo_l1b.py +177 -25
- imap_processing/mag/constants.py +8 -0
- imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +6 -0
- imap_processing/mag/l0/decom_mag.py +10 -3
- imap_processing/mag/l1a/mag_l1a.py +22 -11
- imap_processing/mag/l1a/mag_l1a_data.py +28 -3
- imap_processing/mag/l1b/mag_l1b.py +190 -48
- imap_processing/mag/l1c/interpolation_methods.py +211 -0
- imap_processing/mag/l1c/mag_l1c.py +447 -9
- imap_processing/quality_flags.py +1 -0
- imap_processing/spacecraft/packet_definitions/scid_x252.xml +538 -0
- imap_processing/spacecraft/quaternions.py +123 -0
- imap_processing/spice/geometry.py +16 -19
- imap_processing/spice/repoint.py +120 -0
- imap_processing/swapi/l1/swapi_l1.py +4 -0
- imap_processing/swapi/l2/swapi_l2.py +0 -1
- imap_processing/swe/l1a/swe_l1a.py +47 -8
- imap_processing/swe/l1a/swe_science.py +5 -2
- imap_processing/swe/l1b/swe_l1b_science.py +103 -56
- imap_processing/swe/l2/swe_l2.py +60 -65
- imap_processing/swe/packet_definitions/swe_packet_definition.xml +1121 -1
- imap_processing/swe/utils/swe_constants.py +63 -0
- imap_processing/swe/utils/swe_utils.py +85 -28
- imap_processing/tests/ccsds/test_data/expected_output.xml +40 -1
- imap_processing/tests/ccsds/test_excel_to_xtce.py +23 -20
- imap_processing/tests/cdf/test_data/imap_instrument2_global_cdf_attrs.yaml +0 -2
- imap_processing/tests/codice/conftest.py +1 -1
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-aggregated_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-counters-singles_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-ialirt_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-omni_20241110193700_v0.0.0.cdf +0 -0
- 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_hi-priorities_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-sectored_20241110193700_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-ialirt_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-pha_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_l1a.py +110 -46
- imap_processing/tests/codice/test_decompress.py +4 -4
- imap_processing/tests/conftest.py +166 -10
- imap_processing/tests/ena_maps/conftest.py +51 -0
- imap_processing/tests/ena_maps/test_ena_maps.py +638 -109
- imap_processing/tests/ena_maps/test_map_utils.py +66 -43
- imap_processing/tests/ena_maps/test_spatial_utils.py +16 -20
- imap_processing/tests/hi/data/l0/H45_diag_fee_20250208.bin +0 -0
- imap_processing/tests/hi/data/l0/H45_diag_fee_20250208_verify.csv +205 -0
- imap_processing/tests/hi/test_hi_l1b.py +12 -15
- imap_processing/tests/hi/test_hi_l1c.py +234 -6
- imap_processing/tests/hi/test_l1a.py +30 -0
- imap_processing/tests/hi/test_science_direct_event.py +1 -1
- imap_processing/tests/hi/test_utils.py +24 -2
- imap_processing/tests/hit/helpers/l1_validation.py +39 -39
- imap_processing/tests/hit/test_data/hskp_sample.ccsds +0 -0
- imap_processing/tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts +0 -0
- imap_processing/tests/hit/test_decom_hit.py +4 -0
- imap_processing/tests/hit/test_hit_l1a.py +24 -28
- imap_processing/tests/hit/test_hit_l1b.py +304 -40
- imap_processing/tests/hit/test_hit_l2.py +454 -0
- imap_processing/tests/hit/test_hit_utils.py +112 -2
- imap_processing/tests/hit/validation_data/hskp_sample_eu_3_6_2025.csv +89 -0
- imap_processing/tests/hit/validation_data/hskp_sample_raw.csv +89 -88
- imap_processing/tests/ialirt/test_data/l0/461971383-404.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/461971384-405.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/461971385-406.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/461971386-407.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/461971387-408.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/461971388-409.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/461971389-410.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/461971390-411.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/461971391-412.bin +0 -0
- imap_processing/tests/ialirt/test_data/l0/sample_decoded_i-alirt_data.csv +383 -0
- imap_processing/tests/ialirt/unit/test_grouping.py +81 -0
- imap_processing/tests/ialirt/unit/test_parse_mag.py +168 -0
- imap_processing/tests/ialirt/unit/test_process_swe.py +208 -3
- imap_processing/tests/ialirt/unit/test_time.py +16 -0
- imap_processing/tests/idex/conftest.py +62 -6
- imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231218_v001.pkts +0 -0
- imap_processing/tests/idex/test_data/impact_14_tof_high_data.txt +4508 -4508
- imap_processing/tests/idex/test_idex_l1a.py +48 -4
- imap_processing/tests/idex/test_idex_l1b.py +3 -3
- imap_processing/tests/idex/test_idex_l2a.py +383 -0
- imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20241022_v002.cdf +0 -0
- imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20241022_v002.cdf +0 -0
- imap_processing/tests/lo/test_lo_l1b.py +148 -4
- imap_processing/tests/lo/test_lo_science.py +1 -0
- imap_processing/tests/mag/conftest.py +69 -0
- imap_processing/tests/mag/test_mag_decom.py +1 -1
- imap_processing/tests/mag/test_mag_l1a.py +38 -0
- imap_processing/tests/mag/test_mag_l1b.py +34 -53
- imap_processing/tests/mag/test_mag_l1c.py +251 -20
- imap_processing/tests/mag/test_mag_validation.py +109 -25
- imap_processing/tests/mag/validation/L1b/T009/MAGScience-normal-(2,2)-8s-20250204-16h39.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-magi-out.csv +16 -16
- imap_processing/tests/mag/validation/L1b/T009/mag-l1a-l1b-t009-mago-out.csv +16 -16
- imap_processing/tests/mag/validation/L1b/T010/MAGScience-normal-(2,2)-8s-20250206-12h05.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-magi-out.csv +16 -16
- imap_processing/tests/mag/validation/L1b/T011/mag-l1a-l1b-t011-mago-out.csv +16 -16
- imap_processing/tests/mag/validation/L1b/T012/MAGScience-normal-(2,2)-8s-20250204-16h08.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T012/data.bin +0 -0
- imap_processing/tests/mag/validation/L1b/T012/field_like_all_ranges.txt +19200 -0
- imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-cal.cdf +0 -0
- imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-in.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-magi-out.csv +17 -0
- imap_processing/tests/mag/validation/L1b/T012/mag-l1a-l1b-t012-mago-out.csv +17 -0
- imap_processing/tests/mag/validation/imap_calibration_mag_20240229_v01.cdf +0 -0
- imap_processing/tests/spacecraft/__init__.py +0 -0
- imap_processing/tests/spacecraft/data/SSR_2024_190_20_08_12_0483851794_2_DA_apid0594_1packet.pkts +0 -0
- imap_processing/tests/spacecraft/test_quaternions.py +71 -0
- imap_processing/tests/spice/test_data/fake_repoint_data.csv +5 -0
- imap_processing/tests/spice/test_geometry.py +6 -9
- imap_processing/tests/spice/test_repoint.py +111 -0
- imap_processing/tests/swapi/test_swapi_l1.py +7 -3
- imap_processing/tests/swe/l0_data/2024051010_SWE_HK_packet.bin +0 -0
- imap_processing/tests/swe/l0_data/2024051011_SWE_CEM_RAW_packet.bin +0 -0
- imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_APP_HK_20240510_092742.csv +49 -0
- imap_processing/tests/swe/l0_validation_data/idle_export_eu.SWE_CEM_RAW_20240510_092742.csv +593 -0
- imap_processing/tests/swe/test_swe_l1a.py +18 -0
- imap_processing/tests/swe/test_swe_l1a_cem_raw.py +52 -0
- imap_processing/tests/swe/test_swe_l1a_hk.py +68 -0
- imap_processing/tests/swe/test_swe_l1b_science.py +23 -4
- imap_processing/tests/swe/test_swe_l2.py +112 -30
- imap_processing/tests/test_cli.py +2 -2
- imap_processing/tests/test_utils.py +138 -16
- imap_processing/tests/ultra/data/l0/FM45_UltraFM45_Functional_2024-01-22T0105_20240122T010548.CCSDS +0 -0
- imap_processing/tests/ultra/data/l0/ultra45_raw_sc_ultraimgrates_20220530_00.csv +164 -0
- imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv +3243 -3243
- imap_processing/tests/ultra/data/mock_data.py +341 -0
- imap_processing/tests/ultra/unit/conftest.py +69 -26
- imap_processing/tests/ultra/unit/test_badtimes.py +2 -0
- imap_processing/tests/ultra/unit/test_cullingmask.py +4 -0
- imap_processing/tests/ultra/unit/test_de.py +12 -4
- imap_processing/tests/ultra/unit/test_decom_apid_881.py +44 -0
- imap_processing/tests/ultra/unit/test_spacecraft_pset.py +78 -0
- imap_processing/tests/ultra/unit/test_ultra_l1a.py +28 -12
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +34 -6
- imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +22 -26
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +86 -51
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +94 -52
- imap_processing/ultra/l0/decom_tools.py +6 -5
- imap_processing/ultra/l1a/ultra_l1a.py +28 -56
- imap_processing/ultra/l1b/de.py +72 -28
- imap_processing/ultra/l1b/extendedspin.py +12 -14
- imap_processing/ultra/l1b/ultra_l1b.py +34 -9
- imap_processing/ultra/l1b/ultra_l1b_culling.py +65 -29
- imap_processing/ultra/l1b/ultra_l1b_extended.py +64 -19
- imap_processing/ultra/l1c/spacecraft_pset.py +86 -0
- imap_processing/ultra/l1c/ultra_l1c.py +7 -4
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +112 -61
- imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
- imap_processing/ultra/utils/ultra_l1_utils.py +20 -2
- imap_processing/utils.py +68 -28
- {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/METADATA +8 -5
- {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/RECORD +250 -199
- imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +0 -237
- imap_processing/hi/l1a/housekeeping.py +0 -27
- imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-aggregated_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_hi-counters-singles_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_hi-omni_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_hi-sectored_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_hskp_20100101_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-aggregated_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-counters-singles_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-angular_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-priority_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-nsw-species_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-angular_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-priority_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1a_lo-sw-species_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-aggregated_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_hi-counters-singles_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_hi-omni_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_hi-sectored_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_hskp_20100101_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-aggregated_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-counters-singles_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-angular_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-priority_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-nsw-species_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-angular_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-priority_20240429_v001.cdf +0 -0
- imap_processing/tests/codice/data/imap_codice_l1b_lo-sw-species_20240429_v001.cdf +0 -0
- imap_processing/tests/hi/data/l1/imap_hi_l1b_45sensor-de_20250415_v999.cdf +0 -0
- imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1251.pkts +0 -0
- imap_processing/tests/hit/PREFLIGHT_raw_record_2023_256_15_59_04_apid1252.pkts +0 -0
- imap_processing/tests/hit/validation_data/hskp_sample_eu.csv +0 -89
- imap_processing/tests/hit/validation_data/sci_sample_raw1.csv +0 -29
- imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231214_v001.pkts +0 -0
- imap_processing/tests/lo/test_cdfs/imap_lo_l1a_de_20100101_v001.cdf +0 -0
- imap_processing/tests/lo/test_cdfs/imap_lo_l1a_spin_20100101_v001.cdf +0 -0
- imap_processing/tests/ultra/test_data/mock_data.py +0 -161
- imap_processing/ultra/l1c/pset.py +0 -40
- /imap_processing/tests/ultra/{test_data → data}/l0/FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00_20240207T102740.CCSDS +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/FM45_7P_Phi0.0_BeamCal_LinearScan_phi0.04_theta-0.01_20230821T121304.CCSDS +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.CCSDS +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.CCSDS +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_auxdata_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_enaphxtofhangimg_FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.csv +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultraimgrates_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.csv +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l0/ultra45_raw_sc_ultrarawimgevent_FM45_7P_Phi00_BeamCal_LinearScan_phi004_theta-001_20230821T121304.csv +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E1.cdf +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E12.cdf +0 -0
- /imap_processing/tests/ultra/{test_data → data}/l1/dps_exposure_helio_45_E24.cdf +0 -0
- {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.11.0.dist-info → imap_processing-0.12.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
"""Mock expected data for use in some tests."""
|
|
2
|
+
|
|
3
|
+
import astropy_healpix.healpy as hp
|
|
4
|
+
import numpy as np
|
|
5
|
+
import spiceypy as spice
|
|
6
|
+
import xarray as xr
|
|
7
|
+
|
|
8
|
+
from imap_processing.ena_maps.utils.coordinates import CoordNames
|
|
9
|
+
from imap_processing.spice.kernels import ensure_spice
|
|
10
|
+
from imap_processing.spice.time import str_to_et
|
|
11
|
+
from imap_processing.ultra.l1c.ultra_l1c_pset_bins import build_energy_bins
|
|
12
|
+
|
|
13
|
+
DEFAULT_RECT_SPACING_DEG_L1C = 0.5
|
|
14
|
+
DEFAULT_HEALPIX_NSIDE_L1C = 128
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def mock_l1c_pset_product_rectangular( # noqa: PLR0913
|
|
18
|
+
spacing_deg: float = DEFAULT_RECT_SPACING_DEG_L1C,
|
|
19
|
+
stripe_center_lat: int = 0,
|
|
20
|
+
width_scale: float = 10.0,
|
|
21
|
+
counts_scaling_params: tuple[int, float] = (100, 0.01),
|
|
22
|
+
peak_exposure: float = 1000.0,
|
|
23
|
+
timestr: str = "2025-01-01T00:00:00",
|
|
24
|
+
head: str = "45",
|
|
25
|
+
) -> xr.Dataset:
|
|
26
|
+
"""
|
|
27
|
+
Mock the L1C PSET product with recognizable but unrealistic counts.
|
|
28
|
+
|
|
29
|
+
This is not meant to perfectly mimic the real data, but to provide a
|
|
30
|
+
recognizable structure for L2 testing purposes.
|
|
31
|
+
Function will produce an xarray.Dataset with at least the variables and shapes:
|
|
32
|
+
counts: (1 epoch, num_energy_bins, num_lon_bins, num_lat_bins)
|
|
33
|
+
exposure_time: (num_lon_bins, num_lat_bins)
|
|
34
|
+
sensitivity: (1 epoch, num_energy_bins, num_lon_bins, num_lat_bins)
|
|
35
|
+
|
|
36
|
+
and the coordinate variables:
|
|
37
|
+
the epoch (assumed to be a single time for each product).
|
|
38
|
+
energy: (determined by build_energy_bins function)
|
|
39
|
+
longitude: (num_lon_bins)
|
|
40
|
+
latitude: (num_lat_bins)
|
|
41
|
+
|
|
42
|
+
While not a coordinate, PSETs can also be distinguished by the 'head' attribute.
|
|
43
|
+
head: Either '45' or '90'. Default is '45'.
|
|
44
|
+
|
|
45
|
+
The counts are generated along a stripe, centered at a given latitude.
|
|
46
|
+
This stripe can be thought of as a 'horizontal' line if the lon/az axis is plotted
|
|
47
|
+
as the x-axis and the lat/el axis is plotted as the y-axis. See the figure below.
|
|
48
|
+
|
|
49
|
+
^ Elevation/Latitude
|
|
50
|
+
|
|
|
51
|
+
| 000000000000000000000000000000000000000000000000000 |
|
|
52
|
+
| 000000000000000000000000000000000000000000000000000 |
|
|
53
|
+
| 000000000000000000000000000000000000000000000000000 |
|
|
54
|
+
| 000000000000000000000000000000000000000000000000000 |
|
|
55
|
+
| 000000000000000000000000000000000000000000000000000 \
|
|
56
|
+
| 222222222222222222222222222222222222222222222222222 \
|
|
57
|
+
| 444444444444444444444444444444444444444444444444444 \
|
|
58
|
+
| 666666666666666666666666666666666666666666666666666 |
|
|
59
|
+
| 444444444444444444444444444444444444444444444444444 /
|
|
60
|
+
| 222222222222222222222222222222222222222222222222222 /
|
|
61
|
+
| 000000000000000000000000000000000000000000000000000 /
|
|
62
|
+
| 000000000000000000000000000000000000000000000000000 |
|
|
63
|
+
--------------------------------------------------------->
|
|
64
|
+
Azimuth/Longitude ->
|
|
65
|
+
|
|
66
|
+
Fig. 1: Example of the '90' sensor head stripe
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
spacing_deg : float, optional
|
|
71
|
+
The bin spacing in degrees (default is 0.5 degrees).
|
|
72
|
+
stripe_center_lat : int, optional
|
|
73
|
+
The center latitude of the stripe in degrees (default is 0).
|
|
74
|
+
width_scale : float, optional
|
|
75
|
+
The width of the stripe in degrees (default is 20 degrees).
|
|
76
|
+
counts_scaling_params : tuple[int, float], optional
|
|
77
|
+
The parameters for the binomial distribution of counts (default is (100, 0.01)).
|
|
78
|
+
The 0th element is the number of trials to draw,
|
|
79
|
+
the 1st element scales the probability of success for each trial.
|
|
80
|
+
peak_exposure : float, optional
|
|
81
|
+
The peak exposure time (default is 1000.0).
|
|
82
|
+
timestr : str, optional
|
|
83
|
+
The time string for the epoch (default is "2025-01-01T00:00:00").
|
|
84
|
+
head : str, optional
|
|
85
|
+
The sensor head (either '45' or '90') (default is '45').
|
|
86
|
+
"""
|
|
87
|
+
num_lat_bins = int(180 / spacing_deg)
|
|
88
|
+
num_lon_bins = int(360 / spacing_deg)
|
|
89
|
+
stripe_center_lat_bin = int((stripe_center_lat + 90) / spacing_deg)
|
|
90
|
+
|
|
91
|
+
_, energy_bin_midpoints, _ = build_energy_bins()
|
|
92
|
+
num_energy_bins = len(energy_bin_midpoints)
|
|
93
|
+
|
|
94
|
+
# 1 epoch x num_energy_bins x num_lon_bins x num_lat_bins
|
|
95
|
+
grid_shape = (1, num_energy_bins, num_lon_bins, num_lat_bins)
|
|
96
|
+
|
|
97
|
+
def get_binomial_counts(distance_scaling, lat_bin, central_lat_bin):
|
|
98
|
+
# Note, this is not quite correct, as it won't wrap around at 360 degrees
|
|
99
|
+
# but it's all meant to provide a recognizable pattern for testing
|
|
100
|
+
distance_lat_bin = np.abs(lat_bin - central_lat_bin)
|
|
101
|
+
|
|
102
|
+
rng = np.random.default_rng(seed=42)
|
|
103
|
+
return rng.binomial(
|
|
104
|
+
n=counts_scaling_params[0],
|
|
105
|
+
p=np.maximum(
|
|
106
|
+
1 - (distance_lat_bin / distance_scaling), counts_scaling_params[1]
|
|
107
|
+
),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
counts = np.fromfunction(
|
|
111
|
+
lambda epoch, energy_bin, lon_bin, lat_bin: get_binomial_counts(
|
|
112
|
+
distance_scaling=width_scale,
|
|
113
|
+
lat_bin=lat_bin,
|
|
114
|
+
central_lat_bin=stripe_center_lat_bin,
|
|
115
|
+
),
|
|
116
|
+
shape=grid_shape,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# exposure_time should be a gaussian distribution centered on the stripe
|
|
120
|
+
# with a width of 20 degrees
|
|
121
|
+
exposure_time = np.zeros(grid_shape[2:])
|
|
122
|
+
exposure_time = np.fromfunction(
|
|
123
|
+
lambda lon_bin, lat_bin: np.exp(
|
|
124
|
+
-((lat_bin - stripe_center_lat_bin) ** 2) / (2 * width_scale**2)
|
|
125
|
+
),
|
|
126
|
+
shape=grid_shape[2:],
|
|
127
|
+
)
|
|
128
|
+
exposure_time /= exposure_time.max()
|
|
129
|
+
exposure_time *= peak_exposure
|
|
130
|
+
counts = counts.astype(int)
|
|
131
|
+
sensitivity = np.ones(grid_shape)
|
|
132
|
+
|
|
133
|
+
# Determine the epoch, which is TT time in nanoseconds since J2000 epoch
|
|
134
|
+
tdb_et = str_to_et(timestr)
|
|
135
|
+
tt_j2000ns = (
|
|
136
|
+
ensure_spice(spice.unitim, time_kernels_only=True)(tdb_et, "ET", "TT") * 1e9
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
pset_product = xr.Dataset(
|
|
140
|
+
{
|
|
141
|
+
"counts": (
|
|
142
|
+
[
|
|
143
|
+
CoordNames.TIME.value,
|
|
144
|
+
CoordNames.ENERGY.value,
|
|
145
|
+
CoordNames.AZIMUTH_L1C.value,
|
|
146
|
+
CoordNames.ELEVATION_L1C.value,
|
|
147
|
+
],
|
|
148
|
+
counts,
|
|
149
|
+
),
|
|
150
|
+
"exposure_time": (
|
|
151
|
+
[
|
|
152
|
+
CoordNames.TIME.value,
|
|
153
|
+
CoordNames.AZIMUTH_L1C.value,
|
|
154
|
+
CoordNames.ELEVATION_L1C.value,
|
|
155
|
+
],
|
|
156
|
+
np.expand_dims(exposure_time, axis=0),
|
|
157
|
+
),
|
|
158
|
+
"sensitivity": (
|
|
159
|
+
[
|
|
160
|
+
CoordNames.TIME.value,
|
|
161
|
+
CoordNames.ENERGY.value,
|
|
162
|
+
CoordNames.AZIMUTH_L1C.value,
|
|
163
|
+
CoordNames.ELEVATION_L1C.value,
|
|
164
|
+
],
|
|
165
|
+
sensitivity,
|
|
166
|
+
),
|
|
167
|
+
},
|
|
168
|
+
coords={
|
|
169
|
+
CoordNames.TIME.value: [
|
|
170
|
+
tt_j2000ns,
|
|
171
|
+
],
|
|
172
|
+
CoordNames.ENERGY.value: energy_bin_midpoints,
|
|
173
|
+
CoordNames.AZIMUTH_L1C.value: np.arange(
|
|
174
|
+
0 + spacing_deg / 2, 360, spacing_deg
|
|
175
|
+
),
|
|
176
|
+
CoordNames.ELEVATION_L1C.value: np.arange(
|
|
177
|
+
-90 + spacing_deg / 2, 90, spacing_deg
|
|
178
|
+
),
|
|
179
|
+
},
|
|
180
|
+
attrs={
|
|
181
|
+
"Logical_file_id": (
|
|
182
|
+
f"imap_ultra_l1c_{head}sensor-pset_{timestr[:4]}"
|
|
183
|
+
f"{timestr[5:7]}{timestr[8:10]}-repointNNNNN_vNNN"
|
|
184
|
+
)
|
|
185
|
+
},
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
return pset_product
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def mock_l1c_pset_product_healpix( # noqa: PLR0913
|
|
192
|
+
nside: int = DEFAULT_HEALPIX_NSIDE_L1C,
|
|
193
|
+
stripe_center_lat: int = 0,
|
|
194
|
+
width_scale: float = 10.0,
|
|
195
|
+
counts_scaling_params: tuple[int, float] = (100, 0.01),
|
|
196
|
+
peak_exposure: float = 1000.0,
|
|
197
|
+
timestr: str = "2025-01-01T00:00:00",
|
|
198
|
+
head: str = "45",
|
|
199
|
+
) -> xr.Dataset:
|
|
200
|
+
"""
|
|
201
|
+
Mock the L1C PSET product with recognizable but unrealistic counts.
|
|
202
|
+
|
|
203
|
+
See the docstring for mock_l1c_pset_product_rectangular for more details about
|
|
204
|
+
the structure of the dataset.
|
|
205
|
+
The rectangular and Healpix mocked datasets are very similar in structure, though
|
|
206
|
+
the actual values at a given latitude and longitude may be different. This is only
|
|
207
|
+
meant to provide a recognizable structure for L2 testing purposes.
|
|
208
|
+
|
|
209
|
+
The counts are generated along a stripe, centered at a given latitude.
|
|
210
|
+
This stripe can be thought of as a 'vertical' line if the lon/az axis is plotted
|
|
211
|
+
as the x-axis and the lat/el axis is plotted as the y-axis. See the figure below.
|
|
212
|
+
|
|
213
|
+
^ Elevation/Latitude
|
|
214
|
+
|
|
|
215
|
+
| 00000000000000000000 |
|
|
216
|
+
| 0000000000000000000000000000 |
|
|
217
|
+
| 0000000000000000000000000000000000000 |
|
|
218
|
+
| 0000000000000000000000000000000000000000000 |
|
|
219
|
+
| 00000000000000000000000000000000000000000000000 |
|
|
220
|
+
| 0000000000000000000000000000000000000000000000000 \
|
|
221
|
+
| 222222222222222222222222222222222222222222222222222 \
|
|
222
|
+
| 444444444444444444444444444444444444444444444444444 \
|
|
223
|
+
| 666666666666666666666666666666666666666666666666666 |
|
|
224
|
+
| 4444444444444444444444444444444444444444444444444 /
|
|
225
|
+
| 22222222222222222222222222222222222222222222222 /
|
|
226
|
+
| 0000000000000000000000000000000000000000000 /
|
|
227
|
+
| 0000000000000000000000000000000000000 |
|
|
228
|
+
| 0000000000000000000000000000 |
|
|
229
|
+
| 00000000000000000000 |
|
|
230
|
+
--------------------------------------------------------->
|
|
231
|
+
Azimuth/Longitude ->
|
|
232
|
+
|
|
233
|
+
Fig. 1: Example of the '90' sensor head stripe on a HEALPix grid
|
|
234
|
+
|
|
235
|
+
Parameters
|
|
236
|
+
----------
|
|
237
|
+
nside : int, optional
|
|
238
|
+
The HEALPix nside parameter (default is 128).
|
|
239
|
+
stripe_center_lat : int, optional
|
|
240
|
+
The center latitude of the stripe in degrees (default is 0).
|
|
241
|
+
width_scale : float, optional
|
|
242
|
+
The width of the stripe in degrees (default is 10 degrees).
|
|
243
|
+
counts_scaling_params : tuple[int, float], optional
|
|
244
|
+
The parameters for the binomial distribution of counts (default is (100, 0.01)).
|
|
245
|
+
The 0th element is the number of trials to draw,
|
|
246
|
+
the 1st element scales the probability of success for each trial.
|
|
247
|
+
peak_exposure : float, optional
|
|
248
|
+
The peak exposure time (default is 1000.0).
|
|
249
|
+
timestr : str, optional
|
|
250
|
+
The time string for the epoch (default is "2025-01-01T00:00:00").
|
|
251
|
+
head : str, optional
|
|
252
|
+
The sensor head (either '45' or '90') (default is '45').
|
|
253
|
+
"""
|
|
254
|
+
_, energy_bin_midpoints, _ = build_energy_bins()
|
|
255
|
+
num_energy_bins = len(energy_bin_midpoints)
|
|
256
|
+
npix = hp.nside2npix(nside)
|
|
257
|
+
counts = np.zeros(npix)
|
|
258
|
+
exposure_time = np.zeros(npix)
|
|
259
|
+
|
|
260
|
+
# Get latitude for each healpix pixel
|
|
261
|
+
pix_indices = np.arange(npix)
|
|
262
|
+
lon_pix, lat_pix = hp.pix2ang(nside, pix_indices, lonlat=True)
|
|
263
|
+
|
|
264
|
+
counts = np.zeros(shape=(num_energy_bins, npix))
|
|
265
|
+
|
|
266
|
+
# Calculate probability based on distance from target latitude
|
|
267
|
+
lat_diff = np.abs(lat_pix - stripe_center_lat)
|
|
268
|
+
prob_scaling_factor = counts_scaling_params[1] * np.exp(
|
|
269
|
+
-(lat_diff**2) / (2 * width_scale**2)
|
|
270
|
+
)
|
|
271
|
+
# Generate counts using binomial distribution
|
|
272
|
+
rng = np.random.default_rng(seed=42)
|
|
273
|
+
counts = np.array(
|
|
274
|
+
[
|
|
275
|
+
rng.binomial(n=counts_scaling_params[0], p=prob_scaling_factor)
|
|
276
|
+
for _ in range(num_energy_bins)
|
|
277
|
+
]
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
# Generate exposure times using gaussian distribution
|
|
281
|
+
exposure_time = peak_exposure * (prob_scaling_factor / prob_scaling_factor.max())
|
|
282
|
+
|
|
283
|
+
# Ensure counts are integers
|
|
284
|
+
counts = counts.astype(int)
|
|
285
|
+
# add an epoch dimension
|
|
286
|
+
counts = np.expand_dims(counts, axis=0)
|
|
287
|
+
sensitivity = np.ones_like(counts)
|
|
288
|
+
|
|
289
|
+
# Determine the epoch, which is TT time in nanoseconds since J2000 epoch
|
|
290
|
+
tdb_et = str_to_et(timestr)
|
|
291
|
+
tt_j2000ns = (
|
|
292
|
+
ensure_spice(spice.unitim, time_kernels_only=True)(tdb_et, "ET", "TT") * 1e9
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
pset_product = xr.Dataset(
|
|
296
|
+
{
|
|
297
|
+
"counts": (
|
|
298
|
+
[
|
|
299
|
+
CoordNames.TIME.value,
|
|
300
|
+
CoordNames.ENERGY.value,
|
|
301
|
+
CoordNames.HEALPIX_INDEX.value,
|
|
302
|
+
],
|
|
303
|
+
counts,
|
|
304
|
+
),
|
|
305
|
+
"exposure_time": (
|
|
306
|
+
[CoordNames.HEALPIX_INDEX.value],
|
|
307
|
+
exposure_time,
|
|
308
|
+
),
|
|
309
|
+
"sensitivity": (
|
|
310
|
+
[
|
|
311
|
+
CoordNames.TIME.value,
|
|
312
|
+
CoordNames.ENERGY.value,
|
|
313
|
+
CoordNames.HEALPIX_INDEX.value,
|
|
314
|
+
],
|
|
315
|
+
sensitivity,
|
|
316
|
+
),
|
|
317
|
+
CoordNames.AZIMUTH_L1C.value: (
|
|
318
|
+
[CoordNames.HEALPIX_INDEX.value],
|
|
319
|
+
lon_pix,
|
|
320
|
+
),
|
|
321
|
+
CoordNames.ELEVATION_L1C.value: (
|
|
322
|
+
[CoordNames.HEALPIX_INDEX.value],
|
|
323
|
+
lat_pix,
|
|
324
|
+
),
|
|
325
|
+
},
|
|
326
|
+
coords={
|
|
327
|
+
CoordNames.TIME.value: [
|
|
328
|
+
tt_j2000ns,
|
|
329
|
+
],
|
|
330
|
+
CoordNames.ENERGY.value: energy_bin_midpoints,
|
|
331
|
+
CoordNames.HEALPIX_INDEX.value: pix_indices,
|
|
332
|
+
},
|
|
333
|
+
attrs={
|
|
334
|
+
"Logical_file_id": (
|
|
335
|
+
f"imap_ultra_l1c_{head}sensor-pset_{timestr[:4]}"
|
|
336
|
+
f"{timestr[5:7]}{timestr[8:10]}-repointNNNNN_vNNN"
|
|
337
|
+
)
|
|
338
|
+
},
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
return pset_product
|
|
@@ -4,6 +4,7 @@ from unittest import mock
|
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import pytest
|
|
7
|
+
import xarray as xr
|
|
7
8
|
|
|
8
9
|
from imap_processing import decom, imap_module_directory
|
|
9
10
|
from imap_processing.ultra.l0.decom_ultra import process_ultra_apids
|
|
@@ -24,7 +25,7 @@ def ccsds_path():
|
|
|
24
25
|
imap_module_directory
|
|
25
26
|
/ "tests"
|
|
26
27
|
/ "ultra"
|
|
27
|
-
/ "
|
|
28
|
+
/ "data"
|
|
28
29
|
/ "l0"
|
|
29
30
|
/ "Ultra45_EM_SwRI_Cal_Run7_ThetaScan_20220530T225054.CCSDS"
|
|
30
31
|
)
|
|
@@ -37,7 +38,7 @@ def ccsds_path_events():
|
|
|
37
38
|
imap_module_directory
|
|
38
39
|
/ "tests"
|
|
39
40
|
/ "ultra"
|
|
40
|
-
/ "
|
|
41
|
+
/ "data"
|
|
41
42
|
/ "l0"
|
|
42
43
|
/ "FM45_7P_Phi0.0_BeamCal_LinearScan_phi0.04_theta-0.01_20230821T121304.CCSDS"
|
|
43
44
|
)
|
|
@@ -50,7 +51,7 @@ def ccsds_path_theta_0():
|
|
|
50
51
|
imap_module_directory
|
|
51
52
|
/ "tests"
|
|
52
53
|
/ "ultra"
|
|
53
|
-
/ "
|
|
54
|
+
/ "data"
|
|
54
55
|
/ "l0"
|
|
55
56
|
/ "FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00"
|
|
56
57
|
"_20240207T102740.CCSDS"
|
|
@@ -64,7 +65,7 @@ def ccsds_path_tof():
|
|
|
64
65
|
imap_module_directory
|
|
65
66
|
/ "tests"
|
|
66
67
|
/ "ultra"
|
|
67
|
-
/ "
|
|
68
|
+
/ "data"
|
|
68
69
|
/ "l0"
|
|
69
70
|
/ "FM45_TV_Cycle6_Hot_Ops_Front212_20240124T063837.CCSDS"
|
|
70
71
|
)
|
|
@@ -88,7 +89,7 @@ def rates_test_path():
|
|
|
88
89
|
"ultra45_raw_sc_ultraimgrates_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_"
|
|
89
90
|
"20220530T225054.csv"
|
|
90
91
|
)
|
|
91
|
-
return imap_module_directory / "tests" / "ultra" / "
|
|
92
|
+
return imap_module_directory / "tests" / "ultra" / "data" / "l0" / filename
|
|
92
93
|
|
|
93
94
|
|
|
94
95
|
@pytest.fixture()
|
|
@@ -98,7 +99,7 @@ def aux_test_path():
|
|
|
98
99
|
"ultra45_raw_sc_auxdata_Ultra45_EM_SwRI_Cal_Run7_ThetaScan_"
|
|
99
100
|
"20220530T225054.csv"
|
|
100
101
|
)
|
|
101
|
-
return imap_module_directory / "tests" / "ultra" / "
|
|
102
|
+
return imap_module_directory / "tests" / "ultra" / "data" / "l0" / filename
|
|
102
103
|
|
|
103
104
|
|
|
104
105
|
@pytest.fixture()
|
|
@@ -108,7 +109,7 @@ def events_test_path():
|
|
|
108
109
|
"ultra45_raw_sc_ultrarawimgevent_FM45_7P_Phi00_BeamCal_"
|
|
109
110
|
"LinearScan_phi004_theta-001_20230821T121304.csv"
|
|
110
111
|
)
|
|
111
|
-
return imap_module_directory / "tests" / "ultra" / "
|
|
112
|
+
return imap_module_directory / "tests" / "ultra" / "data" / "l0" / filename
|
|
112
113
|
|
|
113
114
|
|
|
114
115
|
@pytest.fixture()
|
|
@@ -118,7 +119,7 @@ def tof_test_path():
|
|
|
118
119
|
"ultra45_raw_sc_enaphxtofhangimg_FM45_TV_Cycle6_Hot_Ops_"
|
|
119
120
|
"Front212_20240124T063837.csv"
|
|
120
121
|
)
|
|
121
|
-
return imap_module_directory / "tests" / "ultra" / "
|
|
122
|
+
return imap_module_directory / "tests" / "ultra" / "data" / "l0" / filename
|
|
122
123
|
|
|
123
124
|
|
|
124
125
|
@pytest.fixture()
|
|
@@ -126,9 +127,7 @@ def decom_test_data(request, xtce_path):
|
|
|
126
127
|
"""Read test data from file"""
|
|
127
128
|
apid = request.param["apid"]
|
|
128
129
|
filename = request.param["filename"]
|
|
129
|
-
ccsds_path =
|
|
130
|
-
imap_module_directory / "tests" / "ultra" / "test_data" / "l0" / filename
|
|
131
|
-
)
|
|
130
|
+
ccsds_path = imap_module_directory / "tests" / "ultra" / "data" / "l0" / filename
|
|
132
131
|
|
|
133
132
|
packets = decom.decom_packets(ccsds_path, xtce_path)
|
|
134
133
|
grouped_data = group_by_apid(packets)
|
|
@@ -144,7 +143,7 @@ def events_fsw_comparison_theta_0():
|
|
|
144
143
|
"ultra45_raw_sc_ultrarawimg_withFSWcalcs_FM45_40P_Phi28p5_"
|
|
145
144
|
"BeamCal_LinearScan_phi2850_theta-000_20240207T102740.csv"
|
|
146
145
|
)
|
|
147
|
-
return imap_module_directory / "tests" / "ultra" / "
|
|
146
|
+
return imap_module_directory / "tests" / "ultra" / "data" / "l0" / filename
|
|
148
147
|
|
|
149
148
|
|
|
150
149
|
@pytest.fixture()
|
|
@@ -158,17 +157,14 @@ def de_dataset(ccsds_path_theta_0, xtce_path):
|
|
|
158
157
|
decom_ultra_aux = process_ultra_apids(
|
|
159
158
|
grouped_data[ULTRA_AUX.apid[0]], ULTRA_AUX.apid[0]
|
|
160
159
|
)
|
|
161
|
-
|
|
160
|
+
de_dataset = ultra_l1a.create_dataset(
|
|
162
161
|
{
|
|
163
162
|
ULTRA_EVENTS.apid[0]: decom_ultra_events,
|
|
164
163
|
ULTRA_AUX.apid[0]: decom_ultra_aux,
|
|
165
164
|
}
|
|
166
165
|
)
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
dataset["START_TYPE"] != np.iinfo(np.int64).min, drop=True
|
|
170
|
-
)
|
|
171
|
-
return l1a_de_dataset
|
|
166
|
+
|
|
167
|
+
return de_dataset
|
|
172
168
|
|
|
173
169
|
|
|
174
170
|
@pytest.fixture()
|
|
@@ -203,21 +199,49 @@ def aux_dataset(ccsds_path_theta_0, xtce_path):
|
|
|
203
199
|
return l1a_aux_dataset
|
|
204
200
|
|
|
205
201
|
|
|
202
|
+
@pytest.fixture()
|
|
203
|
+
def faux_aux_dataset():
|
|
204
|
+
"""Fixture to compute and return aux test data."""
|
|
205
|
+
|
|
206
|
+
num_spins = 15
|
|
207
|
+
spin_duration = 15 # in seconds
|
|
208
|
+
|
|
209
|
+
epoch = np.arange(0, num_spins, 1)
|
|
210
|
+
spin_number = np.arange(127, 142)
|
|
211
|
+
spin_start_time = np.arange(1905, 2115 + spin_duration, spin_duration)
|
|
212
|
+
spin_period_sec = np.full(num_spins, 15)
|
|
213
|
+
spin_period_sec[-1] = 14
|
|
214
|
+
spin_start_sec = np.arange(1905, 2130, 15)
|
|
215
|
+
spin_start_subsec = np.zeros(num_spins)
|
|
216
|
+
|
|
217
|
+
test_aux_dataset = xr.Dataset(
|
|
218
|
+
data_vars={
|
|
219
|
+
"TIMESPINSTART": ("epoch", spin_start_sec),
|
|
220
|
+
"TIMESPINSTARTSUB": ("epoch", spin_start_subsec),
|
|
221
|
+
"DURATION": ("epoch", spin_period_sec),
|
|
222
|
+
"SPINNUMBER": ("epoch", spin_number),
|
|
223
|
+
"TIMESPINDATA": ("epoch", spin_start_time),
|
|
224
|
+
"SPINPERIOD": ("epoch", spin_period_sec),
|
|
225
|
+
},
|
|
226
|
+
coords={"epoch": ("epoch", epoch)},
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
return test_aux_dataset
|
|
230
|
+
|
|
231
|
+
|
|
206
232
|
@pytest.fixture()
|
|
207
233
|
@mock.patch("imap_processing.ultra.l1b.de.get_annotated_particle_velocity")
|
|
208
|
-
def
|
|
209
|
-
mock_get_annotated_particle_velocity,
|
|
234
|
+
def l1b_de_dataset(
|
|
235
|
+
mock_get_annotated_particle_velocity,
|
|
236
|
+
de_dataset,
|
|
237
|
+
use_fake_spin_data_for_time,
|
|
210
238
|
):
|
|
211
239
|
"""L1B test data"""
|
|
212
240
|
|
|
213
241
|
data_dict = {}
|
|
214
242
|
data_dict[de_dataset.attrs["Logical_source"]] = de_dataset
|
|
215
|
-
#
|
|
216
|
-
|
|
217
|
-
data_dict["imap_ultra_l1a_45sensor-rates"] = rates_dataset
|
|
218
|
-
use_fake_spin_data_for_time(
|
|
219
|
-
de_dataset["EVENTTIMES"][0], de_dataset["EVENTTIMES"][-1]
|
|
220
|
-
)
|
|
243
|
+
# Create a spin table that cover spin 0-141
|
|
244
|
+
use_fake_spin_data_for_time(0, 141 * 15)
|
|
221
245
|
|
|
222
246
|
# Mock get_annotated_particle_velocity to avoid needing kernels
|
|
223
247
|
def side_effect_func(event_times, position, ultra_frame, dps_frame, sc_frame):
|
|
@@ -238,3 +262,22 @@ def l1b_datasets(
|
|
|
238
262
|
output_datasets = ultra_l1b(data_dict, data_version="001")
|
|
239
263
|
|
|
240
264
|
return output_datasets
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
@pytest.fixture()
|
|
268
|
+
def l1b_extendedspin_dataset(
|
|
269
|
+
l1b_de_dataset,
|
|
270
|
+
rates_dataset,
|
|
271
|
+
faux_aux_dataset,
|
|
272
|
+
):
|
|
273
|
+
"""L1B de test data"""
|
|
274
|
+
data_dict = {}
|
|
275
|
+
data_dict["imap_ultra_l1b_45sensor-de"] = l1b_de_dataset[0]
|
|
276
|
+
data_dict["imap_ultra_l1a_45sensor-aux"] = faux_aux_dataset
|
|
277
|
+
# TODO: this is a placeholder for the hk dataset.
|
|
278
|
+
data_dict["imap_ultra_l1a_45sensor-hk"] = faux_aux_dataset
|
|
279
|
+
data_dict["imap_ultra_l1a_45sensor-rates"] = rates_dataset
|
|
280
|
+
|
|
281
|
+
output_datasets = ultra_l1b(data_dict, data_version="001")
|
|
282
|
+
|
|
283
|
+
return output_datasets
|
|
@@ -11,6 +11,7 @@ def test_calculate_badtimes():
|
|
|
11
11
|
|
|
12
12
|
spin_numbers = np.array([0, 1, 2, 3])
|
|
13
13
|
energy_bins = np.array([10, 20, 30, 40])
|
|
14
|
+
spin_start_time = np.array([0, 1, 2, 3])
|
|
14
15
|
|
|
15
16
|
quality_attitude = np.full(
|
|
16
17
|
spin_numbers.shape, ImapAttitudeUltraFlags.NONE.value, dtype=np.uint16
|
|
@@ -36,6 +37,7 @@ def test_calculate_badtimes():
|
|
|
36
37
|
("energy_bin_geometric_mean", "spin_number"),
|
|
37
38
|
quality_ena_rates,
|
|
38
39
|
),
|
|
40
|
+
"spin_start_time": (("spin_number",), spin_start_time),
|
|
39
41
|
},
|
|
40
42
|
coords={
|
|
41
43
|
"spin_number": spin_numbers,
|
|
@@ -10,6 +10,7 @@ def test_calculate_cullingmask_attitude():
|
|
|
10
10
|
|
|
11
11
|
spin_numbers = np.array([0, 1])
|
|
12
12
|
energy_bins = np.array([10, 20, 30, 40])
|
|
13
|
+
spin_start_time = np.array([0, 1])
|
|
13
14
|
|
|
14
15
|
quality_attitude = np.full(
|
|
15
16
|
spin_numbers.shape, ImapAttitudeUltraFlags.NONE.value, dtype=np.uint16
|
|
@@ -29,6 +30,7 @@ def test_calculate_cullingmask_attitude():
|
|
|
29
30
|
("energy_bin_geometric_mean", "spin_number"),
|
|
30
31
|
quality_ena_rates,
|
|
31
32
|
),
|
|
33
|
+
"spin_start_time": (("spin_number",), spin_start_time),
|
|
32
34
|
},
|
|
33
35
|
coords={
|
|
34
36
|
"spin_number": spin_numbers,
|
|
@@ -47,6 +49,7 @@ def test_calculate_cullingmask_rates():
|
|
|
47
49
|
"""Test calculate_cullingmask for rates culling."""
|
|
48
50
|
spin_numbers = np.array([0, 1, 2, 3])
|
|
49
51
|
energy_bins = np.array([10, 20, 30, 40])
|
|
52
|
+
spin_start_time = np.array([0, 1, 2, 3])
|
|
50
53
|
|
|
51
54
|
quality_attitude = np.full(
|
|
52
55
|
spin_numbers.shape, ImapAttitudeUltraFlags.NONE.value, dtype=np.uint16
|
|
@@ -72,6 +75,7 @@ def test_calculate_cullingmask_rates():
|
|
|
72
75
|
("energy_bin_geometric_mean", "spin_number"),
|
|
73
76
|
quality_ena_rates,
|
|
74
77
|
),
|
|
78
|
+
"spin_start_time": (("spin_number",), spin_start_time),
|
|
75
79
|
},
|
|
76
80
|
coords={
|
|
77
81
|
"spin_number": spin_numbers,
|
|
@@ -17,10 +17,13 @@ def df_filt(de_dataset, events_fsw_comparison_theta_0):
|
|
|
17
17
|
return df_filt
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def test_calculate_de(
|
|
20
|
+
def test_calculate_de(l1b_de_dataset, df_filt):
|
|
21
21
|
"""Tests calculate_de function."""
|
|
22
22
|
|
|
23
|
-
l1b_de_dataset =
|
|
23
|
+
l1b_de_dataset = l1b_de_dataset[0]
|
|
24
|
+
l1b_de_dataset = l1b_de_dataset.where(
|
|
25
|
+
l1b_de_dataset["start_type"] != np.iinfo(np.int64).min, drop=True
|
|
26
|
+
)
|
|
24
27
|
# Front and back positions
|
|
25
28
|
assert np.allclose(l1b_de_dataset["x_front"].data, df_filt["Xf"].astype("float"))
|
|
26
29
|
assert np.allclose(l1b_de_dataset["y_front"], df_filt["Yf"].astype("float"))
|
|
@@ -94,8 +97,13 @@ def test_calculate_de(l1b_datasets, df_filt):
|
|
|
94
97
|
rtol=1e-2,
|
|
95
98
|
)
|
|
96
99
|
assert np.allclose(
|
|
97
|
-
l1b_de_dataset["
|
|
98
|
-
df_filt["
|
|
100
|
+
l1b_de_dataset["phi"].values,
|
|
101
|
+
df_filt["phi"].astype("float").values,
|
|
102
|
+
rtol=1e-2,
|
|
103
|
+
)
|
|
104
|
+
assert np.allclose(
|
|
105
|
+
l1b_de_dataset["theta"].values,
|
|
106
|
+
df_filt["theta"].astype("float").values,
|
|
99
107
|
rtol=1e-2,
|
|
100
108
|
)
|
|
101
109
|
|
|
@@ -4,6 +4,7 @@ import numpy as np
|
|
|
4
4
|
import pandas as pd
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
7
|
+
from imap_processing import imap_module_directory
|
|
7
8
|
from imap_processing.ultra.l0.ultra_utils import RATES_KEYS, ULTRA_RATES
|
|
8
9
|
|
|
9
10
|
|
|
@@ -48,3 +49,46 @@ def test_image_rate_decom(decom_test_data, rates_test_path):
|
|
|
48
49
|
for name in RATES_KEYS:
|
|
49
50
|
arr.append(decom_ultra[name][total_packets - 1])
|
|
50
51
|
assert expected_arrn == arr
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@pytest.mark.parametrize(
|
|
55
|
+
"decom_test_data",
|
|
56
|
+
[
|
|
57
|
+
pytest.param(
|
|
58
|
+
{
|
|
59
|
+
"apid": ULTRA_RATES.apid[0],
|
|
60
|
+
"filename": "FM45_UltraFM45_Functional_2024-01-22T0105_"
|
|
61
|
+
"20240122T010548.CCSDS",
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
],
|
|
65
|
+
indirect=True,
|
|
66
|
+
)
|
|
67
|
+
def test_image_rate_decom_zero_width(decom_test_data):
|
|
68
|
+
"""This function tests for cases in which the width is zero within the packet."""
|
|
69
|
+
test_path = (
|
|
70
|
+
imap_module_directory
|
|
71
|
+
/ "tests"
|
|
72
|
+
/ "ultra"
|
|
73
|
+
/ "data"
|
|
74
|
+
/ "l0"
|
|
75
|
+
/ "ultra45_raw_sc_ultraimgrates_20220530_00.csv"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
decom_ultra, _ = decom_test_data
|
|
79
|
+
|
|
80
|
+
df = pd.read_csv(test_path, index_col="MET")
|
|
81
|
+
total_packets = 163
|
|
82
|
+
|
|
83
|
+
np.testing.assert_array_equal(df.SID, decom_ultra["SID"])
|
|
84
|
+
np.testing.assert_array_equal(df.Spin, decom_ultra["SPIN"])
|
|
85
|
+
np.testing.assert_array_equal(df.AbortFlag, decom_ultra["ABORTFLAG"])
|
|
86
|
+
np.testing.assert_array_equal(df.StartDelay, decom_ultra["STARTDELAY"])
|
|
87
|
+
|
|
88
|
+
for i in range(total_packets):
|
|
89
|
+
t = int(df["SequenceCount"].iloc[i]) # Ensure we get an integer value
|
|
90
|
+
expected_arr = json.loads(df.loc[df["SequenceCount"] == t, "Counts"].values[0])
|
|
91
|
+
arr = []
|
|
92
|
+
for name in RATES_KEYS:
|
|
93
|
+
arr.append(decom_ultra[name][i])
|
|
94
|
+
assert expected_arr == arr
|