-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' of github.com:IMAP-Science-Operations-Center/imap_processing into data-access-api
- Loading branch information
Showing
25 changed files
with
46,086 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.