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. 517
      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,
from_var, combine_dims, either, get_iterable, from_var, combine_dims, either, get_iterable,
IterWrapper, is_coordvar, latlon_coordvars, is_mapping, IterWrapper, is_coordvar, latlon_coordvars, is_mapping,
has_time_coord, is_multi_file, is_multi_time_req, 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, from .projection import (WrfProj, NullProjection, LambertConformal, Mercator,
PolarStereographic, LatLon, RotatedLatLon, PolarStereographic, LatLon, RotatedLatLon,
getproj) getproj)
@ -60,7 +63,10 @@ __all__ += ["to_np", "extract_global_attrs", "is_standard_wrf_var",
"from_var", "combine_dims", "either", "get_iterable", "from_var", "combine_dims", "either", "get_iterable",
"IterWrapper", "is_coordvar", "latlon_coordvars", "is_mapping", "IterWrapper", "is_coordvar", "latlon_coordvars", "is_mapping",
"has_time_coord", "is_multi_file", "is_multi_time_req", "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", __all__ += ["WrfProj", "NullProjection", "LambertConformal", "Mercator",
"PolarStereographic", "LatLon", "RotatedLatLon", "getproj"] "PolarStereographic", "LatLon", "RotatedLatLon", "getproj"]
__all__ += ["CoordPair"] __all__ += ["CoordPair"]

8
src/wrf/computation.py

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

54
src/wrf/geobnds.py

@ -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,
return func_wrapper 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", def set_uvmet_alg_metadata(units=None, description="earth rotated u,v",
latarg="lat", windarg="u"): latarg="lat", windarg="u"):

517
src/wrf/projection.py

@ -3,10 +3,10 @@ from __future__ import (absolute_import, division, print_function,
import numpy as np import numpy as np
import math import math
from .coordpair import CoordPair
from .config import basemap_enabled, cartopy_enabled, pyngl_enabled from .config import basemap_enabled, cartopy_enabled, pyngl_enabled
from .constants import Constants, ProjectionTypes from .constants import Constants, ProjectionTypes
from .projutils import dict_keys_to_upper from .projutils import dict_keys_to_upper
from .py3compat import viewitems
if cartopy_enabled(): if cartopy_enabled():
from cartopy import crs from cartopy import crs
@ -109,18 +109,6 @@ class WrfProj(object):
Attributes: 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. map_proj (:obj:`int`): Model projection integer id.
truelat1 (:obj:`float`): True latitude 1. truelat1 (:obj:`float`): True latitude 1.
@ -141,28 +129,11 @@ class WrfProj(object):
""" """
def __init__(self, bottom_left=None, top_right=None, def __init__(self, **proj_params):
lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.WrfProj` object. """Initialize a :class:`wrf.WrfProj` object.
Args: 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 **proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global have the same names as found in WRF output NetCDF global
attributes (case insensitive): attributes (case insensitive):
@ -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) up_proj_params = dict_keys_to_upper(proj_params)
self.map_proj = up_proj_params.get("MAP_PROJ", None) self.map_proj = up_proj_params.get("MAP_PROJ", None)
@ -225,7 +178,7 @@ class WrfProj(object):
self.stand_lon = self._cen_lon self.stand_lon = self._cen_lon
def _basemap(self, resolution='l'): def _basemap(self, geobounds, **kwargs):
return None return None
def _cf_params(self): def _cf_params(self):
@ -234,10 +187,34 @@ class WrfProj(object):
def _cartopy(self): def _cartopy(self):
return None return None
def _cart_extents(self): def _calc_extents(self, geobounds):
return ([self.ll_lon, self.ur_lon], [self.ll_lat, self.ur_lat]) # 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()
def _pyngl(self): 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)
return extents
def _pyngl(self, geobounds):
return None return None
def _proj4(self): def _proj4(self):
@ -249,7 +226,7 @@ class WrfProj(object):
semimajor_axis=Constants.WRF_EARTH_RADIUS, semimajor_axis=Constants.WRF_EARTH_RADIUS,
semiminor_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. """Return the x extents in projected coordinates for cartopy.
Returns: Returns:
@ -261,9 +238,20 @@ class WrfProj(object):
:mod:`cartopy`, :mod:`matplotlib` :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]
def cartopy_ylim(self): return x_extents
def cartopy_ylim(self, geobounds):
"""Return the y extents in projected coordinates for cartopy. """Return the y extents in projected coordinates for cartopy.
Returns: Returns:
@ -275,15 +263,23 @@ class WrfProj(object):
:mod:`cartopy`, :mod:`matplotlib` :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): def __repr__(self):
args = ("bottom_left={}, top_right={}, " args = ("stand_lon={}, moad_cen_lat={}, "
"stand_lon={}, moad_cen_lat={}, "
"truelat1={}, truelat2={}, " "truelat1={}, truelat2={}, "
"pole_lat={}, pole_lon={}".format((self.ll_lat, self.ll_lon), "pole_lat={}, pole_lon={}".format(self.stand_lon,
(self.ur_lat, self.ur_lon),
self.stand_lon,
self.moad_cen_lat, self.moad_cen_lat,
self.truelat1, self.truelat1,
self.truelat2, self.truelat2,
@ -291,13 +287,22 @@ class WrfProj(object):
self.pole_lon)) self.pole_lon))
return "{}({})".format(self.__class__.__name__, args) 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 """Return a :class:`matplotlib.mpl_toolkits.basemap.Basemap` object
for the map projection. for the map projection.
Arguments: 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: Returns:
@ -312,7 +317,8 @@ class WrfProj(object):
if not basemap_enabled(): if not basemap_enabled():
raise RuntimeError("'mpl_toolkits.basemap' is not " raise RuntimeError("'mpl_toolkits.basemap' is not "
"installed or is disabled") "installed or is disabled")
return self._basemap(resolution)
return self._basemap(geobounds, **kwargs)
def cartopy(self): def cartopy(self):
"""Return a :class:`cartopy.crs.Projection` subclass for the """Return a :class:`cartopy.crs.Projection` subclass for the
@ -333,9 +339,19 @@ class WrfProj(object):
"installed or is disabled") "installed or is disabled")
return self._cartopy() return self._cartopy()
def pyngl(self): def pyngl(self, geobounds, **kwargs):
"""Return a :class:`Ngl.Resources` object for the map projection. """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: Returns:
:class:`Ngl.Resources`: A dict-like object that contains the :class:`Ngl.Resources`: A dict-like object that contains the
@ -349,7 +365,7 @@ class WrfProj(object):
if not pyngl_enabled(): if not pyngl_enabled():
raise RuntimeError("'pyngl' is not " raise RuntimeError("'pyngl' is not "
"installed or is disabled") "installed or is disabled")
return self._pyngl() return self._pyngl(geobounds, **kwargs)
def proj4(self): def proj4(self):
"""Return the PROJ.4 string for the map projection. """Return the PROJ.4 string for the map projection.
@ -404,28 +420,11 @@ class LambertConformal(WrfProj):
:class:`Mercator`, :class:`RotatedLatLon` :class:`Mercator`, :class:`RotatedLatLon`
""" """
def __init__(self, bottom_left=None, top_right=None, def __init__(self, **proj_params):
lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.LambertConformal` object. """Initialize a :class:`wrf.LambertConformal` object.
Args: 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 **proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global have the same names as found in WRF output NetCDF global
attributes: attributes:
@ -438,8 +437,7 @@ class LambertConformal(WrfProj):
- 'POLE_LON': Pole longitude. - 'POLE_LON': Pole longitude.
""" """
super(LambertConformal, self).__init__(bottom_left, super(LambertConformal, self).__init__(**proj_params)
top_right, lats, lons, **proj_params)
self._std_parallels = [self.truelat1] self._std_parallels = [self.truelat1]
if self.truelat2 is not None: if self.truelat2 is not None:
@ -457,7 +455,7 @@ class LambertConformal(WrfProj):
return _cf_params return _cf_params
def _pyngl(self): def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled(): if not pyngl_enabled():
return None return None
@ -468,33 +466,40 @@ class LambertConformal(WrfProj):
_pyngl = Resources() _pyngl = Resources()
_pyngl.mpProjection = bytes("LambertConformal") _pyngl.mpProjection = bytes("LambertConformal")
_pyngl.mpDataBaseVersion = bytes("MediumRes") _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.mpLambertMeridianF = self.stand_lon
_pyngl.mpLambertParallel1F = self.truelat1 _pyngl.mpLambertParallel1F = self.truelat1
_pyngl.mpLambertParallel2F = truelat2 _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 return _pyngl
def _basemap(self, resolution='l'): def _basemap(self, geobounds, **kwargs):
if not basemap_enabled(): if not basemap_enabled():
return None return None
_basemap = Basemap(projection = "lcc", local_kwargs = dict(projection = "lcc",
lon_0 = self.stand_lon, lon_0 = self.stand_lon,
lat_0 = self.moad_cen_lat, lat_0 = self.moad_cen_lat,
lat_1 = self.truelat1, lat_1 = self.truelat1,
lat_2 = self.truelat2, lat_2 = self.truelat2,
llcrnrlat = self.ll_lat, llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = self.ur_lat, urcrnrlat = geobounds.top_right.lat,
llcrnrlon = self.ll_lon, llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = self.ur_lon, urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS, rsphere = Constants.WRF_EARTH_RADIUS,
resolution = resolution) resolution = 'l')
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap return _basemap
@ -510,19 +515,6 @@ class LambertConformal(WrfProj):
return _cartopy 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): def _proj4(self):
truelat2 = (self.truelat1 truelat2 = (self.truelat1
if _ismissing(self.truelat2) if _ismissing(self.truelat2)
@ -538,6 +530,7 @@ class LambertConformal(WrfProj):
self.stand_lon)) self.stand_lon))
return _proj4 return _proj4
class Mercator(WrfProj): class Mercator(WrfProj):
"""A :class:`wrf.WrfProj` subclass for Mercator projections. """A :class:`wrf.WrfProj` subclass for Mercator projections.
@ -548,28 +541,11 @@ class Mercator(WrfProj):
:class:`RotatedLatLon`, :class:`LambertConformal` :class:`RotatedLatLon`, :class:`LambertConformal`
""" """
def __init__(self, bottom_left=None, top_right=None, def __init__(self, **proj_params):
lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.Mercator` object. """Initialize a :class:`wrf.Mercator` object.
Args: 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 **proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global have the same names as found in WRF output NetCDF global
attributes: attributes:
@ -582,8 +558,7 @@ class Mercator(WrfProj):
- 'POLE_LON': Pole longitude. - 'POLE_LON': Pole longitude.
""" """
super(Mercator, self).__init__(bottom_left, top_right, super(Mercator, self).__init__(**proj_params)
lats, lons, **proj_params)
self._lat_ts = (None self._lat_ts = (None
if self.truelat1 == 0. or _ismissing(self.truelat1) if self.truelat1 == 0. or _ismissing(self.truelat1)
@ -600,38 +575,45 @@ class Mercator(WrfProj):
return _cf_params return _cf_params
def _pyngl(self): def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled(): if not pyngl_enabled():
return None return None
_pyngl = Resources() _pyngl = Resources()
_pyngl.mpProjection = bytes("Mercator") _pyngl.mpProjection = bytes("Mercator")
_pyngl.mpDataBaseVersion = bytes("MediumRes") _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.mpCenterLatF = 0.0
_pyngl.mpCenterLonF = self.stand_lon _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 return _pyngl
def _basemap(self, resolution='l'): def _basemap(self, geobounds, **kwargs):
if not basemap_enabled(): if not basemap_enabled():
return None return None
_basemap = Basemap(projection = "merc", local_kwargs = dict(projection = "merc",
lon_0 = self.stand_lon, lon_0 = self.stand_lon,
lat_0 = self.moad_cen_lat, lat_0 = self.moad_cen_lat,
lat_ts = self._lat_ts, lat_ts = self._lat_ts,
llcrnrlat = self.ll_lat, llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = self.ur_lat, urcrnrlat = geobounds.top_right.lat,
llcrnrlon = self.ll_lon, llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = self.ur_lon, urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS, rsphere = Constants.WRF_EARTH_RADIUS,
resolution = resolution) resolution = "l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap return _basemap
@ -654,20 +636,6 @@ class Mercator(WrfProj):
return _cartopy 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): def _proj4(self):
_proj4 = ("+proj=merc +units=meters +a={} +b={} " _proj4 = ("+proj=merc +units=meters +a={} +b={} "
@ -690,28 +658,11 @@ class PolarStereographic(WrfProj):
""" """
def __init__(self, bottom_left=None, top_right=None, def __init__(self, **proj_params):
lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.PolarStereographic` object. """Initialize a :class:`wrf.PolarStereographic` object.
Args: 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 **proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global have the same names as found in WRF output NetCDF global
attributes: attributes:
@ -743,18 +694,13 @@ class PolarStereographic(WrfProj):
return _cf_params return _cf_params
def _pyngl(self): def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled(): if not pyngl_enabled():
return None return None
_pyngl = Resources() _pyngl = Resources()
_pyngl.mpProjection = bytes("Stereographic") _pyngl.mpProjection = bytes("Stereographic")
_pyngl.mpDataBaseVersion = bytes("MediumRes") _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.mpCenterLonF = self.stand_lon
if self._hemi > 0: if self._hemi > 0:
@ -762,23 +708,35 @@ class PolarStereographic(WrfProj):
else: else:
_pyngl.mpCenterLatF = -90.0 _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 return _pyngl
def _basemap(self, resolution='l'): def _basemap(self, **kwargs):
if not basemap_enabled(): if not basemap_enabled():
return None return None
_basemap = Basemap(projection = "stere", local_kwargs = dict(projection = "stere",
lon_0 = self.stand_lon, lon_0 = self.stand_lon,
lat_0 = self._hemi, lat_0 = self._hemi,
lat_ts = self._lat_ts, lat_ts = self._lat_ts,
llcrnrlat = self.ll_lat, llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = self.ur_lat, urcrnrlat = geobounds.top_right.lat,
llcrnrlon = self.ll_lon, llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = self.ur_lon, urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS, rsphere = Constants.WRF_EARTH_RADIUS,
resolution = resolution) resolution = "l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap return _basemap
@ -794,19 +752,6 @@ class PolarStereographic(WrfProj):
return _cartopy 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): def _proj4(self):
_proj4 = ("+proj=stere +units=meters +a={} +b={} " _proj4 = ("+proj=stere +units=meters +a={} +b={} "
"+lat0={} +lon_0={} +lat_ts={}".format( "+lat0={} +lon_0={} +lat_ts={}".format(
@ -830,28 +775,11 @@ class LatLon(WrfProj):
:class:`Mercator`, :class:`LambertConformal` :class:`Mercator`, :class:`LambertConformal`
""" """
def __init__(self, bottom_left=None, top_right=None, def __init__(self, **proj_params):
lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.LatLon` object. """Initialize a :class:`wrf.LatLon` object.
Args: 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 **proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global have the same names as found in WRF output NetCDF global
attributes: attributes:
@ -874,37 +802,44 @@ class LatLon(WrfProj):
return _cf_params return _cf_params
def _pyngl(self): def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled(): if not pyngl_enabled():
return None return None
_pyngl = Resources() _pyngl = Resources()
_pyngl.mpProjection = bytes("CylindricalEquidistant") _pyngl.mpProjection = bytes("CylindricalEquidistant")
_pyngl.mpDataBaseVersion = bytes("MediumRes") _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.mpCenterLonF = self.stand_lon
_pyngl.mpCenterLatF = self.moad_cen_lat _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 return _pyngl
def _basemap(self, resolution='l'): def _basemap(self, geobounds, **kwargs):
if not basemap_enabled(): if not basemap_enabled():
return None return None
_basemap = Basemap(projection = "cyl", local_kwargs = dict(projection = "cyl",
lon_0 = self.stand_lon, lon_0 = self.stand_lon,
lat_0 = self.moad_cen_lat, lat_0 = self.moad_cen_lat,
llcrnrlat = self.ll_lat, llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = self.ur_lat, urcrnrlat = geobounds.top_right.lat,
llcrnrlon = self.ll_lon, llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = self.ur_lon, urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS, rsphere = Constants.WRF_EARTH_RADIUS,
resolution = resolution) resolution = "l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap return _basemap
@ -919,8 +854,9 @@ class LatLon(WrfProj):
return _cartopy return _cartopy
def _cart_extents(self): def _cart_extents(self, geobounds):
return ([self.ll_lon, self.ur_lon], [self.ll_lat, self.ur_lat]) return ([geobounds.bottom_left.lon, geobounds.top_right.lon],
[geobounds.bottom_left.lat, geobounds.top_right.lat])
def _proj4(self): def _proj4(self):
@ -971,28 +907,11 @@ class RotatedLatLon(WrfProj):
:class:`Mercator`, :class:`LambertConformal` :class:`Mercator`, :class:`LambertConformal`
""" """
def __init__(self, bottom_left=None, top_right=None, def __init__(self, **proj_params):
lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.RotatedLatLon` object. """Initialize a :class:`wrf.RotatedLatLon` object.
Args: 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 **proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global have the same names as found in WRF output NetCDF global
attributes: attributes:
@ -1005,8 +924,7 @@ class RotatedLatLon(WrfProj):
- 'POLE_LON': Pole longitude. - 'POLE_LON': Pole longitude.
""" """
super(RotatedLatLon, self).__init__(bottom_left, top_right, super(RotatedLatLon, self).__init__(**proj_params)
lats, lons, **proj_params)
# Need to determine hemisphere, typically pole_lon is 0 for southern # Need to determine hemisphere, typically pole_lon is 0 for southern
# hemisphere, 180 for northern hemisphere. If not, going to have # hemisphere, 180 for northern hemisphere. If not, going to have
@ -1062,38 +980,46 @@ class RotatedLatLon(WrfProj):
return _cf_params return _cf_params
def _pyngl(self): def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled(): if not pyngl_enabled():
return None return None
_pyngl = Resources() _pyngl = Resources()
_pyngl.mpProjection = bytes("CylindricalEquidistant") _pyngl.mpProjection = bytes("CylindricalEquidistant")
_pyngl.mpDataBaseVersion = bytes("MediumRes") _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.mpCenterLatF = self._pyngl_cen_lat
_pyngl.mpCenterLonF = self._pyngl_cen_lon _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 return _pyngl
def _basemap(self, resolution='l'): def _basemap(self, geobounds, **kwargs):
if not basemap_enabled(): if not basemap_enabled():
return None return None
_basemap = Basemap(projection = "rotpole", local_kwargs = dict(projection = "rotpole",
o_lat_p = self._bm_cart_pole_lat, o_lat_p = self._bm_cart_pole_lat,
o_lon_p = self.pole_lon, o_lon_p = self.pole_lon,
llcrnrlat = self.ll_lat, llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = self.ur_lat, urcrnrlat = geobounds.top_right.lat,
llcrnrlon = self.ll_lon, llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = self.ur_lon, urcrnrlon = geobounds.top_right.lon,
lon_0 = self._bm_lon_0, lon_0 = self._bm_lon_0,
rsphere = Constants.WRF_EARTH_RADIUS, rsphere = Constants.WRF_EARTH_RADIUS,
resolution = resolution) resolution = "l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap return _basemap
@ -1109,20 +1035,6 @@ class RotatedLatLon(WrfProj):
globe = self._globe()) globe = self._globe())
return _cartopy 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): def _proj4(self):
_proj4 = ("+proj=ob_tran +o_proj=latlon " _proj4 = ("+proj=ob_tran +o_proj=latlon "
"+a={} +b={} +to_meter={} +o_lon_p={} +o_lat_p={} " "+a={} +b={} +to_meter={} +o_lon_p={} +o_lat_p={} "
@ -1135,8 +1047,7 @@ class RotatedLatLon(WrfProj):
return _proj4 return _proj4
def getproj(bottom_left=None, top_right=None, def getproj(**proj_params):
lats=None, lons=None, **proj_params):
"""Return a :class:`wrf.WrfProj` subclass. """Return a :class:`wrf.WrfProj` subclass.
This functions serves as a factory function for returning a This functions serves as a factory function for returning a
@ -1144,22 +1055,6 @@ def getproj(bottom_left=None, top_right=None,
Args: 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 **proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global have the same names as found in WRF output NetCDF global
attributes: attributes:
@ -1183,26 +1078,20 @@ def getproj(bottom_left=None, top_right=None,
proj_type = up_proj_params.get("MAP_PROJ", 0) proj_type = up_proj_params.get("MAP_PROJ", 0)
if proj_type == ProjectionTypes.LAMBERT_CONFORMAL: if proj_type == ProjectionTypes.LAMBERT_CONFORMAL:
return LambertConformal(bottom_left, top_right, return LambertConformal(**proj_params)
lats, lons, **proj_params)
elif proj_type == ProjectionTypes.POLAR_STEREOGRAPHIC: elif proj_type == ProjectionTypes.POLAR_STEREOGRAPHIC:
return PolarStereographic(bottom_left, top_right, return PolarStereographic(**proj_params)
lats, lons, **proj_params)
elif proj_type == ProjectionTypes.MERCATOR: elif proj_type == ProjectionTypes.MERCATOR:
return Mercator(bottom_left, top_right, return Mercator(**proj_params)
lats, lons, **proj_params)
elif (proj_type == ProjectionTypes.ZERO or elif (proj_type == ProjectionTypes.ZERO or
proj_type == ProjectionTypes.LAT_LON): proj_type == ProjectionTypes.LAT_LON):
if (up_proj_params.get("POLE_LAT", None) == 90. if (up_proj_params.get("POLE_LAT", None) == 90.
and up_proj_params.get("POLE_LON", None) == 0.): and up_proj_params.get("POLE_LON", None) == 0.):
return LatLon(bottom_left, top_right, return LatLon(**proj_params)
lats, lons, **proj_params)
else: else:
return RotatedLatLon(bottom_left, top_right, return RotatedLatLon(**proj_params)
lats, lons, **proj_params)
else: else:
# Unknown projection # Unknown projection
return WrfProj(bottom_left, top_right, return WrfProj(**proj_params)
lats, lons, **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 @@
"* __Always uses NaN to represent missing/fill values__, rather than the MaskedArray type familiar to numpy users.\n", "* __Always uses NaN to represent missing/fill values__, rather than the MaskedArray type familiar to numpy users.\n",
"\n", "\n",
"\n", "\n",
"`npvalues` method:\n", "`to_np` method:\n",
"------------------\n", "------------------\n",
"1. If no missing/fill values, simply extracts the numpy array using the `DataArray.values` property.\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." "2. If missing/fill values are found, converts the NaN values to the fill values and returns a MaskedArray."
@ -103,7 +103,7 @@
"import numpy as np\n", "import numpy as np\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"from Nio import open_file\n", "from Nio import open_file\n",
"from wrf import getvar, npvalues\n", "from wrf import getvar, to_np\n",
"\n", "\n",
"# Open the output NetCDF file with PyNIO\n", "# Open the output NetCDF file with PyNIO\n",
"filename = \"wrfout_d01_2010-06-13_21-00-00\"\n", "filename = \"wrfout_d01_2010-06-13_21-00-00\"\n",
@ -123,8 +123,8 @@
"\n", "\n",
"print (terrainx)\n", "print (terrainx)\n",
"\n", "\n",
"# To extract the numpy array, use the npvalues function\n", "# To extract the numpy array, use the to_np function\n",
"terrain_numpy = npvalues(terrainx)\n", "terrain_numpy = to_np(terrainx)\n",
"print (\"\\nExtracted numpy array:\\n\")\n", "print (\"\\nExtracted numpy array:\\n\")\n",
"print (terrain_numpy)" "print (terrain_numpy)"
] ]
@ -148,7 +148,7 @@
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"from matplotlib.cm import get_cmap\n", "from matplotlib.cm import get_cmap\n",
"from Nio import open_file\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", "\n",
"# Open the output NetCDF file with PyNIO\n", "# Open the output NetCDF file with PyNIO\n",
"filename = \"wrfout_d01_2010-06-13_21-00-00\"\n", "filename = \"wrfout_d01_2010-06-13_21-00-00\"\n",
@ -160,17 +160,16 @@
"# Note: can also use the 'ter' variable\n", "# Note: can also use the 'ter' variable\n",
"terrainx = getvar(ncfile, \"HGT\", timeidx=0)\n", "terrainx = getvar(ncfile, \"HGT\", timeidx=0)\n",
"\n", "\n",
"# Use npvalues to extract the numpy array, since matplotlib does not handle xarray.DataArray natively\n", "# Use to_np to extract the numpy array, since matplotlib does not handle xarray.DataArray natively\n",
"terrain_data = npvalues(terrainx)\n", "terrain_data = to_np(terrainx)\n",
"\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", "# handle xarray.DataArray natively.\n",
"lons = npvalues(terrainx.coords[\"XLONG\"])\n", "lons = latlon_coords(terrainx, as_np=True)\n",
"lats = npvalues(terrainx.coords[\"XLAT\"])\n", "lats = latlon_coords(terrainx, as_np=True)\n",
"\n", "\n",
"# Extract the basemap object from the projection information\n", "# Extract the basemap object from the projection information\n",
"wrf_proj = terrainx.attrs[\"projection\"]\n", "bm = get_basemap(terrainx)\n",
"bm = wrf_proj.basemap()\n",
"\n", "\n",
"# Convert the lat/lon coordinates to projected x,y\n", "# Convert the lat/lon coordinates to projected x,y\n",
"x,y = bm(lons, lats)\n", "x,y = bm(lons, lats)\n",
@ -216,7 +215,7 @@
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"from matplotlib.cm import get_cmap\n", "from matplotlib.cm import get_cmap\n",
"from Nio import open_file\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", "\n",
"# Open the output NetCDF file with PyNIO\n", "# Open the output NetCDF file with PyNIO\n",
"filename = \"wrfout_d01_2010-06-13_21-00-00\"\n", "filename = \"wrfout_d01_2010-06-13_21-00-00\"\n",
@ -231,17 +230,16 @@
"# Dewpoint is a 3D variable, so let's just use the lowest level\n", "# Dewpoint is a 3D variable, so let's just use the lowest level\n",
"dewpointx_sfc = dewpointx[0,:,:]\n", "dewpointx_sfc = dewpointx[0,:,:]\n",
"\n", "\n",
"# Use npvalues to extract the numpy array, since matplotlib does not handle xarray.DataArray natively\n", "# Use to_np to extract the numpy array, since matplotlib does not handle xarray.DataArray natively\n",
"dewpoint_ndarray = npvalues(dewpointx_sfc)\n", "dewpoint_ndarray = to_np(dewpointx_sfc)\n",
"\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", "# handle xarray.DataArray natively.\n",
"lons = npvalues(dewpointx_sfc.coords[\"XLONG\"])\n", "lons = latlon_coords(dewpointx_sfc, as_np=True)\n",
"lats = npvalues(dewpointx_sfc.coords[\"XLAT\"])\n", "lats = latlon_coords(dewpointx_sfc, as_np=True)\n",
"\n", "\n",
"# Extract the basemap object from the projection information\n", "# Extract the basemap object from the projection information\n",
"wrf_proj = dewpointx_sfc.attrs[\"projection\"]\n", "bm = get_basemap(dewpointx_sfc)\n",
"bm = wrf_proj.basemap()\n",
"\n", "\n",
"# Convert the lat/lon coordinates to projected x,y\n", "# Convert the lat/lon coordinates to projected x,y\n",
"x,y = bm(lons, lats)\n", "x,y = bm(lons, lats)\n",
@ -288,7 +286,7 @@
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"from matplotlib.cm import get_cmap\n", "from matplotlib.cm import get_cmap\n",
"from Nio import open_file\n", "from Nio import open_file\n",
"from wrf import getvar, vertcross, npvalues\n", "from wrf import getvar, vertcross, to_np\n",
"\n", "\n",
"# Open the output NetCDF file with PyNIO\n", "# Open the output NetCDF file with PyNIO\n",
"filename = \"wrfout_d01_2010-06-13_21-00-00\"\n", "filename = \"wrfout_d01_2010-06-13_21-00-00\"\n",
@ -309,7 +307,7 @@
"p_vertx = vertcross(p, z, pivot_point=pivot_point, angle=angle, latlon=True)\n", "p_vertx = vertcross(p, z, pivot_point=pivot_point, angle=angle, latlon=True)\n",
"\n", "\n",
"# Extract the numpy array\n", "# Extract the numpy array\n",
"p_vert_array = npvalues(p_vertx)\n", "p_vert_array = to_np(p_vertx)\n",
"\n", "\n",
"# Create the figure\n", "# Create the figure\n",
"fig = plt.figure(figsize=(20,8))\n", "fig = plt.figure(figsize=(20,8))\n",
@ -325,13 +323,13 @@
"plt.colorbar(ax=ax)\n", "plt.colorbar(ax=ax)\n",
"\n", "\n",
"# Set the x-ticks to use latitude and longitude labels.\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_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", "plt.xticks(x_ticks[::100], x_labels[::100]) # Only use every 100th tick.\n",
"\n", "\n",
"# Set the y-ticks to be height.\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", "v_ticks = np.arange(vert_vals.shape[0])\n",
"plt.yticks(v_ticks[::10], vert_vals[::10]) # Only use every 10th tick.\n", "plt.yticks(v_ticks[::10], vert_vals[::10]) # Only use every 10th tick.\n",
"\n", "\n",
@ -364,7 +362,7 @@
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"from matplotlib.cm import get_cmap\n", "from matplotlib.cm import get_cmap\n",
"from Nio import open_file\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", "\n",
"# Open the output NetCDF file with PyNIO\n", "# Open the output NetCDF file with PyNIO\n",
"filename = \"wrfout_d01_2010-06-13_21-00-00\"\n", "filename = \"wrfout_d01_2010-06-13_21-00-00\"\n",
@ -385,12 +383,11 @@
"wspd_500 = interplevel(wspd, p, 500)\n", "wspd_500 = interplevel(wspd, p, 500)\n",
"\n", "\n",
"# Get the projection\n", "# Get the projection\n",
"wrf_proj = p.attrs[\"projection\"]\n", "bm = get_basemap(p)\n",
"bm = wrf_proj.basemap()\n",
"\n", "\n",
"# Basemap needs numpy arrays, extract with npvalues\n", "# Basemap needs numpy arrays, extract with to_np\n",
"lons = npvalues(ht_500.coords[\"XLONG\"])\n", "lons = latlon_coords(ht_500, as_np=True)\n",
"lats = npvalues(ht_500.coords[\"XLAT\"])\n", "lats = latlon_coords(ht_500, as_np=True)\n",
"\n", "\n",
"# Convert the lat/lon coordinates to projected x,y\n", "# Convert the lat/lon coordinates to projected x,y\n",
"x,y = bm(lons, lats)\n", "x,y = bm(lons, lats)\n",
@ -404,17 +401,17 @@
"bm.drawstates()\n", "bm.drawstates()\n",
"\n", "\n",
"# Make the 500 hPa height contours\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", "\n",
"# Use contour labels for height\n", "# Use contour labels for height\n",
"plt.clabel(ht_contours, inline=True, fontsize=12, fmt=\"%i\")\n", "plt.clabel(ht_contours, inline=True, fontsize=12, fmt=\"%i\")\n",
"\n", "\n",
"# Make the wind speed filled contours\n", "# Make the wind speed filled contours\n",
"levels = np.arange(40, 120, 10)\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", "\n",
"# Make the wind barbs. Only use every 50th in each direction.\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", "\n",
"# Make the color bar\n", "# Make the color bar\n",
"plt.colorbar(ax=ax, shrink=.7)\n", "plt.colorbar(ax=ax, shrink=.7)\n",

109
test/ipynb/WRF_python_demo.ipynb

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

18
test/ipynb/nocopy_test.ipynb

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

Loading…
Cancel
Save