imap-processing 0.12.0__py3-none-any.whl → 0.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of imap-processing might be problematic. Click here for more details.
- imap_processing/__init__.py +1 -0
- imap_processing/_version.py +2 -2
- imap_processing/ccsds/ccsds_data.py +1 -2
- imap_processing/ccsds/excel_to_xtce.py +1 -2
- imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +18 -12
- imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +569 -0
- imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +1846 -128
- imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +5 -5
- imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +20 -1
- imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +6 -4
- imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +3 -3
- imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +15 -0
- imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +22 -0
- imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +16 -0
- imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +178 -5
- imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +5045 -41
- imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +33 -19
- imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +8 -48
- imap_processing/cdf/utils.py +41 -33
- imap_processing/cli.py +463 -234
- imap_processing/codice/codice_l1a.py +260 -47
- imap_processing/codice/codice_l1b.py +51 -152
- imap_processing/codice/constants.py +38 -1
- imap_processing/ena_maps/ena_maps.py +658 -65
- imap_processing/ena_maps/utils/coordinates.py +1 -1
- imap_processing/ena_maps/utils/spatial_utils.py +10 -5
- imap_processing/glows/l1a/glows_l1a.py +28 -99
- imap_processing/glows/l1a/glows_l1a_data.py +2 -2
- imap_processing/glows/l1b/glows_l1b.py +1 -4
- imap_processing/glows/l1b/glows_l1b_data.py +1 -3
- imap_processing/glows/l2/glows_l2.py +2 -5
- imap_processing/hi/l1a/hi_l1a.py +31 -12
- imap_processing/hi/l1b/hi_l1b.py +80 -43
- imap_processing/hi/l1c/hi_l1c.py +12 -16
- imap_processing/hit/ancillary/imap_hit_l1b-to-l2-sector-dt0-factors_20250219_v002.csv +81 -0
- imap_processing/hit/hit_utils.py +93 -35
- imap_processing/hit/l0/decom_hit.py +3 -1
- imap_processing/hit/l1a/hit_l1a.py +30 -25
- imap_processing/hit/l1b/constants.py +6 -2
- imap_processing/hit/l1b/hit_l1b.py +279 -318
- imap_processing/hit/l2/constants.py +37 -0
- imap_processing/hit/l2/hit_l2.py +373 -264
- imap_processing/ialirt/l0/parse_mag.py +138 -10
- imap_processing/ialirt/l0/process_swapi.py +69 -0
- imap_processing/ialirt/l0/process_swe.py +318 -22
- imap_processing/ialirt/packet_definitions/ialirt.xml +216 -212
- imap_processing/ialirt/packet_definitions/ialirt_codicehi.xml +1 -1
- imap_processing/ialirt/packet_definitions/ialirt_codicelo.xml +1 -1
- imap_processing/ialirt/packet_definitions/ialirt_swapi.xml +14 -14
- imap_processing/ialirt/utils/grouping.py +1 -1
- imap_processing/idex/idex_constants.py +9 -1
- imap_processing/idex/idex_l0.py +22 -8
- imap_processing/idex/idex_l1a.py +75 -44
- imap_processing/idex/idex_l1b.py +9 -8
- imap_processing/idex/idex_l2a.py +79 -45
- imap_processing/idex/idex_l2b.py +120 -0
- imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +33 -39
- imap_processing/idex/packet_definitions/idex_housekeeping_packet_definition.xml +9130 -0
- imap_processing/lo/l0/lo_science.py +1 -2
- imap_processing/lo/l1a/lo_l1a.py +1 -4
- imap_processing/lo/l1b/lo_l1b.py +527 -6
- imap_processing/lo/l1b/tof_conversions.py +11 -0
- imap_processing/lo/l1c/lo_l1c.py +1 -4
- imap_processing/mag/constants.py +43 -0
- imap_processing/mag/imap_mag_sdc_configuration_v001.py +8 -0
- imap_processing/mag/l1a/mag_l1a.py +2 -9
- imap_processing/mag/l1a/mag_l1a_data.py +10 -10
- imap_processing/mag/l1b/mag_l1b.py +84 -17
- imap_processing/mag/l1c/interpolation_methods.py +180 -3
- imap_processing/mag/l1c/mag_l1c.py +236 -70
- imap_processing/mag/l2/mag_l2.py +140 -0
- imap_processing/mag/l2/mag_l2_data.py +288 -0
- imap_processing/spacecraft/quaternions.py +1 -3
- imap_processing/spice/geometry.py +3 -3
- imap_processing/spice/kernels.py +0 -276
- imap_processing/spice/pointing_frame.py +257 -0
- imap_processing/spice/repoint.py +48 -19
- imap_processing/spice/spin.py +38 -33
- imap_processing/spice/time.py +24 -0
- imap_processing/swapi/l1/swapi_l1.py +16 -12
- imap_processing/swapi/l2/swapi_l2.py +116 -4
- imap_processing/swapi/swapi_utils.py +32 -0
- imap_processing/swe/l1a/swe_l1a.py +2 -9
- imap_processing/swe/l1a/swe_science.py +8 -11
- imap_processing/swe/l1b/swe_l1b.py +898 -23
- imap_processing/swe/l2/swe_l2.py +21 -77
- imap_processing/swe/utils/swe_constants.py +1 -0
- imap_processing/tests/ccsds/test_excel_to_xtce.py +1 -1
- imap_processing/tests/cdf/test_utils.py +14 -16
- imap_processing/tests/codice/conftest.py +44 -33
- imap_processing/tests/codice/data/validation/imap_codice_l1a_hi-pha_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/data/validation/imap_codice_l1a_lo-pha_20241110193700_v0.0.0.cdf +0 -0
- imap_processing/tests/codice/test_codice_l1a.py +20 -11
- imap_processing/tests/codice/test_codice_l1b.py +6 -7
- imap_processing/tests/conftest.py +78 -22
- imap_processing/tests/ena_maps/test_ena_maps.py +462 -33
- imap_processing/tests/ena_maps/test_spatial_utils.py +1 -1
- imap_processing/tests/glows/conftest.py +10 -14
- imap_processing/tests/glows/test_glows_decom.py +4 -4
- imap_processing/tests/glows/test_glows_l1a_cdf.py +6 -27
- imap_processing/tests/glows/test_glows_l1a_data.py +6 -8
- imap_processing/tests/glows/test_glows_l1b.py +11 -11
- imap_processing/tests/glows/test_glows_l1b_data.py +5 -5
- imap_processing/tests/glows/test_glows_l2.py +2 -8
- imap_processing/tests/hi/conftest.py +1 -1
- imap_processing/tests/hi/test_hi_l1b.py +10 -12
- imap_processing/tests/hi/test_hi_l1c.py +27 -24
- imap_processing/tests/hi/test_l1a.py +7 -9
- imap_processing/tests/hi/test_science_direct_event.py +2 -2
- imap_processing/tests/hit/helpers/l1_validation.py +44 -43
- imap_processing/tests/hit/test_decom_hit.py +1 -1
- imap_processing/tests/hit/test_hit_l1a.py +9 -9
- imap_processing/tests/hit/test_hit_l1b.py +172 -217
- imap_processing/tests/hit/test_hit_l2.py +380 -118
- imap_processing/tests/hit/test_hit_utils.py +122 -55
- imap_processing/tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv +62 -62
- imap_processing/tests/hit/validation_data/sci_sample_raw.csv +1 -1
- imap_processing/tests/ialirt/unit/test_decom_ialirt.py +16 -81
- imap_processing/tests/ialirt/unit/test_grouping.py +2 -2
- imap_processing/tests/ialirt/unit/test_parse_mag.py +71 -16
- imap_processing/tests/ialirt/unit/test_process_codicehi.py +3 -3
- imap_processing/tests/ialirt/unit/test_process_codicelo.py +3 -10
- imap_processing/tests/ialirt/unit/test_process_ephemeris.py +4 -4
- imap_processing/tests/ialirt/unit/test_process_hit.py +3 -3
- imap_processing/tests/ialirt/unit/test_process_swapi.py +24 -16
- imap_processing/tests/ialirt/unit/test_process_swe.py +115 -7
- imap_processing/tests/idex/conftest.py +72 -7
- imap_processing/tests/idex/test_data/imap_idex_l0_raw_20241206_v001.pkts +0 -0
- imap_processing/tests/idex/test_data/imap_idex_l0_raw_20250108_v001.pkts +0 -0
- imap_processing/tests/idex/test_idex_l0.py +33 -11
- imap_processing/tests/idex/test_idex_l1a.py +50 -23
- imap_processing/tests/idex/test_idex_l1b.py +104 -25
- imap_processing/tests/idex/test_idex_l2a.py +48 -32
- imap_processing/tests/idex/test_idex_l2b.py +93 -0
- imap_processing/tests/lo/test_lo_l1a.py +3 -3
- imap_processing/tests/lo/test_lo_l1b.py +371 -6
- imap_processing/tests/lo/test_lo_l1c.py +1 -1
- imap_processing/tests/lo/test_lo_science.py +6 -7
- imap_processing/tests/lo/test_star_sensor.py +1 -1
- imap_processing/tests/mag/conftest.py +58 -9
- imap_processing/tests/mag/test_mag_decom.py +4 -3
- imap_processing/tests/mag/test_mag_l1a.py +13 -7
- imap_processing/tests/mag/test_mag_l1b.py +9 -9
- imap_processing/tests/mag/test_mag_l1c.py +151 -47
- imap_processing/tests/mag/test_mag_l2.py +130 -0
- imap_processing/tests/mag/test_mag_validation.py +144 -7
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-normal-out.csv +1857 -0
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-normal-out.csv +1857 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-normal-out.csv +1793 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-in.csv +1217 -0
- imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-normal-out.csv +1793 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-burst-in.csv +2561 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-in.csv +961 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-magi-normal-out.csv +1539 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-in.csv +1921 -0
- imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-normal-out.csv +2499 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-in.csv +865 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv +1196 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-in.csv +1729 -0
- imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv +3053 -0
- imap_processing/tests/mag/validation/L2/imap_mag_l1b_norm-mago_20251017_v002.cdf +0 -0
- imap_processing/tests/mag/validation/calibration/imap_mag_l2-calibration-matrices_20251017_v004.cdf +0 -0
- imap_processing/tests/mag/validation/calibration/imap_mag_l2-offsets-norm_20251017_20251017_v001.cdf +0 -0
- imap_processing/tests/spacecraft/test_quaternions.py +1 -1
- imap_processing/tests/spice/test_data/fake_repoint_data.csv +4 -4
- imap_processing/tests/spice/test_data/fake_spin_data.csv +11 -11
- imap_processing/tests/spice/test_geometry.py +3 -3
- imap_processing/tests/spice/test_kernels.py +1 -200
- imap_processing/tests/spice/test_pointing_frame.py +185 -0
- imap_processing/tests/spice/test_repoint.py +20 -10
- imap_processing/tests/spice/test_spin.py +50 -9
- imap_processing/tests/spice/test_time.py +14 -0
- imap_processing/tests/swapi/lut/imap_swapi_esa-unit-conversion_20250211_v000.csv +73 -0
- imap_processing/tests/swapi/lut/imap_swapi_lut-notes_20250211_v000.csv +1025 -0
- imap_processing/tests/swapi/test_swapi_l1.py +7 -9
- imap_processing/tests/swapi/test_swapi_l2.py +180 -8
- imap_processing/tests/swe/lut/checker-board-indices.csv +24 -0
- imap_processing/tests/swe/lut/imap_swe_esa-lut_20250301_v000.csv +385 -0
- imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv +3 -0
- imap_processing/tests/swe/test_swe_l1a.py +6 -6
- imap_processing/tests/swe/test_swe_l1a_science.py +3 -3
- imap_processing/tests/swe/test_swe_l1b.py +162 -24
- imap_processing/tests/swe/test_swe_l2.py +82 -102
- imap_processing/tests/test_cli.py +171 -88
- imap_processing/tests/test_utils.py +2 -1
- imap_processing/tests/ultra/data/mock_data.py +49 -21
- imap_processing/tests/ultra/unit/conftest.py +53 -70
- imap_processing/tests/ultra/unit/test_badtimes.py +2 -4
- imap_processing/tests/ultra/unit/test_cullingmask.py +4 -6
- imap_processing/tests/ultra/unit/test_de.py +3 -10
- imap_processing/tests/ultra/unit/test_decom_apid_880.py +27 -76
- imap_processing/tests/ultra/unit/test_decom_apid_881.py +15 -16
- imap_processing/tests/ultra/unit/test_decom_apid_883.py +12 -10
- imap_processing/tests/ultra/unit/test_decom_apid_896.py +202 -55
- imap_processing/tests/ultra/unit/test_lookup_utils.py +23 -1
- imap_processing/tests/ultra/unit/test_spacecraft_pset.py +3 -4
- imap_processing/tests/ultra/unit/test_ultra_l1a.py +84 -307
- imap_processing/tests/ultra/unit/test_ultra_l1b.py +30 -12
- imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +2 -2
- imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +4 -1
- imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +163 -29
- imap_processing/tests/ultra/unit/test_ultra_l1c.py +5 -5
- imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +32 -43
- imap_processing/tests/ultra/unit/test_ultra_l2.py +230 -0
- imap_processing/ultra/constants.py +1 -1
- imap_processing/ultra/l0/decom_tools.py +21 -34
- imap_processing/ultra/l0/decom_ultra.py +168 -204
- imap_processing/ultra/l0/ultra_utils.py +152 -136
- imap_processing/ultra/l1a/ultra_l1a.py +55 -243
- imap_processing/ultra/l1b/badtimes.py +1 -4
- imap_processing/ultra/l1b/cullingmask.py +2 -6
- imap_processing/ultra/l1b/de.py +62 -47
- imap_processing/ultra/l1b/extendedspin.py +8 -4
- imap_processing/ultra/l1b/lookup_utils.py +72 -9
- imap_processing/ultra/l1b/ultra_l1b.py +3 -8
- imap_processing/ultra/l1b/ultra_l1b_culling.py +4 -4
- imap_processing/ultra/l1b/ultra_l1b_extended.py +236 -78
- imap_processing/ultra/l1c/histogram.py +2 -6
- imap_processing/ultra/l1c/spacecraft_pset.py +2 -4
- imap_processing/ultra/l1c/ultra_l1c.py +1 -5
- imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +107 -60
- imap_processing/ultra/l2/ultra_l2.py +299 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_LeftSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM45_RightSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_LeftSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/Angular_Profiles_FM90_RightSlit.csv +526 -0
- imap_processing/ultra/lookup_tables/FM45_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -2
- imap_processing/ultra/lookup_tables/FM90_Startup1_ULTRA_IMGPARAMS_20240719.csv +2 -0
- imap_processing/ultra/packet_definitions/README.md +38 -0
- imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +15302 -482
- imap_processing/ultra/utils/ultra_l1_utils.py +13 -12
- imap_processing/utils.py +1 -1
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/METADATA +3 -2
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/RECORD +264 -225
- imap_processing/hi/l1b/hi_eng_unit_convert_table.csv +0 -154
- imap_processing/mag/imap_mag_sdc-configuration_v001.yaml +0 -6
- imap_processing/mag/l1b/__init__.py +0 -0
- imap_processing/swe/l1b/swe_esa_lookup_table.csv +0 -1441
- imap_processing/swe/l1b/swe_l1b_science.py +0 -699
- imap_processing/tests/swe/test_swe_l1b_science.py +0 -103
- imap_processing/ultra/lookup_tables/dps_sensitivity45.cdf +0 -0
- imap_processing/ultra/lookup_tables/ultra_90_dps_exposure_compressed.cdf +0 -0
- /imap_processing/idex/packet_definitions/{idex_packet_definition.xml → idex_science_packet_definition.xml} +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/20240827095047_SWE_IALIRT_packet.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971383-404.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971384-405.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971385-406.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971386-407.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971387-408.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971388-409.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971389-410.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971390-411.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/461971391-412.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/BinLog CCSDS_FRAG_TLM_20240826_152323Z_IALIRT_data_for_SDC.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/IALiRT Raw Packet Telemetry.txt +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/apid01152.tlm +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/eu_SWP_IAL_20240826_152033.csv +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/hi_fsw_view_1_ccsds.bin +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.ccsds +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/hit_ialirt_sample.csv +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/idle_export_eu.SWE_IALIRT_20240827_093852.csv +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_hi-ialirt_20240523200000_v0.0.0.cdf +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf +0 -0
- /imap_processing/tests/ialirt/{test_data → data}/l0/sample_decoded_i-alirt_data.csv +0 -0
- /imap_processing/tests/mag/validation/{imap_calibration_mag_20240229_v01.cdf → calibration/imap_mag_l1b-calibration_20240229_v001.cdf} +0 -0
- /imap_processing/{swe/l1b/engineering_unit_convert_table.csv → tests/swe/lut/imap_swe_eu-conversion_20240510_v000.csv} +0 -0
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/LICENSE +0 -0
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/WHEEL +0 -0
- {imap_processing-0.12.0.dist-info → imap_processing-0.13.0.dist-info}/entry_points.txt +0 -0
|
@@ -79,17 +79,22 @@ def build_solid_angle_map(
|
|
|
79
79
|
if spacing <= 0:
|
|
80
80
|
raise ValueError("Spacing must be positive valued, non-zero.")
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
proposed_number_of_lat_bins = 180 / spacing_deg
|
|
83
|
+
number_of_lat_bins = round(180 / spacing_deg)
|
|
84
|
+
number_of_lon_bins = 2 * number_of_lat_bins
|
|
85
|
+
if not np.isclose(proposed_number_of_lat_bins, number_of_lat_bins):
|
|
83
86
|
raise ValueError("Spacing must divide evenly into pi radians.")
|
|
84
87
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
latitude_edges = np.linspace(
|
|
89
|
+
-np.pi / 2, np.pi / 2, num=number_of_lat_bins + 1, endpoint=True
|
|
90
|
+
)
|
|
91
|
+
sine_latitude_edges = np.sin(latitude_edges)
|
|
92
|
+
delta_sine_latitudes = np.diff(sine_latitude_edges)
|
|
88
93
|
solid_angle_by_latitude = np.abs(spacing * delta_sine_latitudes)
|
|
89
94
|
|
|
90
95
|
# Order ensures agreement with build_az_el_grid's order of tiling az/el grid.
|
|
91
96
|
solid_angle_grid = np.repeat(
|
|
92
|
-
solid_angle_by_latitude[np.newaxis, :],
|
|
97
|
+
solid_angle_by_latitude[np.newaxis, :], number_of_lon_bins, axis=0
|
|
93
98
|
)
|
|
94
99
|
|
|
95
100
|
return solid_angle_grid
|
|
@@ -1,32 +1,23 @@
|
|
|
1
1
|
"""Methods for GLOWS Level 1A processing and CDF writing."""
|
|
2
2
|
|
|
3
|
-
from collections import defaultdict
|
|
4
3
|
from pathlib import Path
|
|
5
|
-
from typing import Optional
|
|
6
4
|
|
|
7
5
|
import numpy as np
|
|
8
6
|
import xarray as xr
|
|
9
7
|
|
|
10
8
|
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
|
|
11
9
|
from imap_processing.glows.l0.decom_glows import decom_packets
|
|
12
|
-
from imap_processing.glows.l0.glows_l0_data import DirectEventL0
|
|
10
|
+
from imap_processing.glows.l0.glows_l0_data import DirectEventL0
|
|
13
11
|
from imap_processing.glows.l1a.glows_l1a_data import DirectEventL1A, HistogramL1A
|
|
14
|
-
from imap_processing.glows.l1b.glows_l1b_data import HistogramL1B
|
|
15
12
|
from imap_processing.spice.time import (
|
|
16
|
-
met_to_datetime64,
|
|
17
13
|
met_to_ttj2000ns,
|
|
18
14
|
)
|
|
19
15
|
|
|
20
16
|
|
|
21
|
-
def create_glows_attr_obj(
|
|
17
|
+
def create_glows_attr_obj() -> ImapCdfAttributes:
|
|
22
18
|
"""
|
|
23
19
|
Load in 1la CDF attributes for GLOWS instrument.
|
|
24
20
|
|
|
25
|
-
Parameters
|
|
26
|
-
----------
|
|
27
|
-
data_version : str
|
|
28
|
-
Data version for CDF filename, in the format "vXXX".
|
|
29
|
-
|
|
30
21
|
Returns
|
|
31
22
|
-------
|
|
32
23
|
glows_attrs : ImapCdfAttributes
|
|
@@ -37,23 +28,23 @@ def create_glows_attr_obj(data_version: str) -> ImapCdfAttributes:
|
|
|
37
28
|
# Load in files
|
|
38
29
|
glows_attrs.add_instrument_global_attrs("glows")
|
|
39
30
|
glows_attrs.add_instrument_variable_attrs("glows", "l1a")
|
|
40
|
-
glows_attrs.add_global_attribute("Data_version", data_version)
|
|
41
31
|
return glows_attrs
|
|
42
32
|
|
|
43
33
|
|
|
44
|
-
def glows_l1a(packet_filepath: Path
|
|
34
|
+
def glows_l1a(packet_filepath: Path) -> list[xr.Dataset]:
|
|
45
35
|
"""
|
|
46
36
|
Will process packets into GLOWS L1A CDF files.
|
|
47
37
|
|
|
48
38
|
Outputs Datasets for histogram and direct event GLOWS L1A. This list can be passed
|
|
49
39
|
into write_cdf to output CDF files.
|
|
50
40
|
|
|
41
|
+
We expect one input L0 file to be processed into one L1A file, with one
|
|
42
|
+
observational day's worth of data.
|
|
43
|
+
|
|
51
44
|
Parameters
|
|
52
45
|
----------
|
|
53
46
|
packet_filepath : pathlib.Path
|
|
54
47
|
Path to packet file for processing.
|
|
55
|
-
data_version : str
|
|
56
|
-
Data version for CDF filename, in the format "vXXX".
|
|
57
48
|
|
|
58
49
|
Returns
|
|
59
50
|
-------
|
|
@@ -61,77 +52,30 @@ def glows_l1a(packet_filepath: Path, data_version: str) -> list[xr.Dataset]:
|
|
|
61
52
|
List of the L1A datasets.
|
|
62
53
|
"""
|
|
63
54
|
# Create ImapCdfAttributes object for cdf attributes management
|
|
64
|
-
glows_attrs = create_glows_attr_obj(
|
|
65
|
-
|
|
66
|
-
# TODO: Data version inside file as well?
|
|
55
|
+
glows_attrs = create_glows_attr_obj()
|
|
67
56
|
|
|
68
57
|
# Decompose packet file into histogram, and direct event data.
|
|
69
58
|
hist_l0, de_l0 = decom_packets(packet_filepath)
|
|
70
59
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
hists_by_day = defaultdict(list)
|
|
74
|
-
# Assume the observational day starts with the first packet, then find any new
|
|
75
|
-
# observation days.
|
|
76
|
-
# TODO: replace determine_observational_day with spin table API
|
|
77
|
-
obs_days = [hist_l0[0].SEC]
|
|
78
|
-
obs_days += determine_observational_day(hist_l0)
|
|
79
|
-
|
|
60
|
+
l1a_de = process_de_l0(de_l0)
|
|
61
|
+
l1a_hists = []
|
|
80
62
|
for hist in hist_l0:
|
|
81
|
-
|
|
82
|
-
# Determine the day the histogram belongs to. This finds the observation
|
|
83
|
-
# day in obs_day that is nearest the histogram timestamp without going over.
|
|
84
|
-
hist_day = next(
|
|
85
|
-
(day for day in reversed(obs_days) if day <= hist.SEC), obs_days[-1]
|
|
86
|
-
)
|
|
87
|
-
hists_by_day[hist_day].append(hist_l1a)
|
|
63
|
+
l1a_hists.append(HistogramL1A(hist))
|
|
88
64
|
|
|
89
65
|
# Generate CDF files for each day
|
|
90
66
|
output_datasets = []
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
output_datasets.append(dataset)
|
|
67
|
+
dataset = generate_histogram_dataset(l1a_hists, glows_attrs)
|
|
68
|
+
output_datasets.append(dataset)
|
|
94
69
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
output_datasets.append(dataset)
|
|
70
|
+
dataset = generate_de_dataset(l1a_de, glows_attrs)
|
|
71
|
+
output_datasets.append(dataset)
|
|
98
72
|
|
|
99
73
|
return output_datasets
|
|
100
74
|
|
|
101
75
|
|
|
102
|
-
def determine_observational_day(hist_l0: list[HistogramL0]) -> list:
|
|
103
|
-
"""
|
|
104
|
-
Find the timestamps for each observational day.
|
|
105
|
-
|
|
106
|
-
This function temporarily uses the is_night flag to determine the start of a new
|
|
107
|
-
observational day, but should eventually use the spin table APIs.
|
|
108
|
-
|
|
109
|
-
Parameters
|
|
110
|
-
----------
|
|
111
|
-
hist_l0 : list[HistogramL0]
|
|
112
|
-
List of HistogramL0 objects.
|
|
113
|
-
|
|
114
|
-
Returns
|
|
115
|
-
-------
|
|
116
|
-
list
|
|
117
|
-
List of start times for each observational day.
|
|
118
|
-
"""
|
|
119
|
-
prev_is_night = -1
|
|
120
|
-
obs_day_change = []
|
|
121
|
-
for hist in hist_l0:
|
|
122
|
-
flags = HistogramL1B.deserialize_flags(hist.FLAGS)
|
|
123
|
-
is_night: int = int(flags[6])
|
|
124
|
-
if prev_is_night and not is_night:
|
|
125
|
-
obs_day_change.append(hist.SEC)
|
|
126
|
-
|
|
127
|
-
prev_is_night = is_night
|
|
128
|
-
|
|
129
|
-
return obs_day_change
|
|
130
|
-
|
|
131
|
-
|
|
132
76
|
def process_de_l0(
|
|
133
77
|
de_l0: list[DirectEventL0],
|
|
134
|
-
) ->
|
|
78
|
+
) -> list[DirectEventL1A]:
|
|
135
79
|
"""
|
|
136
80
|
Will process Direct Event packets into GLOWS L1A CDF files.
|
|
137
81
|
|
|
@@ -145,25 +89,22 @@ def process_de_l0(
|
|
|
145
89
|
|
|
146
90
|
Returns
|
|
147
91
|
-------
|
|
148
|
-
de_by_day :
|
|
92
|
+
de_by_day : list[DirectEventL1A]
|
|
149
93
|
Dictionary with keys of days and values of lists of DirectEventL1A objects.
|
|
150
94
|
Each day has one CDF file associated with it.
|
|
151
95
|
"""
|
|
152
|
-
|
|
96
|
+
de_list: list[DirectEventL1A] = []
|
|
153
97
|
|
|
154
98
|
for de in de_l0:
|
|
155
|
-
de_day = (met_to_datetime64(de.MET)).astype("datetime64[D]")
|
|
156
|
-
if de_day not in de_by_day:
|
|
157
|
-
de_by_day[de_day] = [DirectEventL1A(de)]
|
|
158
99
|
# Putting not first data int o last direct event list.
|
|
159
|
-
|
|
100
|
+
if de.SEQ != 0:
|
|
160
101
|
# If the direct event is part of a sequence and is not the first,
|
|
161
|
-
#
|
|
162
|
-
|
|
102
|
+
# add it to the last direct event in the list
|
|
103
|
+
de_list[-1].merge_de_packets(de)
|
|
163
104
|
else:
|
|
164
|
-
|
|
105
|
+
de_list.append(DirectEventL1A(de))
|
|
165
106
|
|
|
166
|
-
return
|
|
107
|
+
return de_list
|
|
167
108
|
|
|
168
109
|
|
|
169
110
|
def generate_de_dataset(
|
|
@@ -263,8 +204,8 @@ def generate_de_dataset(
|
|
|
263
204
|
support_data["number_of_de_packets"].append(int(de.l0.LEN))
|
|
264
205
|
# support_data["missing_packet_sequences"].append(str(de.missing_seq))
|
|
265
206
|
|
|
266
|
-
for key in data_every_second.
|
|
267
|
-
|
|
207
|
+
for key, val in data_every_second.items():
|
|
208
|
+
val.append(de.status_data.__getattribute__(key))
|
|
268
209
|
|
|
269
210
|
# Convert arrays and dictionaries into xarray 'DataArray' objects
|
|
270
211
|
epoch_time = xr.DataArray(
|
|
@@ -284,7 +225,6 @@ def generate_de_dataset(
|
|
|
284
225
|
),
|
|
285
226
|
)
|
|
286
227
|
|
|
287
|
-
# TODO come up with a better name
|
|
288
228
|
within_the_second = xr.DataArray(
|
|
289
229
|
np.arange(direct_events.shape[1]),
|
|
290
230
|
name="within_the_second",
|
|
@@ -304,7 +244,6 @@ def generate_de_dataset(
|
|
|
304
244
|
attrs=glows_cdf_attributes.get_variable_attributes("direct_events"),
|
|
305
245
|
)
|
|
306
246
|
|
|
307
|
-
# TODO: This is the weird global attribute.
|
|
308
247
|
# Create an xarray dataset object, and add DataArray objects into it
|
|
309
248
|
output = xr.Dataset(
|
|
310
249
|
coords={"epoch": time_data},
|
|
@@ -313,9 +252,6 @@ def generate_de_dataset(
|
|
|
313
252
|
|
|
314
253
|
output["direct_events"] = de
|
|
315
254
|
|
|
316
|
-
# TODO: Do we want missing_sequences as support data or as global attrs?
|
|
317
|
-
# Currently: support data, with a string
|
|
318
|
-
|
|
319
255
|
for key, value in support_data.items():
|
|
320
256
|
output[key] = xr.DataArray(
|
|
321
257
|
value,
|
|
@@ -340,7 +276,6 @@ def generate_de_dataset(
|
|
|
340
276
|
def generate_histogram_dataset(
|
|
341
277
|
hist_l1a_list: list[HistogramL1A],
|
|
342
278
|
glows_cdf_attributes: ImapCdfAttributes,
|
|
343
|
-
obs_day: Optional[int] = None,
|
|
344
279
|
) -> xr.Dataset:
|
|
345
280
|
"""
|
|
346
281
|
Generate a dataset for GLOWS L1A histogram data CDF files.
|
|
@@ -351,9 +286,6 @@ def generate_histogram_dataset(
|
|
|
351
286
|
List of HistogramL1A objects for a given day.
|
|
352
287
|
glows_cdf_attributes : ImapCdfAttributes
|
|
353
288
|
Object containing l1a CDF attributes for instrument glows.
|
|
354
|
-
obs_day : int, optional
|
|
355
|
-
Observational day counter. If supplied, it will be included in the
|
|
356
|
-
output file name.
|
|
357
289
|
|
|
358
290
|
Returns
|
|
359
291
|
-------
|
|
@@ -407,12 +339,12 @@ def generate_histogram_dataset(
|
|
|
407
339
|
)
|
|
408
340
|
|
|
409
341
|
# Add support_data keys to the support_data dictionary
|
|
410
|
-
for key in support_data.
|
|
342
|
+
for key, support_val in support_data.items():
|
|
411
343
|
if key not in ["flags_set_onboard", "is_generated_on_ground"]:
|
|
412
|
-
|
|
344
|
+
support_val.append(hist.__getattribute__(key))
|
|
413
345
|
# For the time varying data, convert to seconds and then append
|
|
414
|
-
for key in time_metadata.
|
|
415
|
-
|
|
346
|
+
for key, time_metadata_val in time_metadata.items():
|
|
347
|
+
time_metadata_val.append(hist.__getattribute__(key).to_seconds())
|
|
416
348
|
time_data[index] = epoch_time
|
|
417
349
|
|
|
418
350
|
epoch_time = xr.DataArray(
|
|
@@ -450,9 +382,6 @@ def generate_histogram_dataset(
|
|
|
450
382
|
)
|
|
451
383
|
|
|
452
384
|
attrs = glows_cdf_attributes.get_global_attributes("imap_glows_l1a_hist")
|
|
453
|
-
if obs_day:
|
|
454
|
-
# this needs to be 5 digits, so truncate it from the temporary obs day
|
|
455
|
-
attrs["Repointing"] = int(str(obs_day)[-5:])
|
|
456
385
|
|
|
457
386
|
output = xr.Dataset(
|
|
458
387
|
coords={"epoch": epoch_time, "bins": bins, "bins_label": bin_label},
|
|
@@ -326,7 +326,7 @@ class DirectEventL1A:
|
|
|
326
326
|
|
|
327
327
|
Methods
|
|
328
328
|
-------
|
|
329
|
-
|
|
329
|
+
merge_de_packets
|
|
330
330
|
Add another Level0 instance.
|
|
331
331
|
"""
|
|
332
332
|
|
|
@@ -346,7 +346,7 @@ class DirectEventL1A:
|
|
|
346
346
|
if level0.LEN == 1:
|
|
347
347
|
self._process_de_data()
|
|
348
348
|
|
|
349
|
-
def
|
|
349
|
+
def merge_de_packets(self, second_l0: DirectEventL0) -> None:
|
|
350
350
|
"""
|
|
351
351
|
Merge an additional direct event packet to this DirectEventL1A class.
|
|
352
352
|
|
|
@@ -10,7 +10,7 @@ from imap_processing.glows import FLAG_LENGTH
|
|
|
10
10
|
from imap_processing.glows.l1b.glows_l1b_data import DirectEventL1B, HistogramL1B
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def glows_l1b(input_dataset: xr.Dataset
|
|
13
|
+
def glows_l1b(input_dataset: xr.Dataset) -> xr.Dataset:
|
|
14
14
|
"""
|
|
15
15
|
Will process the GLOWS L1B data and format the output datasets.
|
|
16
16
|
|
|
@@ -18,8 +18,6 @@ def glows_l1b(input_dataset: xr.Dataset, data_version: str) -> xr.Dataset:
|
|
|
18
18
|
----------
|
|
19
19
|
input_dataset : xr.Dataset
|
|
20
20
|
Dataset of input values.
|
|
21
|
-
data_version : str
|
|
22
|
-
Data version.
|
|
23
21
|
|
|
24
22
|
Returns
|
|
25
23
|
-------
|
|
@@ -29,7 +27,6 @@ def glows_l1b(input_dataset: xr.Dataset, data_version: str) -> xr.Dataset:
|
|
|
29
27
|
cdf_attrs = ImapCdfAttributes()
|
|
30
28
|
cdf_attrs.add_instrument_global_attrs("glows")
|
|
31
29
|
cdf_attrs.add_instrument_variable_attrs("glows", "l1b")
|
|
32
|
-
cdf_attrs.add_global_attribute("Data_version", data_version)
|
|
33
30
|
|
|
34
31
|
data_epoch = xr.DataArray(
|
|
35
32
|
input_dataset["epoch"],
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# ruff: noqa: PLR0913
|
|
2
1
|
"""Module for GLOWS L1B data products."""
|
|
3
2
|
|
|
4
3
|
import dataclasses
|
|
@@ -73,8 +72,7 @@ class AncillaryParameters:
|
|
|
73
72
|
|
|
74
73
|
except KeyError as e:
|
|
75
74
|
raise KeyError(
|
|
76
|
-
"GLOWS L1B Ancillary input_table does not conform to "
|
|
77
|
-
"expected format."
|
|
75
|
+
"GLOWS L1B Ancillary input_table does not conform to expected format."
|
|
78
76
|
) from e
|
|
79
77
|
|
|
80
78
|
def decode(self, param_key: str, encoded_value: np.double) -> np.double:
|
|
@@ -12,7 +12,7 @@ from imap_processing.glows.l1b.glows_l1b_data import HistogramL1B
|
|
|
12
12
|
from imap_processing.glows.l2.glows_l2_data import DailyLightcurve, HistogramL2
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def glows_l2(input_dataset: xr.Dataset
|
|
15
|
+
def glows_l2(input_dataset: xr.Dataset) -> list[xr.Dataset]:
|
|
16
16
|
"""
|
|
17
17
|
Will process GLoWS L2 data from L1 data.
|
|
18
18
|
|
|
@@ -20,8 +20,6 @@ def glows_l2(input_dataset: xr.Dataset, data_version: str) -> list[xr.Dataset]:
|
|
|
20
20
|
----------
|
|
21
21
|
input_dataset : xarray.Dataset
|
|
22
22
|
Input L1B dataset.
|
|
23
|
-
data_version : str
|
|
24
|
-
Version for output.
|
|
25
23
|
|
|
26
24
|
Returns
|
|
27
25
|
-------
|
|
@@ -31,7 +29,6 @@ def glows_l2(input_dataset: xr.Dataset, data_version: str) -> list[xr.Dataset]:
|
|
|
31
29
|
cdf_attrs = ImapCdfAttributes()
|
|
32
30
|
cdf_attrs.add_instrument_global_attrs("glows")
|
|
33
31
|
cdf_attrs.add_instrument_variable_attrs("glows", "l2")
|
|
34
|
-
cdf_attrs.add_global_attribute("Data_version", data_version)
|
|
35
32
|
|
|
36
33
|
split_data = split_data_by_observational_day(input_dataset)
|
|
37
34
|
l2_output = []
|
|
@@ -270,7 +267,7 @@ def create_l2_dataset(
|
|
|
270
267
|
|
|
271
268
|
elif key != "daily_lightcurve":
|
|
272
269
|
val = value
|
|
273
|
-
if type(value)
|
|
270
|
+
if type(value) is not np.ndarray:
|
|
274
271
|
val = np.array([value])
|
|
275
272
|
output[key] = xr.DataArray(
|
|
276
273
|
val,
|
imap_processing/hi/l1a/hi_l1a.py
CHANGED
|
@@ -16,7 +16,7 @@ from imap_processing.utils import packet_file_to_datasets
|
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def hi_l1a(packet_file_path: Union[str, Path]
|
|
19
|
+
def hi_l1a(packet_file_path: Union[str, Path]) -> list[xr.Dataset]:
|
|
20
20
|
"""
|
|
21
21
|
Will process IMAP raw data to l1a.
|
|
22
22
|
|
|
@@ -24,20 +24,13 @@ def hi_l1a(packet_file_path: Union[str, Path], data_version: str) -> list[xr.Dat
|
|
|
24
24
|
----------
|
|
25
25
|
packet_file_path : str
|
|
26
26
|
Data packet file path.
|
|
27
|
-
data_version : str
|
|
28
|
-
Version of the data product being created.
|
|
29
27
|
|
|
30
28
|
Returns
|
|
31
29
|
-------
|
|
32
30
|
processed_data : list[xarray.Dataset]
|
|
33
31
|
List of processed xarray dataset.
|
|
34
32
|
"""
|
|
35
|
-
|
|
36
|
-
imap_module_directory / "hi/packet_definitions/TLM_HI_COMBINED_SCI.xml"
|
|
37
|
-
)
|
|
38
|
-
datasets_by_apid = packet_file_to_datasets(
|
|
39
|
-
packet_file=packet_file_path, xtce_packet_definition=packet_def_file
|
|
40
|
-
)
|
|
33
|
+
datasets_by_apid = hi_packet_file_to_datasets(packet_file_path)
|
|
41
34
|
|
|
42
35
|
# Process science to l1a.
|
|
43
36
|
processed_data = []
|
|
@@ -67,9 +60,6 @@ def hi_l1a(packet_file_path: Union[str, Path], data_version: str) -> list[xr.Dat
|
|
|
67
60
|
attr_mgr.add_instrument_global_attrs("hi")
|
|
68
61
|
data.attrs.update(attr_mgr.get_global_attributes(gattr_key))
|
|
69
62
|
|
|
70
|
-
# TODO: revisit this
|
|
71
|
-
data.attrs["Data_version"] = data_version
|
|
72
|
-
|
|
73
63
|
# set the sensor string in Logical_source
|
|
74
64
|
sensor_str = apid_enum.sensor
|
|
75
65
|
data.attrs["Logical_source"] = data.attrs["Logical_source"].format(
|
|
@@ -77,3 +67,32 @@ def hi_l1a(packet_file_path: Union[str, Path], data_version: str) -> list[xr.Dat
|
|
|
77
67
|
)
|
|
78
68
|
processed_data.append(data)
|
|
79
69
|
return processed_data
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def hi_packet_file_to_datasets(
|
|
73
|
+
packet_file_path: Union[str, Path], use_derived_value: bool = False
|
|
74
|
+
) -> dict[int, xr.Dataset]:
|
|
75
|
+
"""
|
|
76
|
+
Extract hi datasets from packet file.
|
|
77
|
+
|
|
78
|
+
Parameters
|
|
79
|
+
----------
|
|
80
|
+
packet_file_path : str
|
|
81
|
+
L0 packet file path.
|
|
82
|
+
use_derived_value : bool
|
|
83
|
+
Whether to use the derived value from the XTCE definition. Default is False.
|
|
84
|
+
|
|
85
|
+
Returns
|
|
86
|
+
-------
|
|
87
|
+
datasets : dict[int, xarray.Dataset]
|
|
88
|
+
Dictionary of xarray datasets keyed by APID.
|
|
89
|
+
"""
|
|
90
|
+
packet_def_file = (
|
|
91
|
+
imap_module_directory / "hi/packet_definitions/TLM_HI_COMBINED_SCI.xml"
|
|
92
|
+
)
|
|
93
|
+
datasets_by_apid = packet_file_to_datasets(
|
|
94
|
+
packet_file=packet_file_path,
|
|
95
|
+
xtce_packet_definition=packet_def_file,
|
|
96
|
+
use_derived_value=use_derived_value,
|
|
97
|
+
)
|
|
98
|
+
return datasets_by_apid
|
imap_processing/hi/l1b/hi_l1b.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
from enum import IntEnum
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Union
|
|
5
7
|
|
|
6
8
|
import numpy as np
|
|
7
9
|
import xarray as xr
|
|
@@ -26,7 +28,7 @@ from imap_processing.spice.spin import (
|
|
|
26
28
|
get_spacecraft_spin_phase,
|
|
27
29
|
)
|
|
28
30
|
from imap_processing.spice.time import met_to_sclkticks, sct_to_et
|
|
29
|
-
from imap_processing.utils import
|
|
31
|
+
from imap_processing.utils import packet_file_to_datasets
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
class TriggerId(IntEnum):
|
|
@@ -43,61 +45,96 @@ ATTR_MGR.add_instrument_global_attrs("hi")
|
|
|
43
45
|
ATTR_MGR.add_instrument_variable_attrs(instrument="hi", level=None)
|
|
44
46
|
|
|
45
47
|
|
|
46
|
-
def hi_l1b(
|
|
48
|
+
def hi_l1b(dependency: Union[str, Path, xr.Dataset]) -> list[xr.Dataset]:
|
|
47
49
|
"""
|
|
48
50
|
High level IMAP-HI L1B processing function.
|
|
49
51
|
|
|
50
52
|
Parameters
|
|
51
53
|
----------
|
|
52
|
-
|
|
53
|
-
L1A dataset to process.
|
|
54
|
-
data_version : str
|
|
55
|
-
Version of the data product being created.
|
|
54
|
+
dependency : str or xarray.Dataset
|
|
55
|
+
Path to L0 file or L1A dataset to process.
|
|
56
56
|
|
|
57
57
|
Returns
|
|
58
58
|
-------
|
|
59
|
-
l1b_dataset : xarray.Dataset
|
|
60
|
-
Processed xarray
|
|
59
|
+
l1b_dataset : list[xarray.Dataset]
|
|
60
|
+
Processed xarray datasets.
|
|
61
61
|
"""
|
|
62
|
-
logger.info(
|
|
63
|
-
f"Running Hi L1B processing on dataset: {l1a_dataset.attrs['Logical_source']}"
|
|
64
|
-
)
|
|
65
|
-
logical_source_parts = parse_filename_like(l1a_dataset.attrs["Logical_source"])
|
|
66
|
-
# TODO: apid is not currently stored in all L1A data but should be.
|
|
67
|
-
# Use apid to determine what L1B processing function to call
|
|
68
|
-
|
|
69
62
|
# Housekeeping processing
|
|
70
|
-
if
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
l1a_dataset,
|
|
78
|
-
conversion_table_path=conversion_table_path,
|
|
79
|
-
packet_name=packet_enum.name,
|
|
80
|
-
comment="#", # type: ignore[arg-type]
|
|
81
|
-
# Todo error, Argument "comment" to "convert_raw_to_eu" has incompatible
|
|
82
|
-
# type "str"; expected "dict[Any, Any]"
|
|
83
|
-
converters={"mnemonic": str.lower},
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
l1b_dataset.attrs.update(ATTR_MGR.get_global_attributes("imap_hi_l1b_hk_attrs"))
|
|
87
|
-
elif logical_source_parts["descriptor"].endswith("de"):
|
|
88
|
-
l1b_dataset = annotate_direct_events(l1a_dataset)
|
|
89
|
-
else:
|
|
90
|
-
raise NotImplementedError(
|
|
91
|
-
f"No Hi L1B processing defined for file type: "
|
|
63
|
+
if isinstance(dependency, (Path, str)):
|
|
64
|
+
logger.info(f"Running Hi L1B processing on file: {dependency}")
|
|
65
|
+
l1b_datasets = housekeeping(dependency)
|
|
66
|
+
elif isinstance(dependency, xr.Dataset):
|
|
67
|
+
l1a_dataset = dependency
|
|
68
|
+
logger.info(
|
|
69
|
+
f"Running Hi L1B processing on dataset: "
|
|
92
70
|
f"{l1a_dataset.attrs['Logical_source']}"
|
|
93
71
|
)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
72
|
+
logical_source_parts = parse_filename_like(l1a_dataset.attrs["Logical_source"])
|
|
73
|
+
# TODO: apid is not currently stored in all L1A data but should be.
|
|
74
|
+
# Use apid to determine what L1B processing function to call
|
|
75
|
+
|
|
76
|
+
# DE processing
|
|
77
|
+
if logical_source_parts["descriptor"].endswith("de"):
|
|
78
|
+
l1b_datasets = [annotate_direct_events(l1a_dataset)]
|
|
79
|
+
l1b_datasets[0].attrs["Logical_source"] = (
|
|
80
|
+
l1b_datasets[0]
|
|
81
|
+
.attrs["Logical_source"]
|
|
82
|
+
.format(sensor=logical_source_parts["sensor"])
|
|
83
|
+
)
|
|
84
|
+
else:
|
|
85
|
+
raise NotImplementedError(
|
|
86
|
+
f"No Hi L1B processing defined for file type: "
|
|
87
|
+
f"{l1a_dataset.attrs['Logical_source']}"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
return l1b_datasets
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def housekeeping(packet_file_path: Union[str, Path]) -> list[xr.Dataset]:
|
|
94
|
+
"""
|
|
95
|
+
Will process IMAP raw data to l1b housekeeping dataset.
|
|
96
|
+
|
|
97
|
+
In order to use `space_packet_parser` and the xtce which contains the
|
|
98
|
+
DN to EU conversion factors, the L0 packet file is used to go straight to
|
|
99
|
+
L1B.
|
|
100
|
+
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
packet_file_path : str
|
|
104
|
+
Packet file path.
|
|
105
|
+
|
|
106
|
+
Returns
|
|
107
|
+
-------
|
|
108
|
+
processed_data : list[xarray.Dataset]
|
|
109
|
+
Housekeeping datasets with engineering units.
|
|
110
|
+
"""
|
|
111
|
+
packet_def_file = (
|
|
112
|
+
imap_module_directory / "hi/packet_definitions/TLM_HI_COMBINED_SCI.xml"
|
|
97
113
|
)
|
|
98
|
-
# TODO:
|
|
99
|
-
|
|
100
|
-
|
|
114
|
+
# TODO: If raw and derived values can be gotten from one call to
|
|
115
|
+
# packet_file_to_datasets, the L1A and L1B could be generated
|
|
116
|
+
# in a single L1A/B function.
|
|
117
|
+
datasets_by_apid = packet_file_to_datasets(
|
|
118
|
+
packet_file=packet_file_path,
|
|
119
|
+
xtce_packet_definition=packet_def_file,
|
|
120
|
+
use_derived_value=True,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Extract only the HK datasets
|
|
124
|
+
attr_mgr = ImapCdfAttributes()
|
|
125
|
+
attr_mgr.add_instrument_global_attrs("hi")
|
|
126
|
+
datasets = list()
|
|
127
|
+
for apid in [HIAPID.H45_APP_NHK, HIAPID.H90_APP_NHK]:
|
|
128
|
+
if apid in datasets_by_apid:
|
|
129
|
+
datasets.append(datasets_by_apid[apid])
|
|
130
|
+
# Update the dataset global attributes
|
|
131
|
+
datasets[-1].attrs.update(
|
|
132
|
+
ATTR_MGR.get_global_attributes("imap_hi_l1b_hk_attrs")
|
|
133
|
+
)
|
|
134
|
+
datasets[-1].attrs["Logical_source"] = (
|
|
135
|
+
datasets[-1].attrs["Logical_source"].format(sensor=apid.sensor)
|
|
136
|
+
)
|
|
137
|
+
return datasets
|
|
101
138
|
|
|
102
139
|
|
|
103
140
|
def annotate_direct_events(l1a_dataset: xr.Dataset) -> xr.Dataset:
|