imap-processing 0.11.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 +11 -11
- imap_processing/_version.py +2 -2
- imap_processing/ccsds/ccsds_data.py +1 -2
- imap_processing/ccsds/excel_to_xtce.py +66 -18
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +24 -40
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +934 -42
- imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
- 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 +27 -14
- 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 +25 -9
- 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_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 +23 -20
- 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_swapi_variable_attrs.yaml +22 -0
- 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 +64 -52
- imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +71 -47
- imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +180 -19
- imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +80 -17
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +32 -57
- imap_processing/cdf/utils.py +52 -38
- imap_processing/cli.py +477 -233
- imap_processing/codice/codice_l1a.py +466 -131
- imap_processing/codice/codice_l1b.py +51 -152
- imap_processing/codice/constants.py +1360 -569
- imap_processing/codice/decompress.py +2 -6
- imap_processing/ena_maps/ena_maps.py +1103 -146
- 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 +55 -52
- 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 +54 -29
- 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 +111 -82
- imap_processing/hi/l1c/hi_l1c.py +416 -32
- imap_processing/hi/utils.py +58 -12
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
- 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 +235 -5
- imap_processing/hit/l0/constants.py +20 -11
- imap_processing/hit/l0/decom_hit.py +21 -5
- imap_processing/hit/l1a/hit_l1a.py +71 -75
- imap_processing/hit/l1b/constants.py +321 -0
- imap_processing/hit/l1b/hit_l1b.py +377 -67
- imap_processing/hit/l2/constants.py +318 -0
- imap_processing/hit/l2/hit_l2.py +723 -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 +374 -0
- imap_processing/ialirt/l0/process_swapi.py +69 -0
- imap_processing/ialirt/l0/process_swe.py +548 -0
- imap_processing/ialirt/packet_definitions/ialirt.xml +216 -208
- 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_mag.xml +115 -0
- imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
- 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 +33 -0
- imap_processing/idex/idex_l0.py +22 -8
- imap_processing/idex/idex_l1a.py +81 -51
- imap_processing/idex/idex_l1b.py +13 -39
- imap_processing/idex/idex_l2a.py +823 -0
- imap_processing/idex/idex_l2b.py +120 -0
- imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +11 -11
- imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
- imap_processing/lo/l0/lo_science.py +7 -2
- imap_processing/lo/l1a/lo_l1a.py +1 -5
- imap_processing/lo/l1b/lo_l1b.py +702 -29
- imap_processing/lo/l1b/tof_conversions.py +11 -0
- imap_processing/lo/l1c/lo_l1c.py +1 -4
- imap_processing/mag/constants.py +51 -0
- imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
- imap_processing/mag/l0/decom_mag.py +10 -3
- imap_processing/mag/l1a/mag_l1a.py +23 -19
- imap_processing/mag/l1a/mag_l1a_data.py +35 -10
- imap_processing/mag/l1b/mag_l1b.py +259 -50
- imap_processing/mag/l1c/interpolation_methods.py +388 -0
- imap_processing/mag/l1c/mag_l1c.py +621 -17
- imap_processing/mag/l2/mag_l2.py +140 -0
- imap_processing/mag/l2/mag_l2_data.py +288 -0
- imap_processing/quality_flags.py +1 -0
- imap_processing/spacecraft/packet_definitions/scid_x252.xml +538 -0
- imap_processing/spacecraft/quaternions.py +121 -0
- imap_processing/spice/geometry.py +19 -22
- imap_processing/spice/kernels.py +0 -276
- imap_processing/spice/pointing_frame.py +257 -0
- imap_processing/spice/repoint.py +149 -0
- imap_processing/spice/spin.py +38 -33
- imap_processing/spice/time.py +24 -0
- imap_processing/swapi/l1/swapi_l1.py +20 -12
- imap_processing/swapi/l2/swapi_l2.py +116 -5
- imap_processing/swapi/swapi_utils.py +32 -0
- imap_processing/swe/l1a/swe_l1a.py +44 -12
- imap_processing/swe/l1a/swe_science.py +13 -13
- imap_processing/swe/l1b/swe_l1b.py +898 -23
- imap_processing/swe/l2/swe_l2.py +75 -136
- imap_processing/swe/packet_definitions/swe_packet_definition.xml +1121 -1
- imap_processing/swe/utils/swe_constants.py +64 -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 +24 -21
- imap_processing/tests/cdf/test_data/imap_instrument2_global_cdf_attrs.yaml +0 -2
- 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-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 +126 -53
- imap_processing/tests/codice/test_codice_l1b.py +6 -7
- imap_processing/tests/codice/test_decompress.py +4 -4
- imap_processing/tests/conftest.py +239 -27
- imap_processing/tests/ena_maps/conftest.py +51 -0
- imap_processing/tests/ena_maps/test_ena_maps.py +1068 -110
- imap_processing/tests/ena_maps/test_map_utils.py +66 -43
- imap_processing/tests/ena_maps/test_spatial_utils.py +17 -21
- 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/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 +22 -27
- imap_processing/tests/hi/test_hi_l1c.py +249 -18
- imap_processing/tests/hi/test_l1a.py +35 -7
- imap_processing/tests/hi/test_science_direct_event.py +3 -3
- imap_processing/tests/hi/test_utils.py +24 -2
- imap_processing/tests/hit/helpers/l1_validation.py +74 -73
- 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 +5 -1
- imap_processing/tests/hit/test_hit_l1a.py +32 -36
- imap_processing/tests/hit/test_hit_l1b.py +300 -81
- imap_processing/tests/hit/test_hit_l2.py +716 -0
- imap_processing/tests/hit/test_hit_utils.py +184 -7
- imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
- 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/hit/validation_data/sci_sample_raw.csv +1 -1
- imap_processing/tests/ialirt/data/l0/461971383-404.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971384-405.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971385-406.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971386-407.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971387-408.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971388-409.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971389-410.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971390-411.bin +0 -0
- imap_processing/tests/ialirt/data/l0/461971391-412.bin +0 -0
- imap_processing/tests/ialirt/data/l0/sample_decoded_i-alirt_data.csv +383 -0
- imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
- imap_processing/tests/ialirt/unit/test_grouping.py +81 -0
- imap_processing/tests/ialirt/unit/test_parse_mag.py +223 -0
- 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 +319 -6
- imap_processing/tests/ialirt/unit/test_time.py +16 -0
- imap_processing/tests/idex/conftest.py +127 -6
- imap_processing/tests/idex/test_data/imap_idex_l0_raw_20231218_v001.pkts +0 -0
- 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_data/impact_14_tof_high_data.txt +4508 -4508
- imap_processing/tests/idex/test_idex_l0.py +33 -11
- imap_processing/tests/idex/test_idex_l1a.py +92 -21
- imap_processing/tests/idex/test_idex_l1b.py +106 -27
- imap_processing/tests/idex/test_idex_l2a.py +399 -0
- imap_processing/tests/idex/test_idex_l2b.py +93 -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_l1a.py +3 -3
- imap_processing/tests/lo/test_lo_l1b.py +515 -6
- imap_processing/tests/lo/test_lo_l1c.py +1 -1
- imap_processing/tests/lo/test_lo_science.py +7 -7
- imap_processing/tests/lo/test_star_sensor.py +1 -1
- imap_processing/tests/mag/conftest.py +120 -2
- imap_processing/tests/mag/test_mag_decom.py +5 -4
- imap_processing/tests/mag/test_mag_l1a.py +51 -7
- imap_processing/tests/mag/test_mag_l1b.py +40 -59
- imap_processing/tests/mag/test_mag_l1c.py +354 -19
- imap_processing/tests/mag/test_mag_l2.py +130 -0
- imap_processing/tests/mag/test_mag_validation.py +247 -26
- 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/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_l1b-calibration_20240229_v001.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/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_data/fake_spin_data.csv +11 -11
- imap_processing/tests/spice/test_geometry.py +9 -12
- 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 +121 -0
- 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 +13 -11
- imap_processing/tests/swapi/test_swapi_l2.py +180 -8
- 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/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 +20 -2
- 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_l1a_science.py +3 -3
- imap_processing/tests/swe/test_swe_l1b.py +162 -24
- imap_processing/tests/swe/test_swe_l2.py +153 -91
- imap_processing/tests/test_cli.py +171 -88
- imap_processing/tests/test_utils.py +140 -17
- 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 +369 -0
- imap_processing/tests/ultra/unit/conftest.py +115 -89
- imap_processing/tests/ultra/unit/test_badtimes.py +4 -4
- imap_processing/tests/ultra/unit/test_cullingmask.py +8 -6
- imap_processing/tests/ultra/unit/test_de.py +14 -13
- imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
- imap_processing/tests/ultra/unit/test_decom_apid_881.py +54 -11
- 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 +77 -0
- imap_processing/tests/ultra/unit/test_ultra_l1a.py +98 -305
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +60 -14
- imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
- imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +26 -27
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +239 -70
- imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +114 -83
- 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 +27 -39
- 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 -271
- imap_processing/ultra/l1b/badtimes.py +1 -4
- imap_processing/ultra/l1b/cullingmask.py +2 -6
- imap_processing/ultra/l1b/de.py +116 -57
- imap_processing/ultra/l1b/extendedspin.py +20 -18
- imap_processing/ultra/l1b/lookup_utils.py +72 -9
- imap_processing/ultra/l1b/ultra_l1b.py +36 -16
- imap_processing/ultra/l1b/ultra_l1b_culling.py +66 -30
- imap_processing/ultra/l1b/ultra_l1b_extended.py +297 -94
- imap_processing/ultra/l1c/histogram.py +2 -6
- imap_processing/ultra/l1c/spacecraft_pset.py +84 -0
- imap_processing/ultra/l1c/ultra_l1c.py +8 -9
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +206 -108
- 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 +31 -12
- imap_processing/utils.py +69 -29
- {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +10 -6
- imap_processing-0.13.0.dist-info/RECORD +578 -0
- imap_processing/cdf/config/imap_mag_l1_variable_attrs.yaml +0 -237
- imap_processing/hi/l1a/housekeeping.py +0 -27
- imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
- imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
- imap_processing/swe/l1b/swe_l1b_science.py +0 -652
- 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/swe/test_swe_l1b_science.py +0 -84
- imap_processing/tests/ultra/test_data/mock_data.py +0 -161
- imap_processing/ultra/l1c/pset.py +0 -40
- imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
- imap_processing-0.11.0.dist-info/RECORD +0 -488
- /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/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/{mag/l1b → tests/spacecraft}/__init__.py +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/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.13.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.11.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
|
@@ -26,15 +26,12 @@ from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
|
26
26
|
from imap_processing.codice import constants
|
|
27
27
|
from imap_processing.codice.codice_l0 import decom_packets
|
|
28
28
|
from imap_processing.codice.decompress import decompress
|
|
29
|
-
from imap_processing.codice.utils import CODICEAPID
|
|
29
|
+
from imap_processing.codice.utils import CODICEAPID, CoDICECompression
|
|
30
30
|
from imap_processing.spice.time import met_to_ttj2000ns
|
|
31
31
|
|
|
32
32
|
logger = logging.getLogger(__name__)
|
|
33
33
|
logger.setLevel(logging.INFO)
|
|
34
34
|
|
|
35
|
-
# TODO: Determine what should go in event data CDF and how it should be
|
|
36
|
-
# structured.
|
|
37
|
-
|
|
38
35
|
|
|
39
36
|
class CoDICEL1aPipeline:
|
|
40
37
|
"""
|
|
@@ -74,6 +71,8 @@ class CoDICEL1aPipeline:
|
|
|
74
71
|
Retrieve the acquisition times via the Lo stepping table.
|
|
75
72
|
get_energy_table()
|
|
76
73
|
Retrieve the ESA sweep values.
|
|
74
|
+
get_hi_energy_table_data(species)
|
|
75
|
+
Retrieve energy table data for CoDICE-Hi products
|
|
77
76
|
reshape_data()
|
|
78
77
|
Reshape the data arrays based on the data product being made.
|
|
79
78
|
set_data_product_config()
|
|
@@ -149,7 +148,7 @@ class CoDICEL1aPipeline:
|
|
|
149
148
|
"""
|
|
150
149
|
self.coords = {}
|
|
151
150
|
|
|
152
|
-
coord_names = ["epoch", *list(self.config["
|
|
151
|
+
coord_names = ["epoch", *list(self.config["output_dims"].keys())]
|
|
153
152
|
|
|
154
153
|
# These are labels unique to lo-counters products coordinates
|
|
155
154
|
if self.config["dataset_name"] in [
|
|
@@ -158,11 +157,19 @@ class CoDICEL1aPipeline:
|
|
|
158
157
|
]:
|
|
159
158
|
coord_names.append("spin_sector_pairs_label")
|
|
160
159
|
|
|
160
|
+
# Define the values for the coordinates
|
|
161
161
|
for name in coord_names:
|
|
162
162
|
if name == "epoch":
|
|
163
163
|
values = self.calculate_epoch_values()
|
|
164
|
-
elif name in [
|
|
165
|
-
|
|
164
|
+
elif name in [
|
|
165
|
+
"esa_step",
|
|
166
|
+
"inst_az",
|
|
167
|
+
"spin_sector",
|
|
168
|
+
"spin_sector_pairs",
|
|
169
|
+
"spin_sector_index",
|
|
170
|
+
"ssd_index",
|
|
171
|
+
]:
|
|
172
|
+
values = np.arange(self.config["output_dims"][name])
|
|
166
173
|
elif name == "spin_sector_pairs_label":
|
|
167
174
|
values = np.array(
|
|
168
175
|
[
|
|
@@ -174,10 +181,6 @@ class CoDICEL1aPipeline:
|
|
|
174
181
|
"150-180 deg",
|
|
175
182
|
]
|
|
176
183
|
)
|
|
177
|
-
else:
|
|
178
|
-
# TODO: May need to implement other types of coords for Hi
|
|
179
|
-
# and/or event data products
|
|
180
|
-
continue
|
|
181
184
|
|
|
182
185
|
coord = xr.DataArray(
|
|
183
186
|
values,
|
|
@@ -226,9 +229,20 @@ class CoDICEL1aPipeline:
|
|
|
226
229
|
cdf_attrs_key = f"{descriptor}-{variable_name}"
|
|
227
230
|
attrs = self.cdf_attrs.get_variable_attributes(cdf_attrs_key)
|
|
228
231
|
|
|
229
|
-
#
|
|
230
|
-
# followed by the dimensions for the specific
|
|
231
|
-
|
|
232
|
+
# For most products, the final CDF dimensions always has "epoch" as
|
|
233
|
+
# the first dimension followed by the dimensions for the specific
|
|
234
|
+
# data product
|
|
235
|
+
dims = ["epoch", *list(self.config["output_dims"].keys())]
|
|
236
|
+
|
|
237
|
+
# However, CoDICE-Hi products use specific energy bins for the
|
|
238
|
+
# energy dimension
|
|
239
|
+
# TODO: This will be expanded to all CoDICE-Hi products once I
|
|
240
|
+
# can validate them. For now, just operate on hi-sectored
|
|
241
|
+
if self.config["dataset_name"] == "imap_codice_l1a_hi-sectored":
|
|
242
|
+
dims = [
|
|
243
|
+
f"energy_{variable_name}" if item == "esa_step" else item
|
|
244
|
+
for item in dims
|
|
245
|
+
]
|
|
232
246
|
|
|
233
247
|
# Create the CDF data variable
|
|
234
248
|
dataset[variable_name] = xr.DataArray(
|
|
@@ -241,6 +255,13 @@ class CoDICEL1aPipeline:
|
|
|
241
255
|
# Add support data variables based on data product
|
|
242
256
|
dataset = self.define_support_variables(dataset)
|
|
243
257
|
|
|
258
|
+
# For CoDICE-Hi products, since energy dimension was replaced, we no
|
|
259
|
+
# longer need the "esa_step" coordinate
|
|
260
|
+
# TODO: This will be expanded to all CoDICE-Hi products once I
|
|
261
|
+
# can validate them. For now, just operate on hi-sectored
|
|
262
|
+
if self.config["dataset_name"] == "imap_codice_l1a_hi-sectored":
|
|
263
|
+
dataset = dataset.drop_vars("esa_step")
|
|
264
|
+
|
|
244
265
|
return dataset
|
|
245
266
|
|
|
246
267
|
def define_support_variables(self, dataset: xr.Dataset) -> xr.Dataset:
|
|
@@ -269,45 +290,88 @@ class CoDICEL1aPipeline:
|
|
|
269
290
|
"st_bias_gain_mode",
|
|
270
291
|
]
|
|
271
292
|
|
|
293
|
+
hi_energy_table_variables = [
|
|
294
|
+
"energy_h",
|
|
295
|
+
"energy_he3",
|
|
296
|
+
"energy_he4",
|
|
297
|
+
"energy_c",
|
|
298
|
+
"energy_o",
|
|
299
|
+
"energy_ne_mg_si",
|
|
300
|
+
"energy_fe",
|
|
301
|
+
"energy_uh",
|
|
302
|
+
"energy_junk",
|
|
303
|
+
"energy_he3he4",
|
|
304
|
+
"energy_cno",
|
|
305
|
+
]
|
|
306
|
+
|
|
272
307
|
for variable_name in self.config["support_variables"]:
|
|
273
|
-
#
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
elif variable_name == "acquisition_time_per_step":
|
|
280
|
-
variable_data = self.get_acquisition_times()
|
|
281
|
-
dims = ["esa_step"]
|
|
282
|
-
attrs = self.cdf_attrs.get_variable_attributes(
|
|
283
|
-
"acquisition_time_per_step"
|
|
308
|
+
# CoDICE-Hi energy tables are treated differently because values
|
|
309
|
+
# are binned and we need to record the energies _and_ their deltas
|
|
310
|
+
if variable_name in hi_energy_table_variables:
|
|
311
|
+
centers, deltas = self.get_hi_energy_table_data(
|
|
312
|
+
variable_name.split("energy_")[-1]
|
|
284
313
|
)
|
|
285
314
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
variable_data = self.dataset.spin_period.data * 0.00032
|
|
302
|
-
dims = ["epoch"]
|
|
303
|
-
attrs = self.cdf_attrs.get_variable_attributes("spin_period")
|
|
315
|
+
# Add bin centers and deltas to the dataset
|
|
316
|
+
dataset[variable_name] = xr.DataArray(
|
|
317
|
+
centers,
|
|
318
|
+
dims=[variable_name],
|
|
319
|
+
attrs=self.cdf_attrs.get_variable_attributes(
|
|
320
|
+
f"{self.config['dataset_name'].split('_')[-1]}-{variable_name}"
|
|
321
|
+
),
|
|
322
|
+
)
|
|
323
|
+
dataset[f"{variable_name}_delta"] = xr.DataArray(
|
|
324
|
+
deltas,
|
|
325
|
+
dims=[f"{variable_name}_delta"],
|
|
326
|
+
attrs=self.cdf_attrs.get_variable_attributes(
|
|
327
|
+
f"{self.config['dataset_name'].split('_')[-1]}-{variable_name}_delta"
|
|
328
|
+
),
|
|
329
|
+
)
|
|
304
330
|
|
|
305
|
-
#
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
331
|
+
# Otherwise, support variable data can be gathered from nominal
|
|
332
|
+
# lookup tables or packet data
|
|
333
|
+
else:
|
|
334
|
+
# These variables require reading in external tables
|
|
335
|
+
if variable_name == "energy_table":
|
|
336
|
+
variable_data = self.get_energy_table()
|
|
337
|
+
dims = ["esa_step"]
|
|
338
|
+
attrs = self.cdf_attrs.get_variable_attributes("energy_table")
|
|
339
|
+
|
|
340
|
+
elif variable_name == "acquisition_time_per_step":
|
|
341
|
+
variable_data = self.get_acquisition_times()
|
|
342
|
+
dims = ["esa_step"]
|
|
343
|
+
attrs = self.cdf_attrs.get_variable_attributes(
|
|
344
|
+
"acquisition_time_per_step"
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
# These variables can be gathered straight from the packet data
|
|
348
|
+
elif variable_name in packet_data_variables:
|
|
349
|
+
variable_data = self.dataset[variable_name].data
|
|
350
|
+
dims = ["epoch"]
|
|
351
|
+
attrs = self.cdf_attrs.get_variable_attributes(variable_name)
|
|
352
|
+
|
|
353
|
+
# Data quality is named differently in packet data and needs to be
|
|
354
|
+
# treated slightly differently
|
|
355
|
+
elif variable_name == "data_quality":
|
|
356
|
+
variable_data = self.dataset.suspect.data
|
|
357
|
+
dims = ["epoch"]
|
|
358
|
+
attrs = self.cdf_attrs.get_variable_attributes("data_quality")
|
|
359
|
+
|
|
360
|
+
# Spin period requires the application of a conversion factor
|
|
361
|
+
# See Table B.5 in the algorithm document
|
|
362
|
+
elif variable_name == "spin_period":
|
|
363
|
+
variable_data = (
|
|
364
|
+
self.dataset.spin_period.data * constants.SPIN_PERIOD_CONVERSION
|
|
365
|
+
).astype(np.float32)
|
|
366
|
+
dims = ["epoch"]
|
|
367
|
+
attrs = self.cdf_attrs.get_variable_attributes("spin_period")
|
|
368
|
+
|
|
369
|
+
# Add variable to the dataset
|
|
370
|
+
dataset[variable_name] = xr.DataArray(
|
|
371
|
+
variable_data,
|
|
372
|
+
dims=dims,
|
|
373
|
+
attrs=attrs,
|
|
374
|
+
)
|
|
311
375
|
|
|
312
376
|
return dataset
|
|
313
377
|
|
|
@@ -315,12 +379,11 @@ class CoDICEL1aPipeline:
|
|
|
315
379
|
"""
|
|
316
380
|
Retrieve the acquisition times via the Lo stepping table.
|
|
317
381
|
|
|
318
|
-
Get the acquisition times from the
|
|
382
|
+
Get the acquisition times from the lookup table based on the values of
|
|
319
383
|
``plan_id`` and ``plan_step``
|
|
320
384
|
|
|
321
385
|
The Lo stepping table defines how many voltage steps and which steps are
|
|
322
386
|
used during each spacecraft spin. A full cycle takes 16 spins. The table
|
|
323
|
-
provides the timing for a given energy step, and most importantly
|
|
324
387
|
provides the "acquisition time", which is the acquisition time, in
|
|
325
388
|
milliseconds, for the energy step.
|
|
326
389
|
|
|
@@ -329,37 +392,15 @@ class CoDICEL1aPipeline:
|
|
|
329
392
|
acquisition_times : list[float]
|
|
330
393
|
The list of acquisition times from the Lo stepping table.
|
|
331
394
|
"""
|
|
332
|
-
# Read in the Lo stepping data table
|
|
333
|
-
lo_stepping_data_file = Path(
|
|
334
|
-
f"{imap_module_directory}/codice/data/lo_stepping_values.csv"
|
|
335
|
-
)
|
|
336
|
-
lo_stepping_data = pd.read_csv(lo_stepping_data_file)
|
|
337
|
-
|
|
338
395
|
# Determine which Lo stepping table is needed
|
|
339
396
|
lo_stepping_table_id = constants.LO_STEPPING_TABLE_ID_LOOKUP[
|
|
340
397
|
(self.plan_id, self.plan_step)
|
|
341
398
|
]
|
|
342
399
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
lo_stepping_data["table_num"] == lo_stepping_table_id
|
|
400
|
+
acquisition_times: list[float] = constants.ACQUISITION_TIMES[
|
|
401
|
+
lo_stepping_table_id
|
|
346
402
|
]
|
|
347
403
|
|
|
348
|
-
# Create a list for the acquisition times
|
|
349
|
-
acquisition_times = []
|
|
350
|
-
|
|
351
|
-
# Only need the energy columns from the table
|
|
352
|
-
energy_steps = lo_stepping_values[
|
|
353
|
-
["e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8"]
|
|
354
|
-
].astype(str) # convert to string to avoid confusion with table index value
|
|
355
|
-
|
|
356
|
-
# For each energy step (0-127), scan the energy columns and find the row
|
|
357
|
-
# number, which corresponds to a specific acquisition time, then append
|
|
358
|
-
# it to the list
|
|
359
|
-
for step_number in range(128):
|
|
360
|
-
row_number = np.argmax(energy_steps == str(step_number), axis=1).argmax()
|
|
361
|
-
acquisition_times.append(lo_stepping_values.acq_time[row_number])
|
|
362
|
-
|
|
363
404
|
return acquisition_times
|
|
364
405
|
|
|
365
406
|
def get_energy_table(self) -> NDArray[float]:
|
|
@@ -400,39 +441,100 @@ class CoDICEL1aPipeline:
|
|
|
400
441
|
|
|
401
442
|
return energy_table
|
|
402
443
|
|
|
444
|
+
def get_hi_energy_table_data(
|
|
445
|
+
self, species: str
|
|
446
|
+
) -> tuple[NDArray[float], NDArray[float]]:
|
|
447
|
+
"""
|
|
448
|
+
Retrieve energy table data for CoDICE-Hi products.
|
|
449
|
+
|
|
450
|
+
This includes the centers and deltas of the energy bins for a given
|
|
451
|
+
species. These data eventually get included in the CoDICE-Hi CDF data
|
|
452
|
+
products.
|
|
453
|
+
|
|
454
|
+
Parameters
|
|
455
|
+
----------
|
|
456
|
+
species : str
|
|
457
|
+
The species of interest, which determines which lookup table to
|
|
458
|
+
use (e.g. ``h``).
|
|
459
|
+
|
|
460
|
+
Returns
|
|
461
|
+
-------
|
|
462
|
+
centers : NDArray[float]
|
|
463
|
+
An array whose values represent the centers of the energy bins.
|
|
464
|
+
deltas : NDArray[float]
|
|
465
|
+
An array whose values represent the deltas of the energy bins.
|
|
466
|
+
"""
|
|
467
|
+
data_product = self.config["dataset_name"].split("-")[-1].upper()
|
|
468
|
+
energy_table = getattr(constants, f"{data_product}_ENERGY_TABLE")[species]
|
|
469
|
+
|
|
470
|
+
# Find the centers and deltas of the energy bins
|
|
471
|
+
centers = np.array(
|
|
472
|
+
[
|
|
473
|
+
(energy_table[i] + energy_table[i + 1]) / 2
|
|
474
|
+
for i in range(len(energy_table) - 1)
|
|
475
|
+
]
|
|
476
|
+
)
|
|
477
|
+
deltas = energy_table[1:] - centers
|
|
478
|
+
|
|
479
|
+
return centers, deltas
|
|
480
|
+
|
|
403
481
|
def reshape_data(self) -> None:
|
|
404
482
|
"""
|
|
405
483
|
Reshape the data arrays based on the data product being made.
|
|
406
484
|
|
|
407
485
|
These data need to be divided up by species or priorities (or
|
|
408
486
|
what I am calling "counters" as a general term), and re-arranged into
|
|
409
|
-
|
|
410
|
-
energies (depending on the data product).
|
|
487
|
+
4D arrays representing dimensions such as time, spin sectors, positions,
|
|
488
|
+
and energies (depending on the data product).
|
|
489
|
+
|
|
490
|
+
However, the existence and order of these dimensions can vary depending
|
|
491
|
+
on the specific data product, so we define this in the "input_dims"
|
|
492
|
+
and "output_dims" values configuration dictionary; the "input_dims"
|
|
493
|
+
defines how the dimensions are written into the packet data, while
|
|
494
|
+
"output_dims" defines how the dimensions should be written to the final
|
|
495
|
+
CDF product.
|
|
411
496
|
"""
|
|
412
497
|
# This will contain the reshaped data for all counters
|
|
413
498
|
self.data = []
|
|
414
499
|
|
|
415
|
-
#
|
|
416
|
-
#
|
|
417
|
-
#
|
|
418
|
-
#
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
500
|
+
# First reshape the data based on how it is written to the data array of
|
|
501
|
+
# the packet data. The number of counters is the first dimension / axis,
|
|
502
|
+
# with the exception of lo-counters-aggregated which is treated slightly
|
|
503
|
+
# differently
|
|
504
|
+
if self.config["dataset_name"] != "imap_codice_l1a_lo-counters-aggregated":
|
|
505
|
+
reshape_dims = (
|
|
506
|
+
self.config["num_counters"],
|
|
507
|
+
*self.config["input_dims"].values(),
|
|
508
|
+
)
|
|
509
|
+
else:
|
|
510
|
+
reshape_dims = (
|
|
511
|
+
*self.config["input_dims"].values(),
|
|
512
|
+
self.config["num_counters"],
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
# Then, transpose the data based on how the dimensions should be written
|
|
516
|
+
# to the CDF file. Since this is specific to each data product, we need
|
|
517
|
+
# to determine this dynamically based on the "output_dims" config.
|
|
518
|
+
# Again, lo-counters-aggregated is treated slightly differently
|
|
519
|
+
input_keys = ["num_counters", *self.config["input_dims"].keys()]
|
|
520
|
+
output_keys = ["num_counters", *self.config["output_dims"].keys()]
|
|
521
|
+
if self.config["dataset_name"] != "imap_codice_l1a_lo-counters-aggregated":
|
|
522
|
+
transpose_axes = [input_keys.index(dim) for dim in output_keys]
|
|
523
|
+
else:
|
|
524
|
+
transpose_axes = [1, 2, 0] # [esa_step, spin_sector_pairs, num_counters]
|
|
422
525
|
|
|
423
|
-
# For each packet/epoch, reshape the data along these dimensions
|
|
424
526
|
for packet_data in self.raw_data:
|
|
425
527
|
reshaped_packet_data = np.array(packet_data, dtype=np.uint32).reshape(
|
|
426
528
|
reshape_dims
|
|
427
529
|
)
|
|
428
|
-
|
|
530
|
+
reshaped_cdf_data = np.transpose(reshaped_packet_data, axes=transpose_axes)
|
|
531
|
+
|
|
532
|
+
self.data.append(reshaped_cdf_data)
|
|
429
533
|
|
|
430
534
|
# No longer need to keep the raw data around
|
|
431
535
|
del self.raw_data
|
|
432
536
|
|
|
433
|
-
def set_data_product_config(
|
|
434
|
-
self, apid: int, dataset: xr.Dataset, data_version: str
|
|
435
|
-
) -> None:
|
|
537
|
+
def set_data_product_config(self, apid: int, dataset: xr.Dataset) -> None:
|
|
436
538
|
"""
|
|
437
539
|
Set the various settings for defining the data products.
|
|
438
540
|
|
|
@@ -442,79 +544,139 @@ class CoDICEL1aPipeline:
|
|
|
442
544
|
The APID of interest.
|
|
443
545
|
dataset : xarray.Dataset
|
|
444
546
|
The dataset for the APID of interest.
|
|
445
|
-
data_version : str
|
|
446
|
-
Version of the data product being created.
|
|
447
547
|
"""
|
|
448
548
|
# Set the packet dataset so that it can be easily called from various
|
|
449
549
|
# methods
|
|
450
550
|
self.dataset = dataset
|
|
451
551
|
|
|
452
552
|
# Set various configurations of the data product
|
|
453
|
-
self.config: dict[str, Any] = constants.DATA_PRODUCT_CONFIGURATIONS
|
|
553
|
+
self.config: dict[str, Any] = constants.DATA_PRODUCT_CONFIGURATIONS[apid]
|
|
454
554
|
|
|
455
555
|
# Gather and set the CDF attributes
|
|
456
556
|
self.cdf_attrs = ImapCdfAttributes()
|
|
457
557
|
self.cdf_attrs.add_instrument_global_attrs("codice")
|
|
458
558
|
self.cdf_attrs.add_instrument_variable_attrs("codice", "l1a")
|
|
459
|
-
self.cdf_attrs.add_global_attribute("Data_version", data_version)
|
|
460
559
|
|
|
461
560
|
|
|
462
|
-
def
|
|
463
|
-
apid: int, packet: xr.Dataset, data_version: str
|
|
464
|
-
) -> xr.Dataset:
|
|
561
|
+
def create_direct_event_dataset(apid: int, packets: xr.Dataset) -> xr.Dataset:
|
|
465
562
|
"""
|
|
466
|
-
Create dataset for event data.
|
|
563
|
+
Create dataset for direct event data.
|
|
564
|
+
|
|
565
|
+
For direct event data, the raw data from the spacecraft is organized first
|
|
566
|
+
by epoch, then by priority, then by events. For example, for a CoDICE-Lo
|
|
567
|
+
dataset with 10 epochs, we expect the length of the `event_data` field to
|
|
568
|
+
be (10 epochs * 8 priorities) = 80 items, with each item being a compressed
|
|
569
|
+
byte object representing a variable number of events (up to 10000 events).
|
|
570
|
+
Each compressed byte object is comprised of several fields with specific
|
|
571
|
+
bit lengths/positions, described by the constants.[LO|HI]_DE_BIT_STRUCTURE
|
|
572
|
+
dictionary. Padding is added to any fields that have less than 10000 events.
|
|
573
|
+
|
|
574
|
+
In order to process these data, we must take the decommed raw data, group
|
|
575
|
+
the packets appropriately based on their `seq_flgs`, decompress the data,
|
|
576
|
+
then arrange the data into CDF data variables for each priority and bit
|
|
577
|
+
field. For example, P2_SpinAngle represents the spin angles for the 2nd
|
|
578
|
+
priority data.
|
|
467
579
|
|
|
468
580
|
Parameters
|
|
469
581
|
----------
|
|
470
582
|
apid : int
|
|
471
583
|
The APID of the packet.
|
|
472
|
-
|
|
473
|
-
The
|
|
474
|
-
data_version : str
|
|
475
|
-
Version of the data product being created.
|
|
584
|
+
packets : xarray.Dataset
|
|
585
|
+
The packets to process..
|
|
476
586
|
|
|
477
587
|
Returns
|
|
478
588
|
-------
|
|
479
589
|
dataset : xarray.Dataset
|
|
480
|
-
Xarray dataset containing the event data.
|
|
590
|
+
Xarray dataset containing the direct event data.
|
|
481
591
|
"""
|
|
592
|
+
# Set some useful variables unique to CoDICE-Lo and CoDICE-Hi
|
|
482
593
|
if apid == CODICEAPID.COD_LO_PHA:
|
|
483
|
-
|
|
594
|
+
num_priorities = 8
|
|
595
|
+
cdf_fields = [
|
|
596
|
+
"NumEvents",
|
|
597
|
+
"DataQuality",
|
|
598
|
+
"APDGain",
|
|
599
|
+
"APD_ID",
|
|
600
|
+
"APDEnergy",
|
|
601
|
+
"TOF",
|
|
602
|
+
"MultiFlag",
|
|
603
|
+
"PHAType",
|
|
604
|
+
"SpinAngle",
|
|
605
|
+
"EnergyStep",
|
|
606
|
+
]
|
|
484
607
|
elif apid == CODICEAPID.COD_HI_PHA:
|
|
485
|
-
|
|
608
|
+
num_priorities = 6
|
|
609
|
+
cdf_fields = [
|
|
610
|
+
"NumEvents",
|
|
611
|
+
"DataQuality",
|
|
612
|
+
"SSDEnergy0,TOF",
|
|
613
|
+
"SSD_ID",
|
|
614
|
+
"ERGE",
|
|
615
|
+
"MultiFlag",
|
|
616
|
+
"Type",
|
|
617
|
+
"SpinAngle",
|
|
618
|
+
"SpinNumber",
|
|
619
|
+
]
|
|
620
|
+
|
|
621
|
+
# Group and decompress the data
|
|
622
|
+
grouped_data = group_data(packets)
|
|
623
|
+
decompressed_data = [
|
|
624
|
+
decompress(group, CoDICECompression.LOSSLESS) for group in grouped_data
|
|
625
|
+
]
|
|
486
626
|
|
|
487
|
-
#
|
|
488
|
-
|
|
627
|
+
# Reshape the packet data into CDF-ready variables
|
|
628
|
+
data = reshape_de_data(packets, decompressed_data, num_priorities)
|
|
489
629
|
|
|
630
|
+
# Gather the CDF attributes
|
|
490
631
|
cdf_attrs = ImapCdfAttributes()
|
|
491
632
|
cdf_attrs.add_instrument_global_attrs("codice")
|
|
492
633
|
cdf_attrs.add_instrument_variable_attrs("codice", "l1a")
|
|
493
|
-
cdf_attrs.add_global_attribute("Data_version", data_version)
|
|
494
634
|
|
|
495
635
|
# Define coordinates
|
|
636
|
+
# For epoch, we take the first epoch from each priority set
|
|
496
637
|
epoch = xr.DataArray(
|
|
497
|
-
|
|
638
|
+
packets.epoch[::num_priorities],
|
|
498
639
|
name="epoch",
|
|
499
640
|
dims=["epoch"],
|
|
500
641
|
attrs=cdf_attrs.get_variable_attributes("epoch"),
|
|
501
642
|
)
|
|
643
|
+
event_num = xr.DataArray(
|
|
644
|
+
np.arange(10000),
|
|
645
|
+
name="event_num",
|
|
646
|
+
dims=["event_num"],
|
|
647
|
+
attrs=cdf_attrs.get_variable_attributes("event_num"),
|
|
648
|
+
)
|
|
502
649
|
|
|
503
650
|
# Create the dataset to hold the data variables
|
|
651
|
+
if apid == CODICEAPID.COD_LO_PHA:
|
|
652
|
+
attrs = cdf_attrs.get_global_attributes("imap_codice_l1a_lo-pha")
|
|
653
|
+
elif apid == CODICEAPID.COD_HI_PHA:
|
|
654
|
+
attrs = cdf_attrs.get_global_attributes("imap_codice_l1a_hi-pha")
|
|
504
655
|
dataset = xr.Dataset(
|
|
505
|
-
coords={
|
|
506
|
-
|
|
507
|
-
},
|
|
508
|
-
attrs=cdf_attrs.get_global_attributes(dataset_name),
|
|
656
|
+
coords={"epoch": epoch, "event_num": event_num},
|
|
657
|
+
attrs=attrs,
|
|
509
658
|
)
|
|
510
659
|
|
|
660
|
+
# Create the CDF data variables for each Priority and Field
|
|
661
|
+
for i in range(num_priorities):
|
|
662
|
+
for field in cdf_fields:
|
|
663
|
+
variable_name = f"P{i}_{field}"
|
|
664
|
+
attrs = cdf_attrs.get_variable_attributes(variable_name)
|
|
665
|
+
if field in ["NumEvents", "DataQuality"]:
|
|
666
|
+
dims = ["epoch"]
|
|
667
|
+
else:
|
|
668
|
+
dims = ["epoch", "event_num"]
|
|
669
|
+
dataset[variable_name] = xr.DataArray(
|
|
670
|
+
np.array(data[variable_name]),
|
|
671
|
+
name=variable_name,
|
|
672
|
+
dims=dims,
|
|
673
|
+
attrs=attrs,
|
|
674
|
+
)
|
|
675
|
+
|
|
511
676
|
return dataset
|
|
512
677
|
|
|
513
678
|
|
|
514
|
-
def create_hskp_dataset(
|
|
515
|
-
packet: xr.Dataset,
|
|
516
|
-
data_version: str,
|
|
517
|
-
) -> xr.Dataset:
|
|
679
|
+
def create_hskp_dataset(packet: xr.Dataset) -> xr.Dataset:
|
|
518
680
|
"""
|
|
519
681
|
Create dataset for each metadata field for housekeeping data.
|
|
520
682
|
|
|
@@ -522,8 +684,6 @@ def create_hskp_dataset(
|
|
|
522
684
|
----------
|
|
523
685
|
packet : xarray.Dataset
|
|
524
686
|
The packet to process.
|
|
525
|
-
data_version : str
|
|
526
|
-
Version of the data product being created.
|
|
527
687
|
|
|
528
688
|
Returns
|
|
529
689
|
-------
|
|
@@ -533,7 +693,6 @@ def create_hskp_dataset(
|
|
|
533
693
|
cdf_attrs = ImapCdfAttributes()
|
|
534
694
|
cdf_attrs.add_instrument_global_attrs("codice")
|
|
535
695
|
cdf_attrs.add_instrument_variable_attrs("codice", "l1a")
|
|
536
|
-
cdf_attrs.add_global_attribute("Data_version", data_version)
|
|
537
696
|
|
|
538
697
|
epoch = xr.DataArray(
|
|
539
698
|
packet.epoch,
|
|
@@ -547,7 +706,23 @@ def create_hskp_dataset(
|
|
|
547
706
|
attrs=cdf_attrs.get_global_attributes("imap_codice_l1a_hskp"),
|
|
548
707
|
)
|
|
549
708
|
|
|
709
|
+
# These variables don't need to carry over from L0 to L1a
|
|
710
|
+
exclude_variables = [
|
|
711
|
+
"spare_1",
|
|
712
|
+
"spare_2",
|
|
713
|
+
"spare_3",
|
|
714
|
+
"spare_4",
|
|
715
|
+
"spare_5",
|
|
716
|
+
"spare_6",
|
|
717
|
+
"spare_62",
|
|
718
|
+
"spare_68",
|
|
719
|
+
"chksum",
|
|
720
|
+
]
|
|
721
|
+
|
|
550
722
|
for variable in packet:
|
|
723
|
+
if variable in exclude_variables:
|
|
724
|
+
continue
|
|
725
|
+
|
|
551
726
|
attrs = cdf_attrs.get_variable_attributes(variable)
|
|
552
727
|
|
|
553
728
|
dataset[variable] = xr.DataArray(
|
|
@@ -596,6 +771,69 @@ def get_params(dataset: xr.Dataset) -> tuple[int, int, int, int]:
|
|
|
596
771
|
return table_id, plan_id, plan_step, view_id
|
|
597
772
|
|
|
598
773
|
|
|
774
|
+
def group_data(packets: xr.Dataset) -> list[bytes]:
|
|
775
|
+
"""
|
|
776
|
+
Organize continuation packets into appropriate groups.
|
|
777
|
+
|
|
778
|
+
Some packets are continuation packets, as in, they are packets that are
|
|
779
|
+
part of a group of packets. These packets are marked by the `seq_flgs` field
|
|
780
|
+
in the CCSDS header of the packet. For CoDICE, the values are defined as
|
|
781
|
+
follows:
|
|
782
|
+
|
|
783
|
+
3 = Packet is not part of a group
|
|
784
|
+
1 = Packet is the first packet of the group
|
|
785
|
+
0 = Packet is in the middle of the group
|
|
786
|
+
2 = Packet is the last packet of the group
|
|
787
|
+
|
|
788
|
+
For packets that are part of a group, the byte count associated with the
|
|
789
|
+
first packet of the group signifies the byte count for the entire group.
|
|
790
|
+
|
|
791
|
+
Parameters
|
|
792
|
+
----------
|
|
793
|
+
packets : xarray.Dataset
|
|
794
|
+
Dataset containing the packets to group.
|
|
795
|
+
|
|
796
|
+
Returns
|
|
797
|
+
-------
|
|
798
|
+
grouped_data : list[bytes]
|
|
799
|
+
The packet data, converted to bytes and grouped appropriately.
|
|
800
|
+
"""
|
|
801
|
+
grouped_data = [] # Holds the properly grouped data to be decompressed
|
|
802
|
+
current_group = bytearray() # Temporary storage for current group
|
|
803
|
+
group_byte_count = None # Temporary storage for current group byte count
|
|
804
|
+
|
|
805
|
+
for packet_data, group_code, byte_count in zip(
|
|
806
|
+
packets.event_data.data, packets.seq_flgs.data, packets.byte_count.data
|
|
807
|
+
):
|
|
808
|
+
# If the group code is 3, this means the data is not part of a group
|
|
809
|
+
# and can be decompressed as-is
|
|
810
|
+
if group_code == 3:
|
|
811
|
+
values_to_decompress = packet_data[:byte_count]
|
|
812
|
+
grouped_data.append(values_to_decompress)
|
|
813
|
+
|
|
814
|
+
# If the group code is 1, this means the data is the first data in a
|
|
815
|
+
# group. Also, set the byte count for the group
|
|
816
|
+
elif group_code == 1:
|
|
817
|
+
group_byte_count = byte_count
|
|
818
|
+
current_group = packet_data
|
|
819
|
+
|
|
820
|
+
# If the group code is 0, this means the data is part of the middle of
|
|
821
|
+
# the group
|
|
822
|
+
elif group_code == 0:
|
|
823
|
+
current_group += packet_data
|
|
824
|
+
|
|
825
|
+
# If the group code is 2, this means the data is the last data in the
|
|
826
|
+
# group
|
|
827
|
+
elif group_code == 2:
|
|
828
|
+
current_group += packet_data
|
|
829
|
+
values_to_decompress = current_group[:group_byte_count]
|
|
830
|
+
grouped_data.append(values_to_decompress)
|
|
831
|
+
current_group = bytearray()
|
|
832
|
+
group_byte_count = None
|
|
833
|
+
|
|
834
|
+
return grouped_data
|
|
835
|
+
|
|
836
|
+
|
|
599
837
|
def log_dataset_info(datasets: dict[int, xr.Dataset]) -> None:
|
|
600
838
|
"""
|
|
601
839
|
Log info about the input data to help with tracking and/or debugging.
|
|
@@ -607,9 +845,9 @@ def log_dataset_info(datasets: dict[int, xr.Dataset]) -> None:
|
|
|
607
845
|
"""
|
|
608
846
|
launch_time = np.datetime64("2010-01-01T00:01:06.184", "ns")
|
|
609
847
|
logger.info("\nThis input file contains the following APIDs:\n")
|
|
610
|
-
for apid in datasets:
|
|
611
|
-
num_packets = len(
|
|
612
|
-
time_deltas = [np.timedelta64(item, "ns") for item in
|
|
848
|
+
for apid, ds in datasets.items():
|
|
849
|
+
num_packets = len(ds.epoch.data)
|
|
850
|
+
time_deltas = [np.timedelta64(item, "ns") for item in ds.epoch.data]
|
|
613
851
|
times = [launch_time + delta for delta in time_deltas]
|
|
614
852
|
start = np.datetime_as_string(times[0])
|
|
615
853
|
end = np.datetime_as_string(times[-1])
|
|
@@ -618,7 +856,102 @@ def log_dataset_info(datasets: dict[int, xr.Dataset]) -> None:
|
|
|
618
856
|
)
|
|
619
857
|
|
|
620
858
|
|
|
621
|
-
def
|
|
859
|
+
def reshape_de_data(
|
|
860
|
+
packets: xr.Dataset, decompressed_data: list[list[int]], num_priorities: int
|
|
861
|
+
) -> dict[str, np.ndarray]:
|
|
862
|
+
"""
|
|
863
|
+
Reshape the decompressed direct event data into CDF-ready arrays.
|
|
864
|
+
|
|
865
|
+
Parameters
|
|
866
|
+
----------
|
|
867
|
+
packets : xarray.Dataset
|
|
868
|
+
Dataset containing the packets, needed to determine priority order
|
|
869
|
+
and data quality.
|
|
870
|
+
decompressed_data : list[list[int]]
|
|
871
|
+
The decompressed data to reshape, in the format <epoch>[<priority>[<event>]].
|
|
872
|
+
num_priorities : int
|
|
873
|
+
The number of priorities in the data product (differs between CoDICE-Lo
|
|
874
|
+
and CoDICE-Hi).
|
|
875
|
+
|
|
876
|
+
Returns
|
|
877
|
+
-------
|
|
878
|
+
data : dict[str, numpy.ndarray]
|
|
879
|
+
The reshaped, CDF-ready arrays. The keys of the dictionary represent the
|
|
880
|
+
CDF variable names, and the values represent the data.
|
|
881
|
+
"""
|
|
882
|
+
# Dictionary to hold all the (soon to be restructured) direct event data
|
|
883
|
+
data: dict[str, np.ndarray] = {}
|
|
884
|
+
|
|
885
|
+
# Determine the number of epochs to help with data array initialization
|
|
886
|
+
# There is one epoch per set of priorities
|
|
887
|
+
num_epochs = len(packets.epoch.data) // num_priorities
|
|
888
|
+
|
|
889
|
+
# Initialize data arrays for each priority and field to store the data
|
|
890
|
+
# We also need arrays to hold number of events and data quality
|
|
891
|
+
for priority_num in range(num_priorities):
|
|
892
|
+
for field in constants.LO_DE_BIT_STRUCTURE:
|
|
893
|
+
if field not in ["Priority", "Spare"]:
|
|
894
|
+
data[f"P{priority_num}_{field}"] = np.full(
|
|
895
|
+
(num_epochs, 10000), 255, dtype=np.uint16
|
|
896
|
+
)
|
|
897
|
+
data[f"P{priority_num}_NumEvents"] = np.full(num_epochs, 255, dtype=np.uint16)
|
|
898
|
+
data[f"P{priority_num}_DataQuality"] = np.full(num_epochs, 255, dtype=np.uint16)
|
|
899
|
+
|
|
900
|
+
# decompressed_data is one large list of values of length
|
|
901
|
+
# (<number of epochs> * <8 priorities>)
|
|
902
|
+
# Chunk the data into each epoch
|
|
903
|
+
for epoch_index in range(num_epochs):
|
|
904
|
+
# Determine the starting and ending indices of the epoch
|
|
905
|
+
epoch_start = epoch_index * num_priorities
|
|
906
|
+
epoch_end = epoch_start + num_priorities
|
|
907
|
+
|
|
908
|
+
# Extract the data for the epoch
|
|
909
|
+
epoch_data = decompressed_data[epoch_start:epoch_end]
|
|
910
|
+
|
|
911
|
+
# The order of the priorities and data quality flags are unique to each
|
|
912
|
+
# epoch and can be gathered from the packet data
|
|
913
|
+
priority_order = packets.priority[epoch_start:epoch_end].data
|
|
914
|
+
data_quality = packets.suspect[epoch_start:epoch_end].data
|
|
915
|
+
|
|
916
|
+
# For each epoch/priority combo, iterate over each event
|
|
917
|
+
for i, priority_num in enumerate(priority_order):
|
|
918
|
+
priority_data = epoch_data[i]
|
|
919
|
+
|
|
920
|
+
# Number of events and data quality can be determined at this stage
|
|
921
|
+
num_events = len(priority_data) // num_priorities
|
|
922
|
+
data[f"P{priority_num}_NumEvents"][epoch_index] = num_events
|
|
923
|
+
data[f"P{priority_num}_DataQuality"][epoch_index] = data_quality[i]
|
|
924
|
+
|
|
925
|
+
# Iterate over each event
|
|
926
|
+
for event_index in range(num_events):
|
|
927
|
+
event_start = event_index * num_priorities
|
|
928
|
+
event_end = event_start + num_priorities
|
|
929
|
+
event = priority_data[event_start:event_end]
|
|
930
|
+
# Separate out each individual field from the bit string
|
|
931
|
+
# The fields are packed into the bit string in reverse order, so
|
|
932
|
+
# we need to back them out in reverse order
|
|
933
|
+
bit_string = (
|
|
934
|
+
f"{int.from_bytes(event, byteorder='big'):0{len(event) * 8}b}"
|
|
935
|
+
)
|
|
936
|
+
bit_position = 0
|
|
937
|
+
for field_name, bit_length in reversed(
|
|
938
|
+
constants.LO_DE_BIT_STRUCTURE.items()
|
|
939
|
+
):
|
|
940
|
+
if field_name in ["Priority", "Spare"]:
|
|
941
|
+
bit_position += bit_length
|
|
942
|
+
continue
|
|
943
|
+
value = int(bit_string[bit_position : bit_position + bit_length], 2)
|
|
944
|
+
data[f"P{priority_num}_{field_name}"][epoch_index, event_index] = (
|
|
945
|
+
value
|
|
946
|
+
)
|
|
947
|
+
bit_position += bit_length
|
|
948
|
+
|
|
949
|
+
# TODO: Implement specific np.dtype and fill_val per field
|
|
950
|
+
|
|
951
|
+
return data
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
def process_codice_l1a(file_path: Path) -> list[xr.Dataset]:
|
|
622
955
|
"""
|
|
623
956
|
Will process CoDICE l0 data to create l1a data products.
|
|
624
957
|
|
|
@@ -626,8 +959,6 @@ def process_codice_l1a(file_path: Path, data_version: str) -> list[xr.Dataset]:
|
|
|
626
959
|
----------
|
|
627
960
|
file_path : pathlib.Path | str
|
|
628
961
|
Path to the CoDICE L0 file to process.
|
|
629
|
-
data_version : str
|
|
630
|
-
Version of the data product being created.
|
|
631
962
|
|
|
632
963
|
Returns
|
|
633
964
|
-------
|
|
@@ -651,14 +982,19 @@ def process_codice_l1a(file_path: Path, data_version: str) -> list[xr.Dataset]:
|
|
|
651
982
|
|
|
652
983
|
# Housekeeping data
|
|
653
984
|
if apid == CODICEAPID.COD_NHK:
|
|
654
|
-
processed_dataset = create_hskp_dataset(dataset
|
|
985
|
+
processed_dataset = create_hskp_dataset(dataset)
|
|
655
986
|
logger.info(f"\nFinal data product:\n{processed_dataset}\n")
|
|
656
987
|
|
|
657
988
|
# Event data
|
|
658
|
-
elif apid
|
|
659
|
-
processed_dataset =
|
|
989
|
+
elif apid == CODICEAPID.COD_LO_PHA:
|
|
990
|
+
processed_dataset = create_direct_event_dataset(apid, dataset)
|
|
660
991
|
logger.info(f"\nFinal data product:\n{processed_dataset}\n")
|
|
661
992
|
|
|
993
|
+
# TODO: Still need to implement
|
|
994
|
+
elif apid == CODICEAPID.COD_HI_PHA:
|
|
995
|
+
logger.info("\tStill need to properly implement")
|
|
996
|
+
processed_dataset = None
|
|
997
|
+
|
|
662
998
|
# Everything else
|
|
663
999
|
elif apid in constants.APIDS_FOR_SCIENCE_PROCESSING:
|
|
664
1000
|
# Extract the data
|
|
@@ -669,7 +1005,7 @@ def process_codice_l1a(file_path: Path, data_version: str) -> list[xr.Dataset]:
|
|
|
669
1005
|
|
|
670
1006
|
# Run the pipeline to create a dataset for the product
|
|
671
1007
|
pipeline = CoDICEL1aPipeline(table_id, plan_id, plan_step, view_id)
|
|
672
|
-
pipeline.set_data_product_config(apid, dataset
|
|
1008
|
+
pipeline.set_data_product_config(apid, dataset)
|
|
673
1009
|
pipeline.decompress_data(science_values)
|
|
674
1010
|
pipeline.reshape_data()
|
|
675
1011
|
pipeline.define_coordinates()
|
|
@@ -677,9 +1013,8 @@ def process_codice_l1a(file_path: Path, data_version: str) -> list[xr.Dataset]:
|
|
|
677
1013
|
|
|
678
1014
|
logger.info(f"\nFinal data product:\n{processed_dataset}\n")
|
|
679
1015
|
|
|
680
|
-
# TODO: Still need to implement I-ALiRT
|
|
1016
|
+
# TODO: Still need to implement I-ALiRT data products
|
|
681
1017
|
elif apid in [
|
|
682
|
-
CODICEAPID.COD_HI_INST_COUNTS_PRIORITIES,
|
|
683
1018
|
CODICEAPID.COD_HI_IAL,
|
|
684
1019
|
CODICEAPID.COD_LO_IAL,
|
|
685
1020
|
]:
|