Skip to content

Commit

Permalink
Updating branch
Browse files Browse the repository at this point in the history
Merge branch 'dev' of github.com:IMAP-Science-Operations-Center/imap_processing into data-access-api
  • Loading branch information
anamanica committed Aug 7, 2024
2 parents 73c5dce + b9abcb3 commit 3121b00
Show file tree
Hide file tree
Showing 25 changed files with 46,086 additions and 67 deletions.
6 changes: 4 additions & 2 deletions imap_processing/ccsds/excel_to_xtce.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@ def _create_container_sets(self) -> None:
if pd.isna(row.get("packetName")):
# This is a poorly formatted row, skip it
continue
name = f"{row['packetName']}_{row['mnemonic']}"
# separate the packet name and mnemonic with a period
# a hyphen is sometimes in the packet name or mnemonic already
name = f"{row['packetName']}.{row['mnemonic']}"
parameter_ref_entry = Et.SubElement(
packet_entry_list, "xtce:ParameterRefEntry"
)
Expand All @@ -247,7 +249,7 @@ def _add_parameter(self, row: pd.Series, total_packet_bits: int) -> None:
"""
parameter = Et.SubElement(self._parameter_set, "xtce:Parameter")
# Combine the packet name and mnemonic to create a unique parameter name
name = f"{row['packetName']}_{row['mnemonic']}"
name = f"{row['packetName']}.{row['mnemonic']}"
parameter.attrib["name"] = name
# UINT8, ...
parameter.attrib["parameterTypeRef"] = name
Expand Down
11 changes: 9 additions & 2 deletions imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,21 @@ instrument_base: &instrument_base
imap_swapi_l1_sci:
<<: *instrument_base
# NOTE: Right now, this Data_level is required to produce valid CDF
Data_level: 1
Data_level: "1"
Data_type: L1_SCI>Level-1 Science data in 1 minute resolution
Logical_source: imap_swapi_l1_sci-1min
Logical_source_description: SWAPI Instrument Level-1 Science Data in 1 minute resolution

imap_swapi_l1_hk:
<<: *instrument_base
Data_level: 1
Data_level: "1"
Data_type: L1_HK>Level-1B Housekeeping data
Logical_source: imap_swapi_l1_hk
Logical_source_description: SWAPI Instrument Level-1 Housekeeping Data

imap_swapi_l2_sci:
<<: *instrument_base
Data_level: "2"
Data_type: L2_SCI>Level-2 Science data in 1 minute resolution
Logical_source: imap_swapi_l2_sci-1min
Logical_source_description: SWAPI Instrument Level-1 Science Data in 1 minute resolution
44 changes: 42 additions & 2 deletions imap_processing/cdf/config/imap_swapi_variable_attrs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ counts_default: &counts_default
DEPEND_1: energy
DISPLAY_TYPE: spectrogram
LABL_PTR_1: energy_label
FILLVAL: -9223372036854775808
FILLVAL: 4294967295
FORMAT: I5
UNITS: counts
VALIDMIN: 0
Expand All @@ -37,7 +37,7 @@ compression_default: &compression_default
DEPEND_1: energy
DISPLAY_TYPE: spectrogram
LABL_PTR_1: energy_label
FILLVAL: -9223372036854775808
FILLVAL: 4294967295
FORMAT: I1
UNITS: ' '
VALIDMIN: 0
Expand All @@ -58,47 +58,87 @@ uncertainty_default: &uncertainty_default
VAR_TYPE: data
SCALETYP: linear

rate_default: &rate_default
DEPEND_0: epoch
DEPEND_1: energy
DISPLAY_TYPE: spectrogram
LABL_PTR_1: energy_label
FILLVAL: -1.0000000E+31
FORMAT: E19.5
UNITS: counts
VALIDMIN: 0.0
VALIDMAX: 1.7976931348623157e+308 # TODO: find actual value
VAR_TYPE: data
SCALETYP: linear

pcem_counts:
<<: *counts_default
CATDESC: Primary Channel Electron Multiplier (CEM) Counts
FIELDNAM: Primary CEM Counts
LABLAXIS: pcem_cnts

scem_counts:
<<: *counts_default
CATDESC: Secondary Channel Electron Multiplier (CEM) Counts
FIELDNAM: Secondary CEM Counts
LABLAXIS: scem_cnts

coin_counts:
<<: *counts_default
CATDESC: Coincidence Counts
FIELDNAM: Coincidence CEM Counts
LABLAXIS: coin_cnts

pcem_flags:
<<: *compression_default
CATDESC: Primary Channel Electron Multiplier (CEM) compression flag
FIELDNAM: Primary CEM Flag
LABLAXIS: pcem_flag

scem_flags:
<<: *compression_default
CATDESC: Secondary Channel Electron Multiplier (CEM) compression flag
FIELDNAM: Secondary CEM Flag
LABLAXIS: scem_flag

coin_flags:
<<: *compression_default
CATDESC: Coincidence compression flag
FIELDNAM: Coincidence Flag
LABLAXIS: coin_flag

pcem_uncertainty:
<<: *uncertainty_default
CATDESC: Primary Channel Electron Multiplier (CEM) uncertainty
FIELDNAM: Primary CEM Uncertainty
LABLAXIS: pcem_unc

scem_uncertainty:
<<: *uncertainty_default
CATDESC: Secondary Channel Electron Multiplier (CEM) uncertainty
FIELDNAM: Secondary CEM Uncertainty
LABLAXIS: scem_unc

coin_uncertainty:
<<: *uncertainty_default
CATDESC: Coincidence uncertainty
FIELDNAM: Coincidence Uncertainty
LABLAXIS: coin_unc

pcem_rate:
<<: *rate_default
CATDESC: Primary Channel Electron Multiplier (CEM) Rates
FIELDNAM: Primary CEM Rates
LABLAXIS: pcem_rate

scem_rate:
<<: *rate_default
CATDESC: Secondary Channel Electron Multiplier (CEM) Rates
FIELDNnam: Secondary CEM Rates
LABLAXIS: scem_rate

coin_rate:
<<: *rate_default
CATDESC: Coincidence Rates
FIELDNAM: Coincidence Rates
LABLAXIS: coin_rate
10 changes: 10 additions & 0 deletions imap_processing/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
from imap_processing.mag.l1b.mag_l1b import mag_l1b
from imap_processing.mag.l1c.mag_l1c import mag_l1c
from imap_processing.swapi.l1.swapi_l1 import swapi_l1
from imap_processing.swapi.l2.swapi_l2 import swapi_l2
from imap_processing.swe.l1a.swe_l1a import swe_l1a
from imap_processing.swe.l1b.swe_l1b import swe_l1b
from imap_processing.ultra.l1a import ultra_l1a
Expand Down Expand Up @@ -725,6 +726,15 @@ def do_processing(self, dependencies: list) -> list[xr.Dataset]:
)
# process data
datasets = [swapi_l1(dependencies[0], self.version)]
elif self.data_level == "l2":
if len(dependencies) > 1:
raise ValueError(
f"Unexpected dependencies found for SWAPI L2:"
f"{dependencies}. Expected only one dependency."
)
# process data
l1_dataset = load_cdf(dependencies[0])
datasets = [swapi_l2(l1_dataset, self.version)]

return datasets

Expand Down
68 changes: 68 additions & 0 deletions imap_processing/quality_flags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"""Bitwise flagging."""

from enum import IntFlag


class FlagNameMixin(IntFlag):
"""Modifies flags for Python versions < 3.11."""

@property
def name(self) -> str:
"""
Override the default name property to handle combined flags.
Returns
-------
combined_name : str
The combined name of the individual flags.
"""
if self._name_ is not None:
return self._name_

members = [member for member in self.__class__ if member & self == member]
return "|".join(str(m).split(".", 1)[-1] for m in members if m != 0x0)


class CommonFlags(FlagNameMixin):
"""Common quality flags."""

NONE = 0x0
INF = 2**0 # bit 0, Infinite value
NEG = 2**1 # bit 1, Negative value


class ENAFlags(FlagNameMixin):
"""Common ENA flags."""

BADSPIN = 2**2 # bit 2, Bad spin


class ImapUltraFlags(FlagNameMixin):
"""IMAP Ultra flags."""

NONE = CommonFlags.NONE
INF = CommonFlags.INF # bit 0
NEG = CommonFlags.NEG # bit 1
BADSPIN = ENAFlags.BADSPIN # bit 2
FLAG1 = 2**3 # bit 2


class ImapLoFlags(FlagNameMixin):
"""IMAP Lo flags."""

NONE = CommonFlags.NONE
INF = CommonFlags.INF # bit 0
NEG = CommonFlags.NEG # bit 1
BADSPIN = ENAFlags.BADSPIN # bit 2
FLAG2 = 2**3 # bit 2


class HitFlags(
FlagNameMixin,
):
"""Hit flags."""

NONE = CommonFlags.NONE
INF = CommonFlags.INF # bit 0
NEG = CommonFlags.NEG # bit 1
FLAG3 = 2**2 # bit 2
15 changes: 7 additions & 8 deletions imap_processing/swapi/l1/swapi_l1.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def decompress_count(
# Decompress counts based on compression indicators
# If 0, value is already decompressed. If 1, value is compressed.
# If 1 and count is 0xFFFF, value is overflow.
new_count = copy.deepcopy(count_data)
new_count = copy.deepcopy(count_data).astype(np.int32)

# If data is compressed, decompress it
compressed_indices = compression_flag == 1
Expand Down Expand Up @@ -488,17 +488,16 @@ def process_swapi_science(sci_dataset: xr.Dataset, data_version: str) -> xr.Data
)

# Add other global attributes
# TODO: add others like below once add_global_attribute is fixed
cdf_manager.add_global_attribute("Data_version", data_version)
cdf_manager.add_global_attribute(
"sweep_table", f"{sci_dataset['sweep_table'].data[0]}"
)
cdf_manager.add_global_attribute(
"plan_id", f"{sci_dataset['plan_id_science'].data[0]}"
)
l1_global_attrs = cdf_manager.get_global_attributes("imap_swapi_l1_sci")
l1_global_attrs["Sweep_table"] = f"{sci_dataset['sweep_table'].data[0]}"
l1_global_attrs["Plan_id"] = f"{sci_dataset['plan_id_science'].data[0]}"
l1_global_attrs["Apid"] = f"{sci_dataset['pkt_apid'].data[0]}"

dataset = xr.Dataset(
coords={"epoch": epoch_time, "energy": energy, "energy_label": energy_label},
attrs=cdf_manager.get_global_attributes("imap_swapi_l1_sci"),
attrs=l1_global_attrs,
)

dataset["swp_pcem_counts"] = xr.DataArray(
Expand Down
Empty file.
97 changes: 97 additions & 0 deletions imap_processing/swapi/l2/swapi_l2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
"""SWAPI L2 processing module."""

import logging

import xarray as xr

from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes

logger = logging.getLogger(__name__)


TIME_PER_BIN = 0.167 # seconds


def swapi_l2(l1_dataset: xr.Dataset, data_version: str) -> xr.Dataset:
"""
Produce science data to L2.
To process science data to L2, we need to:
- convert counts to rates. This is done by dividing the counts by the
TIME_PER_BIN time. TIME_PER_BIN is the exposure time per energy bin which is
obtained by dividing the time for one complete sweep
(12 s, coarse + fine sweep) by the total energy steps (72),
i.e., TIME_PER_BIN = 12/72 = 0.167 s. This will be constant.
- update uncertainty. Calculate new uncertainty value using
SWP_PCEM_ERR data from level one and divide by TIME_PER_BIN. Eg.
SWP_PCEM_UNC = SWP_PCEM_ERR / TIME_PER_BIN
Do the same for SCEM and COIN data.
Parameters
----------
l1_dataset : xarray.Dataset
The L1 data input.
data_version : str
Version of the data product being created.
Returns
-------
data : xarray.Dataset
Processed data to L2.
"""
# Load the CDF attributes
cdf_manager = ImapCdfAttributes()
cdf_manager.add_instrument_global_attrs("swapi")
cdf_manager.load_variable_attributes("imap_swapi_variable_attrs.yaml")

# Copy over only certain variables from L1 to L2 dataset
l1_data_keys = [
"epoch",
"energy",
"energy_label",
"swp_pcem_flags",
"swp_scem_flags",
"swp_coin_flags",
]
l2_dataset = l1_dataset[l1_data_keys]

# Update L2 specific attributes
l2_dataset.attrs["Data_version"] = data_version
l2_global_attrs = cdf_manager.get_global_attributes("imap_swapi_l2_sci")
l2_dataset.attrs["Data_level"] = l2_global_attrs["Data_level"]
l2_dataset.attrs["Data_type"] = l2_global_attrs["Data_type"]
l2_dataset.attrs["Logical_source"] = l2_global_attrs["Logical_source"]
l2_dataset.attrs["Logical_source_description"] = l2_global_attrs[
"Logical_source_description"
]

# convert counts to rate
l2_dataset["swp_pcem_rate"] = l1_dataset["swp_pcem_counts"] / TIME_PER_BIN
l2_dataset["swp_scem_rate"] = l1_dataset["swp_scem_counts"] / TIME_PER_BIN
l2_dataset["swp_coin_rate"] = l1_dataset["swp_coin_counts"] / TIME_PER_BIN
# update attrs
l2_dataset["swp_pcem_rate"].attrs = cdf_manager.get_variable_attributes("pcem_rate")
l2_dataset["swp_scem_rate"].attrs = cdf_manager.get_variable_attributes("scem_rate")
l2_dataset["swp_coin_rate"].attrs = cdf_manager.get_variable_attributes("coin_rate")

# update uncertainty
l2_dataset["swp_pcem_unc"] = l1_dataset["swp_pcem_err"] / TIME_PER_BIN
l2_dataset["swp_scem_unc"] = l1_dataset["swp_scem_err"] / TIME_PER_BIN
l2_dataset["swp_coin_unc"] = l1_dataset["swp_coin_err"] / TIME_PER_BIN
# update attrs
l2_dataset["swp_pcem_unc"].attrs = cdf_manager.get_variable_attributes(
"pcem_uncertainty"
)
l2_dataset["swp_scem_unc"].attrs = cdf_manager.get_variable_attributes(
"scem_uncertainty"
)
l2_dataset["swp_coin_unc"].attrs = cdf_manager.get_variable_attributes(
"coin_uncertainty"
)

# TODO: add thruster firing flag
# TODO: add other flags
logger.info("SWAPI L2 processing complete")

return l2_dataset
Loading

0 comments on commit 3121b00

Please sign in to comment.