Browse Source

Changed the mapping API. Users no longer have to use xarray coordinates directly. Added a new class for GeoBounds. Slices of variables should now be easier to plot. Added better metadata for smooth2d.

main
Bill Ladwig 8 years ago
parent
commit
1d877a6b6c
  1. 10
      src/wrf/api.py
  2. 8
      src/wrf/computation.py
  3. 54
      src/wrf/geobnds.py
  4. 40
      src/wrf/metadecorators.py
  5. 557
      src/wrf/projection.py
  6. 956
      src/wrf/util.py
  7. 728
      test/ipynb/Doc_Examples.ipynb
  8. 65
      test/ipynb/WRF_Workshop_Demo.ipynb
  9. 109
      test/ipynb/WRF_python_demo.ipynb
  10. 18
      test/ipynb/nocopy_test.ipynb

10
src/wrf/api.py

@ -24,7 +24,10 @@ from .util import (to_np, extract_global_attrs, is_standard_wrf_var, @@ -24,7 +24,10 @@ from .util import (to_np, extract_global_attrs, is_standard_wrf_var,
from_var, combine_dims, either, get_iterable,
IterWrapper, is_coordvar, latlon_coordvars, is_mapping,
has_time_coord, is_multi_file, is_multi_time_req,
get_coord_pairs, is_time_coord_var)
get_coord_pairs, is_time_coord_var, geobounds,
get_cartopy, get_basemap, get_pyngl, cartopy_xlim,
cartopy_ylim, latlon_coords)
from .geobnds import GeoBounds, NullGeoBounds
from .projection import (WrfProj, NullProjection, LambertConformal, Mercator,
PolarStereographic, LatLon, RotatedLatLon,
getproj)
@ -60,7 +63,10 @@ __all__ += ["to_np", "extract_global_attrs", "is_standard_wrf_var", @@ -60,7 +63,10 @@ __all__ += ["to_np", "extract_global_attrs", "is_standard_wrf_var",
"from_var", "combine_dims", "either", "get_iterable",
"IterWrapper", "is_coordvar", "latlon_coordvars", "is_mapping",
"has_time_coord", "is_multi_file", "is_multi_time_req",
"get_coord_pairs", "is_time_coord_var"]
"get_coord_pairs", "is_time_coord_var", "geobounds",
"get_cartopy", "get_basemap", "get_pyngl", "cartopy_xlim",
"cartopy_ylim", "latlon_coords"]
__all__ += ["GeoBounds", "NullGeoBounds"]
__all__ += ["WrfProj", "NullProjection", "LambertConformal", "Mercator",
"PolarStereographic", "LatLon", "RotatedLatLon", "getproj"]
__all__ += ["CoordPair"]

8
src/wrf/computation.py

@ -9,11 +9,11 @@ from .extension import (_interpz3d, _interp2dxy, _interp1d, _slp, _tk, _td, @@ -9,11 +9,11 @@ from .extension import (_interpz3d, _interp2dxy, _interp1d, _slp, _tk, _td,
_rh, _uvmet, _smooth2d, _cape, _cloudfrac, _ctt, _dbz,
_srhel, _udhel, _avo, _pvo, _eth, _wetbulb, _tv,
_omega, _pw)
from .util import from_var
from .decorators import convert_units
from .metadecorators import (set_alg_metadata, set_uvmet_alg_metadata,
set_interp_metadata, set_cape_alg_metadata,
set_cloudfrac_alg_metadata)
set_cloudfrac_alg_metadata,
set_smooth_metdata)
from .interputils import get_xy
@set_interp_metadata("xy")
@ -677,9 +677,7 @@ def uvmet(u, v, lat, lon, cen_long, cone, meta=True, units="m s-1"): @@ -677,9 +677,7 @@ def uvmet(u, v, lat, lon, cen_long, cone, meta=True, units="m s-1"):
return _uvmet(u, v, lat, lon, cen_long, cone)
@set_alg_metadata(2, "field",
description=from_var("field", "description"),
units=from_var("field", "units"))
@set_smooth_metdata()
def smooth2d(field, passes, meta=True):
"""Return the field smoothed.

54
src/wrf/geobnds.py

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
from __future__ import (absolute_import, division, print_function,
unicode_literals)
from .coordpair import CoordPair
class GeoBounds(object):
def __init__(self, bottom_left=None, top_right=None, lats=None, lons=None):
""" Initialize a :class:`wrf.GeoBounds` object.
Args:
bottom_left (:class:`wrf.CoordPair`, optional): The lower left
corner. Must also specify *top_right* if used.
Default is None.
top_right (:class:`wrf.CoordPair`, optional): The upper right
corner. Must also specify *bottom_left* if used.
Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
"""
if bottom_left is not None and top_right is not None:
self.bottom_left = bottom_left
self.top_right = top_right
elif lats is not None and lons is not None:
self.bottom_left = CoordPair(lat=lats[0,0], lon=lons[0,0])
self.top_right = CoordPair(lat=lats[-1,-1], lon=lons[-1,-1])
else:
raise ValueError("invalid corner point arguments")
def __repr__(self):
argstr = "{}, {}".format(repr(self.bottom_left),
repr(self.top_right))
return "{}({})".format(self.__class__.__name__, argstr)
class NullGeoBounds(GeoBounds):
def __init__(self):
pass
def __repr__(self):
return "{}()".format(self.__class__.__name__)

40
src/wrf/metadecorators.py

@ -1755,6 +1755,46 @@ def set_alg_metadata(alg_ndims, refvarname, @@ -1755,6 +1755,46 @@ def set_alg_metadata(alg_ndims, refvarname,
return func_wrapper
def set_smooth_metdata():
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"]
if do_meta is None:
do_meta = True
if not xarray_enabled() or not do_meta:
return wrapped(*args, **kwargs)
argvars = from_args(wrapped, ("field", "passes"),
*args, **kwargs)
field = argvars["field"]
passes = argvars["passes"]
result = wrapped(*args, **kwargs)
outname = "smooth2d"
outdimnames = ["dim_{}".format(i) for i in py3range(result.ndim)]
outcoords = OrderedDict()
outattrs = OrderedDict()
if isinstance(field, DataArray):
outname = "smooth_" + ucode(field.name)
outdimnames = list(field.dims)
outcoords.update(field.coords)
outattrs.update(field.attrs)
outattrs["passes"] = passes
if isinstance(result, ma.MaskedArray):
outattrs["_FillValue"] = result.fill_value
outattrs["missing_value"] = result.fill_value
return DataArray(result, name=outname, coords=outcoords,
dims=outdimnames, attrs=outattrs)
return func_wrapper
def set_uvmet_alg_metadata(units=None, description="earth rotated u,v",
latarg="lat", windarg="u"):

557
src/wrf/projection.py

@ -3,10 +3,10 @@ from __future__ import (absolute_import, division, print_function, @@ -3,10 +3,10 @@ from __future__ import (absolute_import, division, print_function,
import numpy as np
import math
from .coordpair import CoordPair
from .config import basemap_enabled, cartopy_enabled, pyngl_enabled
from .constants import Constants, ProjectionTypes
from .projutils import dict_keys_to_upper
from .py3compat import viewitems
if cartopy_enabled():
from cartopy import crs
@ -109,18 +109,6 @@ class WrfProj(object): @@ -109,18 +109,6 @@ class WrfProj(object):
Attributes:
ll_lat (:obj:`float`): Lower left corner latitude.
ll_lat (:obj:`float`): Lower left corner longitude.
ur_lat (:obj:`float`): Upper right corner latitude.
ur_lon (:obj:`float`): Upper right corner longitude.
bottom_left (indexable sequence): A pair of (ll_lat, ll_lon).
top_right (indexable sequence): A pair of (ur_lat, ur_lon).
map_proj (:obj:`int`): Model projection integer id.
truelat1 (:obj:`float`): True latitude 1.
@ -141,28 +129,11 @@ class WrfProj(object): @@ -141,28 +129,11 @@ class WrfProj(object):
"""
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
def __init__(self, **proj_params):
"""Initialize a :class:`wrf.WrfProj` object.
Args:
bottom_left (:class:`wrf.CoordPair`, optional): The lower left
corner. Must also specify *top_right* if used.
Default is None.
top_right (:class:`wrf.CoordPair`, optional): The upper right
corner. Must also specify *bottom_left* if used.
Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes (case insensitive):
@ -177,24 +148,6 @@ class WrfProj(object): @@ -177,24 +148,6 @@ class WrfProj(object):
"""
if bottom_left is not None and top_right is not None:
self.ll_lat = bottom_left.lat
self.ll_lon = bottom_left.lon
self.ur_lat = top_right.lat
self.ur_lon = top_right.lon
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 = CoordPair(lat=self.ll_lat, lon=self.ll_lon)
self.top_right = CoordPair(self.ur_lat, self.ur_lon)
else:
raise ValueError("invalid corner point arguments")
up_proj_params = dict_keys_to_upper(proj_params)
self.map_proj = up_proj_params.get("MAP_PROJ", None)
@ -225,7 +178,7 @@ class WrfProj(object): @@ -225,7 +178,7 @@ class WrfProj(object):
self.stand_lon = self._cen_lon
def _basemap(self, resolution='l'):
def _basemap(self, geobounds, **kwargs):
return None
def _cf_params(self):
@ -234,10 +187,34 @@ class WrfProj(object): @@ -234,10 +187,34 @@ class WrfProj(object):
def _cartopy(self):
return None
def _cart_extents(self):
return ([self.ll_lon, self.ur_lon], [self.ll_lat, self.ur_lat])
def _calc_extents(self, geobounds):
# Need to modify the extents for the new projection
pc = crs.PlateCarree()
xs, ys, _ = self._cartopy().transform_points(pc,
np.array([geobounds.bottom_left.lon,
geobounds.top_right.lon]),
np.array([geobounds.bottom_left.lat,
geobounds.top_right.lat])).T
_xlimits = xs.tolist()
_ylimits = ys.tolist()
return (_xlimits, _ylimits)
def _cart_extents(self, geobounds):
try:
_ = len(geobounds)
except TypeError: # Only a single object
extents = self._calc_extents(geobounds)
else:
extents = np.empty(geobounds.shape, np.object)
for idxs, geobnd_val in np.ndenumerate(geobounds):
extents[idxs] = self._calc_extents(geobnd_val)
def _pyngl(self):
return extents
def _pyngl(self, geobounds):
return None
def _proj4(self):
@ -249,7 +226,7 @@ class WrfProj(object): @@ -249,7 +226,7 @@ class WrfProj(object):
semimajor_axis=Constants.WRF_EARTH_RADIUS,
semiminor_axis=Constants.WRF_EARTH_RADIUS))
def cartopy_xlim(self):
def cartopy_xlim(self, geobounds):
"""Return the x extents in projected coordinates for cartopy.
Returns:
@ -261,9 +238,20 @@ class WrfProj(object): @@ -261,9 +238,20 @@ class WrfProj(object):
:mod:`cartopy`, :mod:`matplotlib`
"""
return self._cart_extents()[0]
try:
_ = len(geobounds)
except TypeError:
x_extents= self._cart_extents(geobounds)[0]
else:
extents = self._cart_extents(geobounds)
x_extents = np.empty(extents.shape, np.object)
for idxs, extent in np.ndenumerate(extents):
x_extents[idxs] = extent[0]
return x_extents
def cartopy_ylim(self):
def cartopy_ylim(self, geobounds):
"""Return the y extents in projected coordinates for cartopy.
Returns:
@ -275,15 +263,23 @@ class WrfProj(object): @@ -275,15 +263,23 @@ class WrfProj(object):
:mod:`cartopy`, :mod:`matplotlib`
"""
return self._cart_extents()[1]
try:
_ = len(geobounds)
except TypeError:
y_extents= self._cart_extents(geobounds)[1]
else:
extents = self._cart_extents(geobounds)
y_extents = np.empty(extents.shape, np.object)
for idxs, extent in np.ndenumerate(extents):
y_extents[idxs] = extent[1]
return y_extents
def __repr__(self):
args = ("bottom_left={}, top_right={}, "
"stand_lon={}, moad_cen_lat={}, "
args = ("stand_lon={}, moad_cen_lat={}, "
"truelat1={}, truelat2={}, "
"pole_lat={}, pole_lon={}".format((self.ll_lat, self.ll_lon),
(self.ur_lat, self.ur_lon),
self.stand_lon,
"pole_lat={}, pole_lon={}".format(self.stand_lon,
self.moad_cen_lat,
self.truelat1,
self.truelat2,
@ -291,13 +287,22 @@ class WrfProj(object): @@ -291,13 +287,22 @@ class WrfProj(object):
self.pole_lon))
return "{}({})".format(self.__class__.__name__, args)
def basemap(self, resolution='l'):
def basemap(self, geobounds, **kwargs):
"""Return a :class:`matplotlib.mpl_toolkits.basemap.Basemap` object
for the map projection.
Arguments:
resolution (:obj:`str`): The map resolution type.
geobounds (:class:`wrf.GeoBounds`, optional): The geobounds to
get the extents. If set to None and using the *var* parameter,
the geobounds will be taken from the variable. If using a
file, then the geobounds will be taken from the native grid.
**kwargs: Keyword arguments for creating a
:class:`matplotlib.mpl_toolkits.basemap.Basemap`. By default,
the domain bounds will be set to the native projection, the
resolution will be set to 'l', and the other projection
parameters will be set by the information in the file.
Returns:
@ -312,7 +317,8 @@ class WrfProj(object): @@ -312,7 +317,8 @@ class WrfProj(object):
if not basemap_enabled():
raise RuntimeError("'mpl_toolkits.basemap' is not "
"installed or is disabled")
return self._basemap(resolution)
return self._basemap(geobounds, **kwargs)
def cartopy(self):
"""Return a :class:`cartopy.crs.Projection` subclass for the
@ -333,9 +339,19 @@ class WrfProj(object): @@ -333,9 +339,19 @@ class WrfProj(object):
"installed or is disabled")
return self._cartopy()
def pyngl(self):
def pyngl(self, geobounds, **kwargs):
"""Return a :class:`Ngl.Resources` object for the map projection.
Args:
geobounds (:class:`wrf.GeoBounds`, optional): The geobounds to
get the extents. If set to None and using the *var* parameter,
the geobounds will be taken from the variable. If using a
file, then the geobounds will be taken from the native grid.
**kwargs: Additional PyNGL resources to set while creating the
:class:`Ngl.Resources` object.
Returns:
:class:`Ngl.Resources`: A dict-like object that contains the
@ -349,7 +365,7 @@ class WrfProj(object): @@ -349,7 +365,7 @@ class WrfProj(object):
if not pyngl_enabled():
raise RuntimeError("'pyngl' is not "
"installed or is disabled")
return self._pyngl()
return self._pyngl(geobounds, **kwargs)
def proj4(self):
"""Return the PROJ.4 string for the map projection.
@ -404,28 +420,11 @@ class LambertConformal(WrfProj): @@ -404,28 +420,11 @@ class LambertConformal(WrfProj):
:class:`Mercator`, :class:`RotatedLatLon`
"""
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
def __init__(self, **proj_params):
"""Initialize a :class:`wrf.LambertConformal` object.
Args:
bottom_left (indexable sequence, optional): The lower left corner
as a (latitude, longitude) pair. Must also specify *top_right*
if used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
@ -438,8 +437,7 @@ class LambertConformal(WrfProj): @@ -438,8 +437,7 @@ class LambertConformal(WrfProj):
- 'POLE_LON': Pole longitude.
"""
super(LambertConformal, self).__init__(bottom_left,
top_right, lats, lons, **proj_params)
super(LambertConformal, self).__init__(**proj_params)
self._std_parallels = [self.truelat1]
if self.truelat2 is not None:
@ -457,7 +455,7 @@ class LambertConformal(WrfProj): @@ -457,7 +455,7 @@ class LambertConformal(WrfProj):
return _cf_params
def _pyngl(self):
def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled():
return None
@ -468,33 +466,40 @@ class LambertConformal(WrfProj): @@ -468,33 +466,40 @@ class LambertConformal(WrfProj):
_pyngl = Resources()
_pyngl.mpProjection = bytes("LambertConformal")
_pyngl.mpDataBaseVersion = bytes("MediumRes")
_pyngl.mpLimitMode = bytes("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
_pyngl.mpLimitMode = bytes("Corners")
_pyngl.mpLeftCornerLonF = geobounds.bottom_left.lon
_pyngl.mpLeftCornerLatF = geobounds.bottom_left.lat
_pyngl.mpRightCornerLonF = geobounds.top_right.lon
_pyngl.mpRightCornerLatF = geobounds.top_right.lat
for key, val in viewitems(kwargs):
setattr(_pyngl, key, val)
return _pyngl
def _basemap(self, resolution='l'):
def _basemap(self, geobounds, **kwargs):
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 = resolution)
local_kwargs = dict(projection = "lcc",
lon_0 = self.stand_lon,
lat_0 = self.moad_cen_lat,
lat_1 = self.truelat1,
lat_2 = self.truelat2,
llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = geobounds.top_right.lat,
llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = 'l')
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap
@ -510,19 +515,6 @@ class LambertConformal(WrfProj): @@ -510,19 +515,6 @@ class LambertConformal(WrfProj):
return _cartopy
def _cart_extents(self):
# Need to modify the extents for the new projection
pc = crs.PlateCarree()
xs, ys, _ = 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)
def _proj4(self):
truelat2 = (self.truelat1
if _ismissing(self.truelat2)
@ -538,6 +530,7 @@ class LambertConformal(WrfProj): @@ -538,6 +530,7 @@ class LambertConformal(WrfProj):
self.stand_lon))
return _proj4
class Mercator(WrfProj):
"""A :class:`wrf.WrfProj` subclass for Mercator projections.
@ -548,28 +541,11 @@ class Mercator(WrfProj): @@ -548,28 +541,11 @@ class Mercator(WrfProj):
:class:`RotatedLatLon`, :class:`LambertConformal`
"""
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
def __init__(self, **proj_params):
"""Initialize a :class:`wrf.Mercator` object.
Args:
bottom_left (indexable sequence, optional): The lower left corner
as a (latitude, longitude) pair. Must also specify *top_right*
if used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
@ -582,8 +558,7 @@ class Mercator(WrfProj): @@ -582,8 +558,7 @@ class Mercator(WrfProj):
- 'POLE_LON': Pole longitude.
"""
super(Mercator, self).__init__(bottom_left, top_right,
lats, lons, **proj_params)
super(Mercator, self).__init__(**proj_params)
self._lat_ts = (None
if self.truelat1 == 0. or _ismissing(self.truelat1)
@ -600,38 +575,45 @@ class Mercator(WrfProj): @@ -600,38 +575,45 @@ class Mercator(WrfProj):
return _cf_params
def _pyngl(self):
def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled():
return None
_pyngl = Resources()
_pyngl.mpProjection = bytes("Mercator")
_pyngl.mpDataBaseVersion = bytes("MediumRes")
_pyngl.mpLimitMode = bytes("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
_pyngl.mpLimitMode = bytes("Corners")
_pyngl.mpLeftCornerLonF = geobounds.bottom_left.lon
_pyngl.mpLeftCornerLatF = geobounds.bottom_left.lat
_pyngl.mpRightCornerLonF = geobounds.top_right.lon
_pyngl.mpRightCornerLatF = geobounds.top_right.lat
for key, val in viewitems(kwargs):
setattr(_pyngl, key, val)
return _pyngl
def _basemap(self, resolution='l'):
def _basemap(self, geobounds, **kwargs):
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 = resolution)
local_kwargs = dict(projection = "merc",
lon_0 = self.stand_lon,
lat_0 = self.moad_cen_lat,
lat_ts = self._lat_ts,
llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = geobounds.top_right.lat,
llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = "l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap
@ -654,20 +636,6 @@ class Mercator(WrfProj): @@ -654,20 +636,6 @@ class Mercator(WrfProj):
return _cartopy
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)
def _proj4(self):
_proj4 = ("+proj=merc +units=meters +a={} +b={} "
@ -690,28 +658,11 @@ class PolarStereographic(WrfProj): @@ -690,28 +658,11 @@ class PolarStereographic(WrfProj):
"""
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
def __init__(self, **proj_params):
"""Initialize a :class:`wrf.PolarStereographic` object.
Args:
bottom_left (indexable sequence, optional): The lower left corner
as a (latitude, longitude) pair. Must also specify *top_right*
if used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
@ -743,18 +694,13 @@ class PolarStereographic(WrfProj): @@ -743,18 +694,13 @@ class PolarStereographic(WrfProj):
return _cf_params
def _pyngl(self):
def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled():
return None
_pyngl = Resources()
_pyngl.mpProjection = bytes("Stereographic")
_pyngl.mpDataBaseVersion = bytes("MediumRes")
_pyngl.mpLimitMode = bytes("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:
@ -762,23 +708,35 @@ class PolarStereographic(WrfProj): @@ -762,23 +708,35 @@ class PolarStereographic(WrfProj):
else:
_pyngl.mpCenterLatF = -90.0
_pyngl.mpLimitMode = bytes("Corners")
_pyngl.mpLeftCornerLonF = geobounds.bottom_left.lon
_pyngl.mpLeftCornerLatF = geobounds.bottom_left.lat
_pyngl.mpRightCornerLonF = geobounds.top_right.lon
_pyngl.mpRightCornerLatF = geobounds.top_right.lat
for key, val in viewitems(kwargs):
setattr(_pyngl, key, val)
return _pyngl
def _basemap(self, resolution='l'):
def _basemap(self, **kwargs):
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 = resolution)
local_kwargs = dict(projection = "stere",
lon_0 = self.stand_lon,
lat_0 = self._hemi,
lat_ts = self._lat_ts,
llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = geobounds.top_right.lat,
llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = "l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap
@ -794,19 +752,6 @@ class PolarStereographic(WrfProj): @@ -794,19 +752,6 @@ class PolarStereographic(WrfProj):
return _cartopy
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)
def _proj4(self):
_proj4 = ("+proj=stere +units=meters +a={} +b={} "
"+lat0={} +lon_0={} +lat_ts={}".format(
@ -830,28 +775,11 @@ class LatLon(WrfProj): @@ -830,28 +775,11 @@ class LatLon(WrfProj):
:class:`Mercator`, :class:`LambertConformal`
"""
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
def __init__(self, **proj_params):
"""Initialize a :class:`wrf.LatLon` object.
Args:
bottom_left (indexable sequence, optional): The lower left corner
as a (latitude, longitude) pair. Must also specify *top_right*
if used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
@ -874,37 +802,44 @@ class LatLon(WrfProj): @@ -874,37 +802,44 @@ class LatLon(WrfProj):
return _cf_params
def _pyngl(self):
def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled():
return None
_pyngl = Resources()
_pyngl.mpProjection = bytes("CylindricalEquidistant")
_pyngl.mpDataBaseVersion = bytes("MediumRes")
_pyngl.mpLimitMode = bytes("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
_pyngl.mpLimitMode = bytes("Corners")
_pyngl.mpLeftCornerLonF = geobounds.bottom_left.lon
_pyngl.mpLeftCornerLatF = geobounds.bottom_left.lat
_pyngl.mpRightCornerLonF = geobounds.top_right.lon
_pyngl.mpRightCornerLatF = geobounds.top_right.lat
for key, val in viewitems(kwargs):
setattr(_pyngl, key, val)
return _pyngl
def _basemap(self, resolution='l'):
def _basemap(self, geobounds, **kwargs):
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 = resolution)
local_kwargs = dict(projection = "cyl",
lon_0 = self.stand_lon,
lat_0 = self.moad_cen_lat,
llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = geobounds.top_right.lat,
llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = "l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap
@ -919,8 +854,9 @@ class LatLon(WrfProj): @@ -919,8 +854,9 @@ class LatLon(WrfProj):
return _cartopy
def _cart_extents(self):
return ([self.ll_lon, self.ur_lon], [self.ll_lat, self.ur_lat])
def _cart_extents(self, geobounds):
return ([geobounds.bottom_left.lon, geobounds.top_right.lon],
[geobounds.bottom_left.lat, geobounds.top_right.lat])
def _proj4(self):
@ -971,28 +907,11 @@ class RotatedLatLon(WrfProj): @@ -971,28 +907,11 @@ class RotatedLatLon(WrfProj):
:class:`Mercator`, :class:`LambertConformal`
"""
def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
def __init__(self, **proj_params):
"""Initialize a :class:`wrf.RotatedLatLon` object.
Args:
bottom_left (indexable sequence, optional): The lower left corner
as a (latitude, longitude) pair. Must also specify *top_right*
if used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
@ -1005,8 +924,7 @@ class RotatedLatLon(WrfProj): @@ -1005,8 +924,7 @@ class RotatedLatLon(WrfProj):
- 'POLE_LON': Pole longitude.
"""
super(RotatedLatLon, self).__init__(bottom_left, top_right,
lats, lons, **proj_params)
super(RotatedLatLon, self).__init__(**proj_params)
# Need to determine hemisphere, typically pole_lon is 0 for southern
# hemisphere, 180 for northern hemisphere. If not, going to have
@ -1062,38 +980,46 @@ class RotatedLatLon(WrfProj): @@ -1062,38 +980,46 @@ class RotatedLatLon(WrfProj):
return _cf_params
def _pyngl(self):
def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled():
return None
_pyngl = Resources()
_pyngl.mpProjection = bytes("CylindricalEquidistant")
_pyngl.mpDataBaseVersion = bytes("MediumRes")
_pyngl.mpLimitMode = bytes("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
_pyngl.mpLimitMode = bytes("Corners")
_pyngl.mpLeftCornerLonF = geobounds.bottom_left.lon
_pyngl.mpLeftCornerLatF = geobounds.bottom_left.lat
_pyngl.mpRightCornerLonF = geobounds.top_right.lon
_pyngl.mpRightCornerLatF = geobounds.top_right.lat
for key, val in viewitems(kwargs):
setattr(_pyngl, key, val)
return _pyngl
def _basemap(self, resolution='l'):
def _basemap(self, geobounds, **kwargs):
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 = resolution)
local_kwargs = dict(projection = "rotpole",
o_lat_p = self._bm_cart_pole_lat,
o_lon_p = self.pole_lon,
llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = geobounds.top_right.lat,
llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = geobounds.top_right.lon,
lon_0 = self._bm_lon_0,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = "l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap
@ -1109,20 +1035,6 @@ class RotatedLatLon(WrfProj): @@ -1109,20 +1035,6 @@ class RotatedLatLon(WrfProj):
globe = self._globe())
return _cartopy
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)
def _proj4(self):
_proj4 = ("+proj=ob_tran +o_proj=latlon "
"+a={} +b={} +to_meter={} +o_lon_p={} +o_lat_p={} "
@ -1135,8 +1047,7 @@ class RotatedLatLon(WrfProj): @@ -1135,8 +1047,7 @@ class RotatedLatLon(WrfProj):
return _proj4
def getproj(bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params):
def getproj(**proj_params):
"""Return a :class:`wrf.WrfProj` subclass.
This functions serves as a factory function for returning a
@ -1144,22 +1055,6 @@ def getproj(bottom_left=None, top_right=None, @@ -1144,22 +1055,6 @@ def getproj(bottom_left=None, top_right=None,
Args:
bottom_left (:class:`wrf.CoordPair`, optional): The lower left
corner. Must also specify *top_right* if used.
Default is None.
top_right (:class:`wrf.CoordPair`, optional): The upper right
corner. Must also specify *bottom_left* if used.
Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
@ -1183,26 +1078,20 @@ def getproj(bottom_left=None, top_right=None, @@ -1183,26 +1078,20 @@ def getproj(bottom_left=None, top_right=None,
proj_type = up_proj_params.get("MAP_PROJ", 0)
if proj_type == ProjectionTypes.LAMBERT_CONFORMAL:
return LambertConformal(bottom_left, top_right,
lats, lons, **proj_params)
return LambertConformal(**proj_params)
elif proj_type == ProjectionTypes.POLAR_STEREOGRAPHIC:
return PolarStereographic(bottom_left, top_right,
lats, lons, **proj_params)
return PolarStereographic(**proj_params)
elif proj_type == ProjectionTypes.MERCATOR:
return Mercator(bottom_left, top_right,
lats, lons, **proj_params)
return Mercator(**proj_params)
elif (proj_type == ProjectionTypes.ZERO or
proj_type == ProjectionTypes.LAT_LON):
if (up_proj_params.get("POLE_LAT", None) == 90.
and up_proj_params.get("POLE_LON", None) == 0.):
return LatLon(bottom_left, top_right,
lats, lons, **proj_params)
return LatLon(**proj_params)
else:
return RotatedLatLon(bottom_left, top_right,
lats, lons, **proj_params)
return RotatedLatLon(**proj_params)
else:
# Unknown projection
return WrfProj(bottom_left, top_right,
lats, lons, **proj_params)
return WrfProj(**proj_params)

956
src/wrf/util.py

File diff suppressed because it is too large Load Diff

728
test/ipynb/Doc_Examples.ipynb

File diff suppressed because one or more lines are too long

65
test/ipynb/WRF_Workshop_Demo.ipynb

@ -47,7 +47,7 @@ @@ -47,7 +47,7 @@
"* __Always uses NaN to represent missing/fill values__, rather than the MaskedArray type familiar to numpy users.\n",
"\n",
"\n",
"`npvalues` method:\n",
"`to_np` method:\n",
"------------------\n",
"1. If no missing/fill values, simply extracts the numpy array using the `DataArray.values` property.\n",
"2. If missing/fill values are found, converts the NaN values to the fill values and returns a MaskedArray."
@ -103,7 +103,7 @@ @@ -103,7 +103,7 @@
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from Nio import open_file\n",
"from wrf import getvar, npvalues\n",
"from wrf import getvar, to_np\n",
"\n",
"# Open the output NetCDF file with PyNIO\n",
"filename = \"wrfout_d01_2010-06-13_21-00-00\"\n",
@ -123,8 +123,8 @@ @@ -123,8 +123,8 @@
"\n",
"print (terrainx)\n",
"\n",
"# To extract the numpy array, use the npvalues function\n",
"terrain_numpy = npvalues(terrainx)\n",
"# To extract the numpy array, use the to_np function\n",
"terrain_numpy = to_np(terrainx)\n",
"print (\"\\nExtracted numpy array:\\n\")\n",
"print (terrain_numpy)"
]
@ -148,7 +148,7 @@ @@ -148,7 +148,7 @@
"import matplotlib.pyplot as plt\n",
"from matplotlib.cm import get_cmap\n",
"from Nio import open_file\n",
"from wrf import getvar, npvalues\n",
"from wrf import getvar, to_np, get_basemap, latlon_coords\n",
"\n",
"# Open the output NetCDF file with PyNIO\n",
"filename = \"wrfout_d01_2010-06-13_21-00-00\"\n",
@ -160,17 +160,16 @@ @@ -160,17 +160,16 @@
"# Note: can also use the 'ter' variable\n",
"terrainx = getvar(ncfile, \"HGT\", timeidx=0)\n",
"\n",
"# Use npvalues to extract the numpy array, since matplotlib does not handle xarray.DataArray natively\n",
"terrain_data = npvalues(terrainx)\n",
"# Use to_np to extract the numpy array, since matplotlib does not handle xarray.DataArray natively\n",
"terrain_data = to_np(terrainx)\n",
"\n",
"# Get the lat/lon 2D coordinate arrays. Use npvalues to extract the numpy array since basemap does not\n",
"# Get the lat/lon 2D coordinate arrays. Use to_np to extract the numpy array since basemap does not\n",
"# handle xarray.DataArray natively.\n",
"lons = npvalues(terrainx.coords[\"XLONG\"])\n",
"lats = npvalues(terrainx.coords[\"XLAT\"])\n",
"lons = latlon_coords(terrainx, as_np=True)\n",
"lats = latlon_coords(terrainx, as_np=True)\n",
"\n",
"# Extract the basemap object from the projection information\n",
"wrf_proj = terrainx.attrs[\"projection\"]\n",
"bm = wrf_proj.basemap()\n",
"bm = get_basemap(terrainx)\n",
"\n",
"# Convert the lat/lon coordinates to projected x,y\n",
"x,y = bm(lons, lats)\n",
@ -216,7 +215,7 @@ @@ -216,7 +215,7 @@
"import matplotlib.pyplot as plt\n",
"from matplotlib.cm import get_cmap\n",
"from Nio import open_file\n",
"from wrf import getvar, npvalues\n",
"from wrf import getvar, to_np, get_basemap, latlon_coords\n",
"\n",
"# Open the output NetCDF file with PyNIO\n",
"filename = \"wrfout_d01_2010-06-13_21-00-00\"\n",
@ -231,17 +230,16 @@ @@ -231,17 +230,16 @@
"# Dewpoint is a 3D variable, so let's just use the lowest level\n",
"dewpointx_sfc = dewpointx[0,:,:]\n",
"\n",
"# Use npvalues to extract the numpy array, since matplotlib does not handle xarray.DataArray natively\n",
"dewpoint_ndarray = npvalues(dewpointx_sfc)\n",
"# Use to_np to extract the numpy array, since matplotlib does not handle xarray.DataArray natively\n",
"dewpoint_ndarray = to_np(dewpointx_sfc)\n",
"\n",
"# Get the lat/lon 2D coordinate arrays. Use npvalues to extract the numpy array since basemap does not\n",
"# Get the lat/lon 2D coordinate arrays. Use to_np to extract the numpy array since basemap does not\n",
"# handle xarray.DataArray natively.\n",
"lons = npvalues(dewpointx_sfc.coords[\"XLONG\"])\n",
"lats = npvalues(dewpointx_sfc.coords[\"XLAT\"])\n",
"lons = latlon_coords(dewpointx_sfc, as_np=True)\n",
"lats = latlon_coords(dewpointx_sfc, as_np=True)\n",
"\n",
"# Extract the basemap object from the projection information\n",
"wrf_proj = dewpointx_sfc.attrs[\"projection\"]\n",
"bm = wrf_proj.basemap()\n",
"bm = get_basemap(dewpointx_sfc)\n",
"\n",
"# Convert the lat/lon coordinates to projected x,y\n",
"x,y = bm(lons, lats)\n",
@ -288,7 +286,7 @@ @@ -288,7 +286,7 @@
"import matplotlib.pyplot as plt\n",
"from matplotlib.cm import get_cmap\n",
"from Nio import open_file\n",
"from wrf import getvar, vertcross, npvalues\n",
"from wrf import getvar, vertcross, to_np\n",
"\n",
"# Open the output NetCDF file with PyNIO\n",
"filename = \"wrfout_d01_2010-06-13_21-00-00\"\n",
@ -309,7 +307,7 @@ @@ -309,7 +307,7 @@
"p_vertx = vertcross(p, z, pivot_point=pivot_point, angle=angle, latlon=True)\n",
"\n",
"# Extract the numpy array\n",
"p_vert_array = npvalues(p_vertx)\n",
"p_vert_array = to_np(p_vertx)\n",
"\n",
"# Create the figure\n",
"fig = plt.figure(figsize=(20,8))\n",
@ -325,13 +323,13 @@ @@ -325,13 +323,13 @@
"plt.colorbar(ax=ax)\n",
"\n",
"# Set the x-ticks to use latitude and longitude labels.\n",
"coord_pairs = npvalues(p_vertx.coords[\"xy_loc\"])\n",
"coord_pairs = to_np(p_vertx.coords[\"xy_loc\"])\n",
"x_ticks = np.arange(coord_pairs.shape[0])\n",
"x_labels = [pair.latlon_str() for pair in npvalues(coord_pairs)]\n",
"x_labels = [pair.latlon_str() for pair in to_np(coord_pairs)]\n",
"plt.xticks(x_ticks[::100], x_labels[::100]) # Only use every 100th tick.\n",
"\n",
"# Set the y-ticks to be height.\n",
"vert_vals = npvalues(p_vertx.coords[\"vertical\"])\n",
"vert_vals = to_np(p_vertx.coords[\"vertical\"])\n",
"v_ticks = np.arange(vert_vals.shape[0])\n",
"plt.yticks(v_ticks[::10], vert_vals[::10]) # Only use every 10th tick.\n",
"\n",
@ -364,7 +362,7 @@ @@ -364,7 +362,7 @@
"import matplotlib.pyplot as plt\n",
"from matplotlib.cm import get_cmap\n",
"from Nio import open_file\n",
"from wrf import getvar, interplevel, npvalues\n",
"from wrf import getvar, interplevel, to_np, get_basemap, latlon_coords\n",
"\n",
"# Open the output NetCDF file with PyNIO\n",
"filename = \"wrfout_d01_2010-06-13_21-00-00\"\n",
@ -385,12 +383,11 @@ @@ -385,12 +383,11 @@
"wspd_500 = interplevel(wspd, p, 500)\n",
"\n",
"# Get the projection\n",
"wrf_proj = p.attrs[\"projection\"]\n",
"bm = wrf_proj.basemap()\n",
"bm = get_basemap(p)\n",
"\n",
"# Basemap needs numpy arrays, extract with npvalues\n",
"lons = npvalues(ht_500.coords[\"XLONG\"])\n",
"lats = npvalues(ht_500.coords[\"XLAT\"])\n",
"# Basemap needs numpy arrays, extract with to_np\n",
"lons = latlon_coords(ht_500, as_np=True)\n",
"lats = latlon_coords(ht_500, as_np=True)\n",
"\n",
"# Convert the lat/lon coordinates to projected x,y\n",
"x,y = bm(lons, lats)\n",
@ -404,17 +401,17 @@ @@ -404,17 +401,17 @@
"bm.drawstates()\n",
"\n",
"# Make the 500 hPa height contours\n",
"ht_contours = bm.contour(x, y, npvalues(ht_500), 10, linewidths=2.0, colors=\"black\")\n",
"ht_contours = bm.contour(x, y, to_np(ht_500), 10, linewidths=2.0, colors=\"black\")\n",
"\n",
"# Use contour labels for height\n",
"plt.clabel(ht_contours, inline=True, fontsize=12, fmt=\"%i\")\n",
"\n",
"# Make the wind speed filled contours\n",
"levels = np.arange(40, 120, 10)\n",
"bm.contourf(x, y, npvalues(wspd_500), levels=levels, extend=\"max\", cmap=get_cmap(\"rainbow\"))\n",
"bm.contourf(x, y, to_np(wspd_500), levels=levels, extend=\"max\", cmap=get_cmap(\"rainbow\"))\n",
"\n",
"# Make the wind barbs. Only use every 50th in each direction.\n",
"bm.barbs(x[::50,::50], y[::50,::50], npvalues(u_500[::50, ::50]), npvalues(v_500[::50, ::50]))\n",
"bm.barbs(x[::50,::50], y[::50,::50], to_np(u_500[::50, ::50]), to_np(v_500[::50, ::50]))\n",
"\n",
"# Make the color bar\n",
"plt.colorbar(ax=ax, shrink=.7)\n",

109
test/ipynb/WRF_python_demo.ipynb

@ -151,8 +151,10 @@ @@ -151,8 +151,10 @@
"outputs": [],
"source": [
"from wrf import ALL_TIMES\n",
"import numpy as np\n",
"wrflist = [ncfile, ncfile, ncfile]\n",
"p_cat = getvar(wrflist, \"P\", timeidx=ALL_TIMES, method=\"cat\")\n",
"\n",
"print(p_cat)\n",
"del p_cat"
]
@ -324,7 +326,7 @@ @@ -324,7 +326,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"(Note all of the NaNs in the above routines which produce missing values (e.g. cape_2d). xarray always converts all masked_array missing values to NaN in order to work with pandas. To get back the original missing values in a numpy masked_array, you need to use the 'npvalues' method from wrf.)"
"(Note all of the NaNs in the above routines which produce missing values (e.g. cape_2d). xarray always converts all masked_array missing values to NaN in order to work with pandas. To get back the original missing values in a numpy masked_array, you need to use the 'to_np' method from wrf.)"
]
},
{
@ -335,8 +337,8 @@ @@ -335,8 +337,8 @@
},
"outputs": [],
"source": [
"from wrf import npvalues\n",
"masked_ndarray = npvalues(vard[\"slp\"])\n",
"from wrf import to_np\n",
"masked_ndarray = to_np(vard[\"slp\"])\n",
"print(type(masked_ndarray))\n",
"del masked_ndarray"
]
@ -443,14 +445,14 @@ @@ -443,14 +445,14 @@
"#print ((lats.shape[-2]-1) / 2)\n",
"#print ((lats.shape[-1]-1) / 2)\n",
"\n",
"#print (npvalues(lats[529, 899]))\n",
"#print (npvalues(lons[529, 899]))\n",
"#print (to_np(lats[529, 899]))\n",
"#print (to_np(lons[529, 899]))\n",
"\n",
"#print (npvalues(lats[529, 0]))\n",
"#print (npvalues(lons[529, 0]))\n",
"#print (to_np(lats[529, 0]))\n",
"#print (to_np(lons[529, 0]))\n",
"\n",
"#print (npvalues(lats[529, -1]))\n",
"#print (npvalues(lons[529, -1]))\n",
"#print (to_np(lats[529, -1]))\n",
"#print (to_np(lons[529, -1]))\n",
"\n",
"pivot_point = CoordPair(lat=38.5, lon=-97.5) \n",
"angle = 90.0\n",
@ -496,14 +498,14 @@ @@ -496,14 +498,14 @@
"#print ((lats.shape[-2]-1) / 2)\n",
"#print ((lats.shape[-1]-1) / 2)\n",
"\n",
"#print (npvalues(lats[529, 899]))\n",
"#print (npvalues(lons[529, 899]))\n",
"#print (to_np(lats[529, 899]))\n",
"#print (to_np(lons[529, 899]))\n",
"\n",
"#print (npvalues(lats[529, 0]))\n",
"#print (npvalues(lons[529, 0]))\n",
"#print (to_np(lats[529, 0]))\n",
"#print (to_np(lons[529, 0]))\n",
"\n",
"#print (npvalues(lats[529, -1]))\n",
"#print (npvalues(lons[529, -1]))\n",
"#print (to_np(lats[529, -1]))\n",
"#print (to_np(lons[529, -1]))\n",
"\n",
"pivot_point = CoordPair(lat=38.5, lon=-97.5) \n",
"angle = 90.0\n",
@ -759,15 +761,13 @@ @@ -759,15 +761,13 @@
"import cartopy.crs as crs\n",
"from cartopy.feature import NaturalEarthFeature\n",
"\n",
"from wrf import npvalues, getvar, smooth2d\n",
"from wrf import to_np, getvar, smooth2d, get_cartopy, cartopy_xlim, cartopy_ylim, latlon_coords\n",
"\n",
"slp = getvar(ncfile, \"slp\")\n",
"smooth_slp = smooth2d(slp, 3)\n",
"lons = npvalues(slp.coords[\"XLONG\"])\n",
"lats = npvalues(slp.coords[\"XLAT\"])\n",
"lats, lons = latlon_coords(slp)\n",
"\n",
"wrf_proj = slp.attrs[\"projection\"]\n",
"cart_proj = wrf_proj.cartopy()\n",
"cart_proj = get_cartopy(slp)\n",
"\n",
"fig = plt.figure(figsize=(10,10))\n",
"ax = plt.axes(projection=cart_proj)\n",
@ -778,16 +778,16 @@ @@ -778,16 +778,16 @@
"ax.coastlines('50m', linewidth=0.8)\n",
"\n",
"# Can only get this to work if I manually transform the lat/lon points to projected space.\n",
"xform_coords = cart_proj.transform_points(crs.PlateCarree(), npvalues(lons), npvalues(lats))\n",
"xform_coords = cart_proj.transform_points(crs.PlateCarree(), to_np(lons), to_np(lats))\n",
"x = xform_coords[:,:,0]\n",
"y = xform_coords[:,:,1]\n",
"\n",
"plt.contour(x, y, npvalues(smooth_slp), 10, colors=\"black\")\n",
"plt.contourf(x, y, npvalues(smooth_slp), 10)\n",
"plt.contour(x, y, to_np(smooth_slp), 10, colors=\"black\")\n",
"plt.contourf(x, y, to_np(smooth_slp), 10)\n",
"plt.colorbar(ax=ax, shrink=.47)\n",
"\n",
"ax.set_xlim(wrf_proj.cartopy_xlim())\n",
"ax.set_ylim(wrf_proj.cartopy_ylim())\n",
"ax.set_xlim(cartopy_xlim(slp))\n",
"ax.set_ylim(cartopy_ylim(slp))\n",
"ax.gridlines()\n"
]
},
@ -808,7 +808,7 @@ @@ -808,7 +808,7 @@
"import cartopy.crs as crs\n",
"from cartopy.feature import NaturalEarthFeature\n",
"\n",
"from wrf import npvalues, getvar, smooth2d\n",
"from wrf import to_np, getvar, smooth2d, get_cartopy, cartopy_xlim, cartopy_ylim, latlon_coords\n",
"\n",
"ncfile = Dataset(\"/Users/ladwig/Documents/wrf_files/wrfout_d01_2016-10-07_00_00_00\")\n",
"\n",
@ -819,14 +819,10 @@ @@ -819,14 +819,10 @@
"smooth_slp = smooth2d(slp, 3)\n",
"\n",
"# Get the numpy array from the XLAT and XLONG coordinates\n",
"lats = npvalues(slp.coords[\"XLAT\"])\n",
"lons = npvalues(slp.coords[\"XLONG\"])\n",
"\n",
"# Get the wrf.WrfProj object\n",
"wrf_proj = slp.attrs[\"projection\"]\n",
"lats, lons = latlon_coords(slp, as_np=True)\n",
"\n",
"# The cartopy() method returns a cartopy.crs projection object\n",
"cart_proj = wrf_proj.cartopy()\n",
"cart_proj = get_cartopy(slp)\n",
"\n",
"# Create a figure that's 10x10\n",
"fig = plt.figure(figsize=(10,10))\n",
@ -842,15 +838,15 @@ @@ -842,15 +838,15 @@
"# Make the contour outlines and filled contours for the smoothed sea level pressure.\n",
"# The transform keyword indicates that the lats and lons arrays are lat/lon coordinates and tells \n",
"# cartopy to transform the points in to grid space.\n",
"plt.contour(lons, lats, npvalues(smooth_slp), 10, colors=\"black\", transform=crs.PlateCarree())\n",
"plt.contourf(lons, lats, npvalues(smooth_slp), 10, transform=crs.PlateCarree())\n",
"plt.contour(lons, lats, to_np(smooth_slp), 10, colors=\"black\", transform=crs.PlateCarree())\n",
"plt.contourf(lons, lats, to_np(smooth_slp), 10, transform=crs.PlateCarree())\n",
"\n",
"# Add a color bar\n",
"plt.colorbar(ax=ax, shrink=.47)\n",
"\n",
"# Set the map limits\n",
"ax.set_xlim(wrf_proj.cartopy_xlim())\n",
"ax.set_ylim(wrf_proj.cartopy_ylim())\n",
"ax.set_xlim(cartopy_xlim(slp))\n",
"ax.set_ylim(cartopy_ylim(slp))\n",
"\n",
"# Add the gridlines\n",
"ax.gridlines()"
@ -871,7 +867,7 @@ @@ -871,7 +867,7 @@
"import cartopy.crs as crs\n",
"from cartopy.feature import NaturalEarthFeature\n",
"\n",
"from wrf import getvar, interplevel, npvalues\n",
"from wrf import getvar, interplevel, to_np, get_cartopy, cartopy_xlim, cartopy_ylim, latlon_coords\n",
"\n",
"\n",
"p = getvar(ncfile, \"pressure\")\n",
@ -883,11 +879,9 @@ @@ -883,11 +879,9 @@
"u_500 = interplevel(ua, p, 500)\n",
"v_500 = interplevel(va, p, 500)\n",
"\n",
"lons = ht_500.coords[\"XLONG\"]\n",
"lats = ht_500.coords[\"XLAT\"]\n",
"lats, lons = latlon_coords(ht_500)\n",
"\n",
"wrf_proj = slp.attrs[\"projection\"]\n",
"cart_proj = wrf_proj.cartopy()\n",
"cart_proj = get_cartopy(slp)\n",
"\n",
"fig = plt.figure(figsize=(20,20))\n",
"ax = plt.axes([0.1,0.1,0.8,0.8], projection=cart_proj)\n",
@ -898,16 +892,16 @@ @@ -898,16 +892,16 @@
"ax.coastlines('50m', linewidth=0.8)\n",
"\n",
"# Can only get this to work if I manually transform the lat/lon points to projected space.\n",
"xform_coords = cart_proj.transform_points(crs.PlateCarree(), npvalues(lons), npvalues(lats))\n",
"xform_coords = cart_proj.transform_points(crs.PlateCarree(), to_np(lons), to_np(lats))\n",
"x = xform_coords[:,:,0]\n",
"y = xform_coords[:,:,1]\n",
"\n",
"plt.contour(x, y, npvalues(ht_500), 20, cmap=get_cmap(\"plasma\"))\n",
"plt.barbs(x[::50,::50], y[::50,::50], npvalues(u_500[::50, ::50]), npvalues(v_500[::50, ::50]))\n",
"plt.contour(x, y, to_np(ht_500), 20, cmap=get_cmap(\"plasma\"))\n",
"plt.barbs(x[::50,::50], y[::50,::50], to_np(u_500[::50, ::50]), to_np(v_500[::50, ::50]))\n",
"plt.colorbar(ax=ax, shrink=.7)\n",
"\n",
"ax.set_xlim(wrf_proj.cartopy_xlim())\n",
"ax.set_ylim(wrf_proj.cartopy_ylim())\n",
"ax.set_xlim(cartopy_xlim(slp))\n",
"ax.set_ylim(cartopy_ylim(slp))\n",
"ax.gridlines()\n",
"\n"
]
@ -926,7 +920,7 @@ @@ -926,7 +920,7 @@
"import matplotlib.pyplot as plt\n",
"from matplotlib.cm import get_cmap\n",
"\n",
"from wrf import getvar, vertcross, npvalues, CoordPair\n",
"from wrf import getvar, vertcross, to_np, CoordPair\n",
"\n",
"p = getvar(ncfile, \"pressure\")\n",
"z = getvar(ncfile, \"z\", units=\"dm\")\n",
@ -962,13 +956,14 @@ @@ -962,13 +956,14 @@
"outputs": [],
"source": [
"import os\n",
"from wrf import getvar\n",
"from wrf import getvar, ALL_TIMES\n",
"from netCDF4 import Dataset as nc\n",
"\n",
"dir = \"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi\"\n",
"ncfilenames = [os.path.join(dir, x) for x in os.listdir(dir) if x.find(\"_d02_\") > 0]\n",
"ncfiles = [nc(x) for x in ncfilenames]\n",
"\n",
"\n",
"#print (ncfiles[0].variables[\"XLONG\"][0,0,-1], ncfiles[0].variables[\"XLONG\"][-1,0,-1])\n",
"#print (ncfiles[1].variables[\"XLONG\"][0,0,-1], ncfiles[1].variables[\"XLONG\"][-1,0,-1])\n",
"#print (ncfiles[-1].variables[\"XLONG\"][0,0,-1], ncfiles[-1].variables[\"XLONG\"][-1,0,-1])\n"
@ -982,7 +977,7 @@ @@ -982,7 +977,7 @@
},
"outputs": [],
"source": [
"p = getvar(ncfiles, \"P\", timeidx=3, method=\"join\", meta=True, squeeze=True)"
"p = getvar(ncfiles, \"ctt\", timeidx=ALL_TIMES)"
]
},
{
@ -1110,12 +1105,12 @@ @@ -1110,12 +1105,12 @@
"ncfiles = [nc(x) for x in ncfilenames]\n",
"\n",
"# Pressure using pivot and angle\n",
"from wrf import getvar, vertcross\n",
"from wrf import getvar, vertcross, CoordPair\n",
"\n",
"timeidx = 0\n",
"z = getvar(ncfiles, \"z\", timeidx, method=\"join\")\n",
"p = getvar(ncfiles, \"pressure\", timeidx, method=\"join\")\n",
"pivot_point = (z.shape[-1] / 2, z.shape[-2] / 2) \n",
"pivot_point = CoordPair(z.shape[-1] / 2, z.shape[-2] / 2) \n",
"angle = 40.0\n",
"\n",
"p_vert = vertcross(p, z, pivot_point=pivot_point, angle=angle)\n",
@ -1124,8 +1119,8 @@ @@ -1124,8 +1119,8 @@
"del p_vert\n",
"\n",
"# Pressure using start_point and end_point\n",
"start_point = (0, z.shape[-2]/2)\n",
"end_point = (-1, z.shape[-2]/2)\n",
"start_point = CoordPair(0, z.shape[-2]/2)\n",
"end_point = CoordPair(-1, z.shape[-2]/2)\n",
"\n",
"p_vert = vertcross(p, z, start_point=start_point, end_point=end_point)\n",
"print(p_vert)\n",
@ -1151,10 +1146,10 @@ @@ -1151,10 +1146,10 @@
"timeidx = None\n",
"\n",
"# T2 using pivot and angle\n",
"from wrf import interpline, getvar, npvalues\n",
"from wrf import interpline, getvar, to_np, CoordPair\n",
"\n",
"t2 = getvar(ncfiles, \"T2\", timeidx)\n",
"pivot_point = (t2.shape[-2] / 2, t2.shape[-1] / 2) \n",
"pivot_point = CoordPair(t2.shape[-2] / 2, t2.shape[-1] / 2) \n",
"angle = 90.0\n",
"\n",
"t2_line = interpline(t2, pivot_point=pivot_point, angle=angle, latlon=True)\n",
@ -1165,8 +1160,8 @@ @@ -1165,8 +1160,8 @@
"del t2_line\n",
"\n",
"# T2 using start_point and end_point\n",
"start_point = (t2.shape[-2]/2, 0)\n",
"end_point = (t2.shape[-2]/2, -1)\n",
"start_point = CoordPair(t2.shape[-2]/2, 0)\n",
"end_point = CoordPair(t2.shape[-2]/2, -1)\n",
"\n",
"t2_line = interpline(t2, start_point=start_point, end_point=end_point, latlon=True)\n",
"print(t2_line)\n",

18
test/ipynb/nocopy_test.ipynb

@ -218,7 +218,7 @@ @@ -218,7 +218,7 @@
},
"outputs": [],
"source": [
"from wrf import (ALL_TIMES, npvalues, Constants, getvar, extract_vars, destagger, \n",
"from wrf import (ALL_TIMES, to_np, Constants, getvar, extract_vars, destagger, \n",
" interp1d, interp2dxy, interpz3d, \n",
" slp, tk, td, rh, uvmet, smooth2d)\n",
"from netCDF4 import Dataset as nc\n",
@ -267,7 +267,7 @@ @@ -267,7 +267,7 @@
"_tk = tk(full_p, full_t)\n",
"_slp = slp(destag_ph, _tk, full_p, qvapor)\n",
"_td = td(full_p, qvapor)\n",
"_smooth2d = smooth2d(npvalues(_slp), 3)\n",
"_smooth2d = smooth2d(to_np(_slp), 3)\n",
"\n",
"_uvmet = getvar(wrfnc, \"uvmet\", timeidx=1)"
]
@ -298,7 +298,7 @@ @@ -298,7 +298,7 @@
},
"outputs": [],
"source": [
"from wrf import (ALL_TIMES, npvalues, Constants, getvar, extract_vars, destagger, \n",
"from wrf import (ALL_TIMES, to_np, Constants, getvar, extract_vars, destagger, \n",
" interp1d, interp2dxy, interpz3d, \n",
" slp, tk, td, rh, uvmet, smooth2d, extract_global_attrs)\n",
"from math import fabs, log, tan, sin, cos\n",
@ -428,7 +428,7 @@ @@ -428,7 +428,7 @@
"outputs": [],
"source": [
"import numpy as np\n",
"from wrf import (ALL_TIMES, npvalues, Constants, getvar, extract_vars, destagger, \n",
"from wrf import (ALL_TIMES, to_np, Constants, getvar, extract_vars, destagger, \n",
" interp1d, interp2dxy, interpz3d, \n",
" slp, tk, td, rh, uvmet, smooth2d, extract_global_attrs, xy)\n",
"from math import fabs, log, tan, sin, cos\n",
@ -557,21 +557,21 @@ @@ -557,21 +557,21 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "Python 2",
"language": "python",
"name": "python3"
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
"pygments_lexer": "ipython2",
"version": "2.7.12"
}
},
"nbformat": 4,

Loading…
Cancel
Save