Source code for swxsoc_reach.util.schema

"""
REACH-specific schema metadata derivations.

Extends :class:`~swxsoc.util.schema.SWXSchema` with REACH-specific
global and variable attribute schema layers (YAML) and custom
derivation functions.

This follows the same pattern established by the HERMES mission
in ``hermes_core.util.schema.HermesDataSchema``.
"""

from pathlib import Path
from typing import Optional

from swxsoc.util.schema import SWXSchema

import swxsoc_reach
from swxsoc_reach.util.util import create_reach_filename

__all__ = ["REACHDataSchema"]

DEFAULT_GLOBAL_CDF_ATTRS_SCHEMA_FILE = "reach_default_global_cdf_attrs_schema.yaml"
DEFAULT_VARIABLE_CDF_ATTRS_SCHEMA_FILE = "reach_default_variable_cdf_attrs_schema.yaml"


[docs] class REACHDataSchema(SWXSchema): """ Schema for REACH CDF data requirements and formatting. Layers REACH-specific global and variable attribute YAML schemas on top of the SWxSOC defaults. Overrides derivation functions for ``Logical_source`` and ``Logical_file_id`` to produce REACH-appropriate values. Parameters ---------- global_schema_layers : list[Path] or None, optional Additional global attribute schema files layered after the REACH defaults. variable_schema_layers : list[Path] or None, optional Additional variable attribute schema files layered after the REACH defaults. use_defaults : bool, optional Whether to include the SWxSOC/SAMMI base defaults (default *True*). """ def __init__( self, global_schema_layers: Optional[list[Path]] = None, variable_schema_layers: Optional[list[Path]] = None, use_defaults: Optional[bool] = True, ): # REACH Default Global Schema global_schema_path = str( Path(swxsoc_reach.__file__).parent / "data" / DEFAULT_GLOBAL_CDF_ATTRS_SCHEMA_FILE ) # REACH Default Variable Schema variable_schema_path = str( Path(swxsoc_reach.__file__).parent / "data" / DEFAULT_VARIABLE_CDF_ATTRS_SCHEMA_FILE ) # Seed Layers with Defaults if not use_defaults: _global_schema_layers = [] _variable_schema_layers = [] else: _global_schema_layers = [global_schema_path] _variable_schema_layers = [variable_schema_path] # Extend any additional caller-supplied layers if global_schema_layers is not None and len(global_schema_layers) > 0: _global_schema_layers.extend(global_schema_layers) if variable_schema_layers is not None and len(variable_schema_layers) > 0: _variable_schema_layers.extend(variable_schema_layers) # Call SWxSOC Initialization to populate Schema super().__init__( global_schema_layers=_global_schema_layers, variable_schema_layers=_variable_schema_layers, use_defaults=use_defaults, ) # ===================================================================== # GLOBAL ATTRIBUTE DERIVATION STUBS # =====================================================================
[docs] def _get_logical_source(self, data): """ Derive the ``Logical_source`` global attribute for REACH. The logical source is the combination of the data source, data type, and instrument mode. Parameters ---------- data : `~swxsoc.swxdata.SWXData` The assembled SWXData instance. Returns ------- str ``Logical_source`` value. """ attr_name = "Logical_source" if (attr_name not in data.meta) or (not data.meta[attr_name]): # Get Parts instrument_id = self._get_instrument_id(data) data_type = self._get_data_type(data) data_type_short_name, _ = data_type.split(">") instrument_mode = self._get_instrument_mode(data) # Build Derivation # reach_all_prelim logical_source = f"{instrument_id}_{instrument_mode}_{data_type_short_name}" else: logical_source = data.meta[attr_name] return logical_source
[docs] def _get_logical_file_id(self, data): """ Derive the ``Logical_file_id`` global attribute for REACH. The attribute stores the name of the CDF File without the file extension (e.g. '.cdf'). This attribute is requires to avoid loss of the originial source in case of renaming. Parameters ---------- data : `~swxsoc.swxdata.SWXData` The assembled SWXData instance. Returns ------- str ``Logical_file_id`` value (CDF filename without extension). """ attr_name = "Logical_file_id" if (attr_name not in data.meta) or (not data.meta[attr_name]): # Get Parts start_time = self._get_start_time(data) data_level = self._get_data_level(data) version = self._get_version(data) mode = self._get_instrument_mode(data) data_type = self._get_data_type(data) data_type_short_name, _ = data_type.split(">") # Build Derivation science_filename = create_reach_filename( time=start_time, level=data_level, version=version, mode=mode, descriptor=data_type_short_name, ) science_filename = science_filename.rstrip( swxsoc_reach.config["mission"]["file_extension"] ) else: science_filename = data.meta[attr_name] return science_filename
[docs] def _get_reach_version(self, data): """ Return the ``swxsoc_reach`` package version used to generate the CDF. Parameters ---------- data : `~swxsoc.swxdata.SWXData` The assembled SWXData instance. Returns ------- str Package version string. """ attr_name = "REACH_version" if attr_name in data.meta and data.meta[attr_name]: return data.meta[attr_name] return swxsoc_reach.__version__