Browse Source

Moved the CoordPair to a new module. Added operators for CoordPair. Fixed some missing from __future__ imports. Fixed some metadata issues due to arg name changes.

main
Bill Ladwig 9 years ago
parent
commit
bf0d26b7b0
  1. 2
      src/wrf/api.py
  2. 131
      src/wrf/coordpair.py
  3. 43
      src/wrf/metadecorators.py
  4. 10
      src/wrf/py3compat.py
  5. 51
      src/wrf/util.py

2
src/wrf/api.py

@ -17,6 +17,7 @@ from .util import (npvalues, extract_global_attrs, @@ -17,6 +17,7 @@ from .util import (npvalues, extract_global_attrs,
extract_dim, extract_vars, extract_times, combine_files,
is_staggered, get_left_indexes, iter_left_indexes,
get_right_slices, get_proj_params)
from .coordpair import CoordPair
from .version import __version__
__all__ = []
@ -39,5 +40,6 @@ __all__ += ["npvalues", "extract_global_attrs", @@ -39,5 +40,6 @@ __all__ += ["npvalues", "extract_global_attrs",
"extract_dim", "extract_vars", "extract_times", "combine_files",
"is_staggered", "get_left_indexes", "iter_left_indexes",
"get_right_slices", "get_proj_params"]
__all__ += ["CoordPair"]
__all__ += ["__version__"]

131
src/wrf/coordpair.py

@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
from __future__ import (absolute_import, division, print_function,
unicode_literals)
from .py3compat import py2round
def _binary_operator(operator):
def func(self, other):
if isinstance(other, CoordPair):
args = [
None if getattr(self, attr) is None or getattr(other, attr) is None
else getattr(getattr(self, attr), operator)(getattr(other, attr))
for attr in ("x", "y", "lat", "lon")]
else:
args = [
None if getattr(self, attr) is None
else getattr(getattr(self, attr), operator)(other)
for attr in ("x", "y", "lat", "lon")]
return CoordPair(*args)
return func
def _unary_operator(operator):
def func(self):
args = [None if getattr(self, attr) is None
else getattr(getattr(self, attr), operator)()
for attr in ("x", "y", "lat", "lon")]
return CoordPair(*args)
return func
def _cmp_operator(operator):
def func(self, other):
vals = [getattr(getattr(self, attr), operator)(getattr(other, attr))
for attr in ("x", "y", "lat", "lon")
if getattr(self, attr) is not None]
return all(vals)
return func
class CoordPair(object):
def __init__(self, x=None, y=None, lat=None, lon=None):
self.x = x
self.y = y
self.lat = lat
self.lon = lon
def __repr__(self):
args = []
if self.x is not None:
args.append("x={}".format(self.x))
args.append("y={}".format(self.y))
if self.lat is not None:
args.append("lat={}".format(self.lat))
args.append("lon={}".format(self.lon))
argstr = ", ".join(args)
return "{}({})".format(self.__class__.__name__, argstr)
def __str__(self):
return self.__repr__()
def xy_str(self, fmt="{:.4f}, {:.4f}"):
if self.x is None or self.y is None:
return None
return fmt.format(self.x, self.y)
def latlon_str(self, fmt="{:.4f}, {:.4f}"):
if self.lat is None or self.lon is None:
return None
return fmt.format(self.lat, self.lon)
def __round__(self, d=None):
args = [None if getattr(self, attr) is None
else py2round(getattr(self, attr), d)
for attr in ("x", "y", "lat", "lon")]
return CoordPair(*args)
def __pow__(self, other, modulo=None):
if isinstance(other, CoordPair):
args = [
None if getattr(self, attr) is None or getattr(other, attr) is None
else getattr(getattr(self, attr), "__pow__")(getattr(other, attr),
modulo)
for attr in ("x", "y", "lat", "lon")]
else:
args = [
None if getattr(self, attr) is None
else getattr(getattr(self, attr), "__pow__")(other, modulo)
for attr in ("x", "y", "lat", "lon")]
return CoordPair(*args)
def __rpow__(self, other):
return self.__pow__(other)
for operator in ("__add__", "__divmod__", "__floordiv__", "__mod__",
"__mul__", "__sub__", "__truediv__", "__radd__",
"__rdivmod__", "__rsub__", "__rmul__", "__rtruediv__",
"__rfloordiv__", "__rmod__"):
setattr(CoordPair, operator, _binary_operator(operator))
for operator in ("__neg__", "__pos__", "__abs__", "__invert__"):
setattr(CoordPair, operator, _unary_operator(operator))
for operator in ("__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__"):
setattr(CoordPair, operator, _cmp_operator(operator))

43
src/wrf/metadecorators.py

@ -8,8 +8,9 @@ import numpy.ma as ma @@ -8,8 +8,9 @@ import numpy.ma as ma
from .extension import _interpline
from .util import (extract_vars, combine_with, either, from_args, arg_location,
is_coordvar, latlon_coordvars, CoordPair, npvalues,
is_coordvar, latlon_coordvars, npvalues,
from_var, iter_left_indexes)
from .coordpair import CoordPair
from .py3compat import viewkeys, viewitems, py3range, ucode
from .interputils import get_xy_z_params, get_xy
from .config import xarray_enabled
@ -637,7 +638,7 @@ def _set_cross_meta(wrapped, instance, args, kwargs): @@ -637,7 +638,7 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
ed_x = xy[-1,0]
ed_y = xy[-1,1]
cross_str = "Cross-Section: ({0}, {1}) to ({2}, {3})".format(st_x, st_y,
cross_str = "({0}, {1}) to ({2}, {3})".format(st_x, st_y,
ed_x, ed_y)
if angle is not None:
cross_str += " ; center={0} ; angle={1}".format(pivot_point,
@ -726,7 +727,7 @@ def _set_cross_meta(wrapped, instance, args, kwargs): @@ -726,7 +727,7 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
outname = "field3d_cross"
outattrs = OrderedDict()
outattrs["Orientation"] = cross_str
outattrs["orientation"] = cross_str
outattrs["missing_value"] = missingval
outattrs["_FillValue"] = missingval
@ -863,7 +864,7 @@ def _set_line_meta(wrapped, instance, args, kwargs): @@ -863,7 +864,7 @@ def _set_line_meta(wrapped, instance, args, kwargs):
outname = "field2d_line"
outattrs = OrderedDict()
outattrs["Orientation"] = cross_str
outattrs["orientation"] = cross_str
return DataArray(result, name=outname, dims=outdimnames,
coords=outcoords, attrs=outattrs)
@ -933,6 +934,11 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs): @@ -933,6 +934,11 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs):
cross_str = "({0},{1}) to ({2},{3})".format(st_x, st_y,
ed_x, ed_y)
outname = None
outdimnames = None
outcoords = None
outattrs = None
# Dims are (...,xy,z)
if isinstance(field3d, DataArray):
outcoords = OrderedDict()
@ -976,56 +982,59 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs): @@ -976,56 +982,59 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs):
else:
outname = "field3d_2dxy"
outattrs["Orientation"] = cross_str
outattrs["orientation"] = cross_str
return DataArray(result, name=outname, dims=outdimnames,
coords=outcoords, attrs=outattrs)
def _set_1d_meta(wrapped, instance, args, kwargs):
argvars = from_args(wrapped, ("v_in", "z_in", "z_out", "missingval"),
argvars = from_args(wrapped, ("field", "z_in", "z_out", "missingval"),
*args, **kwargs)
v_in = argvars["v_in"]
field = argvars["field"]
z_in = argvars["z_in"]
z_out = argvars["z_out"]
missingval = argvars["missingval"]
result = wrapped(*args, **kwargs)
outname = None
outdimnames = None
outcoords = None
outattrs = None
# Dims are (...,xy,z)
if isinstance(v_in, DataArray):
if isinstance(field, DataArray):
outcoords = OrderedDict()
outattrs = OrderedDict()
outdimnames = list(v_in.dims)
#outcoords.update(v_in.coords)
outdimnames = list(field.dims)
outdimnames.pop(-1)
for name in outdimnames:
try:
outcoords[name] = v_in.coords[name]
outcoords[name] = field.coords[name]
except KeyError:
continue
outdimnames.append("z")
outname = "{0}_z".format(v_in.name)
outname = "{0}_z".format(field.name)
outcoords["z"] = z_out
#outattrs.update(v_in.attrs)
outattrs["_FillValue"] = missingval
outattrs["missing_value"] = missingval
desc = v_in.attrs.get("description", None)
desc = field.attrs.get("description", None)
if desc is not None:
outattrs["description"] = desc
units = v_in.attrs.get("units", None)
units = field.attrs.get("units", None)
if units is not None:
outattrs["units"] = units
else:
outname = "v_in_z"
outname = "field_z"
return DataArray(result, name=outname, dims=outdimnames,
@ -1049,7 +1058,7 @@ def _set_xy_meta(wrapped, instance, args, kwargs): @@ -1049,7 +1058,7 @@ def _set_xy_meta(wrapped, instance, args, kwargs):
outname = "{0}_xy".format(field.name)
else:
outname = "xy"
outdimnames = ["line_idx", "x_y"]
outcoords = OrderedDict()
outattrs = OrderedDict()

10
src/wrf/py3compat.py

@ -1,3 +1,6 @@ @@ -1,3 +1,6 @@
from __future__ import (absolute_import, division, print_function,
unicode_literals)
from sys import version_info
from math import floor, copysign
@ -30,12 +33,13 @@ def isstr(s): @@ -30,12 +33,13 @@ def isstr(s):
# Python 2 rounding behavior
def _round2(x, d=0):
def _round2(x, d=None):
d = 0 if d is None else d
p = 10 ** d
return float(floor((x * p) + copysign(0.5, x)))/p
def py2round(x, d=0):
def py2round(x, d=None):
if version_info >= (3,):
return _round2(x, d)
@ -53,4 +57,4 @@ def ucode(*args, **kwargs): @@ -53,4 +57,4 @@ def ucode(*args, **kwargs):
if version_info >= (3, ):
return str(*args, **kwargs)
return unicode(*args, **kwargs)
return unicode(*args, **kwargs)

51
src/wrf/util.py

@ -1507,56 +1507,7 @@ def get_proj_params(wrfnc, timeidx=0, varname=None): @@ -1507,56 +1507,7 @@ def get_proj_params(wrfnc, timeidx=0, varname=None):
return (wrfnc.variables[lat_coord][time_idx_or_slice,:],
wrfnc.variables[lon_coord][time_idx_or_slice,:],
proj_params)
class CoordPair(object):
def __init__(self, x=None, y=None, i=None, j=None, lat=None, lon=None):
self.x = x
self.y = y
self.i = i
self.j = j
self.lat = lat
self.lon = lon
def __repr__(self):
args = []
if self.x is not None:
args.append("x={}".format(self.x))
args.append("y={}".format(self.y))
if self.i is not None:
args.append("i={}".format(self.i))
args.append("j={}".format(self.j))
if self.lat is not None:
args.append("lat={}".format(self.lat))
args.append("lon={}".format(self.lon))
argstr = ", ".join(args)
return "{}({})".format(self.__class__.__name__, argstr)
def __str__(self):
return self.__repr__()
def xy_str(self, fmt="{:.4f}, {:.4f}"):
if self.x is None or self.y is None:
return None
return fmt.format(self.x, self.y)
def latlon_str(self, fmt="{:.4f}, {:.4f}"):
if self.lat is None or self.lon is None:
return None
return fmt.format(self.lat, self.lon)
def ij_str(self, fmt="{:.4f}, {:.4f}"):
if self.i is None or self.j is None:
return None
return fmt.format(self.i, self.j)
def from_args(func, argnames, *args, **kwargs):
"""Parses the function args and kargs looking for the desired argument
@ -1569,7 +1520,7 @@ def from_args(func, argnames, *args, **kwargs): @@ -1569,7 +1520,7 @@ def from_args(func, argnames, *args, **kwargs):
else:
arglist = argnames
result = {}
result = OrderedDict()
for argname in arglist:
arg_loc = arg_location(func, argname, args, kwargs)

Loading…
Cancel
Save