Browse Source

Added projection support. Added configuration to allow cartopy, basemap, xarray, etc to be optional. Began adding metadata support.

main
Bill Ladwig 9 years ago
parent
commit
a887fa1a44
  1. 60
      wrf_open/var/src/python/wrf/var/__init__.py
  2. 4
      wrf_open/var/src/python/wrf/var/cape.py
  3. 81
      wrf_open/var/src/python/wrf/var/config.py
  4. 4
      wrf_open/var/src/python/wrf/var/constants.py
  5. 4
      wrf_open/var/src/python/wrf/var/ctt.py
  6. 2
      wrf_open/var/src/python/wrf/var/dbz.py
  7. 138
      wrf_open/var/src/python/wrf/var/decorators.py
  8. 4
      wrf_open/var/src/python/wrf/var/dewpoint.py
  9. 324
      wrf_open/var/src/python/wrf/var/extension.py
  10. 4
      wrf_open/var/src/python/wrf/var/geoht.py
  11. 20
      wrf_open/var/src/python/wrf/var/helicity.py
  12. 2
      wrf_open/var/src/python/wrf/var/interp.py
  13. 16
      wrf_open/var/src/python/wrf/var/latlon.py
  14. 3
      wrf_open/var/src/python/wrf/var/omega.py
  15. 6
      wrf_open/var/src/python/wrf/var/precip.py
  16. 4
      wrf_open/var/src/python/wrf/var/pressure.py
  17. 748
      wrf_open/var/src/python/wrf/var/projection.py
  18. BIN
      wrf_open/var/src/python/wrf/var/psadlookup.pyc
  19. 4
      wrf_open/var/src/python/wrf/var/pw.py
  20. 4
      wrf_open/var/src/python/wrf/var/rh.py
  21. 2
      wrf_open/var/src/python/wrf/var/slp.py
  22. 13
      wrf_open/var/src/python/wrf/var/temp.py
  23. 4
      wrf_open/var/src/python/wrf/var/terrain.py
  24. 309
      wrf_open/var/src/python/wrf/var/util.py
  25. 28
      wrf_open/var/src/python/wrf/var/uvmet.py
  26. 4
      wrf_open/var/src/python/wrf/var/vorticity.py
  27. 214
      wrf_open/var/test/projtest.py
  28. 2
      wrf_open/var/test/utests.py

60
wrf_open/var/src/python/wrf/var/__init__.py

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
import warnings
from config import *
import config
from extension import *
import extension
from util import *
@ -54,35 +56,39 @@ from times import * @@ -54,35 +56,39 @@ from times import *
import times
from units import *
import units
from projection import *
import projection
__all__ = ["getvar"]
__all__ += extension.__all__
__all__ += util.__all__
__all__ += cape.__all__
__all__ += constants.__all__
__all__ += ctt.__all__
__all__ += dbz.__all__
__all__ += destag.__all__
__all__ += dewpoint.__all__
__all__ += etaconv.__all__
__all__ += geoht.__all__
__all__ += helicity.__all__
__all__ += interp.__all__
__all__ += latlon.__all__
__all__ += omega.__all__
__all__ += precip.__all__
__all__ += psadlookup.__all__
__all__ += pw.__all__
__all__ += rh.__all__
__all__ += slp.__all__
__all__ += temp.__all__
__all__ += terrain.__all__
__all__ += uvmet.__all__
__all__ += vorticity.__all__
__all__ += wind.__all__
__all__ += times.__all__
__all__ += pressure.__all__
__all__ += units.__all__
__all__.extend(config.__all__)
__all__.extend( extension.__all__)
__all__.extend(util.__all__)
__all__.extend(cape.__all__)
__all__.extend(constants.__all__)
__all__.extend(ctt.__all__)
__all__.extend(dbz.__all__)
__all__.extend(destag.__all__)
__all__.extend(dewpoint.__all__)
__all__.extend(etaconv.__all__)
__all__.extend(geoht.__all__)
__all__.extend(helicity.__all__)
__all__.extend(interp.__all__)
__all__.extend(latlon.__all__)
__all__.extend(omega.__all__)
__all__.extend(precip.__all__)
__all__.extend(psadlookup.__all__)
__all__.extend(pw.__all__)
__all__.extend(rh.__all__)
__all__.extend(slp.__all__)
__all__.extend(temp.__all__)
__all__.extend(terrain.__all__)
__all__.extend(uvmet.__all__)
__all__.extend(vorticity.__all__)
__all__.extend(wind.__all__)
__all__.extend(times.__all__)
__all__.extend(pressure.__all__)
__all__.extend(units.__all__)
__all__.extend(projection.__all__)
# func is the function to call. kargs are required arguments that should
# not be altered by the user

4
wrf_open/var/src/python/wrf/var/cape.py

@ -10,7 +10,7 @@ __all__ = ["get_2dcape", "get_3dcape"] @@ -10,7 +10,7 @@ __all__ = ["get_2dcape", "get_3dcape"]
def get_2dcape(wrfnc, timeidx=0, missing=Constants.DEFAULT_FILL):
"""Return the 2d fields of cape, cin, lcl, and lfc"""
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "PB", "QVAPOR", "PH",
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "PB", "QVAPOR", "PH",
"PHB", "HGT", "PSFC"))
t = ncvars["T"]
@ -63,7 +63,7 @@ def get_2dcape(wrfnc, timeidx=0, missing=Constants.DEFAULT_FILL): @@ -63,7 +63,7 @@ def get_2dcape(wrfnc, timeidx=0, missing=Constants.DEFAULT_FILL):
def get_3dcape(wrfnc, timeidx=0, missing=Constants.DEFAULT_FILL):
"""Return the 3d fields of cape and cin"""
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "PB", "QVAPOR",
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "PB", "QVAPOR",
"PH", "PHB", "HGT", "PSFC"))
t = ncvars["T"]
p = ncvars["P"]

81
wrf_open/var/src/python/wrf/var/config.py

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
try:
from xarray import DataArray
except ImportError:
_XARRAY_ENABLED = False
else:
_XARRAY_ENABLED = True
try:
from cartopy import crs
except ImportError:
_CARTOPY_ENABLED = False
else:
_CARTOPY_ENABLED = True
try:
from mpl_toolkits.basemap import Basemap
except ImportError:
_BASEMAP_ENABLED = False
else:
_BASEMAP_ENABLED = True
try:
from Ngl import Resources
except ImportError:
_PYNGL_ENABLED = False
else:
_PYNGL_ENABLED = True
__all__ = ["xarray_enabled", "disable_xarray", "enable_xarray",
"cartopy_enabled", "enable_cartopy", "enable_cartopy",
"basemap_enabled", "disable_basemap", "enable_basemap",
"pyngl_enabled", "enable_pyngl", "disable_pyngl"]
def xarray_enabled():
global _XARRAY_ENABLED
return _XARRAY_ENABLED
def disable_xarray():
global _XARRAY_ENABLED
_XARRAY_ENABLED = False
def enable_xarray():
global _XARRAY_ENABLED
_XARRAY_ENABLED = True
def cartopy_enabled():
global _CARTOPY_ENABLED
return _CARTOPY_ENABLED
def enable_cartopy():
global _CARTOPY_ENABLED
_CARTOPY_ENABLED = True
def disable_cartopy():
global _CARTOPY_ENABLED
_CARTOPY_ENABLED = True
def basemap_enabled():
global _BASEMAP_ENABLED
return _BASEMAP_ENABLED
def enable_basemap():
global _BASEMAP_ENABLED
_BASEMAP_ENABLED = True
def disable_basemap():
global _BASEMAP_ENABLED
_BASEMAP_ENABLED = True
def pyngl_enabled():
global _PYNGL_ENABLED
return _PYNGL_ENABLED
def enable_pyngl():
global _PYNGL_ENABLED
_PYNGL_ENABLED = True
def disable_pyngl():
global _PYNGL_ENABLED
_PYNGL_ENABLED = True

4
wrf_open/var/src/python/wrf/var/constants.py

@ -7,9 +7,9 @@ class Constants(object): @@ -7,9 +7,9 @@ class Constants(object):
G = 9.81
TCK0 = 273.15
T_BASE = 300.0 # In WRF the base temperature is always 300 (not var T00)
PI = 3.14159265
PI = 3.141592653589793
DEFAULT_FILL = 9.9692099683868690e+36 # Value is from netcdf.h
WRF_EARTH_RADIUS = 6370000.
class ConversionFactors(object):
PA_TO_HPA = .01

4
wrf_open/var/src/python/wrf/var/ctt.py

@ -14,8 +14,8 @@ def get_ctt(wrfnc, timeidx=0, units="c"): @@ -14,8 +14,8 @@ def get_ctt(wrfnc, timeidx=0, units="c"):
"""Return the cloud top temperature.
"""
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "PB", "PH" ,"PHB",
"HGT", "QVAPOR"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "PB", "PH" ,
"PHB", "HGT", "QVAPOR"))
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]

2
wrf_open/var/src/python/wrf/var/dbz.py

@ -17,7 +17,7 @@ def get_dbz(wrfnc, timeidx=0, do_varint=False, do_liqskin=False): @@ -17,7 +17,7 @@ def get_dbz(wrfnc, timeidx=0, do_varint=False, do_liqskin=False):
as liquid)
"""
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "PB", "QVAPOR",
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "PB", "QVAPOR",
"QRAIN"))
t = ncvars["T"]
p = ncvars["P"]

138
wrf_open/var/src/python/wrf/var/decorators.py

@ -7,41 +7,65 @@ import numpy.ma as ma @@ -7,41 +7,65 @@ import numpy.ma as ma
from wrf.var.units import do_conversion, check_units
from wrf.var.destag import destagger
from wrf.var.util import iter_left_indexes
from wrf.var.config import xarray_enabled
__all__ = ["convert_units", "handle_left_iter", "uvmet_left_iter",
"handle_casting"]
if xarray_enabled():
from xarray import DataArray
def convert_units(unit_type, alg_unit):
"""A decorator that applies unit conversion to a function's output array.
Arguments:
- unit_type - the unit type category (wind, pressure, etc)
- alg_unit - the units that the function returns by default
__all__ = ["convert_units", "handle_left_iter", "uvmet_left_iter",
"handle_casting" "set_metadata"]
# TODO: In python 3.x, getargspec is deprecated
class from_args(object):
def __init__(self, argname):
self.argname
def __call__(self, func, *args, **kargs):
"""Parses the function args and kargs looking for the desired argument
value. Otherwise, the value is taken from the default keyword argument
using the arg spec.
"""
def convert_decorator(func):
@wraps(func)
def func_wrapper(*args, **kargs):
# If units are provided to the method call, use them.
# Otherwise, need to parse the argspec to find what the default
# value is since wraps does not preserve this.
argspec = getargspec(func)
if self.argname not in argspec.args and self.argname not in kargs:
return None
try:
unit_idx = argspec.args.index("units")
result_idx = argspec.args.index(self.argname)
except ValueError:
unit_idx = None
result_idx = None
if ("units" in kargs):
desired_units = kargs["units"]
elif (len(args) > unit_idx and unit_idx is not None):
desired_units = args[unit_idx]
if (self.argname in kargs):
result = kargs[self.argname]
elif (len(args) > result_idx and result_idx is not None):
result = args[result_idx]
else:
arg_idx_from_right = (len(argspec.args) -
argspec.args.index(self.argname))
result = argspec.defaults[-arg_idx_from_right]
return result
arg_idx_from_right = (len(argspec.args)
- argspec.args.index("units"))
desired_units = argspec.defaults[-arg_idx_from_right]
def convert_units(unit_type, alg_unit):
"""A decorator that applies unit conversion to a function's output array.
Arguments:
- unit_type - the unit type category (wind, pressure, etc)
- alg_unit - the units that the function returns by default
"""
def convert_decorator(func):
@wraps(func)
def func_wrapper(*args, **kargs):
desired_units = from_args("units")(func, *args, **kargs)
check_units(desired_units, unit_type)
# Unit conversion done here
@ -59,7 +83,7 @@ def _calc_out_dims(outvar, left_dims): @@ -59,7 +83,7 @@ def _calc_out_dims(outvar, left_dims):
def handle_left_iter(ref_var_expected_dims, ref_var_idx=-1,
ref_var_name=None,
ignore_args=(), ignore_kargs=()):
ignore_args=None, ignore_kargs=None):
"""Decorator to handle iterating over leftmost dimensions when using
multiple files and/or multiple times.
@ -84,6 +108,8 @@ def handle_left_iter(ref_var_expected_dims, ref_var_idx=-1, @@ -84,6 +108,8 @@ def handle_left_iter(ref_var_expected_dims, ref_var_idx=-1,
def indexing_decorator(func):
@wraps(func)
def func_wrapper(*args, **kargs):
ignore_args = ignore_args if ignore_args is not None else ()
ignore_kargs = ignore_kargs if ignore_kargs is not None else ()
if ref_var_idx >= 0:
ref_var = args[ref_var_idx]
@ -254,7 +280,7 @@ def uvmet_left_iter(): @@ -254,7 +280,7 @@ def uvmet_left_iter():
return indexing_decorator
def handle_casting(ref_idx=0, arg_idxs=(), karg_names=(),dtype=n.float64):
def handle_casting(ref_idx=0, arg_idxs=None, karg_names=None, dtype=n.float64):
"""Decorator to handle casting to/from required dtype used in
numerical routine.
@ -262,6 +288,9 @@ def handle_casting(ref_idx=0, arg_idxs=(), karg_names=(),dtype=n.float64): @@ -262,6 +288,9 @@ def handle_casting(ref_idx=0, arg_idxs=(), karg_names=(),dtype=n.float64):
def cast_decorator(func):
@wraps(func)
def func_wrapper(*args, **kargs):
arg_idxs = arg_idxs if arg_idxs is not None else ()
karg_names = karg_names if karg_names is not None else ()
orig_type = args[ref_idx].dtype
new_args = [arg.astype(dtype)
@ -272,7 +301,6 @@ def handle_casting(ref_idx=0, arg_idxs=(), karg_names=(),dtype=n.float64): @@ -272,7 +301,6 @@ def handle_casting(ref_idx=0, arg_idxs=(), karg_names=(),dtype=n.float64):
if key in karg_names else val)
for key,val in kargs.iteritems()}
res = func(*new_args, **new_kargs)
if isinstance(res, n.ndarray):
@ -288,4 +316,70 @@ def handle_casting(ref_idx=0, arg_idxs=(), karg_names=(),dtype=n.float64): @@ -288,4 +316,70 @@ def handle_casting(ref_idx=0, arg_idxs=(), karg_names=(),dtype=n.float64):
return cast_decorator
def _extract_and_transpose(arg):
if xarray_enabled():
if isinstance(arg, DataArray):
arg = arg.values
if isinstance(arg, n.ndarray):
if not arg.flags.F_CONTIGUOUS:
return arg.T
return arg
def handle_extract_transpose():
"""Decorator to extract the data array from a DataArray and also
transposes if the data is not fortran contiguous.
"""
def extract_transpose_decorator(func):
@wraps(func)
def func_wrapper(*args, **kargs):
new_args = [_extract_and_transpose(arg) for arg in args]
new_kargs = {key:_extract_and_transpose(val)
for key,val in kargs.iteritems()}
res = func(*new_args, **new_kargs)
if isinstance(res, n.ndarray):
if res.flags.F_CONTIGUOUS:
return res.T
else:
return tuple(x.T if x.flags.F_CONTIGUOUS else x for x in res)
return res
return func_wrapper
return extract_transpose_decorator
def set_metadata(copy_from=None, ignore=None, **fixed_kargs):
"""Decorator to set the attributes for a WRF method.
"""
def attr_decorator(func):
@wraps(func)
def func_wrapper(*args, **kargs):
if not xarray_enabled():
return func(*args, **kargs)
result = func(*args, **kargs)
units = from_args("units")(func, *args, **kargs)
if units is not None:
result.attrs["units"] = units
for argname, val in fixed_kargs.iteritems():
result[argname] = val
return result
return func_wrapper
return attr_decorator

4
wrf_open/var/src/python/wrf/var/dewpoint.py

@ -7,7 +7,7 @@ __all__ = ["get_dp", "get_dp_2m"] @@ -7,7 +7,7 @@ __all__ = ["get_dp", "get_dp_2m"]
@convert_units("temp", "c")
def get_dp(wrfnc, timeidx=0, units="c"):
ncvars = extract_vars(wrfnc, timeidx, vars=("P", "PB", "QVAPOR"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("P", "PB", "QVAPOR"))
p = ncvars["P"]
pb = ncvars["PB"]
@ -22,7 +22,7 @@ def get_dp(wrfnc, timeidx=0, units="c"): @@ -22,7 +22,7 @@ def get_dp(wrfnc, timeidx=0, units="c"):
@convert_units("temp", "c")
def get_dp_2m(wrfnc, timeidx=0, units="c"):
ncvars = extract_vars(wrfnc, timeidx, vars=("PSFC", "Q2"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("PSFC", "Q2"))
# Algorithm requires hPa
psfc = .01*(ncvars["PSFC"])

324
wrf_open/var/src/python/wrf/var/extension.py

@ -12,7 +12,7 @@ from wrf.var._wrfext import (f_interpz3d, f_interp2dxy,f_interp1d, @@ -12,7 +12,7 @@ from wrf.var._wrfext import (f_interpz3d, f_interp2dxy,f_interp1d,
f_monotonic, f_filter2d, f_vintrp)
from wrf.var._wrfcape import f_computecape
from wrf.var.decorators import (handle_left_iter, uvmet_left_iter,
handle_casting)
handle_casting, handle_extract_transpose)
__all__ = ["FortranException", "computeslp", "computetk", "computetd",
"computerh", "computeavo", "computepvo", "computeeth",
@ -26,21 +26,24 @@ class FortranException(Exception): @@ -26,21 +26,24 @@ class FortranException(Exception):
@handle_left_iter(3,0, ignore_args=(2,3))
@handle_casting(arg_idxs=(0,1))
@handle_extract_transpose()
def interpz3d(data3d,zdata,desiredloc,missingval):
res = f_interpz3d(data3d.T,
zdata.T,
res = f_interpz3d(data3d,
zdata,
desiredloc,
missingval)
return res.T
return res
@handle_left_iter(3,0)
@handle_casting(arg_idxs=(0,1))
@handle_extract_transpose()
def interp2dxy(data3d,xy):
res = f_interp2dxy(data3d.T,
xy.T)
return res.T
res = f_interp2dxy(data3d,
xy)
return res
@handle_casting(arg_idxs=(0,1,2))
@handle_extract_transpose()
def interp1d(v_in,z_in,z_out,missingval):
res = f_interp1d(v_in,
z_in,
@ -51,113 +54,121 @@ def interp1d(v_in,z_in,z_out,missingval): @@ -51,113 +54,121 @@ def interp1d(v_in,z_in,z_out,missingval):
@handle_left_iter(3,0)
@handle_casting(arg_idxs=(0,1,2,3))
@handle_extract_transpose()
def computeslp(z,t,p,q):
t_surf = n.zeros((z.shape[-2], z.shape[-1]), "float64")
t_sea_level = n.zeros((z.shape[-2], z.shape[-1]), "float64")
level = n.zeros((z.shape[-2], z.shape[-1]), "int32")
res = f_computeslp(z.T,
t.T,
p.T,
q.T,
t_sea_level.T,
t_surf.T,
level.T,
t_surf = n.zeros((z.shape[-2], z.shape[-1]), "float64", order="F")
t_sea_level = n.zeros((z.shape[-2], z.shape[-1]), "float64", order="F")
level = n.zeros((z.shape[-2], z.shape[-1]), "int32", order="F")
res = f_computeslp(z,
t,
p,
q,
t_sea_level, # Should come in with fortran ordering
t_surf,
level,
FortranException())
return res.T
return res
@handle_left_iter(3,0)
@handle_casting(arg_idxs=(0,1))
@handle_extract_transpose()
def computetk(pres, theta):
# No need to transpose here since operations on 1D array
shape = pres.shape
res = f_computetk(pres.flatten("A"),
theta.flatten("A"))
res = n.reshape(res, shape, "A")
res = f_computetk(pres.ravel(order="A"),
theta.ravel(order="A"))
res = n.reshape(res, shape)
return res
# Note: No left iteration decorator needed with 1D arrays
@handle_casting(arg_idxs=(0,1))
@handle_extract_transpose()
def computetd(pressure,qv_in):
shape = pressure.shape
res = f_computetd(pressure.flatten("A"),
qv_in.flatten("A"))
res = n.reshape(res, shape, "A")
res = f_computetd(pressure.ravel(order="A"),
qv_in.ravel(order="A"))
res = n.reshape(res, shape)
return res
# Note: No decorator needed with 1D arrays
@handle_casting(arg_idxs=(0,1,2))
@handle_extract_transpose()
def computerh(qv,q,t):
shape = qv.shape
res = f_computerh(qv.flatten("A"),
q.flatten("A"),
t.flatten("A"))
res = n.reshape(res, shape, "A")
res = f_computerh(qv.ravel(order="A"),
q.ravel(order="A"),
t.ravel(order="A"))
res = n.reshape(res, shape)
return res
@handle_left_iter(3,0, ignore_args=(6,7))
@handle_casting(arg_idxs=(0,1,2,3,4,5))
@handle_extract_transpose()
def computeavo(u,v,msfu,msfv,msfm,cor,dx,dy):
res = f_computeabsvort(u.T,
v.T,
msfu.T,
msfv.T,
msfm.T,
cor.T,
res = f_computeabsvort(u,
v,
msfu,
msfv,
msfm,
cor,
dx,
dy)
return res.T
return res
@handle_left_iter(3,2, ignore_args=(8,9))
@handle_casting(arg_idxs=(0,1,2,3,4,5,6,7))
@handle_extract_transpose()
def computepvo(u,v,theta,prs,msfu,msfv,msfm,cor,dx,dy):
res = f_computepvo(u.T,
v.T,
theta.T,
prs.T,
msfu.T,
msfv.T,
msfm.T,
cor.T,
res = f_computepvo(u,
v,
theta,
prs,
msfu,
msfv,
msfm,
cor,
dx,
dy)
return res.T
return res
@handle_left_iter(3,0)
@handle_casting(arg_idxs=(0,1,2))
@handle_extract_transpose()
def computeeth(qv, tk, p):
res = f_computeeth(qv.T,
tk.T,
p.T)
res = f_computeeth(qv,
tk,
p)
return res.T
return res
@uvmet_left_iter()
@handle_casting(arg_idxs=(0,1,2,3))
@handle_extract_transpose()
def computeuvmet(u,v,lat,lon,cen_long,cone):
longca = n.zeros((lat.shape[-2], lat.shape[-1]), "float64")
longcb = n.zeros((lon.shape[-2], lon.shape[-1]), "float64")
longca = n.zeros((lat.shape[-2], lat.shape[-1]), "float64", order="F")
longcb = n.zeros((lon.shape[-2], lon.shape[-1]), "float64", order="F")
rpd = Constants.PI/180.
# Make the 2D array a 3D array with 1 dimension
if u.ndim < 3:
u = u.reshape((1,u.shape[-2], u.shape[-1]))
v = v.reshape((1,v.shape[-2], v.shape[-1]))
u = u.reshape((u.shape[-2], u.shape[-1], 1), order="F")
v = v.reshape((v.shape[-2], v.shape[-1], 1), order="F")
# istag will always be false since winds are destaggered already
# Missing values don't appear to be used, so setting to 0
res = f_computeuvmet(u.T,
v.T,
longca.T,
longcb.T,
lon.T,
lat.T,
res = f_computeuvmet(u,
v,
longca,
longcb,
lon,
lat,
cen_long,
cone,
rpd,
@ -168,113 +179,123 @@ def computeuvmet(u,v,lat,lon,cen_long,cone): @@ -168,113 +179,123 @@ def computeuvmet(u,v,lat,lon,cen_long,cone):
0)
return n.squeeze(res.T)
return n.squeeze(res)
@handle_left_iter(3,0)
@handle_casting(arg_idxs=(0,1,2,3))
@handle_extract_transpose()
def computeomega(qv, tk, w, p):
res = f_computeomega(qv.T,
tk.T,
w.T,
p.T)
res = f_computeomega(qv,
tk,
w,
p)
#return res.T
return res.T
return res
@handle_left_iter(3,0)
@handle_casting(arg_idxs=(0,1))
@handle_extract_transpose()
def computetv(tk,qv):
res = f_computetv(tk.T,
qv.T)
res = f_computetv(tk,
qv)
return res.T
return res
@handle_left_iter(3,0)
@handle_casting(arg_idxs=(0,1,2))
@handle_extract_transpose()
def computewetbulb(p,tk,qv):
PSADITHTE, PSADIPRS, PSADITMK = get_lookup_tables()
PSADITMK = PSADITMK.T
res = f_computewetbulb(p.T,
tk.T,
qv.T,
res = f_computewetbulb(p,
tk,
qv,
PSADITHTE,
PSADIPRS,
PSADITMK.T,
PSADITMK,
FortranException())
return res.T
return res
@handle_left_iter(3,0, ignore_args=(4,))
@handle_casting(arg_idxs=(0,1,2,3))
@handle_extract_transpose()
def computesrh(u, v, z, ter, top):
res = f_computesrh(u.T,
v.T,
z.T,
ter.T,
res = f_computesrh(u,
v,
z,
ter,
top)
return res.T
return res
@handle_left_iter(3,2, ignore_args=(5,6,7,8))
@handle_casting(arg_idxs=(0,1,2,3,4))
@handle_extract_transpose()
def computeuh(zp, mapfct, u, v, wstag, dx, dy, bottom, top):
tem1 = n.zeros((u.shape[-3],u.shape[-2],u.shape[-1]), "float64")
tem2 = n.zeros((u.shape[-3],u.shape[-2],u.shape[-1]), "float64")
tem1 = n.zeros((u.shape[-3],u.shape[-2],u.shape[-1]), "float64", order="F")
tem2 = n.zeros((u.shape[-3],u.shape[-2],u.shape[-1]), "float64", order="F")
res = f_computeuh(zp.T,
mapfct.T,
res = f_computeuh(zp,
mapfct,
dx,
dy,
bottom,
top,
u.T,
v.T,
wstag.T,
tem1.T,
tem2.T)
u,
v,
wstag,
tem1,
tem2)
return res.T
return res
@handle_left_iter(3,0)
@handle_casting(arg_idxs=(0,1,2,3))
@handle_extract_transpose()
def computepw(p,tv,qv,ht):
# Note, dim -3 is height, we only want y and x
zdiff = n.zeros((p.shape[-2], p.shape[-1]), "float64")
res = f_computepw(p.T,
tv.T,
qv.T,
ht.T,
zdiff.T)
zdiff = n.zeros((p.shape[-2], p.shape[-1]), "float64", order="F")
res = f_computepw(p,
tv,
qv,
ht,
zdiff)
return res.T
return res
@handle_left_iter(3,0, ignore_args=(6,7,8))
@handle_casting(arg_idxs=(0,1,2,3,4,5))
@handle_extract_transpose()
def computedbz(p,tk,qv,qr,qs,qg,sn0,ivarint,iliqskin):
res = f_computedbz(p.T,
tk.T,
qv.T,
qr.T,
qs.T,
qg.T,
res = f_computedbz(p,
tk,
qv,
qr,
qs,
qg,
sn0,
ivarint,
iliqskin)
return res.T
return res
@handle_left_iter(3,0,ignore_args=(6,7,8))
@handle_casting(arg_idxs=(0,1,2,3,4,5))
@handle_extract_transpose()
def computecape(p_hpa,tk,qv,ht,ter,sfp,missing,i3dflag,ter_follow):
flip_cape = n.zeros((p_hpa.shape[-3],p_hpa.shape[-2],p_hpa.shape[-1]),
"float64")
"float64", order="F")
flip_cin = n.zeros((p_hpa.shape[-3],p_hpa.shape[-2],p_hpa.shape[-1]),
"float64")
"float64", order="F")
PSADITHTE, PSADIPRS, PSADITMK = get_lookup_tables()
PSADITMK = PSADITMK.T
# The fortran routine needs pressure to be ascending in z-direction,
# along with tk,qv,and ht.
@ -283,17 +304,17 @@ def computecape(p_hpa,tk,qv,ht,ter,sfp,missing,i3dflag,ter_follow): @@ -283,17 +304,17 @@ def computecape(p_hpa,tk,qv,ht,ter,sfp,missing,i3dflag,ter_follow):
flip_qv = qv[::-1,:,:]
flip_ht = ht[::-1,:,:]
f_computecape(flip_p.T,
flip_tk.T,
flip_qv.T,
flip_ht.T,
ter.T,
sfp.T,
flip_cape.T,
flip_cin.T,
f_computecape(flip_p,
flip_tk,
flip_qv,
flip_ht,
ter,
sfp,
flip_cape,
flip_cin,
PSADITHTE,
PSADIPRS,
PSADITMK.T,
PSADITMK,
missing,
i3dflag,
ter_follow,
@ -304,7 +325,6 @@ def computecape(p_hpa,tk,qv,ht,ter,sfp,missing,i3dflag,ter_follow): @@ -304,7 +325,6 @@ def computecape(p_hpa,tk,qv,ht,ter,sfp,missing,i3dflag,ter_follow):
cape = flip_cape[::-1,:,:]
cin = flip_cin[::-1,:,:]
return (cape, cin)
# TODO: This should handle lists of coords
@ -333,37 +353,40 @@ def computell(map_proj,truelat1,truelat2,stdlon,lat1,lon1, @@ -333,37 +353,40 @@ def computell(map_proj,truelat1,truelat2,stdlon,lat1,lon1,
@handle_left_iter(3,0, ignore_args=(3,))
@handle_casting(arg_idxs=(0,1,2))
@handle_extract_transpose()
def computeeta(full_t, znu, psfc, ptop):
pcalc = n.zeros(full_t.shape, "float64")
mean_t = n.zeros(full_t.shape, "float64")
temp_t = n.zeros(full_t.shape, "float64")
pcalc = n.zeros(full_t.shape, "float64", order="F")
mean_t = n.zeros(full_t.shape, "float64", order="F")
temp_t = n.zeros(full_t.shape, "float64", order="F")
res = f_converteta(full_t.T,
znu.T,
psfc.T,
res = f_converteta(full_t,
znu,
psfc,
ptop,
pcalc.T,
mean_t.T,
temp_t.T)
pcalc,
mean_t,
temp_t)
return res.T
return res
@handle_left_iter(3,0,ignore_args=(7,))
@handle_casting(arg_idxs=(0,1,2,3,4,5,6))
@handle_extract_transpose()
def computectt(p_hpa,tk,qice,qcld,qv,ght,ter,haveqci):
res = f_computectt(p_hpa.T,
tk.T,
qice.T,
qcld.T,
qv.T,
ght.T,
ter.T,
res = f_computectt(p_hpa,
tk,
qice,
qcld,
qv,
ght,
ter,
haveqci)
return res.T
return res
@handle_left_iter(2,0,ignore_args=(1,))
@handle_casting(arg_idxs=(0,))
@handle_extract_transpose()
def smooth2d(field, passes):
# Unlike NCL, this routine will not modify the values in place, but
# copies the original data before modifying it. This allows the decorator
@ -375,10 +398,10 @@ def smooth2d(field, passes): @@ -375,10 +398,10 @@ def smooth2d(field, passes):
missing = Constants.DEFAULT_FILL
field_copy = field.copy()
field_tmp = n.zeros(field_copy.shape, field_copy.dtype)
field_tmp = n.zeros(field_copy.shape, field_copy.dtype, order="F")
f_filter2d(field_copy.T,
field_tmp.T,
f_filter2d(field_copy,
field_tmp,
missing,
passes)
@ -388,32 +411,33 @@ def smooth2d(field, passes): @@ -388,32 +411,33 @@ def smooth2d(field, passes):
@handle_left_iter(3,0,ignore_args=(3,4,5))
@handle_casting(arg_idxs=(0,1,2))
@handle_extract_transpose()
def monotonic(var,lvprs,coriolis,idir,delta,icorsw):
res = f_monotonic(var.T,
lvprs.T,
coriolis.T,
res = f_monotonic(var,
lvprs,
coriolis,
idir,
delta,
icorsw)
return res.T
return res
# TODO: Check those decorators, they might be wrong
@handle_left_iter(3,0,ignore_args=(9,10,11,12,13,14))
@handle_casting(arg_idxs=(0,1,2,3,4,5,6,7,8,9))
@handle_extract_transpose()
def vintrp(field,pres,tk,qvp,ght,terrain,sfp,smsfp,
vcarray,interp_levels,icase,extrap,vcor,logp,
missing):
res = f_vintrp(field.T,
pres.T,
tk.T,
qvp.T,
ght.T,
terrain.T,
sfp.T,
smsfp.T,
vcarray.T,
res = f_vintrp(field,
pres,
tk,
qvp,
ght,
terrain,
sfp,
smsfp,
vcarray,
interp_levels,
icase,
extrap,
@ -421,7 +445,7 @@ def vintrp(field,pres,tk,qvp,ght,terrain,sfp,smsfp, @@ -421,7 +445,7 @@ def vintrp(field,pres,tk,qvp,ght,terrain,sfp,smsfp,
logp,
missing)
return res.T
return res

4
wrf_open/var/src/python/wrf/var/geoht.py

@ -14,10 +14,10 @@ def _get_geoht(wrfnc, timeidx, height=True, msl=True): @@ -14,10 +14,10 @@ def _get_geoht(wrfnc, timeidx, height=True, msl=True):
"""
try:
ph_vars = extract_vars(wrfnc, timeidx, ("PH", "PHB", "HGT"))
ph_vars = extract_vars(wrfnc, timeidx, varnames=("PH", "PHB", "HGT"))
except KeyError:
try:
ght_vars = extract_vars(wrfnc, timeidx, ("GHT", "HGT_U"))
ght_vars = extract_vars(wrfnc, timeidx, varnames=("GHT", "HGT_U"))
except KeyError:
raise RuntimeError("Cannot calculate height with variables in "
"NetCDF file")

20
wrf_open/var/src/python/wrf/var/helicity.py

@ -9,17 +9,17 @@ __all__ = ["get_srh", "get_uh"] @@ -9,17 +9,17 @@ __all__ = ["get_srh", "get_uh"]
def get_srh(wrfnc, timeidx=0, top=3000.0):
# Top can either be 3000 or 1000 (for 0-1 srh or 0-3 srh)
ncvars = extract_vars(wrfnc, timeidx, vars=("HGT", "PH", "PHB"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("HGT", "PH", "PHB"))
ter = ncvars["HGT"]
ph = ncvars["PH"]
phb = ncvars["PHB"]
try:
u_vars = extract_vars(wrfnc, timeidx, vars="U")
u_vars = extract_vars(wrfnc, timeidx, varnames="U")
except KeyError:
try:
uu_vars = extract_vars(wrfnc, timeidx, vars="UU")
uu_vars = extract_vars(wrfnc, timeidx, varnames="UU")
except KeyError:
raise RuntimeError("No valid wind data found in NetCDF file")
else:
@ -28,10 +28,10 @@ def get_srh(wrfnc, timeidx=0, top=3000.0): @@ -28,10 +28,10 @@ def get_srh(wrfnc, timeidx=0, top=3000.0):
u = destagger(u_vars["U"], -1)
try:
v_vars = extract_vars(wrfnc, timeidx, vars="V")
v_vars = extract_vars(wrfnc, timeidx, varnames="V")
except KeyError:
try:
vv_vars = extract_vars(wrfnc, timeidx, vars="VV")
vv_vars = extract_vars(wrfnc, timeidx, varnames="VV")
except KeyError:
raise RuntimeError("No valid wind data found in NetCDF file")
else:
@ -55,7 +55,7 @@ def get_srh(wrfnc, timeidx=0, top=3000.0): @@ -55,7 +55,7 @@ def get_srh(wrfnc, timeidx=0, top=3000.0):
def get_uh(wrfnc, timeidx=0, bottom=2000.0, top=5000.0):
ncvars = extract_vars(wrfnc, timeidx, vars=("W", "PH", "PHB", "MAPFAC_M"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("W", "PH", "PHB", "MAPFAC_M"))
wstag = ncvars["W"]
ph = ncvars["PH"]
@ -67,10 +67,10 @@ def get_uh(wrfnc, timeidx=0, bottom=2000.0, top=5000.0): @@ -67,10 +67,10 @@ def get_uh(wrfnc, timeidx=0, bottom=2000.0, top=5000.0):
dy = attrs["DY"]
try:
u_vars = extract_vars(wrfnc, timeidx, vars="U")
u_vars = extract_vars(wrfnc, timeidx, varnames="U")
except KeyError:
try:
uu_vars = extract_vars(wrfnc, timeidx, vars="UU")
uu_vars = extract_vars(wrfnc, timeidx, varnames="UU")
except KeyError:
raise RuntimeError("No valid wind data found in NetCDF file")
else:
@ -79,10 +79,10 @@ def get_uh(wrfnc, timeidx=0, bottom=2000.0, top=5000.0): @@ -79,10 +79,10 @@ def get_uh(wrfnc, timeidx=0, bottom=2000.0, top=5000.0):
u = destagger(u_vars["U"], -1)
try:
v_vars = extract_vars(wrfnc, timeidx, vars="V")
v_vars = extract_vars(wrfnc, timeidx, varnames="V")
except KeyError:
try:
vv_vars = extract_vars(wrfnc, timeidx, vars="VV")
vv_vars = extract_vars(wrfnc, timeidx, varnames="VV")
except KeyError:
raise RuntimeError("No valid wind data found in NetCDF file")
else:

2
wrf_open/var/src/python/wrf/var/interp.py

@ -324,7 +324,7 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False, @@ -324,7 +324,7 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False,
# Extract vriables
timeidx = -1 # Should this be an argument?
ncvars = extract_vars(wrfnc, timeidx, vars=("PSFC", "QVAPOR", "F"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("PSFC", "QVAPOR", "F"))
sfp = ncvars["PSFC"] * ConversionFactors.PA_TO_HPA
qv = ncvars["QVAPOR"]

16
wrf_open/var/src/python/wrf/var/latlon.py

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
from collections import Iterable
from wrf.var.constants import Constants
from wrf.var.extension import computeij, computell
from wrf.var.util import extract_vars, extract_global_attrs
@ -8,10 +9,10 @@ __all__ = ["get_lat", "get_lon", "get_ij", "get_ll"] @@ -8,10 +9,10 @@ __all__ = ["get_lat", "get_lon", "get_ij", "get_ll"]
def get_lat(wrfnc, timeidx=0):
try:
lat_vars = extract_vars(wrfnc, timeidx, vars="XLAT")
lat_vars = extract_vars(wrfnc, timeidx, varnames="XLAT")
except KeyError:
try:
latm_vars = extract_vars(wrfnc, timeidx, vars="XLAT_M")
latm_vars = extract_vars(wrfnc, timeidx, varnames="XLAT_M")
except:
raise RuntimeError("Latitude variable not found in NetCDF file")
else:
@ -23,10 +24,10 @@ def get_lat(wrfnc, timeidx=0): @@ -23,10 +24,10 @@ def get_lat(wrfnc, timeidx=0):
def get_lon(wrfnc, timeidx=0):
try:
lon_vars = extract_vars(wrfnc, timeidx, vars="XLONG")
lon_vars = extract_vars(wrfnc, timeidx, varnames="XLONG")
except KeyError:
try:
lonm_vars = extract_vars(wrfnc, timeidx, vars="XLONG_M")
lonm_vars = extract_vars(wrfnc, timeidx, varnames="XLONG_M")
except:
raise RuntimeError("Latitude variable not found in NetCDF file")
else:
@ -42,22 +43,21 @@ def _get_proj_params(wrfnc, timeidx): @@ -42,22 +43,21 @@ def _get_proj_params(wrfnc, timeidx):
attrs = extract_global_attrs(wrfnc, attrs=("MAP_PROJ", "TRUELAT1",
"TRUELAT2", "STAND_LON",
"DX", "DY", "STAND_LON"))
"DX", "DY"))
map_proj = attrs["MAP_PROJ"]
truelat1 = attrs["TRUELAT1"]
truelat2 = attrs["TRUELAT2"]
stdlon = attrs["STAND_LON"]
dx = attrs["DX"]
dy = attrs["DY"]
stdlon = attrs["STAND_LON"]
if map_proj == 6:
pole_attrs = extract_global_attrs(wrfnc, attrs=("POLE_LAT",
"POLE_LON"))
pole_lat = pole_attrs["POLE_LAT"]
pole_lon = pole_attrs["POLE_LON"]
latinc = (dy*360.0)/2.0/3.141592653589793/6370000.
loninc = (dx*360.0)/2.0/3.141592653589793/6370000.
latinc = (dy*360.0)/2.0 / Constants.PI/Constants.WRF_EARTH_RADIUS
loninc = (dx*360.0)/2.0 / Constants.PI/Constants.WRF_EARTH_RADIUS
else:
pole_lat = 90.0
pole_lon = 0.0

3
wrf_open/var/src/python/wrf/var/omega.py

@ -7,7 +7,8 @@ from wrf.var.util import extract_vars @@ -7,7 +7,8 @@ from wrf.var.util import extract_vars
__all__ = ["get_omega"]
def get_omega(wrfnc, timeidx=0):
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "W", "PB", "QVAPOR"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "W",
"PB", "QVAPOR"))
t = ncvars["T"]
p = ncvars["P"]
w = ncvars["W"]

6
wrf_open/var/src/python/wrf/var/precip.py

@ -5,7 +5,7 @@ from wrf.var.util import extract_vars @@ -5,7 +5,7 @@ from wrf.var.util import extract_vars
__all__ = ["get_accum_precip", "get_precip_diff"]
def get_accum_precip(wrfnc, timeidx=0):
ncvars = extract_vars(wrfnc, timeidx, vars=("RAINC", "RAINNC"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("RAINC", "RAINNC"))
rainc = ncvars["RAINC"]
rainnc = ncvars["RAINNC"]
@ -14,8 +14,8 @@ def get_accum_precip(wrfnc, timeidx=0): @@ -14,8 +14,8 @@ def get_accum_precip(wrfnc, timeidx=0):
return rainsum
def get_precip_diff(wrfnc1, wrfnc2, timeidx=0):
vars1 = extract_vars(wrfnc1, timeidx, vars=("RAINC", "RAINNC"))
vars2 = extract_vars(wrfnc2, timeidx, vars=("RAINC", "RAINNC"))
vars1 = extract_vars(wrfnc1, timeidx, varnames=("RAINC", "RAINNC"))
vars2 = extract_vars(wrfnc2, timeidx, varnames=("RAINC", "RAINNC"))
rainc1 = vars1["RAINC"]
rainnc1 = vars1["RAINNC"]

4
wrf_open/var/src/python/wrf/var/pressure.py

@ -8,10 +8,10 @@ __all__ = ["get_pressure", "get_pressure_hpa"] @@ -8,10 +8,10 @@ __all__ = ["get_pressure", "get_pressure_hpa"]
def get_pressure(wrfnc, timeidx=0, units="pa"):
try:
p_vars = extract_vars(wrfnc, timeidx, vars=("P", "PB"))
p_vars = extract_vars(wrfnc, timeidx, varnames=("P", "PB"))
except KeyError:
try:
pres_vars = extract_vars(wrfnc, timeidx, vars="PRES")
pres_vars = extract_vars(wrfnc, timeidx, varnames="PRES")
except:
raise RuntimeError("pressure variable not found in NetCDF file")
else:

748
wrf_open/var/src/python/wrf/var/projection.py

@ -0,0 +1,748 @@ @@ -0,0 +1,748 @@
import numpy as np
import math
from wrf.var.config import basemap_enabled, cartopy_enabled, pyngl_enabled
from wrf.var.constants import Constants
if cartopy_enabled():
from cartopy import crs
if basemap_enabled():
from mpl_toolkits.basemap import Basemap
if pyngl_enabled():
from Ngl import Resources
__all__ = ["WrfProj", "LambertConformalProj", "MercatorProj",
"PolarStereographicProj", "LatLonProj", "RotLatLonProj",
"getproj"]
if cartopy_enabled():
class MercatorWithLatTsProj(crs.Mercator):
def __init__(self, central_longitude=0.0,
latitude_true_scale=0.0,
min_latitude=-80.0,
max_latitude=84.0,
globe=None):
proj4_params = [("proj", "merc"),
("lon_0", central_longitude),
("lat_ts", latitude_true_scale),
("k", 1),
("units", "m")]
super(crs.Mercator, self).__init__(proj4_params, globe=globe)
# Calculate limits.
limits = self.transform_points(crs.Geodetic(),
np.array([-180, 180]) + central_longitude,
np.array([min_latitude, max_latitude]))
# When using a latitude of true scale, the min/max x-limits get set
# to the same value, so make sure the left one is negative
xlimits = limits[..., 0]
if xlimits[0] == xlimits[1]:
if xlimits[0] < 0:
xlimits[1] = -xlimits[1]
else:
xlimits[0] = -xlimits[0]
self._xlimits = tuple(xlimits)
self._ylimits = tuple(limits[..., 1])
self._threshold = np.diff(self.x_limits)[0] / 720
def _ismissing(val):
return val is None or val > 90. or val < -90.
class WrfProj(object):
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
if bottom_left is not None and top_right is not None:
self.ll_lat = bottom_left[0]
self.ll_lon = bottom_left[1]
self.ur_lat = top_right[0]
self.ur_lon = top_right[1]
self.bottom_left = bottom_left
self.top_right = top_right
elif lats is not None and lons is not None:
self.ll_lat = lats[0,0]
self.ur_lat = lats[-1,-1]
self.ll_lon = lons[0,0]
self.ur_lon = lons[-1,-1]
self.bottom_left = [self.ll_lat, self.ll_lon]
self.top_right = [self.ur_lat, self.ur_lon]
else:
raise ValueError("invalid corner point arguments")
# These indicate the center of the nest/domain, not necessarily the
# center of the projection
self._cen_lat = proj_params.get("CEN_LAT", None)
self._cen_lon = proj_params.get("CEN_LON", None)
self.truelat1 = proj_params.get("TRUELAT1", None)
self.truelat2 = (proj_params.get("TRUELAT2", None)
if not _ismissing(proj_params.get("TRUELAT2", None))
else None)
self.moad_cen_lat = proj_params.get("MOAD_CEN_LAT", None)
self.stand_lon = proj_params.get("STAND_LON", None)
self.pole_lat = proj_params.get("POLE_LAT", None)
self.pole_lon = proj_params.get("POLE_LON", None)
# Just in case...
if self.moad_cen_lat is None:
self.moad_cen_lat = self._cen_lat
if self.stand_lon is None:
self.stand_lon = self._cen_lon
@property
def _basemap(self):
return None
@property
def _cf_params(self):
return None
@property
def _cartopy(self):
return None
@property
def _cart_extents(self):
return ([self.ll_lon, self.ur_lon], [self.ll_lat, self.ur_lat])
@property
def _pyngl(self):
return None
@property
def _proj4(self):
return None
@property
def _globe(self):
return (None if not cartopy_enabled()
else crs.Globe(ellipse=None,
semimajor_axis=Constants.WRF_EARTH_RADIUS,
semiminor_axis=Constants.WRF_EARTH_RADIUS))
def cartopy_xlim(self):
"""Return the x extents in projected coordinates (for cartopy)"""
return self._cart_extents[0]
def cartopy_ylim(self):
"""Return the y extents in projected coordinates (for cartopy)"""
return self._cart_extents[1]
def __repr__(self):
args = ("bottom_left={}, top_right={}, "
"stand_lon={}, moad_cen_lat={}, "
"pole_lat={}, pole_lon={}".format((self.ll_lat, self.ll_lon),
(self.ur_lat, self.ur_lon),
self.stand_lon,
self.moad_cen_lat,
self.pole_lat,
self.pole_lon))
return "{}({})".format(self.__class__.__name__, args)
def basemap(self):
"""Return a mpl_toolkits.basemap.Basemap instance for the
projection"""
if not basemap_enabled():
raise RuntimeError("'mpl_toolkits.basemap' is not "
"installed or is disabled")
return self._basemap
def cartopy(self):
"""Return a cartopy.crs.Projection subclass for the
projection"""
if not cartopy_enabled():
raise RuntimeError("'cartopy' is not "
"installed or is disabled")
return self._cartopy
def pyngl(self):
"""Return the PyNGL resources for the projection"""
if not pyngl_enabled():
raise RuntimeError("'pyngl' is not "
"installed or is disabled")
return self._pyngl
def proj4(self):
"""Return the proj4 string for the map projection"""
return self._proj4
def cf(self):
"""Return a dictionary with the NetCDF CF parameters for the
projection"""
return self._cf_params
class LambertConformalProj(WrfProj):
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
super(LambertConformalProj, self).__init__(bottom_left,
top_right, lats, lons, **proj_params)
self._std_parallels = [self.truelat1]
if self.truelat2 is not None:
self._std_parallels.append(self.truelat2)
@property
def _cf_params(self):
_cf_params = {}
_cf_params["grid_mapping_name"] = "lambert_conformal_conic";
_cf_params["standard_parallel"] = self._std_parallels
_cf_params["longitude_of_central_meridian"] = self.stand_lon
_cf_params["latitude_of_projection_origin"] = self.moad_cen_lat
_cf_params["semi_major_axis"] = Constants.WRF_EARTH_RADIUS
return _cf_params
@property
def _pyngl(self):
if not pyngl_enabled():
return None
truelat2 = (self.truelat1
if _ismissing(self.truelat2)
else self.truelat2)
_pyngl = Resources()
_pyngl.mpProjection = "LambertConformal"
_pyngl.mpDataBaseVersion = "MediumRes"
_pyngl.mpLimitMode = "Corners"
_pyngl.mpLeftCornerLonF = self.ll_lon
_pyngl.mpLeftCornerLatF = self.ll_lat
_pyngl.mpRightCornerLonF = self.ur_lon
_pyngl.mpRightCornerLatF = self.ur_lat
_pyngl.mpLambertMeridianF = self.stand_lon
_pyngl.mpLambertParallel1F = self.truelat1
_pyngl.mpLambertParallel2F = truelat2
return _pyngl
@property
def _basemap(self):
if not basemap_enabled():
return None
_basemap = Basemap(projection = "lcc",
lon_0 = self.stand_lon,
lat_0 = self.moad_cen_lat,
lat_1 = self.truelat1,
lat_2 = self.truelat2,
llcrnrlat = self.ll_lat,
urcrnrlat = self.ur_lat,
llcrnrlon = self.ll_lon,
urcrnrlon = self.ur_lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = 'l')
return _basemap
@property
def _cartopy(self):
if not cartopy_enabled():
return None
_cartopy = crs.LambertConformal(
central_longitude = self.stand_lon,
central_latitude = self.moad_cen_lat,
standard_parallels = self._std_parallels,
globe = self._globe)
return _cartopy
@property
def _cart_extents(self):
# Need to modify the extents for the new projection
pc = crs.PlateCarree()
xs, ys, zs = self._cartopy.transform_points(pc,
np.array([self.ll_lon, self.ur_lon]),
np.array([self.ll_lat, self.ur_lat])).T
_xlimits = xs.tolist()
_ylimits = ys.tolist()
return (_xlimits, _ylimits)
@property
def _proj4(self):
truelat2 = (self.truelat1
if _ismissing(self.truelat2)
else self.truelat2)
_proj4 = ("+proj=lcc +units=meters +a={} +b={} +lat_1={} "
"+lat_2={} +lat_0={} +lon_0={}".format(
Constants.WRF_EARTH_RADIUS,
Constants.WRF_EARTH_RADIUS,
self.truelat1,
truelat2,
self.moad_cen_lat,
self.stand_lon))
return _proj4
class MercatorProj(WrfProj):
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
super(MercatorProj, self).__init__(bottom_left, top_right,
lats, lons, **proj_params)
self._lat_ts = (None
if self.truelat1 == 0. or _ismissing(self.truelat1)
else self.truelat1)
@property
def _cf_params(self):
_cf_params = {}
_cf_params["grid_mapping_name"] = "mercator"
_cf_params["longitude_of_projection_origin"] = self.stand_lon
_cf_params["standard_parallel"] = self.truelat1
return _cf_params
@property
def _pyngl(self):
if not pyngl_enabled():
return None
_pyngl = Resources()
_pyngl.mpProjection = "Mercator"
_pyngl.mpDataBaseVersion = "MediumRes"
_pyngl.mpLimitMode = "Corners"
_pyngl.mpLeftCornerLonF = self.ll_lon
_pyngl.mpLeftCornerLatF = self.ll_lat
_pyngl.mpRightCornerLonF = self.ur_lon
_pyngl.mpRightCornerLatF = self.ur_lat
_pyngl.mpCenterLatF = 0.0
_pyngl.mpCenterLonF = self.stand_lon
return _pyngl
@property
def _basemap(self):
if not basemap_enabled():
return None
_basemap = Basemap(projection = "merc",
lon_0 = self.stand_lon,
lat_0 = self.moad_cen_lat,
lat_ts = self._lat_ts,
llcrnrlat = self.ll_lat,
urcrnrlat = self.ur_lat,
llcrnrlon = self.ll_lon,
urcrnrlon = self.ur_lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = 'l')
return _basemap
@property
def _cartopy(self):
if not cartopy_enabled():
return None
if self._lat_ts == 0.0:
_cartopy = crs.Mercator(
central_longitude = self.stand_lon,
globe = self._globe)
else:
_cartopy = MercatorWithLatTsProj(
central_longitude = self.stand_lon,
latitude_true_scale = self._lat_ts,
globe = self._globe)
return _cartopy
@property
def _cart_extents(self):
# Need to modify the extents for the new projection
pc = crs.PlateCarree()
xs, ys, zs = self._cartopy.transform_points(pc,
np.array([self.ll_lon, self.ur_lon]),
np.array([self.ll_lat, self.ur_lat])).T
_xlimits = xs.tolist()
_ylimits = ys.tolist()
return (_xlimits, _ylimits)
@property
def _proj4(self):
_proj4 = ("+proj=merc +units=meters +a={} +b={} "
"+lon_0={} +lat_ts={}".format(
Constants.WRF_EARTH_RADIUS,
Constants.WRF_EARTH_RADIUS,
self.stand_lon,
self._lat_ts))
return _proj4
class PolarStereographicProj(WrfProj):
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
super(PolarStereographicProj, self).__init__(bottom_left,
top_right, lats, lons, **proj_params)
self._hemi = -90. if self.truelat1 < 0 else 90.
self._lat_ts = (None
if _ismissing(self.truelat1)
else self.truelat1)
@property
def _cf_params(self):
_cf_params = {}
_cf_params["grid_mapping_name"] = "polar_stereographic"
_cf_params["straight_vertical_longitude_from_pole"] = (
self.stand_lon)
_cf_params["standard_parallel"] = self.truelat1
_cf_params["latitude_of_projection_origin"] = self._hemi
return _cf_params
@property
def _pyngl(self):
if not pyngl_enabled():
return None
_pyngl = Resources()
_pyngl.mpProjection = "Stereographic"
_pyngl.mpDataBaseVersion = "MediumRes"
_pyngl.mpLimitMode = "Corners"
_pyngl.mpLeftCornerLonF = self.ll_lon
_pyngl.mpLeftCornerLatF = self.ll_lat
_pyngl.mpRightCornerLonF = self.ur_lon
_pyngl.mpRightCornerLatF = self.ur_lat
_pyngl.mpCenterLonF = self.stand_lon
if self._hemi > 0:
_pyngl.mpCenterLatF = 90.0
else:
_pyngl.mpCenterLatF = -90.0
return _pyngl
@property
def _basemap(self):
if not basemap_enabled():
return None
_basemap = Basemap(projection = "stere",
lon_0 = self.stand_lon,
lat_0 = self._hemi,
lat_ts = self._lat_ts,
llcrnrlat = self.ll_lat,
urcrnrlat = self.ur_lat,
llcrnrlon = self.ll_lon,
urcrnrlon = self.ur_lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = 'l')
return _basemap
@property
def _cartopy(self):
if not cartopy_enabled():
return None
_cartopy = crs.Stereographic(central_latitude=self._hemi,
central_longitude=self.stand_lon,
true_scale_latitude=self._lat_ts,
globe=self._globe)
return _cartopy
@property
def _cart_extents(self):
# Need to modify the extents for the new projection
pc = crs.PlateCarree()
xs, ys, zs = self._cartopy.transform_points(pc,
np.array([self.ll_lon, self.ur_lon]),
np.array([self.ll_lat, self.ur_lat])).T
_xlimits = xs.tolist()
_ylimits = ys.tolist()
return (_xlimits, _ylimits)
@property
def _proj4(self):
_proj4 = ("+proj=stere +units=meters +a={} +b={} "
"+lat0={} +lon_0={} +lat_ts={}".format(
Constants.WRF_EARTH_RADIUS,
Constants.WRF_EARTH_RADIUS,
self._hemi,
self.stand_lon,
self._lat_ts))
return _proj4
class LatLonProj(WrfProj):
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
super(LatLonProj, self).__init__(bottom_left, top_right,
lats, lons, **proj_params)
@property
def _cf_params(self):
_cf_params = {}
_cf_params["grid_mapping_name"] = "latitude_longitude"
return _cf_params
@property
def _pyngl(self):
if not pyngl_enabled():
return None
_pyngl = Resources()
_pyngl.mpProjection = "CylindricalEquidistant"
_pyngl.mpDataBaseVersion = "MediumRes"
_pyngl.mpLimitMode = "Corners"
_pyngl.mpLeftCornerLonF = self.ll_lon
_pyngl.mpLeftCornerLatF = self.ll_lat
_pyngl.mpRightCornerLonF = self.ur_lon
_pyngl.mpRightCornerLatF = self.ur_lat
_pyngl.mpCenterLonF = self.stand_lon
_pyngl.mpCenterLatF = self.moad_cen_lat
return _pyngl
@property
def _basemap(self):
if not basemap_enabled():
return None
_basemap = Basemap(projection = "cyl",
lon_0 = self.stand_lon,
lat_0 = self.moad_cen_lat,
llcrnrlat = self.ll_lat,
urcrnrlat = self.ur_lat,
llcrnrlon = self.ll_lon,
urcrnrlon = self.ur_lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = 'l')
return _basemap
@property
def _cartopy(self):
if not cartopy_enabled():
return None
_cartopy = crs.PlateCarree(central_longitude=self.stand_lon,
globe=self._globe)
return _cartopy
@property
def _cart_extents(self):
return ([self.ll_lon, self.ur_lon], [self.ll_lat, self.ur_lat])
@property
def _proj4(self):
_proj4 = ("+proj=eqc +units=meters +a={} +b={} "
"+lon_0={}".format(Constants.WRF_EARTH_RADIUS,
Constants.WRF_EARTH_RADIUS,
self.stand_lon))
return _proj4
# Notes (may not be correct since this projection confuses me):
# Each projection system handles this differently.
# 1) In WRF, if following the WPS instructions, POLE_LON is mainly used to
# determine north or south hemisphere. In other words, it determines if
# the globe is tipped toward or away from you. If a non-0 or non-180
# value is chosen, PyNGL cannot plot it.
# 2) In WRF, POLE_LAT is always positive, but should be negative in the
# proj4 based systems when using the southern hemisphere projections.
# 3) In cartopy, pole_longitude is used to describe the dateline, which
# is 180 degrees away from the normal central (standard) longitude
# (e.g. center of the projection), according to the cartopy developer.
# 4) In basemap, lon_0 should be set to the central (standard) longitude.
# 5) In either cartopy, basemap or pyngl, I'm not sure that projections with
# a pole_lon not equal to 0 or 180 can be plotted. Hopefully people
# follow the WPS instructions, otherwise I need to see a sample file and
# a lot of rum.
# 6) For items in 3 - 4, the "longitude" (lon_0 or pole_longitude) is
# determined by WRF's
# STAND_LON values, with the following calculations based on hemisphere:
# BASEMAP: NH: -STAND_LON; SH: 180.0 - STAND_LON
# CARTOPY: NH: -STAND_LON - 180.; SH: -STAND_LON
# 9) For PYNGL/NCL, you only need to set the center lat and center lon,
# Center lat is the offset of the pole from +/- 90 degrees. Center
# lon is -STAND_LON in NH and 180.0 - STAND_LON in SH.
# 10) It also appears that NetCDF CF has no clear documentation on what
# each parameter means. Going to assume it is the same as basemap, since
# basemap appears to mirror the WMO way of doing things (tilt earth, then
# spin globe).
# 11) Basemap and cartopy produce projections that differ in their extent
# calculations by either using negative values or 0-360 (basemap). For
# this reason, the proj4 string for this class will use cartopy's values
# to keep things in the -180 to 180, -90 to 90 range.
# 12) This projection makes me sad.
class RotLatLonProj(WrfProj):
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
super(RotLatLonProj, self).__init__(bottom_left, top_right,
lats, lons, **proj_params)
# Need to determine hemisphere, typically pole_lon is 0 for southern
# hemisphere, 180 for northern hemisphere. If not, going to have
# to guess based on other parameters, but hopefully people follow
# the WPS instructions and this never happens.
self._north = True
if self.pole_lon is not None:
if self.pole_lon == 0.:
self._north = False
elif self.pole_lon != 180.:
if self.moad_cen_lat is not None and self.moad_cen_lat < 0.0:
# Only probably true
self._north = False
else:
if self.moad_cen_lat is not None and self.moad_cen_lat < 0.0:
# Only probably true
self._north = False
if self.pole_lat is not None and self.stand_lon is not None:
self._pyngl_cen_lat = (90. - self.pole_lat if self._north
else self.pole_lat - 90.0)
self._pyngl_cen_lon = (-self.stand_lon if self._north
else 180.0 - self.stand_lon)
self._bm_lon_0 = (-self.stand_lon if self._north
else 180.0 - self.stand_lon)
self._bm_cart_pole_lat = (self.pole_lat if self._north
else -self.pole_lat )
# The important point is that pole longitude is the position
# of the dateline of the new projection, not its central
# longitude (per the creator of cartopy). This is based on
# how it's handled by agencies like WMO, but not proj4.
self._cart_pole_lon = (-self.stand_lon - 180.0 if self._north
else -self.stand_lon)
else:
self._pyngl_cen_lat = self.moad_cen_lat
self._pyngl_cen_lon = self.stand_lon
self._bm_cart_pole_lat = (90.0 - self.moad_cen_lat if self._north
else -90.0 - self.moad_cen_lat)
self._bm_lon_0 = (-self.stand_lon if self._north
else 180.0 - self.stand_lon)
self._cart_pole_lon = (-self.stand_lon - 180.0 if self._north
else -self.stand_lon)
@property
def _cf_params(self):
_cf_params = {}
# Assuming this follows the same guidelines as cartopy
_cf_params["grid_mapping_name"] = "rotated_latitude_longitude"
_cf_params["grid_north_pole_latitude"] = self._bm_cart_pole_lat
_cf_params["grid_north_pole_longitude"] = self.pole_lon
_cf_params["north_pole_grid_longitude"] = self._bm_lon_0
return _cf_params
@property
def _pyngl(self):
if not pyngl_enabled():
return None
_pyngl = Resources()
_pyngl.mpProjection = "CylindricalEquidistant"
_pyngl.mpDataBaseVersion = "MediumRes"
_pyngl.mpLimitMode = "Corners"
_pyngl.mpLeftCornerLonF = self.ll_lon
_pyngl.mpLeftCornerLatF = self.ll_lat
_pyngl.mpRightCornerLonF = self.ur_lon
_pyngl.mpRightCornerLatF = self.ur_lat
_pyngl.mpCenterLatF = self._pyngl_cen_lat
_pyngl.mpCenterLonF = self._pyngl_cen_lon
return _pyngl
@property
def _basemap(self):
if not basemap_enabled():
return None
_basemap = Basemap(projection = "rotpole",
o_lat_p = self._bm_cart_pole_lat,
o_lon_p = self.pole_lon,
llcrnrlat = self.ll_lat,
urcrnrlat = self.ur_lat,
llcrnrlon = self.ll_lon,
urcrnrlon = self.ur_lon,
lon_0 = self._bm_lon_0,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = 'l')
return _basemap
@property
def _cartopy(self):
if not cartopy_enabled():
return None
_cartopy = crs.RotatedPole(
pole_longitude=self._cart_pole_lon,
pole_latitude=self._bm_cart_pole_lat,
central_rotated_longitude=(
180.0 - self.pole_lon), # Probably
globe = self._globe)
return _cartopy
@property
def _cart_extents(self):
# Need to modify the extents for the new projection
pc = crs.PlateCarree()
xs, ys, zs = self._cartopy.transform_points(pc,
np.array([self.ll_lon, self.ur_lon]),
np.array([self.ll_lat, self.ur_lat])).T
_xlimits = xs.tolist()
_ylimits = ys.tolist()
return (_xlimits, _ylimits)
@property
def _proj4(self):
_proj4 = ("+proj=ob_tran +o_proj=latlon "
"+a={} +b={} +to_meter={} +o_lon_p={} +o_lat_p={} "
"+lon_0={}".format(Constants.WRF_EARTH_RADIUS,
Constants.WRF_EARTH_RADIUS,
math.radians(1),
180.0 - self.pole_lon,
self._bm_cart_pole_lat,
180.0 + self._cart_pole_lon))
return _proj4
def getproj(bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
proj_type = proj_params.get("MAP_PROJ", 0)
if proj_type == 1:
return LambertConformalProj(bottom_left, top_right,
lats, lons, **proj_params)
elif proj_type == 2:
return PolarStereographicProj(bottom_left, top_right,
lats, lons, **proj_params)
elif proj_type == 3:
return MercatorProj(bottom_left, top_right,
lats, lons, **proj_params)
elif proj_type == 0 or proj_type == 6:
if (proj_params.get("POLE_LAT", None) == 90.
and proj_params.get("POLE_LON", None) == 0.):
return LatLonProj(bottom_left, top_right,
lats, lons, **proj_params)
else:
return RotLatLonProj(bottom_left, top_right,
lats, lons, **proj_params)
else:
# Unknown projection
return WrfProj(bottom_left, top_right,
lats, lons, **proj_params)

BIN
wrf_open/var/src/python/wrf/var/psadlookup.pyc

Binary file not shown.

4
wrf_open/var/src/python/wrf/var/pw.py

@ -6,8 +6,8 @@ from wrf.var.util import extract_vars @@ -6,8 +6,8 @@ from wrf.var.util import extract_vars
__all__ = ["get_pw"]
def get_pw(wrfnc, timeidx=0):
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "PB", "PH", "PHB",
"QVAPOR"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "PB", "PH",
"PHB", "QVAPOR"))
t = ncvars["T"]
p = ncvars["P"]

4
wrf_open/var/src/python/wrf/var/rh.py

@ -6,7 +6,7 @@ from wrf.var.util import extract_vars @@ -6,7 +6,7 @@ from wrf.var.util import extract_vars
__all__ = ["get_rh", "get_rh_2m"]
def get_rh(wrfnc, timeidx=0):
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "PB", "QVAPOR"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "PB", "QVAPOR"))
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]
@ -21,7 +21,7 @@ def get_rh(wrfnc, timeidx=0): @@ -21,7 +21,7 @@ def get_rh(wrfnc, timeidx=0):
return rh
def get_rh_2m(wrfnc, timeidx=0):
ncvars = extract_vars(wrfnc, timeidx, vars=("T2", "PSFC", "Q2"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("T2", "PSFC", "Q2"))
t2 = ncvars["T2"]
psfc = ncvars["PSFC"]
q2 = ncvars["Q2"]

2
wrf_open/var/src/python/wrf/var/slp.py

@ -8,7 +8,7 @@ __all__ = ["get_slp"] @@ -8,7 +8,7 @@ __all__ = ["get_slp"]
@convert_units("pressure", "hpa")
def get_slp(wrfnc, timeidx=0, units="hpa"):
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "PB", "QVAPOR",
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "PB", "QVAPOR",
"PH", "PHB"))
t = ncvars["T"]

13
wrf_open/var/src/python/wrf/var/temp.py

@ -1,15 +1,16 @@ @@ -1,15 +1,16 @@
from wrf.var.constants import Constants
from wrf.var.extension import computetk, computeeth, computetv, computewetbulb
from wrf.var.decorators import convert_units
from wrf.var.decorators import convert_units, set_metadata
from wrf.var.util import extract_vars
__all__ = ["get_theta", "get_temp", "get_eth", "get_tv", "get_tw",
"get_tk", "get_tc"]
@set_metadata()
@convert_units("temp", "k")
def get_theta(wrfnc, timeidx=0, units="k"):
ncvars = extract_vars(wrfnc, timeidx, vars="T")
ncvars = extract_vars(wrfnc, timeidx, varnames="T")
t = ncvars["T"]
full_t = t + Constants.T_BASE
@ -19,7 +20,7 @@ def get_theta(wrfnc, timeidx=0, units="k"): @@ -19,7 +20,7 @@ def get_theta(wrfnc, timeidx=0, units="k"):
def get_temp(wrfnc, timeidx=0, units="k"):
"""Return the temperature in Kelvin or Celsius"""
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "PB"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "PB"))
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]
@ -34,7 +35,7 @@ def get_temp(wrfnc, timeidx=0, units="k"): @@ -34,7 +35,7 @@ def get_temp(wrfnc, timeidx=0, units="k"):
def get_eth(wrfnc, timeidx=0, units="k"):
"Return equivalent potential temperature (Theta-e) in Kelvin"
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "PB", "QVAPOR"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "PB", "QVAPOR"))
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]
@ -52,7 +53,7 @@ def get_eth(wrfnc, timeidx=0, units="k"): @@ -52,7 +53,7 @@ def get_eth(wrfnc, timeidx=0, units="k"):
def get_tv(wrfnc, timeidx=0, units="k"):
"Return the virtual temperature (tv) in Kelvin or Celsius"
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "PB", "QVAPOR"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "PB", "QVAPOR"))
t = ncvars["T"]
p = ncvars["P"]
@ -72,7 +73,7 @@ def get_tv(wrfnc, timeidx=0, units="k"): @@ -72,7 +73,7 @@ def get_tv(wrfnc, timeidx=0, units="k"):
def get_tw(wrfnc, timeidx=0, units="k"):
"Return the wetbulb temperature (tw)"
ncvars = extract_vars(wrfnc, timeidx, vars=("T", "P", "PB", "QVAPOR"))
ncvars = extract_vars(wrfnc, timeidx, varnames=("T", "P", "PB", "QVAPOR"))
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]

4
wrf_open/var/src/python/wrf/var/terrain.py

@ -8,10 +8,10 @@ __all__ = ["get_terrain"] @@ -8,10 +8,10 @@ __all__ = ["get_terrain"]
def get_terrain(wrfnc, timeidx=0, units="m"):
try:
hgt_vars = extract_vars(wrfnc, timeidx, vars="HGT")
hgt_vars = extract_vars(wrfnc, timeidx, varnames="HGT")
except KeyError:
try:
hgt_m_vars = extract_vars(wrfnc, timeidx, vars="HGT_M")
hgt_m_vars = extract_vars(wrfnc, timeidx, varnames="HGT_M")
except KeyError:
raise RuntimeError("height variable not found in NetCDF file")
else:

309
wrf_open/var/src/python/wrf/var/util.py

@ -1,13 +1,20 @@ @@ -1,13 +1,20 @@
from collections import Iterable
from collections import Iterable, Mapping, OrderedDict
from itertools import product
import datetime as dt
import warnings
import numpy as n
from wrf.var.config import xarray_enabled
from wrf.var.projection import getproj
if xarray_enabled():
from xarray import DataArray
__all__ = ["extract_vars", "extract_global_attrs", "extract_dim",
"combine_files", "is_standard_wrf_var", "extract_times",
"iter_left_indexes", "get_left_indexes", "get_right_slices",
"is_staggered"]
"is_staggered", "get_proj_params"]
def _is_multi_time(timeidx):
if timeidx == -1:
@ -19,8 +26,25 @@ def _is_multi_file(wrfnc): @@ -19,8 +26,25 @@ def _is_multi_file(wrfnc):
return True
return False
def _is_mapping(wrfnc):
if isinstance(wrfnc, Mapping):
return True
return False
def _is_moving_domain(wrfnc, latvar="XLAT", lonvar="XLONG"):
lat1 = wrfnc.variables[latvar][0,:]
lat2 = wrfnc.variables[latvar][-1,:]
lon1 = wrfnc.variables[lonvar][0,:]
lon2 = wrfnc.variables[lonvar][-1,:]
if (lat1[0,0] != lat2[0,0] or lat1[-1,-1] != lat2[-1,-1] or
lon1[0,0] != lon2[0,0] or lon1[-1,-1] != lon2[-1,-1]):
return True
return False
def _get_attr(wrfnc, attr):
val = getattr(wrfnc, attr)
val = getattr(wrfnc, attr, None)
# PyNIO puts single values in to an array
if isinstance(val,n.ndarray):
@ -37,61 +61,274 @@ def extract_global_attrs(wrfnc, attrs): @@ -37,61 +61,274 @@ def extract_global_attrs(wrfnc, attrs):
multifile = _is_multi_file(wrfnc)
if multifile:
if not _is_mapping(wrfnc):
wrfnc = wrfnc[0]
else:
wrfnc = wrfnc[next(wrfnc.iterkeys())]
return {attr:_get_attr(wrfnc, attr) for attr in attrlist}
def extract_dim(wrfnc, dim):
if _is_multi_file(wrfnc):
if not _is_mapping(wrfnc):
wrfnc = wrfnc[0]
else:
wrfnc = wrfnc[next(wrfnc.iterkeys())]
d = wrfnc.dimensions[dim]
if not isinstance(d, int):
return len(d) #netCDF4
return d # PyNIO
def combine_files(wrflist, var, timeidx):
# TODO
def _combine_dict(wrfseq, var, timeidx, method):
"""Dictionary combination creates a new left index for each key, then
does a cat or join for the list of files for that key"""
multitime = _is_multi_time(timeidx)
numfiles = len(wrfseq)
if not multitime:
time_idx_or_slice = timeidx
else:
time_idx_or_slice = slice(None, None, None)
keys = (list(x for x in xrange(numfiles)) if not _is_mapping(wrfseq) else
list(key for key in wrfseq.iterkeys()))
# Check if
if not xarray_enabled():
first_var = wrfseq[keys[0]].variables[var][time_idx_or_slice, :]
else:
first_var = _build_data_array(wrfseq[keys[0]], var, timeidx)
# Create the output data numpy array based on the first array
outdims = [numfiles]
outdims += first_var.shape
outdata = n.zeros(outdims, first_var.dtype)
outdata[0,:] = first_var[:]
for idx, key in enumerate(keys[1:], start=1):
outdata[idx,:] = wrfseq[key].variables[var][time_idx_or_slice, :]
if not xarray_enabled():
outarr = outdata
else:
outname = str(first_var.name)
outcoords = dict(first_var.coords)
outdims = ["sequence"] + list(first_var.dims)
outcoords["sequence"] = keys
outattrs = dict(first_var.attrs)
outarr = DataArray(outdata, name=outname, coords=outcoords,
dims=outdims, attrs=outattrs)
return outarr
def _cat_files(wrfseq, var, timeidx):
file_times = extract_times(wrfseq, timeidx)
multitime = _is_multi_time(timeidx)
time_idx_or_slice = timeidx if not multitime else slice(None, None, None)
first_var = (_build_data_array(wrfseq[0], var, timeidx)
if xarray_enabled() else
wrfseq[0].variables[var][time_idx_or_slice, :])
outdims = [len(file_times)]
# Making a new time dim, so ignore this one
outdims += first_var.shape[1:]
outdata = n.zeros(outdims, first_var.dtype)
numtimes = first_var.shape[0]
startidx = 0
endidx = numtimes
outdata[startidx:endidx, :] = first_var[:]
startidx = endidx
for wrfnc in wrfseq[1:]:
vardata = wrfnc.variables[var][time_idx_or_slice, :]
if multitime:
numtimes = vardata.shape[0]
else:
numtimes = 1
endidx = startidx + numtimes
outdata[startidx:endidx, :] = vardata[:]
startidx = endidx
if xarray_enabled():
# FIXME: If it's a moving nest, then the coord arrays need to have same
# time indexes as the whole data set
outname = str(first_var.name)
outattrs = dict(first_var.attrs)
outcoords = dict(first_var.coords)
outdimnames = list(first_var.dims)
outcoords[outdimnames[0]] = file_times # New time dimension values
outarr = DataArray(outdata, name=outname, coords=outcoords,
dims=outdimnames, attrs=outattrs)
else:
outarr = outdata
return outarr
def _join_files(wrfseq, var, timeidx):
multitime = _is_multi_time(timeidx)
numfiles = len(wrflist)
numfiles = len(wrfseq)
if not multitime:
time_idx_or_slice = timeidx
else:
time_idx_or_slice = slice(None, None, None)
first_var = n.squeeze(wrflist[0].variables[var][time_idx_or_slice, :])
if xarray_enabled():
first_var = _build_data_array(wrfseq[0], var, timeidx)
else:
first_var = wrfseq[0].variables[var][time_idx_or_slice, :]
# Create the output data numpy array based on the first array
outdims = [numfiles]
outdims += first_var.shape
outarr = n.zeros(outdims, first_var.dtype)
outarr[0,:] = first_var[:]
outdata = n.zeros(outdims, first_var.dtype)
outdata[0,:] = first_var[:]
for idx, wrfnc in enumerate(wrflist[1:], start=1):
outarr[idx,:] = n.squeeze(wrfnc.variables[var][time_idx_or_slice, :])
for idx, wrfnc in enumerate(wrfseq[1:], 1):
print idx
outdata[idx,:] = wrfnc.variables[var][time_idx_or_slice, :]
if xarray_enabled():
outname = str(first_var.name)
outcoords = dict(first_var.coords)
outattrs = dict(first_var.attrs)
# New dimensions
outdimnames = ["file_idx"] + list(first_var.dims)
outcoords["file_idx"] = [i for i in xrange(numfiles)]
outarr = DataArray(outdata, name=outname, coords=outcoords,
dims=outdimnames, attrs=outattrs)
else:
outarr = outdata
return outarr
def combine_files(wrfseq, var, timeidx, method="cat", squeeze=True):
# Dictionary is unique
if _is_mapping(wrfseq):
outarr = _combine_dict(wrfseq, var, timeidx, method)
if method.lower() == "cat":
outarr = _cat_files(wrfseq, var, timeidx)
elif method.lower() == "join":
outarr = _join_files(wrfseq, var, timeidx)
else:
raise ValueError("method must be 'cat' or 'join'")
if squeeze:
return outarr.squeeze()
return outarr
def extract_vars(wrfnc, timeidx, vars):
if isinstance(vars, str):
varlist = [vars]
# Note, always returns the full data set with the time dimension included
def _build_data_array(wrfnc, varname, timeidx):
multitime = _is_multi_time(timeidx)
var = wrfnc.variables[varname]
data = var[:]
attrs = OrderedDict(var.__dict__)
dimnames = var.dimensions
# Add the coordinate variables here.
coord_names = getattr(var, "coordinates").split()
lon_coord = coord_names[0]
lat_coord = coord_names[1]
coords = {}
lon_coord_var = wrfnc.variables[lon_coord]
lat_coord_var = wrfnc.variables[lat_coord]
if multitime:
if _is_moving_domain(wrfnc, lat_coord, lon_coord):
# Special case with a moving domain in a multi-time file,
# otherwise the projection parameters don't change
coords[lon_coord] = lon_coord_var.dimensions, lon_coord_var[:]
coords[lat_coord] = lat_coord_var.dimensions, lat_coord_var[:]
# Returned lats/lons arrays will have a time dimension, so proj
# will need to be a list due to moving corner points
lats, lons, proj_params = get_proj_params(wrfnc,
timeidx,
varname)
proj = [getproj(lats=lats[i,:],
lons=lons[i,:],
**proj_params) for i in xrange(lats.shape[0])]
else:
varlist = vars
coords[lon_coord] = (lon_coord_var.dimensions[1:],
lon_coord_var[0,:])
coords[lat_coord] = (lat_coord_var.dimensions[1:],
lat_coord_var[0,:])
# Domain not moving, so just get the first time
lats, lons, proj_params = get_proj_params(wrfnc, 0, varname)
proj = getproj(lats=lats, lons=lons, **proj_params)
else:
coords[lon_coord] = (lon_coord_var.dimensions[1:],
lon_coord_var[timeidx,:])
coords[lat_coord] = (lat_coord_var.dimensions[1:],
lat_coord_var[timeidx,:])
lats, lons, proj_params = get_proj_params(wrfnc, 0, varname)
proj = getproj(lats=lats, lons=lons, **proj_params)
coords[dimnames[0]] = extract_times(wrfnc, timeidx)
attrs["projection"] = proj
data_array = DataArray(data, name=varname, dims=dimnames, coords=coords,
attrs=attrs)
return data_array
def _extract_var(wrfnc, varname, timeidx, method, squeeze):
multitime = _is_multi_time(timeidx)
multifile = _is_multi_file(wrfnc)
# Single file, single time
if not multitime and not multifile:
return {var:wrfnc.variables[var][timeidx,:] for var in varlist}
elif multitime and not multifile:
return {var:n.squeeze(wrfnc.variables[var][:]) for var in varlist}
if not multifile:
if xarray_enabled():
return _build_data_array(wrfnc, varname, timeidx)
else:
return {var:combine_files(wrfnc, var, timeidx) for var in varlist}
if not multitime:
return wrfnc.variables[varname][timeidx,:]
else:
return wrfnc.variables[varname][:]
else:
return combine_files(wrfnc, varname, timeidx, method)
def extract_vars(wrfnc, timeidx, varnames, method="cat", squeeze=True):
if isinstance(varnames, str):
varlist = [varnames]
else:
varlist = varnames
return {var:_extract_var(wrfnc, var, timeidx, method, squeeze)
for var in varlist}
def _make_time(timearr):
return dt.datetime.strptime("".join(timearr[:]), "%Y-%m-%d_%H:%M:%S")
def _file_times(wrfnc,timeidx):
def _file_times(wrfnc, timeidx):
multitime = _is_multi_time(timeidx)
if multitime:
times = wrfnc.variables["Times"][:,:]
@ -102,7 +339,7 @@ def _file_times(wrfnc,timeidx): @@ -102,7 +339,7 @@ def _file_times(wrfnc,timeidx):
yield _make_time(times)
def extract_times(wrfnc,timeidx):
def extract_times(wrfnc, timeidx):
multi_file = _is_multi_file(wrfnc)
if not multi_file:
wrf_list = [wrfnc]
@ -169,6 +406,34 @@ def get_right_slices(var, right_ndims, fixed_val=0): @@ -169,6 +406,34 @@ def get_right_slices(var, right_ndims, fixed_val=0):
return [fixed_val]*extra_dim_num + [slice(None,None,None)]*right_ndims
def get_proj_params(wrfnc, timeidx=0, varname=None):
proj_params = extract_global_attrs(wrfnc, attrs=("MAP_PROJ",
"CEN_LAT", "CEN_LON",
"TRUELAT1", "TRUELAT2",
"MOAD_CEN_LAT", "STAND_LON",
"POLE_LAT", "POLE_LON"))
multitime = _is_multi_time(timeidx)
if not multitime:
time_idx_or_slice = timeidx
else:
time_idx_or_slice = slice(None, None, None)
if varname is not None:
coord_names = getattr(wrfnc.variables[varname], "coordinates").split()
lon_coord = coord_names[0]
lat_coord = coord_names[1]
else:
lat_coord = "XLAT"
lon_coord = "XLONG"
return (wrfnc.variables[lat_coord][time_idx_or_slice,:],
wrfnc.variables[lon_coord][time_idx_or_slice,:],
proj_params)

28
wrf_open/var/src/python/wrf/var/uvmet.py

@ -16,10 +16,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"): @@ -16,10 +16,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"):
if not ten_m:
try:
u_vars = extract_vars(wrfnc, timeidx, vars="U")
u_vars = extract_vars(wrfnc, timeidx, varnames="U")
except KeyError:
try:
uu_vars = extract_vars(wrfnc, timeidx, vars="UU")
uu_vars = extract_vars(wrfnc, timeidx, varnames="UU")
except KeyError:
raise RuntimeError("No valid wind data found in NetCDF file")
else:
@ -28,10 +28,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"): @@ -28,10 +28,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"):
u = destagger(u_vars["U"], -1)
try:
v_vars = extract_vars(wrfnc, timeidx, vars="V")
v_vars = extract_vars(wrfnc, timeidx, varnames="V")
except KeyError:
try:
vv_vars = extract_vars(wrfnc, timeidx, vars="VV")
vv_vars = extract_vars(wrfnc, timeidx, varnames="VV")
except KeyError:
raise RuntimeError("No valid wind data found in NetCDF file")
else:
@ -41,10 +41,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"): @@ -41,10 +41,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"):
else:
try:
u_vars = extract_vars(wrfnc, timeidx, vars="U10")
u_vars = extract_vars(wrfnc, timeidx, varnames="U10")
except KeyError:
try:
uu_vars = extract_vars(wrfnc, timeidx, vars="UU")
uu_vars = extract_vars(wrfnc, timeidx, varnames="UU")
except KeyError:
raise RuntimeError("No valid wind data found in NetCDF file")
else:
@ -55,10 +55,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"): @@ -55,10 +55,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"):
u = u_vars["U10"]
try:
v_vars = extract_vars(wrfnc, timeidx, vars="V10")
v_vars = extract_vars(wrfnc, timeidx, varnames="V10")
except KeyError:
try:
vv_vars = extract_vars(wrfnc, timeidx, vars="VV")
vv_vars = extract_vars(wrfnc, timeidx, varnames="VV")
except KeyError:
raise RuntimeError("No valid wind data found in NetCDF file")
else:
@ -82,12 +82,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"): @@ -82,12 +82,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"):
# No rotation needed for Mercator and Lat/Lon
return u,v
elif map_proj in (1,2):
lat_attrs = extract_global_attrs(wrfnc, attrs=("CEN_LAT",
"TRUELAT1",
lat_attrs = extract_global_attrs(wrfnc, attrs=("TRUELAT1",
"TRUELAT2"))
radians_per_degree = Constants.PI/180.0
# Rotation needed for Lambert and Polar Stereographic
cen_lat = lat_attrs["CEN_LAT"]
true_lat1 = lat_attrs["TRUELAT1"]
true_lat2 = lat_attrs["TRUELAT2"]
@ -104,10 +102,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"): @@ -104,10 +102,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"):
cen_lon = lon_attrs["STAND_LON"]
try:
xlat_m_vars = extract_vars(wrfnc, timeidx, vars="XLAT_M")
xlat_m_vars = extract_vars(wrfnc, timeidx, varnames="XLAT_M")
except KeyError:
try:
xlat_vars = extract_vars(wrfnc, timeidx, vars="XLAT")
xlat_vars = extract_vars(wrfnc, timeidx, varnames="XLAT")
except KeyError:
raise RuntimeError("xlat not found in NetCDF file")
else:
@ -116,10 +114,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"): @@ -116,10 +114,10 @@ def get_uvmet(wrfnc, timeidx=0, ten_m=False, units ="mps"):
lat = xlat_m_vars["XLAT_M"]
try:
xlon_m_vars = extract_vars(wrfnc, timeidx, vars="XLONG_M")
xlon_m_vars = extract_vars(wrfnc, timeidx, varnames="XLONG_M")
except KeyError:
try:
xlon_vars = extract_vars(wrfnc, timeidx, vars="XLONG")
xlon_vars = extract_vars(wrfnc, timeidx, varnames="XLONG")
except KeyError:
raise RuntimeError("xlong not found in NetCDF file")
else:

4
wrf_open/var/src/python/wrf/var/vorticity.py

@ -4,7 +4,7 @@ from wrf.var.util import extract_vars, extract_global_attrs @@ -4,7 +4,7 @@ from wrf.var.util import extract_vars, extract_global_attrs
__all__ = ["get_avo", "get_pvo"]
def get_avo(wrfnc, timeidx=0):
ncvars = extract_vars(wrfnc, timeidx, vars=("U", "V", "MAPFAC_U",
ncvars = extract_vars(wrfnc, timeidx, varnames=("U", "V", "MAPFAC_U",
"MAPFAC_V", "MAPFAC_M",
"F"))
@ -23,7 +23,7 @@ def get_avo(wrfnc, timeidx=0): @@ -23,7 +23,7 @@ def get_avo(wrfnc, timeidx=0):
def get_pvo(wrfnc, timeidx=0):
ncvars = extract_vars(wrfnc, timeidx, vars=("U", "V", "T", "P",
ncvars = extract_vars(wrfnc, timeidx, varnames=("U", "V", "T", "P",
"PB", "MAPFAC_U",
"MAPFAC_V", "MAPFAC_M",
"F"))

214
wrf_open/var/test/projtest.py

@ -0,0 +1,214 @@ @@ -0,0 +1,214 @@
import unittest as ut
from os.path import join, basename
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from netCDF4 import Dataset as NetCDF
PYNGL = True
try:
import Ngl
except ImportError:
PYNGL = False
BASEMAP = True
try:
import mpl_toolkits.basemap
except ImportError:
BASEMAP = False
CARTOPY = True
try:
from cartopy import crs, feature
except ImportError:
CARTOPY = False
from wrf.var import (get_proj_params, getproj, RotLatLonProj,
PolarStereographicProj)
FILE_DIR = "/Users/ladwig/Documents/wrf_files/"
WRF_FILES = [
join(FILE_DIR,"wrfout_d01_2016-02-25_18_00_00"),
join(FILE_DIR, "wrfout_d01_2008-09-29_23-30-00"),
join(FILE_DIR, "wrfout_d01_2010-06-13_21:00:00")]
def nz_proj():
lats = np.array([[-47.824014, -47.824014],
[-32.669853, -32.669853]])
lons = np.array([[163.839595, -179.693502],
[163.839595, -179.693502]])
params = {"MAP_PROJ" : 6,
"CEN_LAT" : -41.814869,
"CEN_LON" : 179.693502,
"TRUELAT1" : 0,
"TRUELAT2": 0,
"MOAD_CEN_LAT" : -41.814869,
"STAND_LON" : 180.0 - 179.693502,
"POLE_LAT" : 48.185131,
"POLE_LON" : 0.0}
return lats, lons, RotLatLonProj(lats=lats, lons=lons, **params)
def argentina_proj():
lats = np.array([[-57.144064, -57.144064],
[-21.154470, -21.154470]])
lons = np.array([[-86.893797, -37.089724],
[-86.893797, -37.089724]])
params = {"MAP_PROJ" : 6,
"CEN_LAT" : -39.222954,
"CEN_LON" : -65.980109,
"TRUELAT1" : 0,
"TRUELAT2": 0,
"MOAD_CEN_LAT" : -39.222954,
"STAND_LON" : 180.0 - -65.980109,
"POLE_LAT" : 90 + -39.222954,
"POLE_LON" : 0.0}
return lats, lons, RotLatLonProj(lats=lats, lons=lons, **params)
def south_polar_proj():
lats = np.array([[-30.0,-30.0],
[-30.0,-30.0]])
lons = np.array([[-120, 60],
[-120, 60]])
params = {"MAP_PROJ" : 2,
"CEN_LAT" : -90.0,
"CEN_LON" : 0,
"TRUELAT1" : -10.0,
"MOAD_CEN_LAT" : -90.0,
"STAND_LON" : 0}
return lats, lons, PolarStereographicProj(lats=lats, lons=lons, **params)
def north_polar_proj():
lats = np.array([[30.0,30.0],
[30.0,30.0]])
lons = np.array([[-45, 140],
[-45, 140]])
params = {"MAP_PROJ" : 2,
"CEN_LAT" : 90.0,
"CEN_LON" : 10,
"TRUELAT1" : 10.0,
"MOAD_CEN_LAT" : 90.0,
"STAND_LON" : 10}
return lats, lons, PolarStereographicProj(lats=lats, lons=lons, **params)
def dateline_rot_proj():
lats = np.array([[60.627974, 60.627974],
[71.717521, 71.717521]])
lons = np.array([[170.332771, -153.456292],
[170.332771, -153.456292]])
params = {"MAP_PROJ" : 6,
"CEN_LAT" : 66.335764,
"CEN_LON" : -173.143792,
"TRUELAT1" : 0,
"TRUELAT2": 0,
"MOAD_CEN_LAT" : 66.335764,
"STAND_LON" : 173.143792,
"POLE_LAT" : 90.0 - 66.335764,
"POLE_LON" : 180.0}
return lats, lons, RotLatLonProj(lats=lats, lons=lons, **params)
class WRFProjTest(ut.TestCase):
longMessage = True
def make_test(wrf_file=None, fixed_case=None):
if wrf_file is not None:
ncfile = NetCDF(wrf_file)
lats, lons, proj_params = get_proj_params(ncfile)
proj = getproj(lats=lats, lons=lons, **proj_params)
name_suffix = basename(wrf_file)
elif fixed_case is not None:
name_suffix = fixed_case
if fixed_case == "south_rot":
lats, lons, proj = nz_proj()
elif fixed_case == "arg_rot":
lats, lons, proj = argentina_proj()
elif fixed_case == "south_polar":
lats, lons, proj = south_polar_proj()
elif fixed_case == "north_polar":
lats, lons, proj = north_polar_proj()
elif fixed_case == "dateline_rot":
lats,lons,proj = dateline_rot_proj()
print "wrf proj4: {}".format(proj.proj4())
if PYNGL:
# PyNGL plotting
wks_type = "png"
wks = Ngl.open_wks(wks_type,"pyngl_{}".format(name_suffix))
mpres = proj.pyngl()
map = Ngl.map(wks,mpres)
Ngl.delete_wks(wks)
if BASEMAP:
# Basemap plotting
fig = plt.figure(figsize=(10,10))
ax = fig.add_axes([0.1,0.1,0.8,0.8])
# Define and plot the meridians and parallels
min_lat = np.amin(lats)
max_lat = np.amax(lats)
min_lon = np.amin(lons)
max_lon = np.amax(lons)
parallels = np.arange(np.floor(min_lat), np.ceil(max_lat),
(max_lat - min_lat)/5.0)
meridians = np.arange(np.floor(min_lon), np.ceil(max_lon),
(max_lon - min_lon)/5.0)
bm = proj.basemap()
bm.drawcoastlines(linewidth=.5)
#bm.drawparallels(parallels,labels=[1,1,1,1],fontsize=10)
#bm.drawmeridians(meridians,labels=[1,1,1,1],fontsize=10)
print "basemap proj4: {}".format(bm.proj4string)
plt.savefig("basemap_{}.png".format(name_suffix))
plt.close(fig)
if CARTOPY:
# Cartopy plotting
fig = plt.figure(figsize=(10,10))
ax = plt.axes([0.1,0.1,0.8,0.8], projection=proj.cartopy())
print "cartopy proj4: {}".format(proj.cartopy().proj4_params)
ax.coastlines('50m', linewidth=0.8)
#print proj.x_extents()
#print proj.y_extents()
ax.set_xlim(proj.cartopy_xlim())
ax.set_ylim(proj.cartopy_ylim())
ax.gridlines()
plt.savefig("cartopy_{}.png".format(name_suffix))
plt.close(fig)
if __name__ == "__main__":
for wrf_file in WRF_FILES:
test_func = make_test(wrf_file=wrf_file)
setattr(WRFProjTest, "test_proj", test_func)
test_func2 = make_test(fixed_case="south_rot")
setattr(WRFProjTest, "test_south_rot", test_func2)
test_func3 = make_test(fixed_case="arg_rot")
setattr(WRFProjTest, "test_arg_rot", test_func3)
test_func4 = make_test(fixed_case="south_polar")
setattr(WRFProjTest, "test_south_polar", test_func4)
test_func5 = make_test(fixed_case="north_polar")
setattr(WRFProjTest, "test_north_polar", test_func5)
test_func6 = make_test(fixed_case="dateline_rot")
setattr(WRFProjTest, "test_dateline_rot", test_func6)
ut.main()

2
wrf_open/var/test/utests.py

@ -440,7 +440,7 @@ if __name__ == "__main__": @@ -440,7 +440,7 @@ if __name__ == "__main__":
if var in ignore_vars:
continue
test_func1 = make_test(var, TEST_FILE, OUT_NC_FILE,pynio=True)
test_func1 = make_test(var, TEST_FILE, OUT_NC_FILE, pynio=True)
test_func2 = make_test(var, TEST_FILE, OUT_NC_FILE, multi=True,
pynio=True)
setattr(WRFVarsTest, 'test_pynio_{0}'.format(var), test_func1)

Loading…
Cancel
Save