diff --git a/imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml b/imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml new file mode 100644 index 000000000..36c336058 --- /dev/null +++ b/imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml @@ -0,0 +1,24 @@ +# <=== Useful Variables ===> +real_fillval: &real_fillval -1.0E+31 + +# <=== Coordinates ===> +energy_per_charge: + CATDESC: Energy per charge + DEPEND_1: esa_step + FIELDNAM: Energy per charge + FILLVAL: *real_fillval + FORMAT: F12.6 + LABLAXIS: E/q + SCALETYP: log + UNITS: keV/e + VALIDMAX: 81.216 + VALIDMIN: 0.00288 + VAR_TYPE: support_data + +# <=== LABL_PTR_i Attributes ===> +energy_per_charge_label: + CATDESC: Energy per charge + DEPEND_1: esa_step + FIELDNAM: Energy per charge + FORMAT: A10 + VAR_TYPE: metadata diff --git a/imap_processing/cdf/config/imap_codice_l2-lo-species_variable_attrs.yaml b/imap_processing/cdf/config/imap_codice_l2-lo-species_variable_attrs.yaml index e4048650a..e0ff5516f 100644 --- a/imap_processing/cdf/config/imap_codice_l2-lo-species_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_codice_l2-lo-species_variable_attrs.yaml @@ -66,14 +66,14 @@ lo-species-attrs: DELTA_MINUS_VAR: unc_{species} DELTA_PLUS_VAR: unc_{species} DEPEND_0: epoch - DEPEND_1: esa_step + DEPEND_1: energy_per_charge DEPEND_2: spin_sector DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential DISPLAY_TYPE: spectrogram FIELDNAM: "Non-sunward - {species}" FILLVAL: *real_fillval FORMAT: F32.1 - LABL_PTR_1: esa_step_label + LABL_PTR_1: energy_per_charge_label LABL_PTR_2: spin_sector_label SCALETYP: log UNITS: "#/(cm^2-s-sr-keV/q)" @@ -86,14 +86,14 @@ lo-pui-species-attrs: DELTA_MINUS_VAR: unc_{species} DELTA_PLUS_VAR: unc_{species} DEPEND_0: epoch - DEPEND_1: esa_step + DEPEND_1: energy_per_charge DEPEND_2: spin_sector DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential DISPLAY_TYPE: spectrogram FIELDNAM: "Sunward - {species}" FILLVAL: *real_fillval FORMAT: F32.1 - LABL_PTR_1: esa_step_label + LABL_PTR_1: energy_per_charge_label LABL_PTR_2: spin_sector_label SCALETYP: log UNITS: "#/(cm^2-s-sr-keV/q)" @@ -106,14 +106,14 @@ lo-sw-species-attrs: DELTA_MINUS_VAR: unc_{species} DELTA_PLUS_VAR: unc_{species} DEPEND_0: epoch - DEPEND_1: esa_step + DEPEND_1: energy_per_charge DEPEND_2: spin_sector DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential DISPLAY_TYPE: spectrogram FIELDNAM: "Sunward Differential Intensity - {species_display}" FILLVAL: *real_fillval FORMAT: F32.1 - LABL_PTR_1: esa_step_label + LABL_PTR_1: energy_per_charge_label LABL_PTR_2: spin_sector_label SCALETYP: log UNITS: "#/(cm^2-s-sr-keV/q)" @@ -124,14 +124,14 @@ lo-sw-species-attrs: lo-species-unc-attrs: CATDESC: "{species} Non-sunward Species uncertainty" DEPEND_0: epoch - DEPEND_1: esa_step + DEPEND_1: energy_per_charge DEPEND_2: spin_sector DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Uncertainty DISPLAY_TYPE: spectrogram FIELDNAM: "Non-sunward - {species}" FILLVAL: *real_fillval FORMAT: F32.1 - LABL_PTR_1: esa_step_label + LABL_PTR_1: energy_per_charge_label LABL_PTR_2: spin_sector_label SCALETYP: log UNITS: "#/(cm^2-s-sr-keV/q)" @@ -142,14 +142,14 @@ lo-species-unc-attrs: lo-pui-species-unc-attrs: CATDESC: "{species} Pickup Ion Sunward Species uncertainty" DEPEND_0: epoch - DEPEND_1: esa_step + DEPEND_1: energy_per_charge DEPEND_2: spin_sector DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Uncertainty DISPLAY_TYPE: spectrogram FIELDNAM: "Sunward - {species}" FILLVAL: *real_fillval FORMAT: F32.1 - LABL_PTR_1: esa_step_label + LABL_PTR_1: energy_per_charge_label LABL_PTR_2: spin_sector_label SCALETYP: log UNITS: "#/(cm^2-s-sr-keV/q)" @@ -160,14 +160,14 @@ lo-pui-species-unc-attrs: lo-sw-species-unc-attrs: CATDESC: "Uncertainty in differential intensity from sunward-looking detectors measuring solar-wind {species_display}" DEPEND_0: epoch - DEPEND_1: esa_step + DEPEND_1: energy_per_charge DEPEND_2: spin_sector DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Uncertainty DISPLAY_TYPE: spectrogram FIELDNAM: "Sunward Uncertainty - {species_display}" FILLVAL: *real_fillval FORMAT: F32.1 - LABL_PTR_1: esa_step_label + LABL_PTR_1: energy_per_charge_label LABL_PTR_2: spin_sector_label SCALETYP: log UNITS: "#/(cm^2-s-sr-keV/q)" diff --git a/imap_processing/codice/codice_l1b.py b/imap_processing/codice/codice_l1b.py index 644f59a3b..77a3cf2e8 100644 --- a/imap_processing/codice/codice_l1b.py +++ b/imap_processing/codice/codice_l1b.py @@ -22,7 +22,11 @@ logger = logging.getLogger(__name__) -def convert_to_rates(dataset: xr.Dataset, descriptor: str) -> np.ndarray: +def convert_to_rates( + dataset: xr.Dataset, + descriptor: str, + cdf_attrs: ImapCdfAttributes | None = None, +) -> np.ndarray: """ Apply a conversion from counts to rates. @@ -35,6 +39,10 @@ def convert_to_rates(dataset: xr.Dataset, descriptor: str) -> np.ndarray: The L1b dataset containing the data to convert. descriptor : str The descriptor of the data product of interest. + cdf_attrs : ImapCdfAttributes + The CDF attributes manager, with L1b variable attributes loaded. + Callers that only need the intermediate values (e.g. I-ALiRT, which + discards them after computing ratios) can omit this. Returns ------- @@ -49,19 +57,31 @@ def convert_to_rates(dataset: xr.Dataset, descriptor: str) -> np.ndarray: ) if descriptor.startswith("lo-"): # Calculate energy_per_charge using voltage_table and k_factor - energy_attrs = dataset["voltage_table"].attrs | { - "UNITS": "keV/e", - "LABLAXIS": "E/q", - "CATDESC": "Energy per charge", - "FIELDNAM": "Energy per charge", - } # 1e3 is to convert eV to keV + energy_per_charge = ( + dataset["voltage_table"].values * dataset["k_factor"].values * 1e-3 + ) dataset["energy_per_charge"] = xr.DataArray( - dataset["voltage_table"].values * dataset["k_factor"].values * 1e-3, + energy_per_charge, dims=[ "esa_step", ], - attrs=energy_attrs, + attrs=cdf_attrs.get_variable_attributes( + "energy_per_charge", check_schema=False + ) + if cdf_attrs is not None + else {}, + ) + dataset["energy_per_charge_label"] = xr.DataArray( + np.array([f"{value:.3f}" for value in energy_per_charge]), + dims=[ + "esa_step", + ], + attrs=cdf_attrs.get_variable_attributes( + "energy_per_charge_label", check_schema=False + ) + if cdf_attrs is not None + else {}, ) if descriptor in [ @@ -180,6 +200,7 @@ def process_codice_l1b(file_path: Path) -> xr.Dataset: # Get the L1b CDF attributes cdf_attrs = ImapCdfAttributes() cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l1b") # Use the L1a data product as a starting point for L1b l1b_dataset = l1a_dataset.copy(deep=True) @@ -190,4 +211,5 @@ def process_codice_l1b(file_path: Path) -> xr.Dataset: return convert_to_rates( l1b_dataset, descriptor, + cdf_attrs, ) diff --git a/imap_processing/ialirt/l0/process_codice.py b/imap_processing/ialirt/l0/process_codice.py index 1675acd66..8fd0684d5 100644 --- a/imap_processing/ialirt/l0/process_codice.py +++ b/imap_processing/ialirt/l0/process_codice.py @@ -477,10 +477,7 @@ def process_codice( l1a_lo = process_by_table_id(cod_lo_dataset, l1a_lut_path, l1a_lo_species) l1b_lo = cast( xr.Dataset, - convert_to_rates( - l1a_lo, - "lo-ialirt", - ), + convert_to_rates(l1a_lo, "lo-ialirt"), ) mid_measurement = int((l1b_lo["epoch"][0] + l1b_lo["epoch"][-1]) // 2) yyyymmdd = datetime.datetime.strptime(