Source code for openairclim.gui.components.utils

"""Provides utility functions for the OpenAirClim GUI."""

from pathlib import Path


# define unicode superscripts, rather than using math mode
_SUPERSCRIPTS = str.maketrans(
    "0123456789-",
    "\u2070\u00b9\u00b2\u00b3\u2074\u2075\u2076\u2077\u2078\u2079\u207b"
)

# visual style
COLORS = [
    "#2271B2", "#3DB7E9", "#F748A5", "#359B73",
    "#D55E00", "#E69F00", "#F0E442"
]
MARKERS = [
    "circle", "square", "triangle", "inverted_triangle",
    "plus", "x", "hex", "diamond",
]

[docs] def superscript(n: str): """Convert an integer to Unicode superscript characters. Args: n (int): Number to convert. Returns: str: Unicode superscript representation. """ return str(n).translate(_SUPERSCRIPTS)
[docs] def load_inventory(working_dir: str, inv_dir: str, inv_file: str): """Load a single emission inventory, promoting spatial fields to coords. Args: working_dir (str): Project working directory. inv_dir (str): Inventory subdirectory from config. inv_file (str): Inventory filename. Returns: xarray.Dataset: Loaded inventory with plev, lat, lon as coordinates. """ import xarray as xr filepath = Path(working_dir) / inv_dir / inv_file ds = xr.load_dataset(filepath) # make lat, lon and plev into coordinates for easier manipulation coord_names = [c for c in ("plev", "lat", "lon") if c in ds.data_vars] if coord_names: ds = ds.set_coords(coord_names) return ds
[docs] def get_numeric_vars(ds): """Return names of plottable numeric data variables. Allows for all numeric data within the inventories to be visualised, even if it is not used by OpenAirClim. Args: ds (xarray.Dataset): Emission inventory. Returns: list: Names of numeric data variables, excluding spatial fields and ac. """ skip = {"ac", "plev", "lat", "lon"} numeric_kinds = "iuf" # signed int, unsigned int, float return [ name for name, var in ds.data_vars.items() if name not in skip and var.dtype.kind in numeric_kinds ]
[docs] def auto_scale(max_val): """Determine a scaling factor for clean axis labels. Values in the range [0.1, 1000) are left unscaled. Otherwise, the appropriate power of 10 is extracted and returned as a label prefix using Unicode superscript characters. Args: max_val (float): Maximum value on the axis. Returns: tuple: (divisor, label_prefix) where divisor is the power of 10 to divide data by, and label_prefix is a string like ``"10\u2078 "`` or ``""`` if no scaling is needed. """ import numpy as np if max_val == 0 or not np.isfinite(max_val): return 1.0, "" exponent = int(np.floor(np.log10(abs(max_val)))) if -1 <= exponent <= 2: return 1.0, "" return 10.0 ** exponent, f"10{superscript(exponent)} "