"""Funcionality for representing a physical variable in aospy."""
import numpy as np
[docs]class Var(object):
"""An object representing a physical quantity to be computed.
Attributes
----------
name : str
The variable's name
alt_names : tuple of strings
All other names that the variable may be referred to in the input data
names : tuple of strings
The combination of `name` and `alt_names`
description : str
A description of the variable
func : function
The function with which to compute the variable
variables : sequence of aospy.Var objects
The variables passed to `func` to compute it
units : str
The variable's physical units
domain : str
The physical domain of the variable, e.g. 'atmos', 'ocean', or 'land'
def_time, def_vert, def_lat, def_lon : bool
Whether the variable is defined, respectively, in time, vertically, in
latitude, and in longitude
math_str : str
The mathematical representation of the variable
colormap : str
The name of the default colormap to be used in plots of this variable
valid_range : length-2 tuple
The range of values outside which to flag as unphysical/erroneous
"""
[docs] def __init__(self, name, alt_names=None, func=None, variables=None,
units='', plot_units='', plot_units_conv=1, domain='atmos',
description='', def_time=False, def_vert=False, def_lat=False,
def_lon=False, math_str=False, colormap='RdBu_r',
valid_range=None):
"""Instantiate a Var object.
Parameters
----------
name : str
The variable's name
alt_names : tuple of strings
All other names that the variable might be referred to in any input
data. Each of these should be unique to this variable in order to
avoid loading the wrong quantity.
description : str
A description of the variable
func : function
The function with which to compute the variable
variables : sequence of aospy.Var objects
The variables passed to `func` to compute it. Order matters:
whenever calculations are performed to generate data corresponding
to this Var, the data corresponding to the elements of `variables`
will be passed to `self.function` in the same order.
units : str
The variable's physical units
domain : str
The physical domain of the variable, e.g. 'atmos', 'ocean', or
'land'. This is only used by aospy by some types of `DataLoader`,
including `GFDLDataLoader`.
def_time, def_vert, def_lat, def_lon : bool
Whether the variable is defined, respectively, in time, vertically,
in latitude, and in longitude
math_str : str
The mathematical representation of the variable. This is typically
a raw string of LaTeX math-mode, e.g. r'$T_\mathrm{sfc}$' for
surface temperature.
colormap : str
(Currently not used by aospy) The name of the default colormap to
be used in plots of this variable.
valid_range : length-2 tuple
The range of values outside which to flag as unphysical/erroneous
""" # noqa: W605
self.name = name
if alt_names is None:
self.names = tuple([name])
else:
self.alt_names = alt_names
self.names = tuple([name] + list(alt_names))
if func is None:
self.func = lambda x: x
self.variables = None
else:
self.func = func
self.variables = variables
self.units = units
if not description:
if self.func.__doc__ is None:
self.description = ''
else:
self.description = self.func.__doc__
else:
self.description = description
self.domain = domain
self.def_time = def_time
self.def_vert = def_vert
self.def_lat = def_lat
self.def_lon = def_lon
self.math_str = math_str
self.colormap = colormap
self.valid_range = valid_range
def __str__(self):
return 'Var instance "' + self.name + '"'
__repr__ = __str__
[docs] def to_plot_units(self, data, dtype_vert=False):
"""Convert the given data to plotting units."""
if dtype_vert == 'vert_av' or not dtype_vert:
conv_factor = self.units.plot_units_conv
elif dtype_vert == ('vert_int'):
conv_factor = self.units.vert_int_plot_units_conv
else:
raise ValueError("dtype_vert value `{0}` not recognized. Only "
"bool(dtype_vert) = False, 'vert_av', and "
"'vert_int' supported.".format(dtype_vert))
if isinstance(data, dict):
return {key: val*conv_factor for key, val in data.items()}
return data*conv_factor
[docs] def mask_unphysical(self, data):
"""Mask data array where values are outside physically valid range."""
if not self.valid_range:
return data
else:
return np.ma.masked_outside(data, np.min(self.valid_range),
np.max(self.valid_range))