Browse Source

Merge branch 'feature/contrib' into develop

lon0
Bill Ladwig 6 years ago
parent
commit
b40d1d6e2d
  1. 63
      doc/source/contrib.rst
  2. 10
      doc/source/index.rst
  3. 21
      src/wrf/__init__.py
  4. 55
      src/wrf/api.py
  5. 139
      src/wrf/cache.py
  6. 2349
      src/wrf/computation.py
  7. 104
      src/wrf/config.py
  8. 43
      src/wrf/constants.py
  9. 243
      src/wrf/coordpair.py
  10. 456
      src/wrf/decorators.py
  11. 56
      src/wrf/destag.py
  12. 1263
      src/wrf/extension.py
  13. 809
      src/wrf/g_cape.py
  14. 688
      src/wrf/g_cloudfrac.py
  15. 149
      src/wrf/g_ctt.py
  16. 228
      src/wrf/g_dbz.py
  17. 191
      src/wrf/g_dewpoint.py
  18. 465
      src/wrf/g_geoht.py
  19. 233
      src/wrf/g_helicity.py
  20. 816
      src/wrf/g_latlon.py
  21. 87
      src/wrf/g_omega.py
  22. 12
      src/wrf/g_precip.py
  23. 183
      src/wrf/g_pressure.py
  24. 95
      src/wrf/g_pw.py
  25. 176
      src/wrf/g_rh.py
  26. 106
      src/wrf/g_slp.py
  27. 623
      src/wrf/g_temp.py
  28. 97
      src/wrf/g_terrain.py
  29. 161
      src/wrf/g_times.py
  30. 1007
      src/wrf/g_uvmet.py
  31. 179
      src/wrf/g_vorticity.py
  32. 989
      src/wrf/g_wind.py
  33. 71
      src/wrf/geobnds.py
  34. 945
      src/wrf/interp.py
  35. 454
      src/wrf/interputils.py
  36. 547
      src/wrf/latlonutils.py
  37. 1841
      src/wrf/metadecorators.py
  38. 988
      src/wrf/projection.py
  39. 13
      src/wrf/projutils.py
  40. 118
      src/wrf/py3compat.py
  41. 489
      src/wrf/routines.py
  42. 463
      src/wrf/specialdec.py
  43. 440
      src/wrf/units.py
  44. 3505
      src/wrf/util.py
  45. 1
      src/wrf/version.py

63
doc/source/contrib.rst

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
.. _contrib_guide:
Contributor Guide
=================================
.. note::
This contributor guide is written for wrf-python v1.3.x. In the
not-too-distant future, wrf-python will undergo a significant refactoring
to remove the wrapt decorators (which don't serialize for dask), but the
concepts will remain the same as described below.
Ways to Contribute
-----------------------------
Users are encouraged to contribute various ways. This includes:
- Submitting a bug report
- Submitting bug fixes
- Submitting new Fortran computational routines
- Submitting new Python computational routines
- Submitting fully wrapped computational routines
Getting the source code
------------------------------
The source code is available on GitHub:
https://github.com/NCAR/wrf-python
To checkout the code::
git clone https://github.com/NCAR/wrf-python
Git Flow
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This project follows the GitFlow Workflow, which you can read about here if it
is new to you:
https://leanpub.com/git-flow/read
When you first clone the repository, by default you will be on the 'develop'
branch, which is what you should use for your development.
Pull Requests
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In order to submit changes, you must use GitHub to issue a pull request.
Overview of WRF-Python Internals
----------------------------------
WRF-Python is a collection of diagnostic and interpolation routines for WRF-ARW
data. The API consists of a handful of functions

10
doc/source/index.rst

@ -13,6 +13,14 @@ @@ -13,6 +13,14 @@
university corporation for atmospheric research,
pynio, pyngl, interpolation
.. .. image:: _static/images/nsf.png
.. :scale: 100%
.. :align: right
.. |
.. |
wrf-python
===========
@ -57,6 +65,7 @@ Indices and tables @@ -57,6 +65,7 @@ Indices and tables
* :ref:`modindex`
* :ref:`search`
--------------------
*The National Center for Atmospheric Research is sponsored by the National
@ -64,4 +73,3 @@ Science Foundation. Any opinions, findings and conclusions or recommendations @@ -64,4 +73,3 @@ Science Foundation. Any opinions, findings and conclusions or recommendations
expressed in this material do not necessarily reflect the views of the
National Science Foundation.*

21
src/wrf/__init__.py

@ -2,19 +2,24 @@ from __future__ import (absolute_import, division, print_function) @@ -2,19 +2,24 @@ from __future__ import (absolute_import, division, print_function)
import os
import pkg_resources
# For gfortran+msvc combination, extra shared libraries may exist (stored by numpy.distutils)
if os.name == "nt":
try:
try:
from . import api
from .api import *
except ImportError:
# For gfortran+msvc combination, extra shared libraries may exist
# (stored by numpy.distutils)
if os.name == "nt":
req = pkg_resources.Requirement.parse("wrf-python")
extra_dll_dir = pkg_resources.resource_filename(req,
extra_dll_dir = pkg_resources.resource_filename(req,
"wrf-python/.libs")
if os.path.isdir(extra_dll_dir):
os.environ["PATH"] += os.pathsep + extra_dll_dir
except ImportError:
pass
from . import api
from .api import *
from . import api
from .api import *
else:
raise
__all__ = []
__all__.extend(api.__all__)

55
src/wrf/api.py

@ -3,24 +3,24 @@ from .config import (xarray_enabled, disable_xarray, enable_xarray, @@ -3,24 +3,24 @@ from .config import (xarray_enabled, disable_xarray, enable_xarray,
basemap_enabled, disable_basemap, enable_basemap,
pyngl_enabled, enable_pyngl, disable_pyngl,
set_cache_size, get_cache_size, omp_enabled)
from .constants import (ALL_TIMES, Constants, ConversionFactors,
from .constants import (ALL_TIMES, Constants, ConversionFactors,
ProjectionTypes, default_fill,
OMP_SCHED_STATIC, OMP_SCHED_DYNAMIC,
OMP_SCHED_STATIC, OMP_SCHED_DYNAMIC,
OMP_SCHED_GUIDED, OMP_SCHED_AUTO)
from .destag import destagger
from .routines import getvar
from .computation import (xy, interp1d, interp2dxy, interpz3d, slp, tk, td, rh,
from .computation import (xy, interp1d, interp2dxy, interpz3d, slp, tk, td, rh,
uvmet, smooth2d, cape_2d, cape_3d, cloudfrac, ctt,
dbz, srhel, udhel, avo, pvo, eth, wetbulb, tvirtual,
omega, pw)
from .extension import (DiagnosticError, omp_set_num_threads,
omp_get_num_threads,
from .extension import (DiagnosticError, omp_set_num_threads,
omp_get_num_threads,
omp_get_max_threads, omp_get_thread_num,
omp_get_num_procs, omp_in_parallel,
omp_get_num_procs, omp_in_parallel,
omp_set_dynamic, omp_get_dynamic, omp_set_nested,
omp_get_nested, omp_set_schedule,
omp_get_schedule, omp_get_thread_limit,
omp_set_max_active_levels,
omp_get_nested, omp_set_schedule,
omp_get_schedule, omp_get_thread_limit,
omp_set_max_active_levels,
omp_get_max_active_levels, omp_get_level,
omp_get_ancestor_thread_num, omp_get_team_size,
omp_get_active_level, omp_in_final,
@ -32,23 +32,23 @@ from .extension import (DiagnosticError, omp_set_num_threads, @@ -32,23 +32,23 @@ from .extension import (DiagnosticError, omp_set_num_threads,
omp_get_wtime, omp_get_wtick)
from .interp import (interplevel, vertcross, interpline, vinterp)
from .g_latlon import (xy_to_ll, ll_to_xy, xy_to_ll_proj, ll_to_xy_proj)
from .py3compat import (viewitems, viewkeys, viewvalues, isstr, py2round,
from .py3compat import (viewitems, viewkeys, viewvalues, isstr, py2round,
py3range, ucode)
from .util import (to_np, extract_global_attrs, is_standard_wrf_var,
extract_dim, extract_vars, extract_times, combine_files,
extract_times, npbytes_to_str, is_moving_domain,
extract_times, npbytes_to_str, is_moving_domain,
is_staggered, get_left_indexes, iter_left_indexes,
get_right_slices, get_proj_params, from_args,
get_right_slices, get_proj_params, from_args,
args_to_list, arg_location, psafilepath, get_id,
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, geo_bounds,
get_coord_pairs, is_time_coord_var, geo_bounds,
get_cartopy, get_basemap, get_pyngl, cartopy_xlim,
cartopy_ylim, latlon_coords, ll_points, pairs_to_latlon)
from .geobnds import GeoBounds, NullGeoBounds
from .projection import (WrfProj, NullProjection, LambertConformal, Mercator,
PolarStereographic, LatLon, RotatedLatLon,
PolarStereographic, LatLon, RotatedLatLon,
getproj)
from .coordpair import CoordPair
from .interputils import to_xy_coords
@ -62,22 +62,22 @@ __all__ += ["xarray_enabled", "disable_xarray", "enable_xarray", @@ -62,22 +62,22 @@ __all__ += ["xarray_enabled", "disable_xarray", "enable_xarray",
"pyngl_enabled", "enable_pyngl", "disable_pyngl",
"set_cache_size", "get_cache_size", "omp_enabled"]
__all__ += ["ALL_TIMES", "Constants", "ConversionFactors", "ProjectionTypes",
"default_fill", "OMP_SCHED_STATIC", "OMP_SCHED_DYNAMIC",
"default_fill", "OMP_SCHED_STATIC", "OMP_SCHED_DYNAMIC",
"OMP_SCHED_GUIDED", "OMP_SCHED_AUTO"]
__all__ += ["destagger"]
__all__ += ["getvar"]
__all__ += ["xy", "interp1d", "interp2dxy", "interpz3d", "slp", "tk", "td",
__all__ += ["xy", "interp1d", "interp2dxy", "interpz3d", "slp", "tk", "td",
"rh", "uvmet", "smooth2d", "cape_2d", "cape_3d", "cloudfrac",
"ctt", "dbz", "srhel", "udhel", "avo", "pvo", "eth", "wetbulb",
"tvirtual", "omega", "pw"]
__all__ += ["DiagnosticError", "omp_set_num_threads",
"omp_get_num_threads",
__all__ += ["DiagnosticError", "omp_set_num_threads",
"omp_get_num_threads",
"omp_get_max_threads", "omp_get_thread_num",
"omp_get_num_procs", "omp_in_parallel",
"omp_get_num_procs", "omp_in_parallel",
"omp_set_dynamic", "omp_get_dynamic", "omp_set_nested",
"omp_get_nested", "omp_set_schedule",
"omp_get_schedule", "omp_get_thread_limit",
"omp_set_max_active_levels",
"omp_get_nested", "omp_set_schedule",
"omp_get_schedule", "omp_get_thread_limit",
"omp_set_max_active_levels",
"omp_get_max_active_levels", "omp_get_level",
"omp_get_ancestor_thread_num", "omp_get_team_size",
"omp_get_active_level", "omp_in_final",
@ -89,18 +89,18 @@ __all__ += ["DiagnosticError", "omp_set_num_threads", @@ -89,18 +89,18 @@ __all__ += ["DiagnosticError", "omp_set_num_threads",
"omp_get_wtime", "omp_get_wtick"]
__all__ += ["interplevel", "vertcross", "interpline", "vinterp"]
__all__ += ["xy_to_ll", "ll_to_xy", "xy_to_ll_proj", "ll_to_xy_proj"]
__all__ += ["viewitems", "viewkeys", "viewvalues", "isstr", "py2round",
__all__ += ["viewitems", "viewkeys", "viewvalues", "isstr", "py2round",
"py3range", "ucode"]
__all__ += ["to_np", "extract_global_attrs", "is_standard_wrf_var",
"extract_dim", "extract_vars", "extract_times", "combine_files",
"extract_times", "npbytes_to_str", "is_moving_domain",
"is_staggered", "get_left_indexes", "iter_left_indexes",
"get_right_slices", "get_proj_params", "from_args",
"extract_times", "npbytes_to_str", "is_moving_domain",
"is_staggered", "get_left_indexes", "iter_left_indexes",
"get_right_slices", "get_proj_params", "from_args",
"args_to_list", "arg_location", "psafilepath", "get_id",
"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", "geo_bounds",
"get_coord_pairs", "is_time_coord_var", "geo_bounds",
"get_cartopy", "get_basemap", "get_pyngl", "cartopy_xlim",
"cartopy_ylim", "latlon_coords", "ll_points", "pairs_to_latlon"]
__all__ += ["GeoBounds", "NullGeoBounds"]
@ -110,4 +110,3 @@ __all__ += ["CoordPair"] @@ -110,4 +110,3 @@ __all__ += ["CoordPair"]
__all__ += ["to_xy_coords"]
__all__ += ["cache_item", "get_cached_item"]
__all__ += ["__version__"]

139
src/wrf/cache.py

@ -11,158 +11,153 @@ _local_storage = local() @@ -11,158 +11,153 @@ _local_storage = local()
def _shrink_cache():
"""Shrink the cache if applicable.
This only applies if a user has modified the cache size, otherwise it
This only applies if a user has modified the cache size, otherwise it
just returns.
Returns:
None
"""
global _local_storage
try:
cache = _local_storage.cache
except AttributeError:
return
diff = len(cache) - get_cache_size()
if diff > 0:
for _ in py3range(diff):
cache.popitem(last=False)
def cache_item(key, product, value):
"""Store an item in the threadlocal cache.
The cache should be viewed as two nested dictionaries. The outer key is
usually the id for the sequence where the cached item was generated. The
The cache should be viewed as two nested dictionaries. The outer key is
usually the id for the sequence where the cached item was generated. The
inner key is the product type.
Storing a cached item behaves like:
cache[key][product] = value
The cache is thread local, so stored items are only available in
The cache is thread local, so stored items are only available in
the thread that cached them.
Args:
key (:obj:`int`): The outer dictionary cache key, which is typically
key (:obj:`int`): The outer dictionary cache key, which is typically
the id of the sequence where the cached item was generated.
product (:obj:`str`): The inner dictionary cache key, which is a
product (:obj:`str`): The inner dictionary cache key, which is a
string for the product type.
value (:obj:`object`): The object to store in the cache.
Returns:
None.
See Also:
:meth:`get_cached_item`
"""
global _local_storage
_shrink_cache()
if key is None or get_cache_size() == 0:
return
try:
cache = _local_storage.cache
except AttributeError:
_local_storage.cache = OrderedDict()
cache = _local_storage.cache
try:
_ = cache[key]
except KeyError:
if len(cache) >= get_cache_size():
cache.popitem(last=False) # Remove the oldest dataset
cache.popitem(last=False) # Remove the oldest dataset
cache[key] = OrderedDict()
cache[key][product] = value
def get_cached_item(key, product):
"""Return an item from the threadlocal cache.
The cache should be viewed as two nested dictionaries. The outer key is
usually the id for the sequence where the cached item was generated. The
The cache should be viewed as two nested dictionaries. The outer key is
usually the id for the sequence where the cached item was generated. The
inner key is the product type.
Retrieving a cached item behaves like:
value = cache[key][product]
The cache is thread local, so stored items are only available in
The cache is thread local, so stored items are only available in
the thread that cached them.
Args:
key (:obj:`int`): The outer dictionary cache key, which is typically
key (:obj:`int`): The outer dictionary cache key, which is typically
the id of the sequence where the cached item was generated.
product (:obj:`str`): The inner dictionary cache key, which is a
product (:obj:`str`): The inner dictionary cache key, which is a
string for the product type.
Returns:
:obj:`object`: The cached object.
See Also:
:meth:`cache_item`
"""
global _local_storage
_shrink_cache()
if key is None or get_cache_size == 0:
return None
cache = getattr(_local_storage, "cache", None)
if cache is None:
return None
if len(cache) == 0:
return None
prod_dict = cache.get(key, None)
if prod_dict is None:
return None
result = prod_dict.get(product, None)
return result
def _get_cache():
"""Return the threadlocal cache.
This is primarily used for testing.
Returns:
:class:`threading.local`
"""
global _local_storage
_shrink_cache()
return getattr(_local_storage, "cache", None)

2349
src/wrf/computation.py

File diff suppressed because it is too large Load Diff

104
src/wrf/config.py

@ -3,42 +3,43 @@ from __future__ import (absolute_import, division, print_function) @@ -3,42 +3,43 @@ from __future__ import (absolute_import, division, print_function)
from threading import local
import wrapt
from ._wrffortran import (fomp_enabled, fomp_set_num_threads,
from ._wrffortran import (fomp_enabled, fomp_set_num_threads,
fomp_set_schedule, fomp_set_dynamic,
omp_constants)
_local_config = local()
def _init_local():
global _local_config
_local_config.xarray_enabled = True
_local_config.cartopy_enabled = True
_local_config.basemap_enabled = True
_local_config.pyngl_enabled = True
_local_config.cache_size = 20
_local_config.initialized = True
try:
from xarray import DataArray
except ImportError:
_local_config.xarray_enabled = False
try:
from cartopy import crs
except ImportError:
_local_config.cartopy_enabled = False
try:
from mpl_toolkits.basemap import Basemap
except ImportError:
_local_config.basemap_enabled = False
try:
from Ngl import Resources
except ImportError:
_local_config.pyngl_enabled = False
# Initialize the main thread's configuration
_init_local()
@ -55,21 +56,21 @@ def init_local(): @@ -55,21 +56,21 @@ def init_local():
_init_local()
else:
if not init:
_init_local()
_init_local()
return wrapped(*args, **kwargs)
return func_wrapper
@init_local()
def xarray_enabled():
"""Return True if xarray is installed and enabled.
Returns:
:obj:`bool`: True if xarray is installed and enabled.
"""
global _local_config
return _local_config.xarray_enabled
@ -80,23 +81,23 @@ def disable_xarray(): @@ -80,23 +81,23 @@ def disable_xarray():
"""Disable xarray."""
global _local_config
_local_config.xarray_enabled = False
@init_local()
def enable_xarray():
"""Enable xarray."""
global _local_config
_local_config.xarray_enabled = True
@init_local()
def cartopy_enabled():
"""Return True if cartopy is installed and enabled.
Returns:
:obj:`bool`: True if cartopy is installed and enabled.
"""
global _local_config
return _local_config.cartopy_enabled
@ -107,23 +108,23 @@ def enable_cartopy(): @@ -107,23 +108,23 @@ def enable_cartopy():
"""Enable cartopy."""
global _local_config
_local_config.cartopy_enabled = True
@init_local()
def disable_cartopy():
"""Disable cartopy."""
global _local_config
_local_config.cartopy_enabled = True
@init_local()
def basemap_enabled():
"""Return True if basemap is installed and enabled.
Returns:
:obj:`bool`: True if basemap is installed and enabled.
"""
global _local_config
return _local_config.basemap_enabled
@ -134,7 +135,7 @@ def enable_basemap(): @@ -134,7 +135,7 @@ def enable_basemap():
"""Enable basemap."""
global _local_config
_local_config.basemap_enabled = True
@init_local()
def disable_basemap():
@ -146,11 +147,11 @@ def disable_basemap(): @@ -146,11 +147,11 @@ def disable_basemap():
@init_local()
def pyngl_enabled():
"""Return True if pyngl is installed and enabled.
Returns:
:obj:`bool`: True if pyngl is installed and enabled.
"""
global _local_config
return _local_config.pyngl_enabled
@ -161,63 +162,64 @@ def enable_pyngl(): @@ -161,63 +162,64 @@ def enable_pyngl():
"""Enable pyngl."""
global _local_config
_local_config.pyngl_enabled = True
@init_local()
@init_local()
def disable_pyngl():
"""Disable pyngl."""
global _local_config
_local_config.pyngl_enabled = True
@init_local()
@init_local()
def set_cache_size(size):
"""Set the maximum number of items that the threadlocal cache can retain.
This cache is primarily used for coordinate variables.
Args:
size (:obj:`int`): The number of items to retain in the cache.
Returns:
None
"""
global _local_config
_local_config.cache_size = size
@init_local()
@init_local()
def get_cache_size():
"""Return the maximum number of items that the threadlocal cache can retain.
"""Return the maximum number of items that the threadlocal cache can
retain.
Returns:
:obj:`int`: The maximum number of items the cache can retain.
"""
global _local_config
return int(_local_config.cache_size)
def omp_enabled():
"""Return True if OpenMP is enabled.
OpenMP is only enabled if compiled with OpenMP features.
Returns:
:obj:`bool`: True if OpenMP is enabled, otherwise False.
"""
return True if fomp_enabled() else False
# Set OpenMP to use 1 thread, static scheduler, and no dynamic
# Note: Using the raw extension functions here to prevent possible
# Note: Using the raw extension functions here to prevent possible
# circular import problems in the future.
fomp_set_num_threads(1)
fomp_set_schedule(omp_constants.fomp_sched_static, 0)

43
src/wrf/constants.py

@ -10,10 +10,12 @@ from ._wrffortran import wrf_constants, omp_constants @@ -10,10 +10,12 @@ from ._wrffortran import wrf_constants, omp_constants
#: Indicates that all times should be used in a diagnostic routine.
ALL_TIMES = None
class Constants(object):
pass
for key,val in viewitems(wrf_constants.__dict__):
for key, val in viewitems(wrf_constants.__dict__):
setattr(Constants, key.upper(), np.asscalar(val))
OMP_SCHED_STATIC = omp_constants.fomp_sched_static
@ -35,7 +37,7 @@ class ConversionFactors(object): @@ -35,7 +37,7 @@ class ConversionFactors(object):
M_TO_DM = 1.0/10.0
M_TO_FT = 3.28084
M_TO_MILES = .000621371
class ProjectionTypes(object):
ZERO = 0
@ -44,21 +46,22 @@ class ProjectionTypes(object): @@ -44,21 +46,22 @@ class ProjectionTypes(object):
MERCATOR = 3
LAT_LON = 6
# Create the default fill mapping based on type.
# Create the default fill mapping based on type.
_DEFAULT_FILL_MAP = {None: Constants.DEFAULT_FILL,
np.dtype(np.bool_) : False,
np.dtype(np.intc) : Constants.DEFAULT_FILL_INT32, # Usually true
np.dtype(np.int8) : Constants.DEFAULT_FILL_INT8,
np.dtype(np.uint8) : 255,
np.dtype(np.int16) : Constants.DEFAULT_FILL_INT16,
np.dtype(np.uint16) : 65535,
np.dtype(np.int32) : Constants.DEFAULT_FILL_INT32,
np.dtype(np.uint32) : 4294967295,
np.dtype(np.int64) : Constants.DEFAULT_FILL_INT64,
np.dtype(np.uint64) : 18446744073709551614,
np.dtype(np.float_) : Constants.DEFAULT_FILL_DOUBLE,
np.dtype(np.float32) : Constants.DEFAULT_FILL_FLOAT,
np.dtype(np.float64) : Constants.DEFAULT_FILL_DOUBLE
np.dtype(np.bool_): False,
np.dtype(np.intc): Constants.DEFAULT_FILL_INT32,
np.dtype(np.int8): Constants.DEFAULT_FILL_INT8,
np.dtype(np.uint8): 255,
np.dtype(np.int16): Constants.DEFAULT_FILL_INT16,
np.dtype(np.uint16): 65535,
np.dtype(np.int32): Constants.DEFAULT_FILL_INT32,
np.dtype(np.uint32): 4294967295,
np.dtype(np.int64): Constants.DEFAULT_FILL_INT64,
np.dtype(np.uint64): 18446744073709551614,
np.dtype(np.float_): Constants.DEFAULT_FILL_DOUBLE,
np.dtype(np.float32): Constants.DEFAULT_FILL_FLOAT,
np.dtype(np.float64): Constants.DEFAULT_FILL_DOUBLE
}
if version_info >= (3, ):
@ -76,9 +79,3 @@ else: @@ -76,9 +79,3 @@ else:
def default_fill(dtype=None):
dt = np.dtype(dtype) if dtype is not None else None
return _DEFAULT_FILL_MAP.get(dt, Constants.DEFAULT_FILL)

243
src/wrf/coordpair.py

@ -1,265 +1,254 @@ @@ -1,265 +1,254 @@
from __future__ import (absolute_import, division, print_function)
from .py3compat import py2round
def _binary_operator(operator):
"""Function wrapper for binary operators.
Args:
operator (method): The operator to wrap.
Returns:
method: An implementation for the *operator* type.
"""
def func(self, other):
"""Operator implementation.
Operator action is performed across the same class attributes when
Operator action is performed across the same class attributes when
the *other* object is a :class:`CoordPair`. If the *other* object is
a scalar value, the operator action is performed across all
a scalar value, the operator action is performed across all
attributes with the scalar value.
Args:
other (:class:`CoordPair` or scalar): A separate :class:`CoordPair`
other (:class:`CoordPair` or scalar): A separate :class:`CoordPair`
object or scalar value.
Returns:
:class:`CoordPair`: A new :class:`CoordPair` object that is the
:class:`CoordPair`: A new :class:`CoordPair` object that is the
result of the operator action.
"""
if isinstance(other, CoordPair):
args = [
None if getattr(self, attr) is None or getattr(other, attr) is None
else getattr(getattr(self, attr), operator)(getattr(other, attr))
for attr in ("x", "y", "lat", "lon")]
args = [None if getattr(self, attr) is None or
getattr(other, attr) is None else
getattr(getattr(self, attr), operator)(getattr(other,
attr))
for attr in ("x", "y", "lat", "lon")]
else:
args = [
None if getattr(self, attr) is None
else getattr(getattr(self, attr), operator)(other)
for attr in ("x", "y", "lat", "lon")]
args = [None if getattr(self, attr) is None
else getattr(getattr(self, attr), operator)(other)
for attr in ("x", "y", "lat", "lon")]
return CoordPair(*args)
return func
def _unary_operator(operator):
"""Function wrapper for unary operators.
Args:
operator (method): The operator to wrap.
Returns:
method: An implementation for the *operator* type.
"""
def func(self):
"""Operator implementation.
Operator action is performed across all class attributes.
Returns:
:class:`CoordPair`: A new :class:`CoordPair` object that is the
:class:`CoordPair`: A new :class:`CoordPair` object that is the
result of the operator action.
"""
args = [None if getattr(self, attr) is None
else getattr(getattr(self, attr), operator)()
else getattr(getattr(self, attr), operator)()
for attr in ("x", "y", "lat", "lon")]
return CoordPair(*args)
return func
def _cmp_operator(operator):
"""Function wrapper for comparison operators.
Args:
operator (method): The operator to wrap.
Returns:
method: An implementation for the *operator* type.
"""
def func(self, other):
"""Operator implementation.
Performs a comparison operation across all of the same class
attributes, and returns True if all these operations are True.
Performs a comparison operation across all of the same class
attributes, and returns True if all these operations are True.
Returns:
:obj:`boot`: Returns True if all comparisons across class
:obj:`boot`: Returns True if all comparisons across class
attributes returns True, otherwise False.
"""
vals = [getattr(getattr(self, attr), operator)(getattr(other, attr))
for attr in ("x", "y", "lat", "lon")
for attr in ("x", "y", "lat", "lon")
if getattr(self, attr) is not None]
return all(vals)
return func
class CoordPair(object):
"""A class that stores (x, y) and/or (latitude, longitude)
"""A class that stores (x, y) and/or (latitude, longitude)
coordinate pairs.
Most math operators are supplied. When the other operand is a
:class:`CoordPair`, the operation is performed with the same attribute.
When a math operation uses a scalar as the other operand, the
operation is applied across all attributes.
Most math operators are supplied. When the other operand is a
:class:`CoordPair`, the operation is performed with the same attribute.
When a math operation uses a scalar as the other operand, the
operation is applied across all attributes.
Attributes:
x (:obj:`float`): The x-coordinate.
y (:obj:`float`): The y-coordinate.
lat (:obj:`float`): The latitude coordinate.
lon (:obj:`float`): The longitude coordinate.
"""
def __init__(self, x=None, y=None, lat=None, lon=None):
"""Initialize a :class:`CoordPair` object.
Args:
x (:obj:`float`, optional): The x-coordinate.
y (:obj:`float`, optional): The y-coordinate.
lat (:obj:`float`, optional): The latitude coordinate.
lon (:obj:`float`, optional): The longitude coordinate.
"""
self.x = x
self.y = y
self.lat = lat
self.lon = lon
def __repr__(self):
args = []
if self.x is not None:
args.append("x={}".format(self.x))
args.append("y={}".format(self.y))
if self.lat is not None:
args.append("lat={}".format(self.lat))
args.append("lon={}".format(self.lon))
argstr = ", ".join(args)
return "{}({})".format(self.__class__.__name__, argstr)
def __str__(self):
return self.__repr__()
def xy_str(self, fmt="{:.4f}, {:.4f}"):
"""Return a :obj:`str` for the (x,y) coordinate pair.
Args:
fmt (:obj:`str`): The format string. Default is '{:.4f}, {:.4f}'
Returns:
:obj:`str`: A string for the (x,y) coordinate pair
"""
if self.x is None or self.y is None:
return None
return fmt.format(self.x, self.y)
def latlon_str(self, fmt="{:.4f}, {:.4f}"):
"""Return a :obj:`str` for the (latitude, longitude) coordinate pair.
Args:
fmt (:obj:`str`): The format string. Default is '{:.4f}, {:.4f}'
Returns:
:obj:`str`: A string for the (latitude, longitude) coordinate pair
"""
if self.lat is None or self.lon is None:
return None
return fmt.format(self.lat, self.lon)
def __round__(self, ndigits=None):
"""Return a new :class:`CoordPair` object with all coordinate values
rounded to the nearest integer.
Args:
ndigits (:obj:`int`): The number of digits.
Returns:
:class:`CoordPair`: A CoordPair object.
"""
args = [None if getattr(self, attr) is None
else py2round(getattr(self, attr), ndigits)
else py2round(getattr(self, attr), ndigits)
for attr in ("x", "y", "lat", "lon")]
return CoordPair(*args)
def __pow__(self, other, modulo=None):
if isinstance(other, CoordPair):
args = [
None if getattr(self, attr) is None or getattr(other, attr) is None
else getattr(getattr(self, attr), "__pow__")(getattr(other, attr),
modulo)
for attr in ("x", "y", "lat", "lon")]
args = [None if getattr(self, attr) is None or
getattr(other, attr) is None
else getattr(getattr(self, attr), "__pow__")(
getattr(other, attr), modulo)
for attr in ("x", "y", "lat", "lon")]
else:
args = [
None if getattr(self, attr) is None
else getattr(getattr(self, attr), "__pow__")(other, modulo)
for attr in ("x", "y", "lat", "lon")]
args = [None if getattr(self, attr) is None
else getattr(getattr(self, attr), "__pow__")(other, modulo)
for attr in ("x", "y", "lat", "lon")]
return CoordPair(*args)
def __rpow__(self, other):
return self.__pow__(other)
for operator in ("__add__", "__divmod__", "__floordiv__", "__mod__",
"__mul__", "__sub__", "__truediv__", "__radd__",
"__rdivmod__", "__rsub__", "__rmul__", "__rtruediv__",
for operator in ("__add__", "__divmod__", "__floordiv__", "__mod__",
"__mul__", "__sub__", "__truediv__", "__radd__",
"__rdivmod__", "__rsub__", "__rmul__", "__rtruediv__",
"__rfloordiv__", "__rmod__"):
setattr(CoordPair, operator, _binary_operator(operator))
for operator in ("__neg__", "__pos__", "__abs__", "__invert__"):
setattr(CoordPair, operator, _unary_operator(operator))
for operator in ("__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__"):
setattr(CoordPair, operator, _cmp_operator(operator))

456
src/wrf/decorators.py

@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function) @@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function)
from collections import Iterable, OrderedDict
import wrapt
import wrapt
import numpy as np
import numpy.ma as ma
@ -14,188 +14,177 @@ from .constants import default_fill @@ -14,188 +14,177 @@ from .constants import default_fill
if xarray_enabled():
from xarray import DataArray
def convert_units(unit_type, alg_unit):
"""A decorator that converts the units from the wrapped function's output.
The desired units are determined from the wrapped function's arguments.
Args:
unit_type (:obj:`str`): The unit type. Choices are: 'wind',
unit_type (:obj:`str`): The unit type. Choices are: 'wind',
'pressure', 'temp', or 'height'.
alg_unit (:obj:`str`): The units returned by the wrapped function,
alg_unit (:obj:`str`): The units returned by the wrapped function,
which is usually the units returned by the Fortran routine.
Returns:
:class:`numpy.ndarray`: The wrapped function's output in the desired
:class:`numpy.ndarray`: The wrapped function's output in the desired
units.
"""
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
desired_units = from_args(wrapped, "units", *args, **kwargs)["units"]
u_cleaned = dealias_and_clean_unit(desired_units)
check_units(u_cleaned, unit_type)
# Unit conversion done here
return do_conversion(wrapped(*args, **kwargs), unit_type,
return do_conversion(wrapped(*args, **kwargs), unit_type,
alg_unit, desired_units)
return func_wrapper
return func_wrapper
#def _calc_out_dims(outvar, left_dims):
# """
#
# """
# #left_dims = [x for x in left_dims]
# #right_dims = [x for x in outvar.shape]
# #return left_dims + right_dims
#
# return left_dims + outvar.shape
def left_iteration(ref_var_expected_dims,
ref_var_right_ndims,
insert_dims=None,
ref_var_idx=None,
ref_var_name=None,
ignore_args=None,
ignore_args=None,
ignore_kargs=None,
outviews="outview",
alg_dtype=np.float64,
cast_output=True):
"""A decorator to handle iterating over the leftmost dimensions.
For example, if a wrapped function works with three-dimensional arrays, but
the variables include a 4th leftmost dimension for 'Time', this decorator
the variables include a 4th leftmost dimension for 'Time', this decorator
will iterate over all times, call the 3D Fortran routine, and aggregate the
results in to a 4D output array.
It is also important to note that the final output array is allocated
first, and then views are passed to the wrapped function so that values
It is also important to note that the final output array is allocated
first, and then views are passed to the wrapped function so that values
do not need to get copied in to the final output array.
Args:
ref_var_expected_dims (:obj:`int`): The number of dimensions that the
ref_var_expected_dims (:obj:`int`): The number of dimensions that the
Fortran routine is expecting for the reference variable.
ref_var_right_ndims (:obj:`int`): The number of dimensions from the
right to keep for the reference variable when making the output.
Can also be a :class:`combine_dims` object if the sizes are
ref_var_right_ndims (:obj:`int`): The number of dimensions from the
right to keep for the reference variable when making the output.
Can also be a :class:`combine_dims` object if the sizes are
determined from multiple variables.
insert_dims (sequence of :obj:`int`, optional): A sequence of
dimensions to insert between the left dimensions (e.g. time) and
insert_dims (sequence of :obj:`int`, optional): A sequence of
dimensions to insert between the left dimensions (e.g. time) and
the kept right dimensions. Default is None.
ref_var_idx (:obj:`int`, optional): The index in the wrapped function's
positional arguments to be used as the reference variable for
determining the leftmost dimensions. Must be specified if
ref_var_idx (:obj:`int`, optional): The index in the wrapped function's
positional arguments to be used as the reference variable for
determining the leftmost dimensions. Must be specified if
*ref_var_name* is None. Default is None.
ref_var_name (:obj:`str`, optional): The keyword argument name for the
wrapped function's keyword arguments to be used as the reference
variable for calculating the leftmost dimensions. Must be
ref_var_name (:obj:`str`, optional): The keyword argument name for the
wrapped function's keyword arguments to be used as the reference
variable for calculating the leftmost dimensions. Must be
specified if *ref_var_idx* is None. Default is None.
ignore_args (sequence of :obj:`int`): Indexes of any arguments that
should be ignored when creating the sliced views that are
should be ignored when creating the sliced views that are
passed to the Fortran routine.
ignore_kargs (sequence of :obj:`str`): Keys of any keyword arguments
that should be ignored when creating the sliced views that are
ignore_kargs (sequence of :obj:`str`): Keys of any keyword arguments
that should be ignored when creating the sliced views that are
passed to the Fortran routine.
outviews (:obj:`str` or a sequence): A single key or sequence of keys
that indicate the wrapped function's keyword argument to use
outviews (:obj:`str` or a sequence): A single key or sequence of keys
that indicate the wrapped function's keyword argument to use
as the output variable(s) in the wrapped function.
alg_dtype (:class:`numpy.dtype` or :obj:`str`): The numpy data type
alg_dtype (:class:`numpy.dtype` or :obj:`str`): The numpy data type
used in the wrapped function.
cast_output (:obj:`bool`): Set to True to cast the wrapped function's
cast_output (:obj:`bool`): Set to True to cast the wrapped function's
output to the same type as the reference variable.
Returns:
:class:`numpy.ndarray`: The aggregated output array that includes
:class:`numpy.ndarray`: The aggregated output array that includes
all extra leftmost dimensions found in the reference variable.
"""
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
_ignore_args = ignore_args if ignore_args is not None else ()
_ignore_kargs = ignore_kargs if ignore_kargs is not None else ()
_outkeys = [outviews] if isstr(outviews) else outviews
if ref_var_idx is not None:
ref_var = args[ref_var_idx]
else:
ref_var = kwargs[ref_var_name]
ref_var_dtype = ref_var.dtype
ref_var_shape = ref_var.shape
extra_dim_num = ref_var.ndim - ref_var_expected_dims
# No special left side iteration, return the function result
if (extra_dim_num == 0):
return wrapped(*args, **kwargs)
# Start by getting the left-most 'extra' dims
extra_dims = ref_var_shape[0:extra_dim_num]
extra_dims = ref_var_shape[0:extra_dim_num]
mid_dims = () if insert_dims is None else tuple(insert_dims)
if not isinstance(ref_var_right_ndims, combine_dims):
right_dims = ref_var_shape[-ref_var_right_ndims:]
else:
right_dims = ref_var_right_ndims(*args)
left_dims = extra_dims
outdims = left_dims + mid_dims + right_dims
if "outview" not in kwargs:
outd = OrderedDict((outkey, np.empty(outdims, alg_dtype))
for outkey in _outkeys)
for outkey in _outkeys)
mask_output = False
for left_idxs in iter_left_indexes(extra_dims):
# Make the left indexes plus a single slice object
# The single slice will handle all the dimensions to
# the right (e.g. [1,1,:])
left_and_slice_idxs = left_idxs + (slice(None), )
# Slice the args if applicable
new_args = [arg[left_and_slice_idxs]
if i not in _ignore_args else arg
for i,arg in enumerate(args)]
new_args = [arg[left_and_slice_idxs]
if i not in _ignore_args else arg
for i, arg in enumerate(args)]
# Slice the kwargs if applicable
new_kargs = {key:(val[left_and_slice_idxs]
new_kargs = {key: (val[left_and_slice_idxs]
if key not in _ignore_kargs else val)
for key,val in viewitems(kwargs)}
for key, val in viewitems(kwargs)}
# Skip the possible empty/missing arrays for the join method
skip_missing = False
for arg in new_args:
try:
_ = arg.ndim
except AttributeError:
continue # Not an array object
continue # Not an array object
else:
arr = to_np(arg)
try:
all_masked = arr.mask.all()
except AttributeError:
pass # Not a masked array
pass # Not a masked array
else:
if all_masked:
for output in viewvalues(outd):
@ -204,261 +193,257 @@ def left_iteration(ref_var_expected_dims, @@ -204,261 +193,257 @@ def left_iteration(ref_var_expected_dims,
skip_missing = True
mask_output = True
break
if skip_missing:
continue
# Insert the output views if one hasn't been provided
if "outview" not in new_kargs:
for outkey,output in viewitems(outd):
for outkey, output in viewitems(outd):
outview = output[left_and_slice_idxs]
new_kargs[outkey] = outview
result = wrapped(*new_args, **new_kargs)
# Make sure the result is the same data as what got passed in
# Make sure the result is the same data as what got passed in
# Can delete this once everything works
if (result.__array_interface__["data"][0] !=
outview.__array_interface__["data"][0]):
if (result.__array_interface__["data"][0] !=
outview.__array_interface__["data"][0]):
raise RuntimeError("output array was copied")
if len(outd) == 1:
output = next(iter(viewvalues(outd)))
else:
output = tuple(arr for arr in viewvalues(outd))
if cast_output:
if isinstance(output, np.ndarray):
output = output.astype(ref_var_dtype)
else:
output = tuple(arr.astype(ref_var_dtype) for arr in output)
# Mostly when used with join
if mask_output:
if isinstance(output, np.ndarray):
output = ma.masked_values(output, default_fill(np.float64))
else:
output = tuple(ma.masked_values(arr, default_fill(np.float64))
output = tuple(ma.masked_values(arr, default_fill(np.float64))
for arr in output)
return output
return func_wrapper
def cast_type(ref_idx=0, arg_idxs=None, karg_names=None,
def cast_type(ref_idx=0, arg_idxs=None, karg_names=None,
alg_dtype=np.float64, outviews="outview"):
"""A decorator to handle type casting.
This decorator is used to cast variables to and from the required
"""A decorator to handle type casting.
This decorator is used to cast variables to and from the required
:class:`numpy.dtype` used in the wrapped function.
Args:
ref_idx (:obj:`int`, optional): The index in the wrapped function's
positional arguments to be used as the reference variable for
ref_idx (:obj:`int`, optional): The index in the wrapped function's
positional arguments to be used as the reference variable for
determining the :class:`numpy.dtype` to return. Default is 0.
arg_idxs (sequence of :obj:`int`, optional): A sequence of indexes in the
wrapped function's positional arguments that indicate which
arg_idxs (sequence of :obj:`int`, optional): A sequence of indexes in
the wrapped function's positional arguments that indicate which
arguments to cast. Must be specified if *karg_names* is None.
Default is None.
karg_names (sequence of :obj:`str`): A sequence of keyword arguments
in the wrapped function's keyword arguments that indicate the
arguments to cast. Must be specified if *arg_idxs* is None.
in the wrapped function's keyword arguments that indicate the
arguments to cast. Must be specified if *arg_idxs* is None.
Default is None.
alg_dtype (:class:`numpy.dtype` or :obj:`str`): The numpy data type used
in the wrapped function.
outviews (:obj:`str` or a sequence): A single key or sequence of keys
that indicate the wrapped function's keyword argument to use
alg_dtype (:class:`numpy.dtype` or :obj:`str`): The numpy data type
used in the wrapped function.
outviews (:obj:`str` or a sequence): A single key or sequence of keys
that indicate the wrapped function's keyword argument to use
as the output variable(s) in the wrapped function.
Returns:
:class:`numpy.ndarray`: The wrapped function's output cast to the
:class:`numpy.ndarray`: The wrapped function's output cast to the
same :class:`numpy.dtype` as the reference variable.
"""
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
_arg_idxs = arg_idxs if arg_idxs is not None else ()
_karg_names = karg_names if karg_names is not None else ()
# Handle output views if applicable
_outkeys = [outviews] if isstr(outviews) else outviews
_outviews = from_args(wrapped, _outkeys, *args, **kwargs)
has_outview = False
for outkey in _outkeys:
_outview = _outviews[outkey]
if _outview is not None:
has_outview = True
orig_type = args[ref_idx].dtype
new_args = [arg.astype(alg_dtype)
if i in _arg_idxs else arg
for i,arg in enumerate(args)]
new_kargs = {key:(val.astype(alg_dtype)
if key in _karg_names else val)
for key,val in viewitems(kwargs)}
result = wrapped(*new_args, **new_kargs)
if i in _arg_idxs else arg
for i, arg in enumerate(args)]
new_kargs = {key: (val.astype(alg_dtype)
if key in _karg_names else val)
for key, val in viewitems(kwargs)}
result = wrapped(*new_args, **new_kargs)
# Do nothing for supplied output views
if not has_outview:
if isinstance(result, np.ndarray):
if result.dtype == orig_type:
return result
return result.astype(orig_type)
elif isinstance(result, Iterable): # got back a sequence of arrays
return tuple(arr.astype(orig_type)
elif isinstance(result, Iterable): # got back a sequence of arrays
return tuple(arr.astype(orig_type)
if arr.dtype != orig_type else arr
for arr in result)
return result
return func_wrapper
def _extract_and_transpose(arg, do_transpose):
"""Return a transposed view of the :class:`numpy.ndarray` inside of a
"""Return a transposed view of the :class:`numpy.ndarray` inside of a
:class:`xarray.DataArray` object.
If the *arg* parameter is not a :class:`xarray.DataArray` object, then
If the *arg* parameter is not a :class:`xarray.DataArray` object, then
*arg* is returned.
Args:
arg (:class:`xarray.DataArray` or :obj:`object`): Can be any object
arg (:class:`xarray.DataArray` or :obj:`object`): Can be any object
type.
do_transpose: Set to False to only extract the variable. When True,
the extracted array will also be transposed to a Fortran view if
it is not already Fortran contiguous.
Returns:
:class:`numpy.ndarray`: A numpy array. If *do_transpose* is True,
:class:`numpy.ndarray`: A numpy array. If *do_transpose* is True,
the numpy array will also be a Fortran contiguous view.
"""
if xarray_enabled():
if isinstance(arg, DataArray):
arg = to_np(arg)
if do_transpose:
if isinstance(arg, np.ndarray):
if not arg.flags.f_contiguous and arg.ndim > 1:
return arg.T
return arg
def extract_and_transpose(do_transpose=True, outviews="outview"):
"""A decorator to extract the data array from a :class:`xarray.DataArray`
This decorator also transposes the view of the data to Fortran
"""A decorator to extract the data array from a :class:`xarray.DataArray`
This decorator also transposes the view of the data to Fortran
contiguous if *do_transpose* is True.
Args:
do_transpose: Set to False to only extract the variable. When True,
the extracted array will also be transposed to a Fortran view if
it is not already Fortran contiguous.
outviews (:obj:`str` or a sequence): A single key or sequence of keys
that indicate the wrapped function's keyword argument to use
outviews (:obj:`str` or a sequence): A single key or sequence of keys
that indicate the wrapped function's keyword argument to use
as the output variable(s) in the wrapped function.
Returns:
:class:`numpy.ndarray`: A numpy array. If *do_transpose* is True,
:class:`numpy.ndarray`: A numpy array. If *do_transpose* is True,
the numpy array will also be a Fortran contiguous view.
"""
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
# Handle output views if applicable
_outkeys = [outviews] if isstr(outviews) else outviews
_outviews = from_args(wrapped, _outkeys, *args, **kwargs)
has_outview = False
for outkey in _outkeys:
_outview = _outviews[outkey]
if _outview is not None:
has_outview = True
new_args = [_extract_and_transpose(arg, do_transpose) for arg in args]
new_kargs = {key:_extract_and_transpose(val, do_transpose)
for key,val in viewitems(kwargs)}
result = wrapped(*new_args, **new_kargs)
new_kargs = {key: _extract_and_transpose(val, do_transpose)
for key, val in viewitems(kwargs)}
result = wrapped(*new_args, **new_kargs)
# Do nothing for supplied output views
if has_outview:
return result
if isinstance(result, np.ndarray):
if result.flags.f_contiguous and result.ndim > 1:
return result.T
elif isinstance(result, Iterable):
return tuple(x.T if x.flags.f_contiguous and x.ndim > 1 else x
return tuple(x.T if x.flags.f_contiguous and x.ndim > 1 else x
for x in result)
return result
return func_wrapper
def check_args(refvaridx, refvarndim, rightdims, stagger=None,
refstagdim=None):
"""A decorator to check that the wrapped function's arguments are valid.
An exception is raised when an invalid argument is found.
Args:
refvaridx (:obj:`int`): The wrapped function's positional argument
refvaridx (:obj:`int`): The wrapped function's positional argument
index to use as the reference variable.
refvarndim (:obj:`int`): The number of dimensions for the reference
refvarndim (:obj:`int`): The number of dimensions for the reference
variable that is expected by the wrapped function.
rightdims (sequence of :obj:`int`): The expected number of right
rightdims (sequence of :obj:`int`): The expected number of right
dimensions for each argument.
stagger (sequence of :obj:`int` or :obj:`None`, optional): The
dimension that is staggered for each argument in the wrapped
function. Use :obj:`None` in the sequence to indicate no
stagger (sequence of :obj:`int` or :obj:`None`, optional): The
dimension that is staggered for each argument in the wrapped
function. Use :obj:`None` in the sequence to indicate no
staggering for that argument. Default is None.
refstagdim (:obj:`int`, optional): The staggered dimension for the
refstagdim (:obj:`int`, optional): The staggered dimension for the
reference variable, if applicable. Default is None.
Returns:
None
Raises:
:class:`ValueError`: Raised when an invalid argument is detected.
"""
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
refvar = args[refvaridx]
try:
_ndim = refvar.ndim
@ -467,7 +452,7 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None, @@ -467,7 +452,7 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None,
"object".format(refvaridx))
else:
extra_dims = refvar.ndim - refvarndim
# Always use unstaggered as the basis of comparison
if refstagdim is not None:
_refshape = list(refvar.shape)
@ -475,33 +460,34 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None, @@ -475,33 +460,34 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None,
_refshape = tuple(_refshape)
else:
_refshape = refvar.shape
if stagger is None:
_stagger = [None]*len(rightdims)
else:
_stagger = stagger
for i,ndim in enumerate(rightdims):
for i, ndim in enumerate(rightdims):
if ndim is None:
continue
var = args[i]
try:
_ = var.ndim
except AttributeError:
raise ValueError("argument {} is not an arraylike "
"object".format(i))
right_var_ndims = rightdims[i]
# Check that the number of dims is correct
if (var.ndim - extra_dims != right_var_ndims):
raise ValueError("invalid number of dimensions for argument "
"{} (got {}, expected {}).".format(i,
var.ndim,
right_var_ndims + extra_dims))
"{} (got {}, expected {}).".format(
i,
var.ndim,
right_var_ndims + extra_dims))
# Add 1 to the reference staggered dim index before doing the check
if _stagger[i] is not None:
ref_shape = list(_refshape)
@ -509,27 +495,19 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None, @@ -509,27 +495,19 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None,
ref_shape = tuple(ref_shape)
else:
ref_shape = _refshape
ref_right_sizes = ref_shape[extra_dims:]
# Check that right dimensions are lined up
if (var.shape[-right_var_ndims:] !=
ref_right_sizes[-right_var_ndims:]):
raise ValueError("invalid shape for argument "
"{} (got {}, expected {})".format(i,
var.shape[-right_var_ndims:],
ref_right_sizes[-right_var_ndims:]))
return wrapped(*args, **kwargs)
return func_wrapper
ref_right_sizes = ref_shape[extra_dims:]
# Check that right dimensions are lined up
if (var.shape[-right_var_ndims:] !=
ref_right_sizes[-right_var_ndims:]):
raise ValueError("invalid shape for argument "
"{} (got {}, expected {})".format(
i,
var.shape[-right_var_ndims:],
ref_right_sizes[-right_var_ndims:]))
return wrapped(*args, **kwargs)
return func_wrapper

56
src/wrf/destag.py

@ -8,57 +8,55 @@ from .metadecorators import set_destag_metadata @@ -8,57 +8,55 @@ from .metadecorators import set_destag_metadata
@extract_and_transpose(do_transpose=False)
def destagger(var, stagger_dim, meta=False):
"""Return the variable on the unstaggered grid.
This function destaggers the variable by taking the average of the
values located on either side of the grid box.
This function destaggers the variable by taking the average of the
values located on either side of the grid box.
Args:
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A variable
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A variable
on a staggered grid.
stagger_dim (:obj:`int`): The dimension index to destagger.
Negative values can be used to choose dimensions referenced
Negative values can be used to choose dimensions referenced
from the right hand side (-1 is the rightmost dimension).
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is False.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`:
The destaggered variable. If xarray is enabled and
the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
The destaggered variable. If xarray is enabled and
the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
"""
var_shape = var.shape
num_dims = var.ndim
stagger_dim_size = var_shape[stagger_dim]
# Dynamically building the range slices to create the appropriate
# Dynamically building the range slices to create the appropriate
# number of ':'s in the array accessor lists.
# For example, for a 3D array, the calculation would be
# result = .5 * (var[:,:,0:stagger_dim_size-2]
# For example, for a 3D array, the calculation would be
# result = .5 * (var[:,:,0:stagger_dim_size-2]
# + var[:,:,1:stagger_dim_size-1])
# for stagger_dim=2. So, full slices would be used for dims 0 and 1, but
# dim 2 needs the special slice.
# for stagger_dim=2. So, full slices would be used for dims 0 and 1, but
# dim 2 needs the special slice.
full_slice = slice(None)
slice1 = slice(0, stagger_dim_size - 1, 1)
slice2 = slice(1, stagger_dim_size, 1)
# default to full slices
dim_ranges_1 = [full_slice] * num_dims
dim_ranges_2 = [full_slice] * num_dims
# for the stagger dim, insert the appropriate slice range
dim_ranges_1[stagger_dim] = slice1
dim_ranges_2[stagger_dim] = slice2
result = .5*(var[tuple(dim_ranges_1)] + var[tuple(dim_ranges_2)])
return result
return result

1263
src/wrf/extension.py

File diff suppressed because it is too large Load Diff

809
src/wrf/g_cape.py

File diff suppressed because it is too large Load Diff

688
src/wrf/g_cloudfrac.py

@ -11,142 +11,142 @@ from .g_geoht import _get_geoht @@ -11,142 +11,142 @@ from .g_geoht import _get_geoht
@set_cloudfrac_metadata()
def get_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None, mid_thresh=None,
high_thresh=None, missing=default_fill(np.float64)):
def get_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None, mid_thresh=None,
high_thresh=None, missing=default_fill(np.float64)):
"""Return the cloud fraction for low, mid, and high level clouds.
The leftmost dimension of the returned array represents three different
The leftmost dimension of the returned array represents three different
quantities:
- return_val[0,...] will contain LOW level cloud fraction
- return_val[1,...] will contain MID level cloud fraction
- return_val[2,...] will contain HIGH level cloud fraction
If the vertical coordinate type is 'height_agl' or 'height_msl', the
If the vertical coordinate type is 'height_agl' or 'height_msl', the
default cloud levels are defined as:
300 m <= low_cloud < 2000 m
2000 m <= mid_cloud < 6000 m
6000 m <= high_cloud
For 'pressure', the default cloud levels are defined as:
For 'pressure', the default cloud levels are defined as:
97000 Pa <= low_cloud < 80000 Pa
80000 Pa <= mid_cloud < 45000 Pa
45000 Pa <= high_cloud
Note that the default low cloud levels are chosen to
exclude clouds near the surface (fog). If you want fog included, set
*low_thresh* to ~99500 Pa if *vert_type* is set to 'pressure', or 15 m if
using 'height_msl' or 'height_agl'. Keep in mind that the lowest mass grid
points are slightly above the ground, and in order to find clouds, the
*low_thresh* needs to be set to values that are slightly greater than
exclude clouds near the surface (fog). If you want fog included, set
*low_thresh* to ~99500 Pa if *vert_type* is set to 'pressure', or 15 m if
using 'height_msl' or 'height_agl'. Keep in mind that the lowest mass grid
points are slightly above the ground, and in order to find clouds, the
*low_thresh* needs to be set to values that are slightly greater than
(less than) the lowest height (pressure) values.
When using 'pressure' or 'height_agl' for *vert_type*, there is a
possibility that the lowest WRF level will be higher than the low_cloud or
mid_cloud threshold, particularly for mountainous regions. When this
When using 'pressure' or 'height_agl' for *vert_type*, there is a
possibility that the lowest WRF level will be higher than the low_cloud or
mid_cloud threshold, particularly for mountainous regions. When this
happens, a fill value will be used in the output.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
vert_type (:obj:`str`, optional): The type of vertical coordinate used
to determine cloud type thresholds. Must be 'height_agl',
vert_type (:obj:`str`, optional): The type of vertical coordinate used
to determine cloud type thresholds. Must be 'height_agl',
'height_msl', or 'pres'. The default is 'height_agl'.
low_thresh (:obj:`float`, optional): The lower bound for what is
considered a low cloud. If *vert_type* is 'pres', the default is
97000 Pa. If *vert_type* is 'height_agl' or 'height_msl', then the
default is 300 m.
mid_thresh (:obj:`float`, optional): The lower bound for what is
considered a mid level cloud. If *vert_type* is 'pres', the
default is 80000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 2000 m.
high_thresh (:obj:`float`, optional): The lower bound for what is
considered a high level cloud. If *vert_type* is 'pres', the
default is 45000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 6000 m.
low_thresh (:obj:`float`, optional): The lower bound for what is
considered a low cloud. If *vert_type* is 'pres', the default is
97000 Pa. If *vert_type* is 'height_agl' or 'height_msl', then the
default is 300 m.
mid_thresh (:obj:`float`, optional): The lower bound for what is
considered a mid level cloud. If *vert_type* is 'pres', the
default is 80000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 2000 m.
high_thresh (:obj:`float`, optional): The lower bound for what is
considered a high level cloud. If *vert_type* is 'pres', the
default is 45000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 6000 m.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud fraction array whose leftmost dimension is 3 (LOW=0, MID=1,
HIGH=2).
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud fraction array whose leftmost dimension is 3 (LOW=0, MID=1,
HIGH=2).
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
ncvars = extract_vars(wrfin, timeidx, ("P", "PB", "QVAPOR", "T"),
ncvars = extract_vars(wrfin, timeidx, ("P", "PB", "QVAPOR", "T"),
method, squeeze, cache, meta=False,
_key=_key)
p = ncvars["P"]
pb = ncvars["PB"]
qv = ncvars["QVAPOR"]
t = ncvars["T"]
full_p = p + pb
full_t = t + Constants.T_BASE
tk = _tk(full_p, full_t)
rh = _rh(qv, full_p, tk)
if vert_type.lower() == "pres" or vert_type.lower() == "pressure":
v_coord = full_p
_low_thresh = 97000. if low_thresh is None else low_thresh
_mid_thresh = 80000. if mid_thresh is None else mid_thresh
_high_thresh = 45000. if high_thresh is None else high_thresh
vert_inc_w_height = 0
elif (vert_type.lower() == "height_msl"
elif (vert_type.lower() == "height_msl"
or vert_type.lower() == "height_agl"):
is_msl = vert_type.lower() == "height_msl"
v_coord = _get_geoht(wrfin, timeidx, method, squeeze,
cache, meta=False, _key=_key, height=True,
v_coord = _get_geoht(wrfin, timeidx, method, squeeze,
cache, meta=False, _key=_key, height=True,
msl=is_msl)
_low_thresh = 300. if low_thresh is None else low_thresh
_mid_thresh = 2000. if mid_thresh is None else mid_thresh
@ -155,344 +155,346 @@ def get_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True, @@ -155,344 +155,346 @@ def get_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
else:
raise ValueError("'vert_type' must be 'pres', 'height_msl', "
"or 'height_agl'")
cfrac = _cloudfrac(v_coord, rh, vert_inc_w_height,
_low_thresh, _mid_thresh, _high_thresh, missing)
cfrac = _cloudfrac(v_coord, rh, vert_inc_w_height,
_low_thresh, _mid_thresh, _high_thresh, missing)
return ma.masked_values(cfrac, missing)
def get_low_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None, mid_thresh=None,
high_thresh=None, missing=default_fill(np.float64)):
def get_low_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None,
mid_thresh=None, high_thresh=None,
missing=default_fill(np.float64)):
"""Return the cloud fraction for the low level clouds.
If the vertical coordinate type is 'height_agl' or 'height_msl', the
If the vertical coordinate type is 'height_agl' or 'height_msl', the
default cloud levels are defined as:
300 m <= low_cloud < 2000 m
2000 m <= mid_cloud < 6000 m
6000 m <= high_cloud
For 'pressure', the default cloud levels are defined as:
For 'pressure', the default cloud levels are defined as:
97000 Pa <= low_cloud < 80000 Pa
80000 Pa <= mid_cloud < 45000 Pa
45000 Pa <= high_cloud
Note that the default low cloud levels are chosen to
exclude clouds near the surface (fog). If you want fog included, set
*low_thresh* to ~99500 Pa if *vert_type* is set to 'pressure', or 15 m if
using 'height_msl' or 'height_agl'. Keep in mind that the lowest mass grid
points are slightly above the ground, and in order to find clouds, the
*low_thresh* needs to be set to values that are slightly greater than
exclude clouds near the surface (fog). If you want fog included, set
*low_thresh* to ~99500 Pa if *vert_type* is set to 'pressure', or 15 m if
using 'height_msl' or 'height_agl'. Keep in mind that the lowest mass grid
points are slightly above the ground, and in order to find clouds, the
*low_thresh* needs to be set to values that are slightly greater than
(less than) the lowest height (pressure) values.
When using 'pressure' or 'height_agl' for *vert_type*, there is a
possibility that the lowest WRF level will be higher than the low_cloud or
mid_cloud threshold, particularly for mountainous regions. When this
When using 'pressure' or 'height_agl' for *vert_type*, there is a
possibility that the lowest WRF level will be higher than the low_cloud or
mid_cloud threshold, particularly for mountainous regions. When this
happens, a fill value will be used in the output.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
vert_type (:obj:`str`, optional): The type of vertical coordinate used
to determine cloud type thresholds. Must be 'height_agl',
vert_type (:obj:`str`, optional): The type of vertical coordinate used
to determine cloud type thresholds. Must be 'height_agl',
'height_msl', or 'pres'. The default is 'height_agl'.
low_thresh (:obj:`float`, optional): The lower bound for what is
considered a low cloud. If *vert_type* is 'pres', the default is
97000 Pa. If *vert_type* is 'height_agl' or 'height_msl', then the
default is 300 m.
mid_thresh (:obj:`float`, optional): The lower bound for what is
considered a mid level cloud. If *vert_type* is 'pres', the
default is 80000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 2000 m.
high_thresh (:obj:`float`, optional): The lower bound for what is
considered a high level cloud. If *vert_type* is 'pres', the
default is 45000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 6000 m.
low_thresh (:obj:`float`, optional): The lower bound for what is
considered a low cloud. If *vert_type* is 'pres', the default is
97000 Pa. If *vert_type* is 'height_agl' or 'height_msl', then the
default is 300 m.
mid_thresh (:obj:`float`, optional): The lower bound for what is
considered a mid level cloud. If *vert_type* is 'pres', the
default is 80000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 2000 m.
high_thresh (:obj:`float`, optional): The lower bound for what is
considered a high level cloud. If *vert_type* is 'pres', the
default is 45000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 6000 m.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud fraction array for low level clouds.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud fraction array for low level clouds.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key,
vert_type, low_thresh, mid_thresh,
high_thresh, missing)[0,:]
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key, vert_type, low_thresh,
mid_thresh, high_thresh, missing)[0, :]
if meta:
result.attrs["description"] = "low clouds"
return result
def get_mid_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None, mid_thresh=None,
high_thresh=None, missing=default_fill(np.float64)):
def get_mid_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None,
mid_thresh=None, high_thresh=None,
missing=default_fill(np.float64)):
"""Return the cloud fraction for the mid level clouds.
If the vertical coordinate type is 'height_agl' or 'height_msl', the
If the vertical coordinate type is 'height_agl' or 'height_msl', the
default cloud levels are defined as:
300 m <= low_cloud < 2000 m
2000 m <= mid_cloud < 6000 m
6000 m <= high_cloud
For 'pressure', the default cloud levels are defined as:
For 'pressure', the default cloud levels are defined as:
97000 Pa <= low_cloud < 80000 Pa
80000 Pa <= mid_cloud < 45000 Pa
45000 Pa <= high_cloud
Note that the default low cloud levels are chosen to
exclude clouds near the surface (fog). If you want fog included, set
*low_thresh* to ~99500 Pa if *vert_type* is set to 'pressure', or 15 m if
using 'height_msl' or 'height_agl'. Keep in mind that the lowest mass grid
points are slightly above the ground, and in order to find clouds, the
*low_thresh* needs to be set to values that are slightly greater than
exclude clouds near the surface (fog). If you want fog included, set
*low_thresh* to ~99500 Pa if *vert_type* is set to 'pressure', or 15 m if
using 'height_msl' or 'height_agl'. Keep in mind that the lowest mass grid
points are slightly above the ground, and in order to find clouds, the
*low_thresh* needs to be set to values that are slightly greater than
(less than) the lowest height (pressure) values.
When using 'pressure' or 'height_agl' for *vert_type*, there is a
possibility that the lowest WRF level will be higher than the low_cloud or
mid_cloud threshold, particularly for mountainous regions. When this
When using 'pressure' or 'height_agl' for *vert_type*, there is a
possibility that the lowest WRF level will be higher than the low_cloud or
mid_cloud threshold, particularly for mountainous regions. When this
happens, a fill value will be used in the output.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
vert_type (:obj:`str`, optional): The type of vertical coordinate used
to determine cloud type thresholds. Must be 'height_agl',
vert_type (:obj:`str`, optional): The type of vertical coordinate used
to determine cloud type thresholds. Must be 'height_agl',
'height_msl', or 'pres'. The default is 'height_agl'.
low_thresh (:obj:`float`, optional): The lower bound for what is
considered a low cloud. If *vert_type* is 'pres', the default is
97000 Pa. If *vert_type* is 'height_agl' or 'height_msl', then the
default is 300 m.
mid_thresh (:obj:`float`, optional): The lower bound for what is
considered a mid level cloud. If *vert_type* is 'pres', the
default is 80000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 2000 m.
high_thresh (:obj:`float`, optional): The lower bound for what is
considered a high level cloud. If *vert_type* is 'pres', the
default is 45000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 6000 m.
low_thresh (:obj:`float`, optional): The lower bound for what is
considered a low cloud. If *vert_type* is 'pres', the default is
97000 Pa. If *vert_type* is 'height_agl' or 'height_msl', then the
default is 300 m.
mid_thresh (:obj:`float`, optional): The lower bound for what is
considered a mid level cloud. If *vert_type* is 'pres', the
default is 80000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 2000 m.
high_thresh (:obj:`float`, optional): The lower bound for what is
considered a high level cloud. If *vert_type* is 'pres', the
default is 45000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 6000 m.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud fraction array for mid level clouds.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud fraction array for mid level clouds.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key,
vert_type, low_thresh, mid_thresh,
high_thresh, missing)[1,:]
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key,
vert_type, low_thresh, mid_thresh,
high_thresh, missing)[1, :]
if meta:
result.attrs["description"] = "mid clouds"
return result
def get_high_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None, mid_thresh=None,
high_thresh=None, missing=default_fill(np.float64)):
def get_high_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None,
mid_thresh=None, high_thresh=None,
missing=default_fill(np.float64)):
"""Return the cloud fraction for the high level clouds.
If the vertical coordinate type is 'height_agl' or 'height_msl', the
If the vertical coordinate type is 'height_agl' or 'height_msl', the
default cloud levels are defined as:
300 m <= low_cloud < 2000 m
2000 m <= mid_cloud < 6000 m
6000 m <= high_cloud
For 'pressure', the default cloud levels are defined as:
For 'pressure', the default cloud levels are defined as:
97000 Pa <= low_cloud < 80000 Pa
80000 Pa <= mid_cloud < 45000 Pa
45000 Pa <= high_cloud
Note that the default low cloud levels are chosen to
exclude clouds near the surface (fog). If you want fog included, set
*low_thresh* to ~99500 Pa if *vert_type* is set to 'pressure', or 15 m if
using 'height_msl' or 'height_agl'. Keep in mind that the lowest mass grid
points are slightly above the ground, and in order to find clouds, the
*low_thresh* needs to be set to values that are slightly greater than
exclude clouds near the surface (fog). If you want fog included, set
*low_thresh* to ~99500 Pa if *vert_type* is set to 'pressure', or 15 m if
using 'height_msl' or 'height_agl'. Keep in mind that the lowest mass grid
points are slightly above the ground, and in order to find clouds, the
*low_thresh* needs to be set to values that are slightly greater than
(less than) the lowest height (pressure) values.
When using 'pressure' or 'height_agl' for *vert_type*, there is a
possibility that the lowest WRF level will be higher than the low_cloud or
mid_cloud threshold, particularly for mountainous regions. When this
When using 'pressure' or 'height_agl' for *vert_type*, there is a
possibility that the lowest WRF level will be higher than the low_cloud or
mid_cloud threshold, particularly for mountainous regions. When this
happens, a fill value will be used in the output.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
vert_type (:obj:`str`, optional): The type of vertical coordinate used
to determine cloud type thresholds. Must be 'height_agl',
vert_type (:obj:`str`, optional): The type of vertical coordinate used
to determine cloud type thresholds. Must be 'height_agl',
'height_msl', or 'pres'. The default is 'height_agl'.
low_thresh (:obj:`float`, optional): The lower bound for what is
considered a low cloud. If *vert_type* is 'pres', the default is
97000 Pa. If *vert_type* is 'height_agl' or 'height_msl', then the
default is 300 m.
mid_thresh (:obj:`float`, optional): The lower bound for what is
considered a mid level cloud. If *vert_type* is 'pres', the
default is 80000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 2000 m.
high_thresh (:obj:`float`, optional): The lower bound for what is
considered a high level cloud. If *vert_type* is 'pres', the
default is 45000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 6000 m.
low_thresh (:obj:`float`, optional): The lower bound for what is
considered a low cloud. If *vert_type* is 'pres', the default is
97000 Pa. If *vert_type* is 'height_agl' or 'height_msl', then the
default is 300 m.
mid_thresh (:obj:`float`, optional): The lower bound for what is
considered a mid level cloud. If *vert_type* is 'pres', the
default is 80000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 2000 m.
high_thresh (:obj:`float`, optional): The lower bound for what is
considered a high level cloud. If *vert_type* is 'pres', the
default is 45000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 6000 m.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud fraction array for high level clouds.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud fraction array for high level clouds.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key,
vert_type, low_thresh, mid_thresh,
high_thresh, missing)[2,:]
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key,
vert_type, low_thresh, mid_thresh,
high_thresh, missing)[2, :]
if meta:
result.attrs["description"] = "high clouds"
return result

149
src/wrf/g_ctt.py

@ -3,11 +3,10 @@ from __future__ import (absolute_import, division, print_function) @@ -3,11 +3,10 @@ from __future__ import (absolute_import, division, print_function)
import numpy as np
import numpy.ma as ma
#from .extension import computectt, computetk
from .extension import _ctt, _tk
from .constants import Constants, ConversionFactors, default_fill
from .destag import destagger
from .decorators import convert_units
from .decorators import convert_units
from .metadecorators import copy_and_set_metadata
from .util import extract_vars
@ -17,86 +16,86 @@ from .util import extract_vars @@ -17,86 +16,86 @@ from .util import extract_vars
description="cloud top temperature",
MemoryOrder="XY")
@convert_units("temp", "c")
def get_ctt(wrfin, timeidx=0, method="cat",
def get_ctt(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None,
fill_nocloud=False, missing=default_fill(np.float64),
fill_nocloud=False, missing=default_fill(np.float64),
opt_thresh=1.0, units="degC"):
"""Return the cloud top temperature.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
fill_nocloud (:obj:`bool`, optional): Set to True to use fill values in
regions where clouds are not detected (optical depth less than 1).
Otherwise, the output will contain the surface temperature for
fill_nocloud (:obj:`bool`, optional): Set to True to use fill values in
regions where clouds are not detected (optical depth less than 1).
Otherwise, the output will contain the surface temperature for
areas without clouds. Default is False.
missing (:obj:`float`, optional): The fill value to use for areas
where no clouds are detected. Only used if *fill_nocloud* is
True. Default is
:data:`wrf.default_fill(numpy.float64)`.
opt_thresh (:obj:`float`, optional): The amount of optical
depth (integrated from top down) required to trigger a cloud top
temperature calculation. The cloud top temperature is calculated at
the vertical level where this threshold is met. Vertical columns
with less than this threshold will be treated as cloud free areas.
In general, the larger the value is for this
threshold, the lower the altitude will be for the cloud top
temperature calculation, and therefore higher cloud top
temperature values. Default is 1.0, which should be sufficient for
missing (:obj:`float`, optional): The fill value to use for areas
where no clouds are detected. Only used if *fill_nocloud* is
True. Default is
:data:`wrf.default_fill(numpy.float64)`.
opt_thresh (:obj:`float`, optional): The amount of optical
depth (integrated from top down) required to trigger a cloud top
temperature calculation. The cloud top temperature is calculated at
the vertical level where this threshold is met. Vertical columns
with less than this threshold will be treated as cloud free areas.
In general, the larger the value is for this
threshold, the lower the altitude will be for the cloud top
temperature calculation, and therefore higher cloud top
temperature values. Default is 1.0, which should be sufficient for
most users.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'ctt'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'ctt'. Default
is 'degC'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud top temperature.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames = ("T", "P", "PB", "PH", "PHB", "HGT", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
@ -107,40 +106,40 @@ def get_ctt(wrfin, timeidx=0, method="cat", @@ -107,40 +106,40 @@ def get_ctt(wrfin, timeidx=0, method="cat",
ph = ncvars["PH"]
phb = ncvars["PHB"]
ter = ncvars["HGT"]
qv = ncvars["QVAPOR"] * 1000.0 # g/kg
qv = ncvars["QVAPOR"] * 1000.0 # g/kg
haveqci = 1
try:
icevars = extract_vars(wrfin, timeidx, "QICE",
icevars = extract_vars(wrfin, timeidx, "QICE",
method, squeeze, cache, meta=False,
_key=_key)
except KeyError:
qice = np.zeros(qv.shape, qv.dtype)
haveqci = 0
else:
qice = icevars["QICE"] * 1000.0 #g/kg
qice = icevars["QICE"] * 1000.0 # g/kg
try:
cldvars = extract_vars(wrfin, timeidx, "QCLOUD",
cldvars = extract_vars(wrfin, timeidx, "QCLOUD",
method, squeeze, cache, meta=False,
_key=_key)
except KeyError:
raise RuntimeError("'QCLOUD' not found in NetCDF file")
else:
qcld = cldvars["QCLOUD"] * 1000.0 #g/kg
qcld = cldvars["QCLOUD"] * 1000.0 # g/kg
full_p = p + pb
p_hpa = full_p * ConversionFactors.PA_TO_HPA
full_t = t + Constants.T_BASE
tk = _tk(full_p, full_t)
geopt = ph + phb
geopt_unstag = destagger(geopt, -3)
ght = geopt_unstag / Constants.G
_fill_nocloud = 1 if fill_nocloud else 0
ctt = _ctt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci, _fill_nocloud,
missing, opt_thresh)
return ma.masked_values(ctt, missing)

228
src/wrf/g_dbz.py

@ -2,82 +2,81 @@ from __future__ import (absolute_import, division, print_function) @@ -2,82 +2,81 @@ from __future__ import (absolute_import, division, print_function)
import numpy as np
#from .extension import computedbz,computetk
from .extension import _dbz, _tk
from .constants import Constants
from .util import extract_vars, to_np
from .metadecorators import copy_and_set_metadata
@copy_and_set_metadata(copy_varname="T", name="dbz",
@copy_and_set_metadata(copy_varname="T", name="dbz",
description="radar reflectivity",
units="dBZ")
def get_dbz(wrfin, timeidx=0, method="cat",
def get_dbz(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None,
use_varint=False, use_liqskin=False):
"""Return the simulated radar reflectivity.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
use_varint (:obj:`bool`, optional): When set to False,
the intercept parameters are assumed constant
(as in MM5's Reisner-2 bulk microphysical scheme).
When set to True, the variable intercept
parameters are used as in the more recent version of Reisner-2
(based on Thompson, Rasmussen, and Manning, 2004, Monthly weather
Review, Vol. 132, No. 2, pp. 519-542.).
use_liqskin (:obj:`bool`, optional): When set to True, frozen particles
that are at a temperature above freezing are assumed to scatter
use_varint (:obj:`bool`, optional): When set to False,
the intercept parameters are assumed constant
(as in MM5's Reisner-2 bulk microphysical scheme).
When set to True, the variable intercept
parameters are used as in the more recent version of Reisner-2
(based on Thompson, Rasmussen, and Manning, 2004, Monthly weather
Review, Vol. 132, No. 2, pp. 519-542.).
use_liqskin (:obj:`bool`, optional): When set to True, frozen particles
that are at a temperature above freezing are assumed to scatter
as a liquid particle. Set to False to disable.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The simulated
radar reflectivity.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The simulated
radar reflectivity.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames = ("T", "P", "PB", "QVAPOR", "QRAIN")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
@ -87,113 +86,112 @@ def get_dbz(wrfin, timeidx=0, method="cat", @@ -87,113 +86,112 @@ def get_dbz(wrfin, timeidx=0, method="cat",
pb = ncvars["PB"]
qv = ncvars["QVAPOR"]
qr = ncvars["QRAIN"]
try:
snowvars = extract_vars(wrfin, timeidx, "QSNOW",
snowvars = extract_vars(wrfin, timeidx, "QSNOW",
method, squeeze, cache, meta=False,
_key=_key)
except KeyError:
qs = np.zeros(qv.shape, qv.dtype)
else:
qs = snowvars["QSNOW"]
try:
graupvars = extract_vars(wrfin, timeidx, "QGRAUP",
graupvars = extract_vars(wrfin, timeidx, "QGRAUP",
method, squeeze, cache, meta=False,
_key=_key)
except KeyError:
qg = np.zeros(qv.shape, qv.dtype)
else:
qg = graupvars["QGRAUP"]
full_t = t + Constants.T_BASE
full_p = p + pb
tk = _tk(full_p, full_t)
# If qsnow is not all 0, set sn0 to 1
sn0 = 1 if qs.any() else 0
ivarint = 1 if use_varint else 0
iliqskin = 1 if use_liqskin else 0
return _dbz(full_p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin)
@copy_and_set_metadata(copy_varname="T", name="max_dbz",
@copy_and_set_metadata(copy_varname="T", name="max_dbz",
remove_dims=("bottom_top",),
description="maximum radar reflectivity",
units="dBZ",
MemoryOrder="XY")
def get_max_dbz(wrfin, timeidx=0, method="cat",
def get_max_dbz(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None,
use_varint=False, use_liqskin=False):
"""Return the maximum simulated radar reflectivity.
This function returns the maximum reflectivity found in the column for
This function returns the maximum reflectivity found in the column for
each grid point.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
use_varint (:obj:`bool`, optional): When set to False,
the intercept parameters are assumed constant
(as in MM5's Reisner-2 bulk microphysical scheme).
When set to True, the variable intercept
parameters are used as in the more recent version of Reisner-2
(based on Thompson, Rasmussen, and Manning, 2004, Monthly weather
Review, Vol. 132, No. 2, pp. 519-542.).
use_liqskin (:obj:`bool`, optional): When set to True, frozen particles
that are at a temperature above freezing are assumed to scatter
use_varint (:obj:`bool`, optional): When set to False,
the intercept parameters are assumed constant
(as in MM5's Reisner-2 bulk microphysical scheme).
When set to True, the variable intercept
parameters are used as in the more recent version of Reisner-2
(based on Thompson, Rasmussen, and Manning, 2004, Monthly weather
Review, Vol. 132, No. 2, pp. 519-542.).
use_liqskin (:obj:`bool`, optional): When set to True, frozen particles
that are at a temperature above freezing are assumed to scatter
as a liquid particle. Set to False to disable.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The maximum
simulated radar reflectivity.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The maximum
simulated radar reflectivity.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
return np.amax(to_np(get_dbz(wrfin, timeidx, method, squeeze, cache, meta,
_key, use_varint, use_liqskin)),
axis=-3)
_key, use_varint, use_liqskin)),
axis=-3)

191
src/wrf/g_dewpoint.py

@ -1,164 +1,163 @@ @@ -1,164 +1,163 @@
from __future__ import (absolute_import, division, print_function)
#from .extension import computetd
from .extension import _td
from .decorators import convert_units
from .metadecorators import copy_and_set_metadata
from .util import extract_vars
@copy_and_set_metadata(copy_varname="QVAPOR", name="td",
@copy_and_set_metadata(copy_varname="QVAPOR", name="td",
description="dew point temperature")
@convert_units("temp", "c")
def get_dp(wrfin, timeidx=0, method="cat", squeeze=True,
def get_dp(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, units="degC"):
"""Return the dewpoint temperature.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'td'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'td'. Default
is 'degC'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
dewpoint temperature.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("P", "PB", "QVAPOR")
varnames = ("P", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
p = ncvars["P"]
pb = ncvars["PB"]
# Copy needed for the mmap nonsense of scipy.io.netcdf, which seems to
# Copy needed for the mmap nonsense of scipy.io.netcdf, which seems to
# break with every release
qvapor = ncvars["QVAPOR"].copy()
# Algorithm requires hPa
full_p = .01*(p + pb)
qvapor[qvapor < 0] = 0
td = _td(full_p, qvapor)
return td
@copy_and_set_metadata(copy_varname="Q2", name="td2",
@copy_and_set_metadata(copy_varname="Q2", name="td2",
description="2m dew point temperature")
@convert_units("temp", "c")
def get_dp_2m(wrfin, timeidx=0, method="cat", squeeze=True,
def get_dp_2m(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, units="degC"):
"""Return the 2m dewpoint temperature.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'td2'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'td2'. Default
is 'degC'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
2m dewpoint temperature.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("PSFC", "Q2")
varnames = ("PSFC", "Q2")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
# Algorithm requires hPa
psfc = .01*(ncvars["PSFC"])
# Copy needed for the mmap nonsense of scipy.io.netcdf, which seems to
# Copy needed for the mmap nonsense of scipy.io.netcdf, which seems to
# break with every release
q2 = ncvars["Q2"].copy()
q2[q2 < 0] = 0
td = _td(psfc, q2)
return td
return td

465
src/wrf/g_geoht.py

@ -8,79 +8,80 @@ from .decorators import convert_units @@ -8,79 +8,80 @@ from .decorators import convert_units
from .metadecorators import set_height_metadata
from .util import extract_vars, either
def _get_geoht(wrfin, timeidx, method="cat", squeeze=True,
def _get_geoht(wrfin, timeidx, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
height=True, msl=True, stag=False):
"""Return the geopotential or geopotential height.
If *height* is False, then geopotential is returned in units of
[m2 s-2]. If *height* is True, then geopotential height is
returned in units of [m]. If *msl* is True, then geopotential height
is return as Mean Sea Level (MSL). If *msl* is False, then geopotential
If *height* is False, then geopotential is returned in units of
[m2 s-2]. If *height* is True, then geopotential height is
returned in units of [m]. If *msl* is True, then geopotential height
is return as Mean Sea Level (MSL). If *msl* is False, then geopotential
height is returned as Above Ground Level (AGL).
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
height (:obj:`bool`, optional): Set to True to return geopotential
height (:obj:`bool`, optional): Set to True to return geopotential
height instead of geopotential. Default is True.
msl (:obj:`bool`, optional): Set to True to return geopotential height
as Mean Sea Level (MSL). Set to False to return the
geopotential height as Above Ground Level (AGL) by subtracting
as Mean Sea Level (MSL). Set to False to return the
geopotential height as Above Ground Level (AGL) by subtracting
the terrain height. Default is True.
stag (:obj:`bool`, optional): Set to True to use the vertical
stag (:obj:`bool`, optional): Set to True to use the vertical
staggered grid, rather than the mass grid. Default is False.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
geopotential or geopotential height.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
varname = either("PH", "GHT")(wrfin)
if varname == "PH":
ph_vars = extract_vars(wrfin, timeidx, ("PH", "PHB", "HGT"),
@ -100,11 +101,11 @@ def _get_geoht(wrfin, timeidx, method="cat", squeeze=True, @@ -100,11 +101,11 @@ def _get_geoht(wrfin, timeidx, method="cat", squeeze=True,
_key=_key)
geopt_unstag = ght_vars["GHT"] * Constants.G
hgt = ght_vars["HGT_M"]
if stag:
warnings.warn("file contains no vertically staggered geopotential "
"height variable, returning unstaggered result "
"instead" )
"instead")
if height:
if msl:
return geopt_unstag / Constants.G
@ -113,70 +114,70 @@ def _get_geoht(wrfin, timeidx, method="cat", squeeze=True, @@ -113,70 +114,70 @@ def _get_geoht(wrfin, timeidx, method="cat", squeeze=True,
# array needs to be reshaped to a 3D array so the right dims
# line up
new_dims = list(hgt.shape)
new_dims.insert(-2,1)
new_dims.insert(-2, 1)
hgt = hgt.reshape(new_dims)
return (geopt_unstag / Constants.G) - hgt
else:
return geopt_unstag
@set_height_metadata(geopt=True, stag=False)
def get_geopt(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
def get_geopt(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return the geopotential.
The geopotential is returned in units of [m2 s-2].
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
geopotential.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
return _get_geoht(wrfin, timeidx, method, squeeze, cache, meta, _key,
False, True)
@ -184,135 +185,135 @@ def get_geopt(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -184,135 +185,135 @@ def get_geopt(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
@set_height_metadata(geopt=False, stag=False)
@convert_units("height", "m")
def get_height(wrfin, timeidx=0, method="cat", squeeze=True,
def get_height(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
msl=True, units="m"):
"""Return the geopotential height.
If *msl* is True, then geopotential height is returned as Mean Sea Level
(MSL). If *msl* is False, then geopotential height is returned as
If *msl* is True, then geopotential height is returned as Mean Sea Level
(MSL). If *msl* is False, then geopotential height is returned as
Above Ground Level (AGL) by subtracting the terrain height.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
msl (:obj:`bool`, optional): Set to True to return geopotential height
as Mean Sea Level (MSL). Set to False to return the
geopotential height as Above Ground Level (AGL) by subtracting
as Mean Sea Level (MSL). Set to False to return the
geopotential height as Above Ground Level (AGL) by subtracting
the terrain height. Default is True.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'z'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'z'. Default
is 'm'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
geopotential height.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
return _get_geoht(wrfin, timeidx, method, squeeze, cache, meta, _key,
True, msl)
@set_height_metadata(geopt=True, stag=True)
def get_stag_geopt(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
def get_stag_geopt(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return the geopotential for the vertically staggered grid.
The geopotential is returned in units of [m2 s-2].
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
geopotential.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
return _get_geoht(wrfin, timeidx, method, squeeze, cache, meta, _key,
False, True, stag=True)
@ -320,75 +321,73 @@ def get_stag_geopt(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -320,75 +321,73 @@ def get_stag_geopt(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
@set_height_metadata(geopt=False, stag=True)
@convert_units("height", "m")
def get_stag_height(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
msl=True, units="m"):
def get_stag_height(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, msl=True, units="m"):
"""Return the geopotential height for the vertically staggered grid.
If *msl* is True, then geopotential height is returned as Mean Sea Level
(MSL). If *msl* is False, then geopotential height is returned as
If *msl* is True, then geopotential height is returned as Mean Sea Level
(MSL). If *msl* is False, then geopotential height is returned as
Above Ground Level (AGL) by subtracting the terrain height.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
msl (:obj:`bool`, optional): Set to True to return geopotential height
as Mean Sea Level (MSL). Set to False to return the
geopotential height as Above Ground Level (AGL) by subtracting
as Mean Sea Level (MSL). Set to False to return the
geopotential height as Above Ground Level (AGL) by subtracting
the terrain height. Default is True.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'z'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'z'. Default
is 'm'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
geopotential height.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
return _get_geoht(wrfin, timeidx, method, squeeze, cache, meta, _key,
True, msl, stag=True)

233
src/wrf/g_helicity.py

@ -9,87 +9,88 @@ from .util import extract_vars, extract_global_attrs, either @@ -9,87 +9,88 @@ from .util import extract_vars, extract_global_attrs, either
from .metadecorators import copy_and_set_metadata
from .g_latlon import get_lat
@copy_and_set_metadata(copy_varname="HGT", name="srh",
@copy_and_set_metadata(copy_varname="HGT", name="srh",
description="storm relative helicity",
units="m2 s-2")
def get_srh(wrfin, timeidx=0, method="cat", squeeze=True,
def get_srh(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, top=3000.0):
"""Return the storm relative helicity.
The *top* argument specifies the top of the integration in [m].
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
top (:obj:`float`, optional): The top of the integration in [m].
top (:obj:`float`, optional): The top of the integration in [m].
Default is 3000.0.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
storm relative helicity.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
# Top can either be 3000 or 1000 (for 0-1 srh or 0-3 srh)
lats = get_lat(wrfin, timeidx, method, squeeze,
lats = get_lat(wrfin, timeidx, method, squeeze,
cache, meta=False, _key=_key, stagger=None)
ncvars = extract_vars(wrfin, timeidx, ("HGT", "PH", "PHB"),
method, squeeze, cache, meta=False,
_key=_key)
ter = ncvars["HGT"]
ph = ncvars["PH"]
phb = ncvars["PHB"]
# As coded in NCL, but not sure this is possible
varname = either("U", "UU")(wrfin)
u_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key)
u = destagger(u_vars[varname], -1)
u = destagger(u_vars[varname], -1)
varname = either("V", "VV")(wrfin)
v_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key)
@ -97,117 +98,113 @@ def get_srh(wrfin, timeidx=0, method="cat", squeeze=True, @@ -97,117 +98,113 @@ def get_srh(wrfin, timeidx=0, method="cat", squeeze=True,
geopt = ph + phb
geopt_unstag = destagger(geopt, -3)
z = geopt_unstag / Constants.G
# Re-ordering from high to low
u1 = np.ascontiguousarray(u[...,::-1,:,:])
v1 = np.ascontiguousarray(v[...,::-1,:,:])
z1 = np.ascontiguousarray(z[...,::-1,:,:])
u1 = np.ascontiguousarray(u[..., ::-1, :, :])
v1 = np.ascontiguousarray(v[..., ::-1, :, :])
z1 = np.ascontiguousarray(z[..., ::-1, :, :])
srh = _srhel(u1, v1, z1, ter, lats, top)
return srh
@copy_and_set_metadata(copy_varname="MAPFAC_M", name="updraft_helicity",
@copy_and_set_metadata(copy_varname="MAPFAC_M", name="updraft_helicity",
description="updraft helicity",
units="m2 s-2")
def get_uh(wrfin, timeidx=0, method="cat", squeeze=True,
def get_uh(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
bottom=2000.0, top=5000.0):
"""Return the updraft helicity.
The *bottom* and *top* arguments specify the bottom and top limits
The *bottom* and *top* arguments specify the bottom and top limits
for the integration in [m].
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
bottom (:obj:`float`, optional): The bottom limit for the integration
bottom (:obj:`float`, optional): The bottom limit for the integration
in [m]. Default is 2000.0.
top (:obj:`float`, optional): The top limit for the integration in [m].
top (:obj:`float`, optional): The top limit for the integration in [m].
Default is 5000.0.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
updraft helicity.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
ncvars = extract_vars(wrfin, timeidx, ("W", "PH", "PHB", "MAPFAC_M"),
method, squeeze, cache, meta=False, _key=_key)
wstag = ncvars["W"]
ph = ncvars["PH"]
phb = ncvars["PHB"]
mapfct = ncvars["MAPFAC_M"]
attrs = extract_global_attrs(wrfin, attrs=("DX", "DY"))
attrs = extract_global_attrs(wrfin, attrs=("DX", "DY"))
dx = attrs["DX"]
dy = attrs["DY"]
# As coded in NCL, but not sure this is possible
varname = either("U", "UU")(wrfin)
u_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key)
u = destagger(u_vars[varname], -1)
u = destagger(u_vars[varname], -1)
varname = either("V", "VV")(wrfin)
v_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key)
v = destagger(v_vars[varname], -2)
v = destagger(v_vars[varname], -2)
zp = (ph + phb) / Constants.G
uh = _udhel(zp, mapfct, u, v, wstag, dx, dy, bottom, top)
return uh
return uh

816
src/wrf/g_latlon.py

File diff suppressed because it is too large Load Diff

87
src/wrf/g_omega.py

@ -7,64 +7,64 @@ from .util import extract_vars @@ -7,64 +7,64 @@ from .util import extract_vars
from .metadecorators import copy_and_set_metadata
@copy_and_set_metadata(copy_varname="T", name="omega",
@copy_and_set_metadata(copy_varname="T", name="omega",
description="omega",
units="Pa s-1")
def get_omega(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return Omega.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: Omega.
If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`xarray.DataArray` or :class:`numpy.ndarray`: Omega.
If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "W", "PB", "QVAPOR")
varnames = ("T", "P", "W", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
@ -72,13 +72,12 @@ def get_omega(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -72,13 +72,12 @@ def get_omega(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
w = ncvars["W"]
pb = ncvars["PB"]
qv = ncvars["QVAPOR"]
wa = destagger(w, -3)
full_t = t + Constants.T_BASE
full_p = p + pb
tk = _tk(full_p, full_t)
omega = _omega(qv, tk, wa, full_p)
return omega

12
src/wrf/g_precip.py

@ -2,29 +2,29 @@ from __future__ import (absolute_import, division, print_function) @@ -2,29 +2,29 @@ from __future__ import (absolute_import, division, print_function)
from .util import extract_vars
__all__ = ["get_accum_precip", "get_precip_diff"]
def get_accum_precip(wrfin, timeidx=0):
ncvars = extract_vars(wrfin, timeidx, varnames=("RAINC", "RAINNC"))
rainc = ncvars["RAINC"]
rainnc = ncvars["RAINNC"]
rainsum = rainc + rainnc
return rainsum
def get_precip_diff(wrfin1, wrfin2, timeidx=0):
vars1 = extract_vars(wrfin1, timeidx, varnames=("RAINC", "RAINNC"))
vars2 = extract_vars(wrfin2, timeidx, varnames=("RAINC", "RAINNC"))
rainc1 = vars1["RAINC"]
rainnc1 = vars1["RAINNC"]
rainc2 = vars2["RAINC"]
rainnc2 = vars2["RAINNC"]
rainsum1 = rainc1 + rainnc1
rainsum2 = rainc2 + rainnc2
return (rainsum1 - rainsum2)
# TODO: Handle bucket flipping

183
src/wrf/g_pressure.py

@ -5,144 +5,141 @@ from .metadecorators import copy_and_set_metadata @@ -5,144 +5,141 @@ from .metadecorators import copy_and_set_metadata
from .util import extract_vars, either
@copy_and_set_metadata(copy_varname=either("P", "PRES"), name="pressure",
@copy_and_set_metadata(copy_varname=either("P", "PRES"), name="pressure",
description="pressure")
@convert_units("pressure", "pa")
def get_pressure(wrfin, timeidx=0, method="cat", squeeze=True,
def get_pressure(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
units="Pa"):
"""Return the pressure in the specified units.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'pres'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'pres'. Default
is 'Pa'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The pressure in
the specified units.
If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The pressure in
the specified units.
If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
"""
varname = either("P", "PRES")(wrfin)
if varname == "P":
p_vars = extract_vars(wrfin, timeidx, ("P", "PB"),
p_vars = extract_vars(wrfin, timeidx, ("P", "PB"),
method, squeeze, cache, meta=False,
_key=_key)
p = p_vars["P"]
pb = p_vars["PB"]
pres = p + pb
else:
pres = extract_vars(wrfin, timeidx, "PRES",
pres = extract_vars(wrfin, timeidx, "PRES",
method, squeeze, cache, meta=False,
_key=_key)["PRES"]
return pres
def get_pressure_hpa(wrfin, timeidx=0, method="cat", squeeze=True,
def get_pressure_hpa(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None):
"""Return the pressure in [hPa].
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The pressure in
[hPa].
If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The pressure in
[hPa].
If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
"""
return get_pressure(wrfin, timeidx, method, squeeze, cache, meta, _key,
units="hPa")

95
src/wrf/g_pw.py

@ -1,91 +1,86 @@ @@ -1,91 +1,86 @@
from __future__ import (absolute_import, division, print_function)
#from .extension import computepw,computetv,computetk
from .extension import _pw, _tv, _tk
from .constants import Constants
from .util import extract_vars
from .metadecorators import copy_and_set_metadata
@copy_and_set_metadata(copy_varname="T", name="pw",
@copy_and_set_metadata(copy_varname="T", name="pw",
remove_dims=("bottom_top",),
description="precipitable water",
MemoryOrder="XY",
units="kg m-2")
def get_pw(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
def get_pw(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return the preciptiable water.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The preciptable
water. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The preciptable
water. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "PH", "PHB", "QVAPOR")
varnames = ("T", "P", "PB", "PH", "PHB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]
ph = ncvars["PH"]
phb = ncvars["PHB"]
qv = ncvars["QVAPOR"]
full_p = p + pb
ht = (ph + phb)/Constants.G
full_t = t + Constants.T_BASE
tk = _tk(full_p, full_t)
tv = _tv(tk, qv)
return _pw(full_p, tv, qv, ht)

176
src/wrf/g_rh.py

@ -1,156 +1,154 @@ @@ -1,156 +1,154 @@
from __future__ import (absolute_import, division, print_function)
from .constants import Constants
#from .extension import computerh, computetk
from .constants import Constants
from .extension import _rh, _tk
from .util import extract_vars
from .metadecorators import copy_and_set_metadata
@copy_and_set_metadata(copy_varname="T", name="rh",
@copy_and_set_metadata(copy_varname="T", name="rh",
description="relative humidity",
units="%")
def get_rh(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
def get_rh(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return the relative humidity.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The relative
humidity. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The relative
humidity. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]
# Copy needed for the mmap nonsense of scipy.io.netcdf, which seems to
# Copy needed for the mmap nonsense of scipy.io.netcdf, which seems to
# break with every release
qvapor = ncvars["QVAPOR"].copy()
full_t = t + Constants.T_BASE
full_p = p + pb
qvapor[qvapor < 0] = 0
tk = _tk(full_p, full_t)
rh = _rh(qvapor, full_p, tk)
return rh
@copy_and_set_metadata(copy_varname="T2", name="rh2",
@copy_and_set_metadata(copy_varname="T2", name="rh2",
description="2m relative humidity",
units="%")
def get_rh_2m(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return the 2m relative humidity.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The 2m relative
humidity. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
humidity. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
"""
varnames=("T2", "PSFC", "Q2")
varnames = ("T2", "PSFC", "Q2")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t2 = ncvars["T2"]
psfc = ncvars["PSFC"]
# Copy needed for the mmap nonsense of scipy.io.netcdf, which seems to
# Copy needed for the mmap nonsense of scipy.io.netcdf, which seems to
# break with every release
q2 = ncvars["Q2"].copy()
q2[q2 < 0] = 0
rh = _rh(q2, psfc, t2)
return rh
return rh

106
src/wrf/g_slp.py

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
from __future__ import (absolute_import, division, print_function)
#from .extension import computeslp, computetk
from .extension import _slp, _tk
from .constants import Constants
from .destag import destagger
@ -10,94 +9,93 @@ from .util import extract_vars @@ -10,94 +9,93 @@ from .util import extract_vars
@copy_and_set_metadata(copy_varname="T", name="slp",
remove_dims=("bottom_top",),
remove_dims=("bottom_top",),
description="sea level pressure",
MemoryOrder="XY")
@convert_units("pressure", "hpa")
def get_slp(wrfin, timeidx=0, method="cat", squeeze=True,
def get_slp(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
units="hPa"):
"""Return the sea level pressure in the specified units.
This function extracts the necessary variables from the NetCDF file
This function extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'slp'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'slp'. Default
is 'Pa'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The sea level
pressure in the specified units. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The sea level
pressure in the specified units. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR", "PH", "PHB")
varnames = ("T", "P", "PB", "QVAPOR", "PH", "PHB")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]
# Copy needed for the mmap nonsense of scipy.io.netcdf, which seems to
# Copy needed for the mmap nonsense of scipy.io.netcdf, which seems to
# break with every release
qvapor = ncvars["QVAPOR"].copy()
ph = ncvars["PH"]
phb = ncvars["PHB"]
full_t = t + Constants.T_BASE
full_p = p + pb
qvapor[qvapor < 0] = 0.
full_ph = (ph + phb) / Constants.G
destag_ph = destagger(full_ph, -3)
tk = _tk(full_p, full_t)
slp = _slp(destag_ph, tk, full_p, qvapor)
return slp
return slp

623
src/wrf/g_temp.py

@ -7,70 +7,70 @@ from .metadecorators import copy_and_set_metadata @@ -7,70 +7,70 @@ from .metadecorators import copy_and_set_metadata
from .util import extract_vars
@copy_and_set_metadata(copy_varname="T", name="theta",
@copy_and_set_metadata(copy_varname="T", name="theta",
description="potential temperature")
@convert_units("temp", "k")
def get_theta(wrfin, timeidx=0, method="cat", squeeze=True,
def get_theta(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
units="K"):
"""Return the potential temperature.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'theta'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'theta'. Default
is 'K'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
potential temperature.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames = ("T",)
varnames = ("T", )
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
@ -79,438 +79,435 @@ def get_theta(wrfin, timeidx=0, method="cat", squeeze=True, @@ -79,438 +79,435 @@ def get_theta(wrfin, timeidx=0, method="cat", squeeze=True,
return full_t
@copy_and_set_metadata(copy_varname="T", name="temp",
@copy_and_set_metadata(copy_varname="T", name="temp",
description="temperature")
@convert_units("temp", "k")
def get_temp(wrfin, timeidx=0, method="cat", squeeze=True,
def get_temp(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
units="K"):
"""Return the temperature in the specified units.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'temp'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'temp'. Default
is 'K'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
temperature in the specified units.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB")
varnames = ("T", "P", "PB")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]
full_t = t + Constants.T_BASE
full_p = p + pb
tk = _tk(full_p, full_t)
return tk
@copy_and_set_metadata(copy_varname="T", name="theta_e",
@copy_and_set_metadata(copy_varname="T", name="theta_e",
description="equivalent potential temperature")
@convert_units("temp", "K")
def get_eth(wrfin, timeidx=0, method="cat", squeeze=True,
def get_eth(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
units="K"):
"""Return the equivalent potential temperature.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'eth'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'eth'. Default
is 'K'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
equivalent potential temperature.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]
qv = ncvars["QVAPOR"]
full_t = t + Constants.T_BASE
full_p = p + pb
tk = _tk(full_p, full_t)
eth = _eth(qv, tk, full_p)
return eth
@copy_and_set_metadata(copy_varname="T", name="tv",
@copy_and_set_metadata(copy_varname="T", name="tv",
description="virtual temperature")
@convert_units("temp", "k")
def get_tv(wrfin, timeidx=0, method="cat", squeeze=True,
def get_tv(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
units="K"):
"""Return the virtual temperature.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'tv'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'tv'. Default
is 'K'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
virtual temperature.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]
qv = ncvars["QVAPOR"]
full_t = t + Constants.T_BASE
full_p = p + pb
tk = _tk(full_p, full_t)
tv = _tv(tk, qv)
return tv
@copy_and_set_metadata(copy_varname="T", name="twb",
@copy_and_set_metadata(copy_varname="T", name="twb",
description="wetbulb temperature")
@convert_units("temp", "k")
def get_tw(wrfin, timeidx=0, method="cat", squeeze=True,
def get_tw(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
units="K"):
"""Return the wetbulb temperature.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'twb'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'twb'. Default
is 'K'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
wetbulb temperature.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
p = ncvars["P"]
pb = ncvars["PB"]
qv = ncvars["QVAPOR"]
full_t = t + Constants.T_BASE
full_p = p + pb
tk = _tk(full_p, full_t)
tw = _wetbulb(full_p, tk, qv)
return tw
def get_tk(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
def get_tk(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return the temperature in [K].
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
temperature in [K].
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
return get_temp(wrfin, timeidx, method, squeeze, cache, meta, _key,
return get_temp(wrfin, timeidx, method, squeeze, cache, meta, _key,
units="K")
def get_tc(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return the temperature in [degC].
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
temperature in [degC].
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
return get_temp(wrfin, timeidx, method, squeeze, cache, meta, _key,
units="degC")

97
src/wrf/g_terrain.py

@ -6,73 +6,70 @@ from .util import extract_vars, either @@ -6,73 +6,70 @@ from .util import extract_vars, either
# Need to handle either
@copy_and_set_metadata(copy_varname=either("HGT", "HGT_M"), name="terrain",
@copy_and_set_metadata(copy_varname=either("HGT", "HGT_M"), name="terrain",
description="terrain height")
@convert_units("height", "m")
def get_terrain(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=False, _key=None, units="m"):
def get_terrain(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=False, _key=None, units="m"):
"""Return the terrain height in the specified units.
This functions extracts the necessary variables from the NetCDF file
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'ter'. Default
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'ter'. Default
is 'm'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The terrain
height in the specified units. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The terrain
height in the specified units. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
"""
varname = either("HGT", "HGT_M")(wrfin)
return extract_vars(wrfin, timeidx, varname,
return extract_vars(wrfin, timeidx, varname,
method, squeeze, cache, meta=False,
_key=_key)[varname]

161
src/wrf/g_times.py

@ -3,119 +3,118 @@ from __future__ import (absolute_import, division, print_function) @@ -3,119 +3,118 @@ from __future__ import (absolute_import, division, print_function)
from .util import extract_times
def get_times(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
def get_times(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return a sequence of time objects.
This function reads the 'Times' variable and creates a sequence of
This function reads the 'Times' variable and creates a sequence of
:class:`datetime.datetime` objects.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: A sequence of
:class:`datetime.datetime` objects. If *meta* is True, the sequence
will be of type :class:`xarray.DataArray`, otherwise the sequence is
:class:`xarray.DataArray` or :class:`numpy.ndarray`: A sequence of
:class:`datetime.datetime` objects. If *meta* is True, the sequence
will be of type :class:`xarray.DataArray`, otherwise the sequence is
:class:`numpy.ndarray`.
"""
return extract_times(wrfin, timeidx, method, squeeze, cache,
return extract_times(wrfin, timeidx, method, squeeze, cache,
meta=meta, do_xtime=False)
def get_xtimes(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
def get_xtimes(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return a sequence of time objects.
This function reads the 'XTIME' variable and creates a sequence of
:obj:`float` objects.
This function reads the 'XTIME' variable and creates a sequence of
:obj:`float` objects.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: A sequence of
:obj:`float` objects. If *meta* is True, the sequence will be of type
:class:`xarray.DataArray`, otherwise the sequence is
:class:`xarray.DataArray` or :class:`numpy.ndarray`: A sequence of
:obj:`float` objects. If *meta* is True, the sequence will be of type
:class:`xarray.DataArray`, otherwise the sequence is
:class:`numpy.ndarray`.
Raises:
:class:`KeyError`: Raised if the 'XTIME' variable is not present
:class:`KeyError`: Raised if the 'XTIME' variable is not present
in the NetCDF file.
"""
return extract_times(wrfin, timeidx, method, squeeze, cache,
return extract_times(wrfin, timeidx, method, squeeze, cache,
meta=meta, do_xtime=True)

1007
src/wrf/g_uvmet.py

File diff suppressed because it is too large Load Diff

179
src/wrf/g_vorticity.py

@ -5,69 +5,69 @@ from .util import extract_vars, extract_global_attrs @@ -5,69 +5,69 @@ from .util import extract_vars, extract_global_attrs
from .metadecorators import copy_and_set_metadata
@copy_and_set_metadata(copy_varname="T", name="avo",
@copy_and_set_metadata(copy_varname="T", name="avo",
description="absolute vorticity",
units="10-5 s-1")
def get_avo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
def get_avo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return the absolute vorticity.
This function extracts the necessary variables from the NetCDF file
This function extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The absolute
vorticity. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The absolute
vorticity. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
"""
ncvars = extract_vars(wrfin, timeidx, ("U", "V", "MAPFAC_U",
"MAPFAC_V", "MAPFAC_M",
"F"),
method, squeeze, cache, meta=False, _key=_key)
attrs = extract_global_attrs(wrfin, attrs=("DX", "DY"))
u = ncvars["U"]
v = ncvars["V"]
@ -75,70 +75,70 @@ def get_avo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -75,70 +75,70 @@ def get_avo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
msfv = ncvars["MAPFAC_V"]
msfm = ncvars["MAPFAC_M"]
cor = ncvars["F"]
dx = attrs["DX"]
dy = attrs["DY"]
return _avo(u, v, msfu, msfv, msfm, cor, dx, dy)
@copy_and_set_metadata(copy_varname="T", name="pvo",
@copy_and_set_metadata(copy_varname="T", name="pvo",
description="potential vorticity",
units="PVU")
def get_pvo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
def get_pvo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None):
"""Return the potential vorticity.
This function extracts the necessary variables from the NetCDF file
This function extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The potential
vorticity. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The potential
vorticity. If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
"""
ncvars = extract_vars(wrfin, timeidx, ("U", "V", "T", "P",
"PB", "MAPFAC_U",
@ -146,7 +146,7 @@ def get_pvo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -146,7 +146,7 @@ def get_pvo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
"F"),
method, squeeze, cache, meta=False, _key=_key)
attrs = extract_global_attrs(wrfin, attrs=("DX", "DY"))
u = ncvars["U"]
v = ncvars["V"]
t = ncvars["T"]
@ -156,12 +156,11 @@ def get_pvo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -156,12 +156,11 @@ def get_pvo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
msfv = ncvars["MAPFAC_V"]
msfm = ncvars["MAPFAC_M"]
cor = ncvars["F"]
dx = attrs["DX"]
dy = attrs["DY"]
full_t = t + 300
full_p = p + pb
return _pvo(u, v, full_t, full_p, msfu, msfv, msfm, cor, dx, dy)

989
src/wrf/g_wind.py

File diff suppressed because it is too large Load Diff

71
src/wrf/geobnds.py

@ -2,46 +2,47 @@ from __future__ import (absolute_import, division, print_function) @@ -2,46 +2,47 @@ from __future__ import (absolute_import, division, print_function)
from .coordpair import CoordPair
class GeoBounds(object):
"""A class that stores the geographic boundaries.
Currently, only corner points are used, specified as the bottom left and
top right corners. Users can specify the corner points directly, or
Currently, only corner points are used, specified as the bottom left and
top right corners. Users can specify the corner points directly, or
specify two-dimensional latitude and longitude arrays and the corner points
will be extracted from them.
Attributes:
bottom_left (:class:`wrf.CoordPair`): The bottom left coordinate.
top_right (:class:`wrf.CoordPair`): The top right coordinate.
"""
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.
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.
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
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
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
# Make sure the users set lat/lon coordinates
if self.bottom_left.lat is None:
raise ValueError("'bottom_left' parameter does not contain a "
@ -56,35 +57,31 @@ class GeoBounds(object): @@ -56,35 +57,31 @@ class GeoBounds(object):
raise ValueError("'top_right' parameter does not contain a"
"'lon' attribute")
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])
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("must specify either 'bottom_top' and "
"'top_right' parameters "
"or 'lats' and 'lons' parameters")
def __repr__(self):
argstr = "{}, {}".format(repr(self.bottom_left),
argstr = "{}, {}".format(repr(self.bottom_left),
repr(self.top_right))
return "{}({})".format(self.__class__.__name__, argstr)
class NullGeoBounds(GeoBounds):
"""An emtpy :class:`wrf.GeoBounds` subclass.
This is used for initializing arrays of :class:`wrf.GeoBounds`, in
particular when working with moving domains and variables combined with the
This is used for initializing arrays of :class:`wrf.GeoBounds`, in
particular when working with moving domains and variables combined with the
'join' method.
"""
def __init__(self):
""" Initialize a :class:`wrf.NullGeoBounds` object."""
pass
def __repr__(self):
return "{}()".format(self.__class__.__name__)

945
src/wrf/interp.py

File diff suppressed because it is too large Load Diff

454
src/wrf/interputils.py

@ -14,165 +14,164 @@ from .util import pairs_to_latlon @@ -14,165 +14,164 @@ from .util import pairs_to_latlon
def to_positive_idxs(shape, coord):
"""Return the positive index values.
This function converts negative index values to positive index values.
Args:
shape (indexable sequence): The array shape.
coord (indexable sequence): The coordinate pair for x and y.
Returns:
:obj:`list`: The coordinate values with all positive indexes.
"""
if (coord[-2] >= 0 and coord[-1] >= 0):
return coord
return [x if (x >= 0) else shape[-i-1]+x for (i,x) in enumerate(coord)]
return [x if (x >= 0) else shape[-i-1]+x for (i, x) in enumerate(coord)]
def _calc_xy(xdim, ydim, pivot_point=None, angle=None,
start_point=None, end_point=None):
def _calc_xy(xdim, ydim, pivot_point=None, angle=None,
start_point=None, end_point=None):
"""Return the x,y points for the horizontal cross section line.
Args:
xdim (:obj:`int`): The x-dimension size.
ydim (:obj:`int`): The y-dimension size.
pivot_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries,
in the form of [x, y] (or [west_east, south_north]), which
indicates the x,y location through which the plane will pass.
pivot_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries,
in the form of [x, y] (or [west_east, south_north]), which
indicates the x,y location through which the plane will pass.
Must also specify `angle`.
angle (:obj:`float`, optional): Only valid for cross sections where
a plane will be plotted through
a given point on the model domain. 0.0 represents a S-N cross
section. 90.0 is a W-E cross section.
start_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the start
angle (:obj:`float`, optional): Only valid for cross sections where
a plane will be plotted through
a given point on the model domain. 0.0 represents a S-N cross
section. 90.0 is a W-E cross section.
start_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the start
x,y location through which the plane will pass.
end_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the end x,y
end_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the end x,y
location through which the plane will pass.
Returns:
:class:`np.ndarray`: A two-dimensional array with the left index
representing each point along the line, and the rightmost dimension
:class:`np.ndarray`: A two-dimensional array with the left index
representing each point along the line, and the rightmost dimension
having two values for the x and y coordinates [0=X, 1=Y].
"""
# Have a pivot point with an angle to find cross section
if pivot_point is not None and angle is not None:
xp = pivot_point[-2]
yp = pivot_point[-1]
if xp >= xdim or yp >= ydim:
raise ValueError("pivot point {} is outside of domain "
"with shape {}".format(pivot_point,
(xdim, ydim)))
if (angle > 315.0 or angle < 45.0
or ((angle > 135.0) and (angle < 225.0))):
#x = y*slope + intercept
(xdim, ydim)))
if (angle > 315.0 or angle < 45.0
or ((angle > 135.0) and (angle < 225.0))):
slope = -(360.-angle)/45.
if( angle < 45. ):
if(angle < 45.):
slope = angle/45.
if( angle > 135.):
if(angle > 135.):
slope = (angle-180.)/45.
intercept = xp - yp*slope
# find intersections with domain boundaries
y0 = 0.
x0 = y0*slope + intercept
if( x0 < 0.): # intersect outside of left boundary
if(x0 < 0.): # intersect outside of left boundary
x0 = 0.
y0 = (x0 - intercept)/slope
if( x0 > xdim-1): #intersect outside of right boundary
y0 = (x0 - intercept)/slope
if(x0 > xdim-1): # intersect outside of right boundary
x0 = xdim-1
y0 = (x0 - intercept)/slope
y1 = ydim-1. #need to make sure this will be a float?
y0 = (x0 - intercept)/slope
y1 = ydim-1. # need to make sure this will be a float?
x1 = y1*slope + intercept
if( x1 < 0.): # intersect outside of left boundary
if(x1 < 0.): # intersect outside of left boundary
x1 = 0.
y1 = (x1 - intercept)/slope
if( x1 > xdim-1): # intersect outside of right boundary
y1 = (x1 - intercept)/slope
if(x1 > xdim-1): # intersect outside of right boundary
x1 = xdim-1
y1 = (x1 - intercept)/slope
y1 = (x1 - intercept)/slope
else:
# y = x*slope + intercept
slope = (90.-angle)/45.
if( angle > 225. ):
if (angle > 225.):
slope = (270.-angle)/45.
intercept = yp - xp*slope
#find intersections with domain boundaries
# Find intersections with domain boundaries
x0 = 0.
y0 = x0*slope + intercept
if( y0 < 0.): # intersect outside of bottom boundary
if (y0 < 0.): # intersect outside of bottom boundary
y0 = 0.
x0 = (y0 - intercept)/slope
if( y0 > ydim-1): # intersect outside of top boundary
x0 = (y0 - intercept)/slope
if (y0 > ydim-1): # intersect outside of top boundary
y0 = ydim-1
x0 = (y0 - intercept)/slope
x1 = xdim-1. # need to make sure this will be a float?
x0 = (y0 - intercept)/slope
x1 = xdim-1. # need to make sure this will be a float?
y1 = x1*slope + intercept
if( y1 < 0.): # intersect outside of bottom boundary
if (y1 < 0.): # intersect outside of bottom boundary
y1 = 0.
x1 = (y1 - intercept)/slope
if( y1 > ydim-1):# intersect outside of top boundary
x1 = (y1 - intercept)/slope
if (y1 > ydim-1): # intersect outside of top boundary
y1 = ydim-1
x1 = (y1 - intercept)/slope
x1 = (y1 - intercept)/slope
elif start_point is not None and end_point is not None:
x0 = start_point[-2]
y0 = start_point[-1]
x1 = end_point[-2]
y1 = end_point[-1]
if x0 >= xdim or y0 >= ydim:
raise ValueError("start_point {} is outside of domain "
"with shape {}".format(start_point, (xdim, ydim)))
if x1 >= xdim or y1 >= ydim:
raise ValueError("end_point {} is outside of domain "
"with shape {}".format(end_point, (xdim, ydim)))
else:
raise ValueError("invalid start/end or pivot/angle arguments")
dx = x1 - x0
dy = y1 - y0
distance = (dx*dx + dy*dy)**0.5
npts = int(distance) + 1
xy = np.zeros((npts,2), "float")
xy = np.zeros((npts, 2), "float")
dx = dx/(npts-1)
dy = dy/(npts-1)
for i in py3range(npts):
xy[i,0] = x0 + i*dx
xy[i,1] = y0 + i*dy
xy[i, 0] = x0 + i*dx
xy[i, 1] = y0 + i*dy
return xy
@ -180,66 +179,66 @@ def get_xy_z_params(z, pivot_point=None, angle=None, @@ -180,66 +179,66 @@ def get_xy_z_params(z, pivot_point=None, angle=None,
start_point=None, end_point=None,
levels=None, autolevels=100):
"""Return the cross section parameters.
This function returns the xy horizontal cross section line coordinates,
the xy x z vertical values interpolated along the xy cross section
This function returns the xy horizontal cross section line coordinates,
the xy x z vertical values interpolated along the xy cross section
line, and the fixed vertical levels to be used by the cross section
algorithm (at ~1% increments for the minimum to maximum vertical
algorithm (at ~1% increments for the minimum to maximum vertical
span).
Args:
z (:class:`numpy.ndarray`): The vertical coordinate, whose rightmost
z (:class:`numpy.ndarray`): The vertical coordinate, whose rightmost
dimensions are bottom_top x south_north x west_east.
pivot_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries,
in the form of [x, y] (or [west_east, south_north]), which
indicates the x,y location through which the plane will pass.
pivot_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries,
in the form of [x, y] (or [west_east, south_north]), which
indicates the x,y location through which the plane will pass.
Must also specify `angle`.
angle (:obj:`float`, optional): Only valid for cross sections where
a plane will be plotted through
a given point on the model domain. 0.0 represents a S-N cross
section. 90.0 is a W-E cross section.
start_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the start
angle (:obj:`float`, optional): Only valid for cross sections where
a plane will be plotted through
a given point on the model domain. 0.0 represents a S-N cross
section. 90.0 is a W-E cross section.
start_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the start
x,y location through which the plane will pass.
end_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the end x,y
end_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the end x,y
location through which the plane will pass.
levels (sequence): A sequence of :obj:`float` for the desired
vertical levels in the output array. If None, a fixed set of
vertical levels in the output array. If None, a fixed set of
vertical levels is provided. Default is None.
autolevels(:obj:`int`, optional): The number of evenly spaced
automatically chosen vertical levels to use when *levels*
autolevels(:obj:`int`, optional): The number of evenly spaced
automatically chosen vertical levels to use when *levels*
is None. Default is 100.
Returns:
:obj:`tuple`: A tuple containing the xy horizontal cross section
coordinates, the vertical values interpolated along the xy cross
section line, and the fixed vertical levels used by the
cross section algorithm at ~1% increments of minimum to maximum
:obj:`tuple`: A tuple containing the xy horizontal cross section
coordinates, the vertical values interpolated along the xy cross
section line, and the fixed vertical levels used by the
cross section algorithm at ~1% increments of minimum to maximum
vertical span.
"""
xy = get_xy(z, pivot_point, angle, start_point, end_point)
# Interp z
var2dz = _interp2dxy(z, xy)
extra_dim_num = z.ndim - 3
idx1 = tuple([0]*extra_dim_num + [0,0])
idx2 = tuple([0]*extra_dim_num + [-1,0])
idx1 = tuple([0]*extra_dim_num + [0, 0])
idx2 = tuple([0]*extra_dim_num + [-1, 0])
if levels is None:
# interp to constant z grid
if(var2dz[idx1] > var2dz[idx2]): # monotonically decreasing coordinate
@ -255,181 +254,182 @@ def get_xy_z_params(z, pivot_point=None, angle=None, @@ -255,181 +254,182 @@ def get_xy_z_params(z, pivot_point=None, angle=None,
dz = (1.0/autolevels)*z_max
z_var2d = np.zeros((autolevels), dtype=z.dtype)
z_var2d[0] = z_min
for i in py3range(1,autolevels):
for i in py3range(1, autolevels):
z_var2d[i] = z_var2d[0] + i*dz
else:
z_var2d = np.asarray(levels, z.dtype)
return xy, var2dz, z_var2d
def get_xy(var, pivot_point=None, angle=None,
def get_xy(var, pivot_point=None, angle=None,
start_point=None, end_point=None):
"""Return the x,y points for the horizontal cross section line.
Args:
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A variable
that contains a :attr:`shape` attribute.
pivot_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries,
in the form of [x, y] (or [west_east, south_north]), which
indicates the x,y location through which the plane will pass.
pivot_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries,
in the form of [x, y] (or [west_east, south_north]), which
indicates the x,y location through which the plane will pass.
Must also specify `angle`.
angle (:obj:`float`, optional): Only valid for cross sections where
a plane will be plotted through
a given point on the model domain. 0.0 represents a S-N cross
section. 90.0 is a W-E cross section.
start_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the start
angle (:obj:`float`, optional): Only valid for cross sections where
a plane will be plotted through
a given point on the model domain. 0.0 represents a S-N cross
section. 90.0 is a W-E cross section.
start_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the start
x,y location through which the plane will pass.
end_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the end x,y
end_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
[x, y] (or [west_east, south_north]), which indicates the end x,y
location through which the plane will pass.
Returns:
:class:`np.ndarray`: A two-dimensional array with the left index
representing each point along the line, and the rightmost dimension
:class:`np.ndarray`: A two-dimensional array with the left index
representing each point along the line, and the rightmost dimension
having two values for the x and y coordinates [0=X, 1=Y].
"""
if pivot_point is not None:
pos_pivot = to_positive_idxs(var.shape[-2:], pivot_point)
else:
pos_pivot = pivot_point
if start_point is not None:
pos_start = to_positive_idxs(var.shape[-2:], start_point)
else:
pos_start = start_point
if end_point is not None:
pos_end = to_positive_idxs(var.shape[-2:], end_point)
else:
pos_end = start_point
xdim = var.shape[-1]
ydim = var.shape[-2]
xy = _calc_xy(xdim, ydim, pos_pivot, angle, pos_start, pos_end)
return xy
def to_xy_coords(pairs, wrfin=None, timeidx=0, stagger=None, projection=None,
ll_point=None):
"""Return the coordinate pairs in grid space.
This function converts latitude,longitude coordinate pairs to
This function converts latitude,longitude coordinate pairs to
x,y coordinate pairs.
Args:
pairs (:class:`CoordPair` or sequence): A single coordinate pair or
pairs (:class:`CoordPair` or sequence): A single coordinate pair or
a sequence of coordinate pairs to be converted.
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable, optional): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable, optional): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types. This is used
to obtain the map projection when using latitude,longitude
coordinates. Should not be used when working with x,y
to obtain the map projection when using latitude,longitude
coordinates. Should not be used when working with x,y
coordinates. Default is None.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index when obtaining map boundary information
from moving nests. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. Only required when
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index when obtaining map boundary information
from moving nests. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. Only required when
*wrfin* is specified and the nest is moving. Default is 0.
stagger (:obj:`str`): If using latitude, longitude coordinate pairs
for *start_point*, *end_point*, or *pivot_point*,
stagger (:obj:`str`): If using latitude, longitude coordinate pairs
for *start_point*, *end_point*, or *pivot_point*,
set the appropriate grid staggering type for *field2d*. By default,
the mass grid is used. The options are:
- 'm': Use the mass grid (default).
- 'u': Use the same staggered grid as the u wind component,
- 'u': Use the same staggered grid as the u wind component,
which has a staggered west_east (x) dimension.
- 'v': Use the same staggered grid as the v wind component,
- 'v': Use the same staggered grid as the v wind component,
which has a staggered south_north (y) dimension.
projection (:class:`wrf.WrfProj`, optional): The map
projection object to use when working with latitude, longitude
coordinates, and must be specified if *wrfin* is None. Default
projection (:class:`wrf.WrfProj`, optional): The map
projection object to use when working with latitude, longitude
coordinates, and must be specified if *wrfin* is None. Default
is None.
ll_point (:class:`wrf.CoordPair`, sequence of :class:`wrf.CoordPair`, \
optional): The lower left latitude, longitude point for your domain,
and must be specified
if *wrfin* is None. If the domain is a moving nest, this should be
optional): The lower left latitude, longitude point for your domain,
and must be specified
if *wrfin* is None. If the domain is a moving nest, this should be
a sequence of :class:`wrf.CoordPair`. Default is None.
Returns:
:class:`wrf.CoordPair` or sequence: The coordinate pair(s) in
:class:`wrf.CoordPair` or sequence: The coordinate pair(s) in
x,y grid coordinates.
"""
if (wrfin is None and (projection is None or ll_point is None)):
raise ValueError ("'wrfin' parameter or "
"'projection' and 'll_point' parameters "
"are required")
raise ValueError("'wrfin' parameter or "
"'projection' and 'll_point' parameters "
"are required")
lat, lon = pairs_to_latlon(pairs)
if wrfin is not None:
xy_vals = _ll_to_xy(lat, lon, wrfin=wrfin, timeidx=timeidx,
squeeze=True, meta=False, stagger=stagger, as_int=True)
xy_vals = _ll_to_xy(lat, lon, wrfin=wrfin, timeidx=timeidx,
squeeze=True, meta=False, stagger=stagger,
as_int=True)
else:
map_proj = projection.map_proj
if map_proj == ProjectionTypes.LAT_LON:
pole_lat = projection.pole_lat
pole_lon = projection.pole_lon
latinc = ((projection.dy*360.0)/2.0 /
latinc = ((projection.dy*360.0)/2.0 /
Constants.PI/Constants.WRF_EARTH_RADIUS)
loninc = ((projection.dx*360.0)/2.0 /
loninc = ((projection.dx*360.0)/2.0 /
Constants.PI/Constants.WRF_EARTH_RADIUS)
else:
pole_lat = 90.0
pole_lon = 0.0
latinc = 0.0
loninc = 0.0
ll_lat, ll_lon = pairs_to_latlon(ll_point)
xy_vals = _ll_to_xy(lat, lon, meta=False, squeeze=True,
xy_vals = _ll_to_xy(lat, lon, meta=False, squeeze=True,
as_int=True,
map_proj=projection.map_proj,
truelat1=projection.truelat1,
truelat2=projection.truelat2,
stand_lon=projection.stand_lon,
ref_lat=ll_lat,
ref_lon=ll_lon,
pole_lat=pole_lat,
pole_lon=pole_lon,
known_x=0,
known_y=0,
dx=projection.dx,
dy=projection.dy,
latinc=latinc,
map_proj=projection.map_proj,
truelat1=projection.truelat1,
truelat2=projection.truelat2,
stand_lon=projection.stand_lon,
ref_lat=ll_lat,
ref_lon=ll_lon,
pole_lat=pole_lat,
pole_lon=pole_lon,
known_x=0,
known_y=0,
dx=projection.dx,
dy=projection.dy,
latinc=latinc,
loninc=loninc)
xy_vals = xy_vals.squeeze()
if xy_vals.ndim == 1:
return CoordPair(x=xy_vals[0], y=xy_vals[1])
else:
return [CoordPair(x=xy_vals[0,i], y=xy_vals[1,i])
return [CoordPair(x=xy_vals[0, i], y=xy_vals[1, i])
for i in py3range(xy_vals.shape[1])]

547
src/wrf/latlonutils.py

@ -6,36 +6,36 @@ import numpy as np @@ -6,36 +6,36 @@ import numpy as np
from .constants import Constants, ProjectionTypes
from .extension import _lltoxy, _xytoll
from .util import (extract_vars, extract_global_attrs,
either, is_moving_domain, is_multi_time_req,
iter_left_indexes, is_mapping, is_multi_file)
from .util import (extract_vars, extract_global_attrs,
either, is_moving_domain, iter_left_indexes,
is_mapping, is_multi_file)
from .py3compat import viewkeys, viewitems
from .projutils import dict_keys_to_upper
def _lat_varname(wrfin, stagger):
"""Return the latitude variable name for the specified stagger type.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
stagger (:obj:`str`): The staggered grid type which is one of the
stagger (:obj:`str`): The staggered grid type which is one of the
following:
- 'm': Use the mass grid (default).
- 'u': Use the same staggered grid as the u wind component,
- 'u': Use the same staggered grid as the u wind component,
which has a staggered west_east (x) dimension.
- 'v': Use the same staggered grid as the v wind component,
- 'v': Use the same staggered grid as the v wind component,
which has a staggered south_north (y) dimension.
Returns:
:obj:`str`: The latitude variable name.
"""
if stagger is None or stagger.lower() == "m":
varname = either("XLAT", "XLAT_M")(wrfin)
@ -43,32 +43,33 @@ def _lat_varname(wrfin, stagger): @@ -43,32 +43,33 @@ def _lat_varname(wrfin, stagger):
varname = "XLAT_{}".format(stagger.upper())
else:
raise ValueError("invalid 'stagger' value")
return varname
def _lon_varname(wrfin, stagger):
"""Return the longitude variable name for the specified stagger type.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
stagger (:obj:`str`): The staggered grid type, which is one of the
stagger (:obj:`str`): The staggered grid type, which is one of the
following:
- 'm': Use the mass grid (default).
- 'u': Use the same staggered grid as the u wind component,
- 'u': Use the same staggered grid as the u wind component,
which has a staggered west_east (x) dimension.
- 'v': Use the same staggered grid as the v wind component,
- 'v': Use the same staggered grid as the v wind component,
which has a staggered south_north (y) dimension.
Returns:
:obj:`str`: The latitude variable name.
"""
if stagger is None or stagger.lower() == "m":
varname = either("XLONG", "XLONG_M")(wrfin)
@ -76,64 +77,65 @@ def _lon_varname(wrfin, stagger): @@ -76,64 +77,65 @@ def _lon_varname(wrfin, stagger):
varname = "XLONG_{}".format(stagger.upper())
else:
raise ValueError("invalid 'stagger' value")
return varname
def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key):
"""Return the map projection parameters.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
stagger (:obj:`str`): The staggered grid type, which is one of the
stagger (:obj:`str`): The staggered grid type, which is one of the
following:
- 'm': Use the mass grid (default).
- 'u': Use the same staggered grid as the u wind component,
- 'u': Use the same staggered grid as the u wind component,
which has a staggered west_east (x) dimension.
- 'v': Use the same staggered grid as the v wind component,
- 'v': Use the same staggered grid as the v wind component,
which has a staggered south_north (y) dimension.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
"""
if timeidx is not None:
if timeidx < 0:
raise ValueError("'timeidx' must be greater than 0")
attrs = extract_global_attrs(wrfin, attrs=("MAP_PROJ", "TRUELAT1",
"TRUELAT2", "STAND_LON",
"DX", "DY"))
@ -143,9 +145,9 @@ def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key): @@ -143,9 +145,9 @@ def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key):
stdlon = attrs["STAND_LON"]
dx = attrs["DX"]
dy = attrs["DY"]
if map_proj == ProjectionTypes.LAT_LON:
pole_attrs = extract_global_attrs(wrfin, attrs=("POLE_LAT",
pole_attrs = extract_global_attrs(wrfin, attrs=("POLE_LAT",
"POLE_LON"))
pole_lat = pole_attrs["POLE_LAT"]
pole_lon = pole_attrs["POLE_LON"]
@ -156,20 +158,20 @@ def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key): @@ -156,20 +158,20 @@ def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key):
pole_lon = 0.0
latinc = 0.0
loninc = 0.0
latvar = _lat_varname(wrfin, stagger)
lonvar = _lon_varname(wrfin, stagger)
lat_timeidx = timeidx
is_moving = is_moving_domain(wrfin, latvar=latvar, lonvar=lonvar,
is_moving = is_moving_domain(wrfin, latvar=latvar, lonvar=lonvar,
_key=_key)
# Only need one file and one time if the domain is not moving
if not is_moving:
# Always use the 0th time for non-moving domains to avoid problems
lat_timeidx = 0
if is_multi_file(wrfin):
if not is_mapping(wrfin):
wrfin = next(iter(wrfin)) # only need one file
@ -177,43 +179,43 @@ def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key): @@ -177,43 +179,43 @@ def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key):
first_entry = next(iter(viewkeys(wrfin)))
wrfin = wrfin[first_entry]
key = _key[first_entry]
return _get_proj_params(wrfin, timeidx, stagger,
return _get_proj_params(wrfin, timeidx, stagger,
method, squeeze, cache, key)
xlat = extract_vars(wrfin, lat_timeidx, (latvar,), method, squeeze, cache,
meta=False, _key=_key)[latvar]
meta=False, _key=_key)[latvar]
xlon = extract_vars(wrfin, lat_timeidx, (lonvar,), method, squeeze, cache,
meta=False, _key=_key)[lonvar]
meta=False, _key=_key)[lonvar]
ref_lat = np.ravel(xlat[..., 0, 0])
ref_lon = np.ravel(xlon[..., 0, 0])
# Note: fortran index
known_x = 1.0
known_y = 1.0
return (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc, loninc)
# known_x and known_y are 0-based
def _kwarg_proj_params(**projparams):
"""Return the map projection parameters.
This function aggregates the projection parameter keyword
This function aggregates the projection parameter keyword
arguments and also performs sanity checking on them.
Args:
**projparams: Projection parameter keyword arguments.
Returns:
:obj:`tuple`: The map projection parameters.
"""
projparams = dict_keys_to_upper(projparams)
map_proj = projparams.get("MAP_PROJ")
truelat1 = projparams.get("TRUELAT1")
truelat2 = projparams.get("TRUELAT2")
@ -222,164 +224,164 @@ def _kwarg_proj_params(**projparams): @@ -222,164 +224,164 @@ def _kwarg_proj_params(**projparams):
ref_lon = projparams.get("REF_LON")
pole_lat = projparams.get("POLE_LAT", 90.0)
pole_lon = projparams.get("POLE_LON", 0.0)
known_x = projparams.get("KNOWN_X") # Use 0-based
known_y = projparams.get("KNOWN_Y") # Use 0-based
known_x = projparams.get("KNOWN_X") # Use 0-based
known_y = projparams.get("KNOWN_Y") # Use 0-based
dx = projparams.get("DX")
dy = projparams.get("DY")
latinc = projparams.get("LATINC")
loninc = projparams.get("LONINC")
# Sanity checks
# Required args for all projections
for name, var in viewitems({"MAP_PROJ" : map_proj,
"REF_LAT" : ref_lat,
"REF_LON" : ref_lon,
"KNOWN_X" : known_x,
"KNOWN_Y" : known_y,
"DX" : dx}):
for name, var in viewitems({"MAP_PROJ": map_proj,
"REF_LAT": ref_lat,
"REF_LON": ref_lon,
"KNOWN_X": known_x,
"KNOWN_Y": known_y,
"DX": dx}):
if var is None:
raise ValueError("'{}' argument required".format(name))
# ref_lat and ref_lon are expected to be lists
ref_lat = np.ravel(np.asarray([ref_lat]))
ref_lon = np.ravel(np.asarray([ref_lon]))
# Fortran wants 1-based indexing
known_x = known_x + 1
known_y = known_y + 1
if map_proj in (ProjectionTypes.LAMBERT_CONFORMAL,
ProjectionTypes.POLAR_STEREOGRAPHIC,
if map_proj in (ProjectionTypes.LAMBERT_CONFORMAL,
ProjectionTypes.POLAR_STEREOGRAPHIC,
ProjectionTypes.MERCATOR):
if truelat1 is None:
raise ValueError("'TRUELAT1' argument required")
else:
if truelat1 is None:
truelat1 = 0.0
# Map projection 6 (lat lon) required latinc, loninc, and dy
if map_proj == ProjectionTypes.LAT_LON:
if latinc is None:
raise ValueError("'LATINC' argument required")
if loninc is None:
raise ValueError("'LONINC' argument required")
if dy is None:
raise ValueError("'DY' argument required")
else:
latinc = 0.0
loninc = 0.0
dy = 0.0
return (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, pole_lat,
pole_lon, known_x, known_y, dx, dy, latinc, loninc)
# Will return 0-based indexes
def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0,
stagger=None, method="cat", squeeze=True, cache=None,
_key=None, as_int=True, **projparams):
stagger=None, method="cat", squeeze=True, cache=None,
_key=None, as_int=True, **projparams):
"""Return the x,y coordinates for a specified latitude and longitude.
The *latitude* and *longitude* arguments can be a single value or a
The *latitude* and *longitude* arguments can be a single value or a
sequence of values.
The leftmost dimension of the returned array represents two different
The leftmost dimension of the returned array represents two different
quantities:
- return_val[0,...] will contain the X (west_east) values.
- return_val[1,...] will contain the Y (south_north) values.
Args:
latitude (:obj:`float` or sequence): A single latitude or a sequence
latitude (:obj:`float` or sequence): A single latitude or a sequence
of latitude values to be converted.
longitude (:obj:`float` or sequence): A single longitude or a sequence
longitude (:obj:`float` or sequence): A single longitude or a sequence
of latitude values to be converted.
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
stagger (:obj:`str`): By default, the latitude and longitude are
returned on the mass grid, but a staggered grid can be chosen
stagger (:obj:`str`): By default, the latitude and longitude are
returned on the mass grid, but a staggered grid can be chosen
with the following options:
- 'm': Use the mass grid (default).
- 'u': Use the same staggered grid as the u wind component,
- 'u': Use the same staggered grid as the u wind component,
which has a staggered west_east (x) dimension.
- 'v': Use the same staggered grid as the v wind component,
- 'v': Use the same staggered grid as the v wind component,
which has a staggered south_north (y) dimension.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
as_int (:obj:`bool`): Set to True to return the x,y values as
as_int (:obj:`bool`): Set to True to return the x,y values as
:obj:`int`, otherwise they will be returned as :obj:`float`.
**projparams: Map projection keyword arguments to set manually.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
x,y coordinate value(s) whose leftmost dimension is 2 (0=X, 1=Y).
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
if wrfin is not None:
(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc) = _get_proj_params(wrfin, timeidx, stagger, method, squeeze,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc) = _get_proj_params(wrfin, timeidx, stagger, method, squeeze,
cache, _key)
else:
(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc) = _kwarg_proj_params(**projparams)
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc) = _kwarg_proj_params(**projparams)
if isinstance(latitude, Iterable):
lats = np.asarray(latitude)
lons = np.asarray(longitude)
# Note: For scalars, this will make a single element array
lats = lats.ravel()
lons = lons.ravel()
if (lats.size != lons.size):
raise ValueError("'latitude' and 'longitude' "
"must be the same length")
if ref_lat.size == 1:
outdim = [2, lats.size]
extra_dims = [outdim[1]]
@ -387,11 +389,10 @@ def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0, @@ -387,11 +389,10 @@ def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0,
# Moving domain will have moving ref_lats/ref_lons
outdim = [2, ref_lat.size, lats.size]
extra_dims = outdim[1:]
result = np.empty(outdim, np.float64)
for left_idxs in iter_left_indexes(extra_dims):
#left_and_slice_idxs = left_idxs + (slice(None), )
# Left indexes is a misnomer, since these will be on the right
x_idxs = (0,) + left_idxs
y_idxs = (1,) + left_idxs
@ -401,149 +402,148 @@ def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0, @@ -401,149 +402,148 @@ def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0,
else:
ref_lat_val = ref_lat[left_idxs[-2]]
ref_lon_val = ref_lon[left_idxs[-2]]
lat = lats[left_idxs[-1]]
lon = lons[left_idxs[-1]]
xy = _lltoxy(map_proj, truelat1, truelat2, stdlon,
ref_lat_val, ref_lon_val, pole_lat, pole_lon,
known_x, known_y, dx, dy, latinc, loninc,
lat, lon)
ref_lat_val, ref_lon_val, pole_lat, pole_lon,
known_x, known_y, dx, dy, latinc, loninc,
lat, lon)
# Note: comes back from fortran as y,x
result[x_idxs] = xy[1]
result[y_idxs] = xy[0]
else:
result = np.empty((2,), np.float64)
fort_out = _lltoxy(map_proj, truelat1, truelat2, stdlon,
ref_lat, ref_lon, pole_lat, pole_lon,
known_x, known_y, dx, dy, latinc, loninc,
latitude, longitude)
ref_lat, ref_lon, pole_lat, pole_lon,
known_x, known_y, dx, dy, latinc, loninc,
latitude, longitude)
# Note, comes back from fortran as y,x. So, need to swap them.
result[0] = fort_out[1]
result[1] = fort_out[0]
# Make indexes 0-based
result = result - 1
if as_int:
result = np.rint(result).astype(int)
return result
# X and Y should be 0-based
def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None,
method="cat", squeeze=True, cache=None, _key=None,
**projparams):
def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None,
method="cat", squeeze=True, cache=None, _key=None,
**projparams):
"""Return the latitude and longitude for specified x,y coordinates.
The *x* and *y* arguments can be a single value or a sequence of values.
The leftmost dimension of the returned array represents two different
The leftmost dimension of the returned array represents two different
quantities:
- return_val[0,...] will contain the latitude values.
- return_val[1,...] will contain the longitude values.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
x (:obj:`float` or sequence): A single x-coordinate or a sequence
x (:obj:`float` or sequence): A single x-coordinate or a sequence
of x-coordinate values to be converted.
y (:obj:`float` or sequence): A single y-coordinate or a sequence
y (:obj:`float` or sequence): A single y-coordinate or a sequence
of y-coordinate values to be converted.
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
stagger (:obj:`str`): By default, the latitude and longitude are
returned on the mass grid, but a staggered grid can be chosen
stagger (:obj:`str`): By default, the latitude and longitude are
returned on the mass grid, but a staggered grid can be chosen
with the following options:
- 'm': Use the mass grid (default).
- 'u': Use the same staggered grid as the u wind component,
- 'u': Use the same staggered grid as the u wind component,
which has a staggered west_east (x) dimension.
- 'v': Use the same staggered grid as the v wind component,
- 'v': Use the same staggered grid as the v wind component,
which has a staggered south_north (y) dimension.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
_key (:obj:`int`, optional): A caching key. This is used for internal
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
**projparams: Map projection keyword arguments to set manually.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
latitude and longitude values whose leftmost dimension is 2
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
latitude and longitude values whose leftmost dimension is 2
(0=latitude, 1=longitude).
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
if wrfin is not None:
(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc) = _get_proj_params(wrfin, timeidx, stagger, method, squeeze,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc) = _get_proj_params(wrfin, timeidx, stagger, method, squeeze,
cache, _key)
else:
(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc) = _kwarg_proj_params(**projparams)
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc) = _kwarg_proj_params(**projparams)
if isinstance(x, Iterable):
x_arr = np.asarray(x)
y_arr = np.asarray(y)
# Convert 0-based x, y to 1-based
x_arr = x_arr + 1
y_arr = y_arr + 1
x_arr = x_arr.ravel()
y_arr = y_arr.ravel()
if (x_arr.size != y_arr.size):
raise ValueError("'x' and 'y' must be the same length")
if ref_lat.size == 1:
outdim = [2, x_arr.size]
extra_dims = [outdim[1]]
@ -551,44 +551,37 @@ def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None, @@ -551,44 +551,37 @@ def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None,
# Moving domain will have moving ref_lats/ref_lons
outdim = [2, ref_lat.size, x_arr.size]
extra_dims = outdim[1:]
result = np.empty(outdim, np.float64)
for left_idxs in iter_left_indexes(extra_dims):
#left_and_slice_idxs = left_idxs + (slice(None), )
lat_idxs = (0,) + left_idxs
lon_idxs = (1,) + left_idxs
if ref_lat.size == 1:
ref_lat_val = ref_lat[0]
ref_lon_val = ref_lon[0]
else:
ref_lat_val = ref_lat[left_idxs[-2]]
ref_lon_val = ref_lon[left_idxs[-2]]
x_val = x_arr[left_idxs[-1]]
y_val = y_arr[left_idxs[-1]]
ll = _xytoll(map_proj, truelat1, truelat2, stdlon, ref_lat_val,
ll = _xytoll(map_proj, truelat1, truelat2, stdlon, ref_lat_val,
ref_lon_val, pole_lat, pole_lon, known_x, known_y,
dx, dy, latinc, loninc, x_val, y_val)
#result[left_and_slice_idxs] = ll[:]
result[lat_idxs] = ll[0]
result[lon_idxs] = ll[1]
else:
# Convert 0-based to 1-based for Fortran
x_val = x + 1
y_val = y + 1
result = _xytoll(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc, x_val, y_val)
return result
result = _xytoll(map_proj, truelat1, truelat2, stdlon, ref_lat,
ref_lon, pole_lat, pole_lon, known_x, known_y,
dx, dy, latinc, loninc, x_val, y_val)
return result

1841
src/wrf/metadecorators.py

File diff suppressed because it is too large Load Diff

988
src/wrf/projection.py

File diff suppressed because it is too large Load Diff

13
src/wrf/projutils.py

@ -2,16 +2,17 @@ from __future__ import (absolute_import, division, print_function) @@ -2,16 +2,17 @@ from __future__ import (absolute_import, division, print_function)
from .py3compat import viewitems
def dict_keys_to_upper(d):
"""Return a dictionary with the keys changed to uppercase.
Args:
d (:obj:`dict`): A dictionary.
Returns:
:obj:`dict`: A dictionary with uppercase keys.
"""
return {key.upper() : val for key, val in viewitems(d)}
return {key.upper(): val for key, val in viewitems(d)}

118
src/wrf/py3compat.py

@ -3,18 +3,19 @@ from __future__ import (absolute_import, division, print_function) @@ -3,18 +3,19 @@ from __future__ import (absolute_import, division, print_function)
from sys import version_info
from math import floor, copysign
# Dictionary python 2-3 compatibility stuff
def viewitems(d):
"""Return either the items or viewitems method for a dictionary.
Args:
d (:obj:`dict`): A dictionary.
Returns:
view method: Either the items or viewitems method.
"""
func = getattr(d, "viewitems", None)
if func is None:
@ -24,15 +25,15 @@ def viewitems(d): @@ -24,15 +25,15 @@ def viewitems(d):
def viewkeys(d):
"""Return either the keys or viewkeys method for a dictionary.
Args:
d (:obj:`dict`): A dictionary.
Returns:
view method: Either the keys or viewkeys method.
"""
func = getattr(d, "viewkeys", None)
if func is None:
@ -42,32 +43,33 @@ def viewkeys(d): @@ -42,32 +43,33 @@ def viewkeys(d):
def viewvalues(d):
"""Return either the values or viewvalues method for a dictionary.
Args:
d (:obj:`dict`): A dictionary.
Returns:
view method: Either the values or viewvalues method.
"""
func = getattr(d, "viewvalues", None)
if func is None:
func = d.values
return func()
def isstr(s):
"""Return True if the object is a string type.
Args:
s (string): A string (str, unicode, bytes).
Returns:
:obj:`bool`: True if the object is a type of string. Otherwise, False.
"""
try:
return isinstance(s, basestring)
@ -75,25 +77,25 @@ def isstr(s): @@ -75,25 +77,25 @@ def isstr(s):
return isinstance(s, str)
# Python 2 rounding behavior
# Python 2 rounding behavior
def _round2(x, d=None):
"""Return the result of Python 2.x rounding, which is to round the number
"""Return the result of Python 2.x rounding, which is to round the number
to the nearest integer.
Python 3.x uses banker's rounding, which is not applicable for nearest
Python 3.x uses banker's rounding, which is not applicable for nearest
neighbor approaches with grid boxes.
Args:
x (:obj:`float`): A number, usually a float.
d (:obj:`int`, optional): The number of digits. Default is None,
d (:obj:`int`, optional): The number of digits. Default is None,
which indicates the nearest integer.
Returns:
:obj:`float`: The rounded number.
"""
d = 0 if d is None else d
p = 10 ** d
@ -101,69 +103,67 @@ def _round2(x, d=None): @@ -101,69 +103,67 @@ def _round2(x, d=None):
def py2round(x, d=None):
"""Return the result of Python 2.x rounding, which is to round the number
"""Return the result of Python 2.x rounding, which is to round the number
to the nearest integer.
Python 3.x uses banker's rounding, which is not applicable for nearest
Python 3.x uses banker's rounding, which is not applicable for nearest
neighbor approaches with grid boxes.
Args:
x (:obj:`float`): A number, usually a float.
d (:obj:`int`, optional): The number of digits. Default is None,
d (:obj:`int`, optional): The number of digits. Default is None,
which indicates the nearest integer.
Returns:
:obj:`float`: The rounded number.
"""
if version_info >= (3,):
return _round2(x, d)
return round(x, d)
def py3range(*args):
"""Return the equivalent of the range function in Python 3.x.
For Python 2.x, this is the same as the xrange function.
Args:
*args: The function arguments for range or xrange.
Returns:
iterable: An iterable sequence.
"""
if version_info >= (3,):
return range(*args)
return xrange(*args)
def ucode(*args, **kwargs):
"""Return a Python 3.x unicode string.
For Python 2.x, this is accomplished by using the unicode function.
Args:
*args: The function positional arguments for str or unicode.
**kwargs: The function keyword arguments for str or unicode.
Returns:
string: A unicode string.
"""
if version_info >= (3, ):
return str(*args, **kwargs)
return unicode(*args, **kwargs)
return unicode(*args, **kwargs)

489
src/wrf/routines.py

@ -2,8 +2,8 @@ from __future__ import (absolute_import, division, print_function) @@ -2,8 +2,8 @@ from __future__ import (absolute_import, division, print_function)
from .util import (get_iterable, is_standard_wrf_var, extract_vars, viewkeys,
get_id)
from .g_cape import (get_2dcape, get_3dcape, get_cape2d_only,
get_cin2d_only, get_lcl, get_lfc, get_3dcape_only,
from .g_cape import (get_2dcape, get_3dcape, get_cape2d_only,
get_cin2d_only, get_lcl, get_lfc, get_3dcape_only,
get_3dcin_only)
from .g_ctt import get_ctt
from .g_dbz import get_dbz, get_max_dbz
@ -16,334 +16,337 @@ from .g_pressure import get_pressure, get_pressure_hpa @@ -16,334 +16,337 @@ from .g_pressure import get_pressure, get_pressure_hpa
from .g_pw import get_pw
from .g_rh import get_rh, get_rh_2m
from .g_slp import get_slp
from .g_temp import get_tc, get_eth, get_temp, get_theta, get_tk, get_tv, get_tw
from .g_temp import (get_tc, get_eth, get_temp, get_theta, get_tk, get_tv,
get_tw)
from .g_terrain import get_terrain
from .g_uvmet import (get_uvmet, get_uvmet10, get_uvmet10_wspd_wdir,
from .g_uvmet import (get_uvmet, get_uvmet10, get_uvmet10_wspd_wdir,
get_uvmet_wspd_wdir, get_uvmet_wspd, get_uvmet_wdir,
get_uvmet10_wspd, get_uvmet10_wdir)
from .g_vorticity import get_avo, get_pvo
from .g_wind import (get_destag_wspd_wdir, get_destag_wspd_wdir10,
get_u_destag, get_v_destag, get_w_destag,
get_destag_wspd, get_destag_wdir, get_destag_wspd10,
get_destag_wdir10)
from .g_wind import (get_destag_wspd_wdir, get_destag_wspd_wdir10,
get_u_destag, get_v_destag, get_w_destag,
get_destag_wspd, get_destag_wdir, get_destag_wspd10,
get_destag_wdir10)
from .g_times import get_times, get_xtimes
from .g_cloudfrac import (get_cloudfrac, get_low_cloudfrac, get_mid_cloudfrac,
get_high_cloudfrac)
# func is the function to call. kargs are required arguments that should
# func is the function to call. kargs are required arguments that should
# not be altered by the user
_FUNC_MAP = {"cape2d" : get_2dcape,
"cape3d" : get_3dcape,
"dbz" : get_dbz,
"maxdbz" : get_max_dbz,
"dp" : get_dp,
"dp2m" : get_dp_2m,
"height" : get_height,
"geopt" : get_geopt,
"srh" : get_srh,
"uhel" : get_uh,
"omega" : get_omega,
"pw" : get_pw,
"rh" : get_rh,
"rh2m" : get_rh_2m,
"slp" : get_slp,
"theta" : get_theta,
"temp" : get_temp,
"tk" : get_tk,
"tc" : get_tc,
"theta_e" : get_eth,
"tv" : get_tv,
"twb" : get_tw,
"terrain" : get_terrain,
"times" : get_times,
"xtimes" : get_xtimes,
"uvmet" : get_uvmet,
"uvmet10" : get_uvmet10,
"avo" : get_avo,
"pvo" : get_pvo,
"ua" : get_u_destag,
"va" : get_v_destag,
"wa" : get_w_destag,
"lat" : get_lat,
"lon" : get_lon,
"pressure" : get_pressure_hpa,
"pres" : get_pressure,
"wspd_wdir" : get_destag_wspd_wdir,
"wspd_wdir10" : get_destag_wspd_wdir10,
"uvmet_wspd_wdir" : get_uvmet_wspd_wdir,
"uvmet10_wspd_wdir" : get_uvmet10_wspd_wdir,
"ctt" : get_ctt,
"cloudfrac" : get_cloudfrac,
"geopt_stag" : get_stag_geopt,
"zstag" : get_stag_height,
_FUNC_MAP = {"cape2d": get_2dcape,
"cape3d": get_3dcape,
"dbz": get_dbz,
"maxdbz": get_max_dbz,
"dp": get_dp,
"dp2m": get_dp_2m,
"height": get_height,
"geopt": get_geopt,
"srh": get_srh,
"uhel": get_uh,
"omega": get_omega,
"pw": get_pw,
"rh": get_rh,
"rh2m": get_rh_2m,
"slp": get_slp,
"theta": get_theta,
"temp": get_temp,
"tk": get_tk,
"tc": get_tc,
"theta_e": get_eth,
"tv": get_tv,
"twb": get_tw,
"terrain": get_terrain,
"times": get_times,
"xtimes": get_xtimes,
"uvmet": get_uvmet,
"uvmet10": get_uvmet10,
"avo": get_avo,
"pvo": get_pvo,
"ua": get_u_destag,
"va": get_v_destag,
"wa": get_w_destag,
"lat": get_lat,
"lon": get_lon,
"pressure": get_pressure_hpa,
"pres": get_pressure,
"wspd_wdir": get_destag_wspd_wdir,
"wspd_wdir10": get_destag_wspd_wdir10,
"uvmet_wspd_wdir": get_uvmet_wspd_wdir,
"uvmet10_wspd_wdir": get_uvmet10_wspd_wdir,
"ctt": get_ctt,
"cloudfrac": get_cloudfrac,
"geopt_stag": get_stag_geopt,
"zstag": get_stag_height,
# Diagnostics below are extracted from multi-product diagnostics
"cape2d_only" : get_cape2d_only,
"cin2d_only" : get_cin2d_only,
"lcl" : get_lcl,
"lfc" : get_lfc,
"cape3d_only" : get_3dcape_only,
"cape2d_only": get_cape2d_only,
"cin2d_only": get_cin2d_only,
"lcl": get_lcl,
"lfc": get_lfc,
"cape3d_only": get_3dcape_only,
"cin3d_only": get_3dcin_only,
"uvmet_wspd" : get_uvmet_wspd,
"uvmet_wdir" : get_uvmet_wdir,
"uvmet10_wspd" : get_uvmet10_wspd,
"uvmet10_wdir" : get_uvmet10_wdir,
"wspd" : get_destag_wspd,
"wdir" : get_destag_wdir,
"wspd10" : get_destag_wspd10,
"wdir10" : get_destag_wdir10,
"low_cloudfrac" : get_low_cloudfrac,
"mid_cloudfrac" : get_mid_cloudfrac,
"high_cloudfrac" : get_high_cloudfrac
"uvmet_wspd": get_uvmet_wspd,
"uvmet_wdir": get_uvmet_wdir,
"uvmet10_wspd": get_uvmet10_wspd,
"uvmet10_wdir": get_uvmet10_wdir,
"wspd": get_destag_wspd,
"wdir": get_destag_wdir,
"wspd10": get_destag_wspd10,
"wdir10": get_destag_wdir10,
"low_cloudfrac": get_low_cloudfrac,
"mid_cloudfrac": get_mid_cloudfrac,
"high_cloudfrac": get_high_cloudfrac
}
_VALID_KARGS = {"cape2d" : ["missing"],
"cape3d" : ["missing"],
"dbz" : ["do_variant", "do_liqskin"],
"maxdbz" : ["do_variant", "do_liqskin"],
"dp" : ["units"],
"dp2m" : ["units"],
"height" : ["msl", "units"],
"geopt" : [],
"srh" : ["top"],
"uhel" : ["bottom", "top"],
"omega" : [],
"pw" : [],
"rh" : [],
"rh2m" : [],
"slp" : ["units"],
"temp" : ["units"],
"tk" : [],
"tc" : [],
"theta" : ["units"],
"theta_e" : ["units"],
"tv" : ["units"],
"twb" : ["units"],
"terrain" : ["units"],
"times" : [],
"xtimes" : [],
"uvmet" : ["units"],
"uvmet10" : ["units"],
"avo" : [],
"pvo" : [],
"ua" : ["units"],
"va" : ["units"],
"wa" : ["units"],
"lat" : [],
"lon" : [],
"pres" : ["units"],
"pressure" : ["units"],
"wspd_wdir" : ["units"],
"wspd_wdir10" : ["units"],
"uvmet_wspd_wdir" : ["units"],
"uvmet10_wspd_wdir" : ["units"],
"ctt" : ["fill_nocloud", "missing", "opt_thresh", "units"],
"cloudfrac" : ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"geopt_stag" : [],
"zstag" : ["msl", "units"],
"cape2d_only" : ["missing"],
"cin2d_only" : ["missing"],
"lcl" : ["missing"],
"lfc" : ["missing"],
"cape3d_only" : ["missing"],
"cin3d_only": ["missing"],
"uvmet_wspd" : ["units"],
"uvmet_wdir" : ["units"],
"uvmet10_wspd" : ["units"],
"uvmet10_wdir" : ["units"],
"wspd" : ["units"],
"wdir" : ["units"],
"wspd10" : ["units"],
"wdir10" : ["units"],
"low_cloudfrac" : ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"mid_cloudfrac" : ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"high_cloudfrac" : ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"default" : []
}
_ALIASES = {"cape_2d" : "cape2d",
"cape_3d" : "cape3d",
"eth" : "theta_e",
"mdbz" : "maxdbz",
"geopotential" : "geopt",
"helicity" : "srh",
"latitude" : "lat",
"longitude" : "lon",
"omg" : "omega",
"p" : "pres",
"rh2" : "rh2m",
_VALID_KARGS = {"cape2d": ["missing"],
"cape3d": ["missing"],
"dbz": ["do_variant", "do_liqskin"],
"maxdbz": ["do_variant", "do_liqskin"],
"dp": ["units"],
"dp2m": ["units"],
"height": ["msl", "units"],
"geopt": [],
"srh": ["top"],
"uhel": ["bottom", "top"],
"omega": [],
"pw": [],
"rh": [],
"rh2m": [],
"slp": ["units"],
"temp": ["units"],
"tk": [],
"tc": [],
"theta": ["units"],
"theta_e": ["units"],
"tv": ["units"],
"twb": ["units"],
"terrain": ["units"],
"times": [],
"xtimes": [],
"uvmet": ["units"],
"uvmet10": ["units"],
"avo": [],
"pvo": [],
"ua": ["units"],
"va": ["units"],
"wa": ["units"],
"lat": [],
"lon": [],
"pres": ["units"],
"pressure": ["units"],
"wspd_wdir": ["units"],
"wspd_wdir10": ["units"],
"uvmet_wspd_wdir": ["units"],
"uvmet10_wspd_wdir": ["units"],
"ctt": ["fill_nocloud", "missing", "opt_thresh", "units"],
"cloudfrac": ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"geopt_stag": [],
"zstag": ["msl", "units"],
"cape2d_only": ["missing"],
"cin2d_only": ["missing"],
"lcl": ["missing"],
"lfc": ["missing"],
"cape3d_only": ["missing"],
"cin3d_only": ["missing"],
"uvmet_wspd": ["units"],
"uvmet_wdir": ["units"],
"uvmet10_wspd": ["units"],
"uvmet10_wdir": ["units"],
"wspd": ["units"],
"wdir": ["units"],
"wspd10": ["units"],
"wdir10": ["units"],
"low_cloudfrac": ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"mid_cloudfrac": ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"high_cloudfrac": ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"default": []
}
_ALIASES = {"cape_2d": "cape2d",
"cape_3d": "cape3d",
"eth": "theta_e",
"mdbz": "maxdbz",
"geopotential": "geopt",
"helicity": "srh",
"latitude": "lat",
"longitude": "lon",
"omg": "omega",
"p": "pres",
"rh2": "rh2m",
"z": "height",
"ter" : "terrain",
"updraft_helicity" : "uhel",
"td" : "dp",
"td2" : "dp2m",
"cfrac" : "cloudfrac",
"wspd_wdir_uvmet" : "uvmet_wspd_wdir",
"wspd_wdir_uvmet10" : "uvmet10_wspd_wdir",
"th" : "theta",
"low_cfrac" : "low_cloudfrac",
"mid_cfrac" : "mid_cloudfrac",
"high_cfrac" : "high_cloudfrac",
"wspd_uvmet" : "uvmet_wspd" ,
"wdir_uvmet" : "uvmet_wdir" ,
"wspd_uvmet10" : "uvmet10_wspd" ,
"wdir_uvmet10" : "uvmet10_wdir" ,
"ter": "terrain",
"updraft_helicity": "uhel",
"td": "dp",
"td2": "dp2m",
"cfrac": "cloudfrac",
"wspd_wdir_uvmet": "uvmet_wspd_wdir",
"wspd_wdir_uvmet10": "uvmet10_wspd_wdir",
"th": "theta",
"low_cfrac": "low_cloudfrac",
"mid_cfrac": "mid_cloudfrac",
"high_cfrac": "high_cloudfrac",
"wspd_uvmet": "uvmet_wspd",
"wdir_uvmet": "uvmet_wdir",
"wspd_uvmet10": "uvmet10_wspd",
"wdir_uvmet10": "uvmet10_wdir",
}
class ArgumentError(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg
def _undo_alias(alias):
actual = _ALIASES.get(alias, None)
if actual is None:
return alias
else:
return actual
def _check_kargs(var, kargs):
for arg in viewkeys(kargs):
if arg not in _VALID_KARGS[var]:
if var != "default":
raise ValueError("'{}' is an invalid keyword "
"argument for '{}'".format(arg, var))
"argument for '{}'".format(arg, var))
else:
raise ValueError("'{}' is an invalid keyword "
"argument".format(arg))
def getvar(wrfin, varname, timeidx=0,
method="cat", squeeze=True, cache=None, meta=True,
def getvar(wrfin, varname, timeidx=0,
method="cat", squeeze=True, cache=None, meta=True,
**kwargs):
"""Returns basic diagnostics from the WRF ARW model output.
A table of all available diagnostics is below.
.. include:: ../../_templates/product_table.txt
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
varname (:obj:`str`) : The variable name.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
**kwargs: Optional keyword arguments for certain diagnostics.
**kwargs: Optional keyword arguments for certain diagnostics.
See table above.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`xarray.DataArray` or :class:`numpy.ndarray`: If xarray is
enabled and the *meta* parameter is True, then the result will be a
:class:`xarray.DataArray` object. Otherwise, the result will be a
:class:`numpy.ndarray` object with no metadata.
Raises:
:class:`ValueError`: Raised when an invalid diagnostic type or
:class:`ValueError`: Raised when an invalid diagnostic type or
keyword argument is passed to the routine.
:class:`FortranError`: Raised when a problem occurs during a Fortran
calculation.
See Also:
:class:`numpy.ndarray`, :class:`xarray.DataArray`
Examples:
Using netCDF4
.. code-block:: python
from netCDF4 import Dataset
from wrf import getvar
wrfnc = Dataset("wrfout_d02_2010-06-13_21:00:00")
slp = getvar(wrfnc, "slp")
Using PyNIO
.. code-block:: python
from Nio import open_file
from wrf import getvar
wrfnc = open_file("wrfout_d02_2010-06-13_21:00:00"+".nc", "r")
slp = getvar(wrfnc, "slp")
Using Iterables:
.. code-block:: python
import os
from netCDF4 import Dataset
from wrf import getvar
filedir = "/path/to/wrf/files"
wrfin = [Dataset(f) for f in os.listdir(filedir)
wrfin = [Dataset(f) for f in os.listdir(filedir)
if f.startswith("wrfout_d02_")]
uvmet = getvar(wrfin, "uvmet", timeidx=3, units="kt")
"""
_key = get_id(wrfin)
wrfin = get_iterable(wrfin)
if is_standard_wrf_var(wrfin, varname) and varname != "Times":
_check_kargs("default", kwargs)
return extract_vars(wrfin, timeidx, varname,
return extract_vars(wrfin, timeidx, varname,
method, squeeze, cache, meta, _key)[varname]
elif varname == "Times":
varname = "times" # Diverting to the get_times routine
actual_var = _undo_alias(varname)
if actual_var not in _VALID_KARGS:
raise ValueError("'%s' is not a valid variable name" % (varname))
raise ValueError("'{}' is not a valid variable name".format(varname))
_check_kargs(actual_var, kwargs)
return _FUNC_MAP[actual_var](wrfin, timeidx, method, squeeze, cache,
return _FUNC_MAP[actual_var](wrfin, timeidx, method, squeeze, cache,
meta, _key, **kwargs)

463
src/wrf/specialdec.py

@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function) @@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function)
import numpy as np
import wrapt
import wrapt
from .util import iter_left_indexes, to_np
from .py3compat import py3range
@ -14,28 +14,28 @@ if xarray_enabled(): @@ -14,28 +14,28 @@ if xarray_enabled():
def uvmet_left_iter(alg_dtype=np.float64):
"""A decorator to handle iterating over the leftmost dimensions for the
"""A decorator to handle iterating over the leftmost dimensions for the
uvmet diagnostic.
For example, if a wrapped function works with three-dimensional arrays, but
the variables include a 4th leftmost dimension for 'Time', this decorator
the variables include a 4th leftmost dimension for 'Time', this decorator
will iterate over all times, call the 3D Fortran routine, and aggregate the
results in to a 4D output array.
It is also important to note that the final output array is allocated
first, and then views are passed to the wrapped function so that values
It is also important to note that the final output array is allocated
first, and then views are passed to the wrapped function so that values
do not need to get copied in to the final output array.
Args:
alg_dtype (:class:`np.dtype` or :obj:`str`): The numpy data type used
alg_dtype (:class:`np.dtype` or :obj:`str`): The numpy data type used
in the wrapped function.
Returns:
:class:`numpy.ndarray`: The aggregated uvmet output array that includes
:class:`numpy.ndarray`: The aggregated uvmet output array that includes
all extra leftmost dimensions.
"""
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
@ -43,64 +43,62 @@ def uvmet_left_iter(alg_dtype=np.float64): @@ -43,64 +43,62 @@ def uvmet_left_iter(alg_dtype=np.float64):
v = args[1]
lat = args[2]
lon = args[3]
cen_long = args[4]
cen_long = args[4]
cone = args[5]
orig_dtype = u.dtype
lat_lon_fixed = False
if lat.ndim == 2:
lat_lon_fixed = True
if lon.ndim == 2 and not lat_lon_fixed:
raise ValueError("'lat' and 'lon' shape mismatch")
num_left_dims_u = u.ndim - 2
num_left_dims_lat = lat.ndim - 2
if (num_left_dims_lat > num_left_dims_u):
raise ValueError("number of 'lat' dimensions is greater than 'u'")
if lat_lon_fixed:
mode = 0 # fixed lat/lon
mode = 0 # fixed lat/lon
else:
if num_left_dims_u == num_left_dims_lat:
mode = 1 # lat/lon same as u
mode = 1 # lat/lon same as u
else:
mode = 2 # probably 3D with 2D lat/lon plus Time
mode = 2 # probably 3D with 2D lat/lon plus Time
has_missing = False
u_arr = to_np(u)
v_arr = to_np(v)
umissing = default_fill(np.float64)
umissing = default_fill(np.float64)
if isinstance(u_arr, np.ma.MaskedArray):
has_missing = True
umissing = u_arr.fill_value
vmissing = default_fill(np.float64)
vmissing = default_fill(np.float64)
if isinstance(v_arr, np.ma.MaskedArray):
has_missing = True
vmissing = v_arr.fill_value
uvmetmissing = umissing
is_stag = 0
if (u.shape[-1] != lat.shape[-1] or u.shape[-2] != lat.shape[-2]):
is_stag = 1
# Sanity check
if (v.shape[-1] == lat.shape[-1] or v.shape[-2] == lat.shape[-2]):
raise ValueError("u is staggered but v is not")
if (v.shape[-1] != lat.shape[-1] or v.shape[-2] != lat.shape[-2]):
is_stag = 1
# Sanity check
if (u.shape[-1] == lat.shape[-1] or u.shape[-2] == lat.shape[-2]):
raise ValueError("v is staggered but u is not")
# No special left side iteration, return the function result
if (num_left_dims_u == 0):
return wrapped(u, v, lat, lon, cen_long, cone, isstag=is_stag,
@ -109,44 +107,43 @@ def uvmet_left_iter(alg_dtype=np.float64): @@ -109,44 +107,43 @@ def uvmet_left_iter(alg_dtype=np.float64):
# Initial output is time,nz,2,ny,nx to create contiguous views
outdims = u.shape[0:num_left_dims_u]
extra_dims = tuple(outdims) # Copy the left-most dims for iteration
extra_dims = tuple(outdims) # Copy the left-most dims for iteration
outdims += (2,)
outdims += lat.shape[-2:]
outview_array = np.empty(outdims, alg_dtype)
# Final Output moves the u_v dimension to left side
output_dims = (2,)
output_dims += extra_dims
output_dims += lat.shape[-2:]
output = np.empty(output_dims, orig_dtype)
for left_idxs in iter_left_indexes(extra_dims):
left_and_slice_idxs = left_idxs + (slice(None),)
if mode == 0:
lat_left_and_slice = (slice(None),)
elif mode == 1:
lat_left_and_slice = left_and_slice_idxs
elif mode == 2:
# Only need the left-most
lat_left_and_slice = tuple(left_idx
for left_idx in left_idxs[0:num_left_dims_lat])
lat_left_and_slice = tuple(
left_idx for left_idx in left_idxs[0:num_left_dims_lat])
u_output_idxs = (0,) + left_idxs + (slice(None),)
v_output_idxs = (1,) + left_idxs + (slice(None),)
u_view_idxs = left_idxs + (0, slice(None))
v_view_idxs = left_idxs + (1, slice(None))
v_view_idxs = left_idxs + (1, slice(None))
new_u = u[left_and_slice_idxs]
new_v = v[left_and_slice_idxs]
new_lat = lat[lat_left_and_slice]
new_lon = lon[lat_left_and_slice]
outview = outview_array[left_and_slice_idxs]
# Skip the possible empty/missing arrays for the join method
skip_missing = False
for arg in (new_u, new_v, new_lat, new_lon):
@ -154,70 +151,69 @@ def uvmet_left_iter(alg_dtype=np.float64): @@ -154,70 +151,69 @@ def uvmet_left_iter(alg_dtype=np.float64):
if arg.mask.all():
output[u_output_idxs] = uvmetmissing
output[v_output_idxs] = uvmetmissing
skip_missing = True
has_missing = True
if skip_missing:
continue
# Call the numerical routine
result = wrapped(new_u, new_v, new_lat, new_lon, cen_long, cone,
isstag=is_stag, has_missing=has_missing,
umissing=umissing, vmissing=vmissing,
isstag=is_stag, has_missing=has_missing,
umissing=umissing, vmissing=vmissing,
uvmetmissing=uvmetmissing, outview=outview)
# Make sure the result is the same data as what got passed in
# Make sure the result is the same data as what got passed in
# Can delete this once everything works
if (result.__array_interface__["data"][0] !=
outview.__array_interface__["data"][0]):
if (result.__array_interface__["data"][0] !=
outview.__array_interface__["data"][0]):
raise RuntimeError("output array was copied")
output[u_output_idxs] = (
outview_array[u_view_idxs].astype(orig_dtype))
output[v_output_idxs] = (
outview_array[v_view_idxs].astype(orig_dtype))
if has_missing:
output = np.ma.masked_values(output, uvmetmissing)
return output
return func_wrapper
def cape_left_iter(alg_dtype=np.float64):
"""A decorator to handle iterating over the leftmost dimensions for the
"""A decorator to handle iterating over the leftmost dimensions for the
cape diagnostic.
For example, if a wrapped function works with three-dimensional arrays, but
the variables include a 4th leftmost dimension for 'Time', this decorator
the variables include a 4th leftmost dimension for 'Time', this decorator
will iterate over all times, call the 3D Fortran routine, and aggregate the
results in to a 4D output array.
It is also important to note that the final output array is allocated
first, and then views are passed to the wrapped function so that values
It is also important to note that the final output array is allocated
first, and then views are passed to the wrapped function so that values
do not need to get copied in to the final output array.
Args:
alg_dtype (:class:`np.dtype` or :obj:`str`): The numpy data type used
alg_dtype (:class:`np.dtype` or :obj:`str`): The numpy data type used
in the wrapped function.
Returns:
:class:`numpy.ndarray`: The aggregated cape output array that includes
:class:`numpy.ndarray`: The aggregated cape output array that includes
all extra leftmost dimensions.
"""
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
# The cape calculations use an ascending vertical pressure coordinate
new_args = list(args)
new_kwargs = dict(kwargs)
p_hpa = args[0]
tk = args[1]
qv = args[2]
@ -227,19 +223,19 @@ def cape_left_iter(alg_dtype=np.float64): @@ -227,19 +223,19 @@ def cape_left_iter(alg_dtype=np.float64):
missing = args[6]
i3dflag = args[7]
ter_follow = args[8]
is2d = i3dflag == 0
# Note: This should still work with DataArrays
is1d = np.isscalar(sfp) or np.size(sfp) == 1
# Make sure sfp and terrain are regular floats for 1D case
# This should also work with DataArrays
if is1d:
ter = float(ter)
sfp = float(sfp)
sfp = float(sfp)
orig_dtype = p_hpa.dtype
if not is1d:
# Need to order in ascending pressure order
flip = False
@ -247,48 +243,48 @@ def cape_left_iter(alg_dtype=np.float64): @@ -247,48 +243,48 @@ def cape_left_iter(alg_dtype=np.float64):
top_idxs = list(bot_idxs)
top_idxs[-3] = -1
top_idxs = tuple(top_idxs)
if p_hpa[bot_idxs] > p_hpa[top_idxs]:
flip = True
p_hpa = np.ascontiguousarray(p_hpa[...,::-1,:,:])
tk = np.ascontiguousarray(tk[...,::-1,:,:])
qv = np.ascontiguousarray(qv[...,::-1,:,:])
ht = np.ascontiguousarray(ht[...,::-1,:,:])
p_hpa = np.ascontiguousarray(p_hpa[..., ::-1, :, :])
tk = np.ascontiguousarray(tk[..., ::-1, :, :])
qv = np.ascontiguousarray(qv[..., ::-1, :, :])
ht = np.ascontiguousarray(ht[..., ::-1, :, :])
new_args[0] = p_hpa
new_args[1] = tk
new_args[2] = qv
new_args[3] = ht
num_left_dims = p_hpa.ndim - 3
else:
# Need to order in ascending pressure order
flip = False
if p_hpa[0] > p_hpa[-1]:
flip = True
p_hpa = np.ascontiguousarray(p_hpa[::-1])
tk = np.ascontiguousarray(tk[::-1])
qv = np.ascontiguousarray(qv[::-1])
ht = np.ascontiguousarray(ht[::-1])
# Need to make 3D views for the fortran code.
# Going to make these fortran ordered, since the f_contiguous and
# c_contiguous flags are broken in numpy 1.11 (always false). This
# should work across all numpy versions.
# c_contiguous flags are broken in numpy 1.11 (always false). This
# should work across all numpy versions.
new_args[0] = p_hpa.reshape((1, 1, p_hpa.shape[0]), order='F')
new_args[1] = tk.reshape((1, 1, tk.shape[0]), order='F')
new_args[2] = qv.reshape((1, 1, qv.shape[0]), order='F')
new_args[3] = ht.reshape((1, 1, ht.shape[0]), order='F')
new_args[4] = np.full((1,1), ter, orig_dtype)
new_args[5] = np.full((1,1), sfp, orig_dtype)
new_args[4] = np.full((1, 1), ter, orig_dtype)
new_args[5] = np.full((1, 1), sfp, orig_dtype)
num_left_dims = 0
# No special left side iteration, build the output from the cape,cin
# result
if (num_left_dims == 0):
cape, cin = wrapped(*new_args, **new_kwargs)
output_dims = (2,)
if not is1d:
output_dims += p_hpa.shape[-3:]
@ -296,26 +292,26 @@ def cape_left_iter(alg_dtype=np.float64): @@ -296,26 +292,26 @@ def cape_left_iter(alg_dtype=np.float64):
output_dims += (p_hpa.shape[0], 1, 1)
output = np.empty(output_dims, orig_dtype)
if flip and not is2d:
output[0,:] = cape[::-1,:,:]
output[1,:] = cin[::-1,:,:]
output[0, :] = cape[::-1, :, :]
output[1, :] = cin[::-1, :, :]
else:
output[0,:] = cape[:]
output[1,:] = cin[:]
output[0, :] = cape[:]
output[1, :] = cin[:]
return output
# Initial output is ...,cape_cin,nz,ny,nx to create contiguous views
outdims = p_hpa.shape[0:num_left_dims]
extra_dims = tuple(outdims) # Copy the left-most dims for iteration
outdims += (2,) # cape_cin
extra_dims = tuple(outdims) # Copy the left-most dims for iteration
outdims += (2,) # cape_cin
outdims += p_hpa.shape[-3:]
outview_array = np.empty(outdims, alg_dtype)
# Create the output array where the leftmost dim is the product type
output_dims = (2,)
output_dims += extra_dims
@ -326,14 +322,14 @@ def cape_left_iter(alg_dtype=np.float64): @@ -326,14 +322,14 @@ def cape_left_iter(alg_dtype=np.float64):
left_and_slice_idxs = left_idxs + (slice(None),)
cape_idxs = left_idxs + (0, slice(None))
cin_idxs = left_idxs + (1, slice(None))
cape_output_idxs = (0,) + left_idxs + (slice(None),)
cin_output_idxs = (1,) + left_idxs + (slice(None),)
view_cape_reverse_idxs = left_idxs + (0, slice(None,None,-1),
view_cape_reverse_idxs = left_idxs + (0, slice(None, None, -1),
slice(None))
view_cin_reverse_idxs = left_idxs + (1, slice(None,None,-1),
view_cin_reverse_idxs = left_idxs + (1, slice(None, None, -1),
slice(None))
new_args[0] = p_hpa[left_and_slice_idxs]
new_args[1] = tk[left_and_slice_idxs]
new_args[2] = qv[left_and_slice_idxs]
@ -342,9 +338,9 @@ def cape_left_iter(alg_dtype=np.float64): @@ -342,9 +338,9 @@ def cape_left_iter(alg_dtype=np.float64):
new_args[5] = sfp[left_and_slice_idxs]
capeview = outview_array[cape_idxs]
cinview = outview_array[cin_idxs]
# Skip the possible empty/missing arrays for the join method
# Note: Masking handled by cape.py or computation.py, so only
# Note: Masking handled by cape.py or computation.py, so only
# supply the fill values here.
skip_missing = False
for arg in (new_args[0:6]):
@ -356,25 +352,24 @@ def cape_left_iter(alg_dtype=np.float64): @@ -356,25 +352,24 @@ def cape_left_iter(alg_dtype=np.float64):
else:
output[cape_output_idxs] = missing
output[cin_output_idxs] = missing
skip_missing = True
if skip_missing:
continue
# Call the numerical routine
new_kwargs["capeview"] = capeview
new_kwargs["cinview"] = cinview
cape, cin = wrapped(*new_args, **new_kwargs)
# Make sure the result is the same data as what got passed in
# Make sure the result is the same data as what got passed in
# Can delete this once everything works
if (cape.__array_interface__["data"][0] !=
capeview.__array_interface__["data"][0]):
if (cape.__array_interface__["data"][0] !=
capeview.__array_interface__["data"][0]):
raise RuntimeError("output array was copied")
if flip and not is2d:
output[cape_output_idxs] = (
outview_array[view_cape_reverse_idxs].astype(orig_dtype))
@ -382,82 +377,82 @@ def cape_left_iter(alg_dtype=np.float64): @@ -382,82 +377,82 @@ def cape_left_iter(alg_dtype=np.float64):
outview_array[view_cin_reverse_idxs].astype(orig_dtype))
else:
output[cape_output_idxs] = (
outview_array[cape_idxs].astype(orig_dtype))
outview_array[cape_idxs].astype(orig_dtype))
output[cin_output_idxs] = (
outview_array[cin_idxs].astype(orig_dtype))
outview_array[cin_idxs].astype(orig_dtype))
return output
return func_wrapper
def cloudfrac_left_iter(alg_dtype=np.float64):
"""A decorator to handle iterating over the leftmost dimensions for the
"""A decorator to handle iterating over the leftmost dimensions for the
cloud fraction diagnostic.
For example, if a wrapped function works with three-dimensional arrays, but
the variables include a 4th leftmost dimension for 'Time', this decorator
the variables include a 4th leftmost dimension for 'Time', this decorator
will iterate over all times, call the 3D Fortran routine, and aggregate the
results in to a 4D output array.
It is also important to note that the final output array is allocated
first, and then views are passed to the wrapped function so that values
It is also important to note that the final output array is allocated
first, and then views are passed to the wrapped function so that values
do not need to get copied in to the final output array.
Args:
alg_dtype (:class:`np.dtype` or :obj:`str`): The numpy data type used
alg_dtype (:class:`np.dtype` or :obj:`str`): The numpy data type used
in the wrapped function.
Returns:
:class:`numpy.ndarray`: The aggregated cloud fraction output array
:class:`numpy.ndarray`: The aggregated cloud fraction output array
that includes all extra leftmost dimensions.
"""
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
new_args = list(args)
new_kwargs = dict(kwargs)
vert = args[0]
rh = args[1]
num_left_dims = vert.ndim - 3
orig_dtype = vert.dtype
# No special left side iteration, build the output from the
# No special left side iteration, build the output from the
# low, mid, high results.
if (num_left_dims == 0):
low, mid, high = wrapped(*new_args, **new_kwargs)
output_dims = (3,)
output_dims += vert.shape[-2:]
output = np.empty(output_dims, orig_dtype)
output[0,:] = low[:]
output[1,:] = mid[:]
output[2,:] = high[:]
output[0, :] = low[:]
output[1, :] = mid[:]
output[2, :] = high[:]
return output
# Initial output is ...,low_mid_high,nz,ny,nx to create contiguous views
# Initial output is ...,low_mid_high,nz,ny,nx to create contiguous
# views
outdims = vert.shape[0:num_left_dims]
extra_dims = tuple(outdims) # Copy the left-most dims for iteration
outdims += (3,) # low_mid_high
extra_dims = tuple(outdims) # Copy the left-most dims for iteration
outdims += (3,) # low_mid_high
outdims += vert.shape[-2:]
outview_array = np.empty(outdims, alg_dtype)
# Create the output array where the leftmost dim is the cloud type
output_dims = (3,)
output_dims += extra_dims
output_dims += vert.shape[-2:]
output = np.empty(output_dims, orig_dtype)
has_missing = False
missing = default_fill(np.float64)
for left_idxs in iter_left_indexes(extra_dims):
@ -465,16 +460,16 @@ def cloudfrac_left_iter(alg_dtype=np.float64): @@ -465,16 +460,16 @@ def cloudfrac_left_iter(alg_dtype=np.float64):
low_idxs = left_idxs + (0, slice(None))
mid_idxs = left_idxs + (1, slice(None))
high_idxs = left_idxs + (2, slice(None))
low_output_idxs = (0,) + left_idxs + (slice(None),)
mid_output_idxs = (1,) + left_idxs + (slice(None),)
high_output_idxs = (2,) + left_idxs + (slice(None),)
new_args[0] = vert[left_and_slice_idxs]
new_args[1] = rh[left_and_slice_idxs]
# Skip the possible empty/missing arrays for the join method
# Note: Masking handled by cloudfrac.py or computation.py, so only
# Note: Masking handled by cloudfrac.py or computation.py, so only
# supply the fill values here.
skip_missing = False
for arg in (new_args[0:2]):
@ -483,41 +478,41 @@ def cloudfrac_left_iter(alg_dtype=np.float64): @@ -483,41 +478,41 @@ def cloudfrac_left_iter(alg_dtype=np.float64):
output[low_output_idxs] = missing
output[mid_output_idxs] = missing
output[high_output_idxs] = missing
skip_missing = True
has_missing = True
if skip_missing:
continue
lowview = outview_array[low_idxs]
midview = outview_array[mid_idxs]
highview = outview_array[high_idxs]
new_kwargs["lowview"] = lowview
new_kwargs["midview"] = midview
new_kwargs["highview"] = highview
low, mid, high = wrapped(*new_args, **new_kwargs)
# Make sure the result is the same data as what got passed in
# Make sure the result is the same data as what got passed in
# Can delete this once everything works
if (low.__array_interface__["data"][0] !=
lowview.__array_interface__["data"][0]):
if (low.__array_interface__["data"][0] !=
lowview.__array_interface__["data"][0]):
raise RuntimeError("output array was copied")
output[low_output_idxs] = (
outview_array[low_idxs].astype(orig_dtype))
outview_array[low_idxs].astype(orig_dtype))
output[mid_output_idxs] = (
outview_array[mid_idxs].astype(orig_dtype))
outview_array[mid_idxs].astype(orig_dtype))
output[high_output_idxs] = (
outview_array[high_idxs].astype(orig_dtype))
outview_array[high_idxs].astype(orig_dtype))
if has_missing:
output = np.ma.masked_values(output, missing)
return output
return func_wrapper
@ -526,95 +521,94 @@ def interplevel_left_iter(is2dlev, alg_dtype=np.float64): @@ -526,95 +521,94 @@ def interplevel_left_iter(is2dlev, alg_dtype=np.float64):
def func_wrapper(wrapped, instance, args, kwargs):
new_args = list(args)
new_kwargs = dict(kwargs)
field3d = args[0]
z = args[1]
levels = args[2]
num_left_dims = z.ndim - 3
orig_dtype = field3d.dtype
left_dims = z.shape[0:num_left_dims]
multiproduct = True if field3d.ndim - z.ndim == 1 else False
# No special left side iteration, build the output from the
# No special left side iteration, build the output from the
# low, mid, high results.
if (num_left_dims == 0):
if multiproduct:
if not is2dlev:
outshape = (field3d.shape[0:-3] + levels.shape +
outshape = (field3d.shape[0:-3] + levels.shape +
field3d.shape[-2:])
else:
outshape = (field3d.shape[0:-3] + field3d.shape[-2:])
output = np.empty(outshape, dtype=alg_dtype)
for i in py3range(field3d.shape[0]):
new_args[0] = field3d[i,:]
new_kwargs["outview"] = output[i,:]
new_args[0] = field3d[i, :]
new_kwargs["outview"] = output[i, :]
_ = wrapped(*new_args, **new_kwargs)
else:
output = wrapped(*args, **kwargs)
return output
if multiproduct:
outdims = field3d.shape[0:1] + left_dims
else:
outdims = left_dims
extra_dims = tuple(outdims)
if not is2dlev:
outdims += levels.shape
outdims += z.shape[-2:]
outview_array = np.empty(outdims, alg_dtype)
for left_idxs in iter_left_indexes(extra_dims):
field_out_slice_idxs = left_idxs + (slice(None),)
if multiproduct:
z_slice_idxs = left_idxs[1:] + (slice(None),)
else:
z_slice_idxs = left_idxs + (slice(None),)
new_args[0] = field3d[field_out_slice_idxs]
new_args[1] = z[z_slice_idxs]
if is2dlev:
if levels.ndim > 2:
new_args[2] = levels[z_slice_idxs]
new_kwargs["outview"] = outview_array[field_out_slice_idxs]
_ = wrapped(*new_args, **new_kwargs)
output = outview_array.astype(orig_dtype)
return output
return func_wrapper
def check_cape_args():
"""A decorator to check that the cape_3d arguments are valid.
An exception is raised when an invalid argument is found.
Returns:
None
Raises:
:class:`ValueError`: Raised when an invalid argument is detected.
"""
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
p_hpa = args[0]
tk = args[1]
qv = args[2]
@ -624,11 +618,11 @@ def check_cape_args(): @@ -624,11 +618,11 @@ def check_cape_args():
missing = args[6]
i3dflag = args[7]
ter_follow = args[8]
is2d = False if i3dflag != 0 else True
is1d = ((np.isscalar(sfp) or np.size(sfp) == 1) or
is1d = ((np.isscalar(sfp) or np.size(sfp) == 1) or
(np.isscalar(ter) or np.size(ter) == 1))
if not (p_hpa.shape == tk.shape == qv.shape == ht.shape):
raise ValueError("arguments 0, 1, 2, 3 must be the same shape")
@ -641,41 +635,41 @@ def check_cape_args(): @@ -641,41 +635,41 @@ def check_cape_args():
if np.size(ter) != np.size(sfp):
raise ValueError("arguments 4 and 5 must both be scalars or "
"both be arrays")
# Only need to test p_hpa since we assured args 0-3 have same ndim
if p_hpa.ndim != 1:
raise ValueError("arguments 0-3 "
"must be 1-dimensional when "
"arguments 4 and 5 are scalars")
return wrapped(*args, **kwargs)
return func_wrapper
def check_interplevel_args(is2dlev):
"""A decorator to check that the interplevel arguments are valid.
An exception is raised when an invalid argument is found.
Returns:
None
Raises:
:class:`ValueError`: Raised when an invalid argument is detected.
"""
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
field3d = args[0]
z = args[1]
levels = args[2]
multiproduct = True if (field3d.ndim - z.ndim) == 1 else False
if not multiproduct:
if field3d.shape != z.shape:
raise ValueError("arguments 0 and 1 must have the same shape")
@ -683,16 +677,15 @@ def check_interplevel_args(is2dlev): @@ -683,16 +677,15 @@ def check_interplevel_args(is2dlev):
if field3d.shape[1:] != z.shape:
raise ValueError("argument 0 and 1 must have same rightmost "
"dimensions")
if is2dlev:
if levels.ndim != 2:
if (levels.shape[0:-2] != z.shape[0:-3] or
levels.shape[-2:] != z.shape[-2:]):
if (levels.shape[0:-2] != z.shape[0:-3] or
levels.shape[-2:] != z.shape[-2:]):
raise ValueError("argument 1 and 2 must have "
"the same leftmost and rightmost "
"dimensions")
return wrapped(*args, **kwargs)
return func_wrapper
return func_wrapper

440
src/wrf/units.py

@ -4,31 +4,31 @@ from .constants import Constants, ConversionFactors @@ -4,31 +4,31 @@ from .constants import Constants, ConversionFactors
def _apply_conv_fact(var, vartype, var_unit, dest_unit):
"""Return the variable converted to different units using a conversion
"""Return the variable converted to different units using a conversion
factor.
Args:
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
variable.
vartype (:obj:`str`): The type of variable. Choices are: 'wind',
vartype (:obj:`str`): The type of variable. Choices are: 'wind',
'pressure', 'temp', or 'height'.
var_unit (:obj:`str`): The variable's current units.
dest_unit (:obj:`str`): The desired units.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The variable in
the desired units.
the desired units.
"""
if var_unit == dest_unit:
return var
# Note, case where var_unit and dest_unit are base unit, should be
# Note, case where var_unit and dest_unit are base unit, should be
# handled above
if var_unit == _BASE_UNITS[vartype]:
return var*(_CONV_FACTORS[vartype]["to_dest"][dest_unit])
@ -36,62 +36,62 @@ def _apply_conv_fact(var, vartype, var_unit, dest_unit): @@ -36,62 +36,62 @@ def _apply_conv_fact(var, vartype, var_unit, dest_unit):
if dest_unit == _BASE_UNITS[vartype]:
return var*(_CONV_FACTORS[vartype]["to_base"][var_unit])
else:
return var*(_CONV_FACTORS[vartype]["to_base"][var_unit] *
_CONV_FACTORS[vartype]["to_dest"][dest_unit])
return var*(_CONV_FACTORS[vartype]["to_base"][var_unit] *
_CONV_FACTORS[vartype]["to_dest"][dest_unit])
def _to_kelvin(var, var_unit):
"""Return the variable in Kelvin.
Args:
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
variable.
var_unit (:obj:`str`): The variable's current units.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The variable in
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The variable in
Kelvin.
"""
if var_unit == "c":
return var + Constants.CELKEL
elif var_unit == "f":
return (var - 32.0) * (5.0/9.0) + Constants.CELKEL
def _k_to_c(var):
"""Return the variable in Celsius.
Args:
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
variable in units of Kelvin.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The variable in
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The variable in
Celsius.
"""
return var - Constants.CELKEL
def _k_to_f(var):
"""Return the variable in Fahrenheit.
Args:
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
variable in units of Kelvin.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The variable in
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The variable in
Fahrenheit.
"""
return 1.8 * _k_to_c(var) + 32.0
@ -99,25 +99,25 @@ def _k_to_f(var): @@ -99,25 +99,25 @@ def _k_to_f(var):
def _apply_temp_conv(var, var_unit, dest_unit):
"""Return the variable converted to different units using a temperature
conversion algorithm.
Args:
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
variable.
var_unit (:obj:`str`): The variable's current units.
dest_unit (:obj:`str`): The desired units.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The variable in
the desired units.
the desired units.
"""
if dest_unit == var_unit:
return var
if var_unit != _BASE_UNITS["temp"]:
tk = _to_kelvin(var, var_unit)
if dest_unit == _BASE_UNITS["temp"]:
@ -126,247 +126,237 @@ def _apply_temp_conv(var, var_unit, dest_unit): @@ -126,247 +126,237 @@ def _apply_temp_conv(var, var_unit, dest_unit):
return (_TEMP_CONV_METHODS[dest_unit])(tk)
else:
return (_TEMP_CONV_METHODS[dest_unit])(var)
# A mapping of unit names to their dictionary key names
_UNIT_ALIASES = {"mps" : "m s-1",
"m/s" : "m s-1",
"ms-1" : "m s-1",
"meters_per_second" : "m s-1",
"metres_per_second" : "m s-1",
"knots" : "kt",
"knot" : "kt",
"kts" : "kt",
"kn" : "kt",
"miles_per_hour" : "mi h-1",
"mih-1" : "mi h-1",
"mph" : "mi h-1",
"mi/h" : "mi h-1",
"kmph" : "km h-1",
"kmh-1" : "km h-1",
"km/h" : "km h-1",
"kilometers_per_hour" : "km h-1",
"kilometres_per_hour" : "km h-1",
"ft/s" : "ft s-1",
"ft/sec" : "ft s-1",
"fps" : "ft s-1",
"fs-1" : "ft s-1",
"feet_per_second" : "ft s-1",
"pascal" : "pa",
"pascals" : "pa",
"hecto_pascal" : "hpa",
"hecto_pascals" : "hpa",
"millibar" : "mb",
"millibars" : "mb",
"mbar" : "mb",
"kelvin" : "k",
"degree_kelvin" : "k",
"degrees_kelvin" : "k",
"degree_k" : "k",
"degrees_k" : "k",
"degreek" : "k",
"degreesk" : "k",
"degk" : "k",
"degsk" : "k",
"deg_k" : "k",
"degs_k" : "k",
"deg k" : "k",
"degs k" : "k",
"celsius" : "c",
"degree_celsius" : "c",
"degrees_celsius" : "c",
"degree_c" : "c",
"degrees_c" : "c",
"degreec" : "c",
"degreesc" : "c",
"degc" : "c",
"degsc" : "c",
"deg_c" : "c",
"degs_c" : "c",
"deg c" : "c",
"degs c" : "c",
"fahrenheit" : "f",
"degree_fahrenheit" : "f",
"degrees_fahrenheit" : "f",
"degree_f" : "f",
"degrees_f" : "f",
"degreef" : "f",
"degreesf" : "f",
"degf" : "f",
"degsf" : "f",
"deg_f" : "f",
"degs_f" : "f",
"deg f" : "f",
"degs f" : "f",
"meter" : "m",
"meters" : "m",
"metre" : "m",
"metres" : "m",
"kilometer" : "km",
"kilometers" : "km",
"dekameter" : "dm",
"dekameters" : "dm",
"decameter" : "dm",
"decameters" : "dm",
"dekametre" : "dm",
"dekametres" : "dm",
"decametre" : "dm",
"decametres" : "dm",
"dam" : "dm",
"dkm" : "dm",
"feet" : "ft",
"foot" : "ft",
"mile" : "mi",
"miles" : "mi"
}
_UNIT_ALIASES = {"mps": "m s-1",
"m/s": "m s-1",
"ms-1": "m s-1",
"meters_per_second": "m s-1",
"metres_per_second": "m s-1",
"knots": "kt",
"knot": "kt",
"kts": "kt",
"kn": "kt",
"miles_per_hour": "mi h-1",
"mih-1": "mi h-1",
"mph": "mi h-1",
"mi/h": "mi h-1",
"kmph": "km h-1",
"kmh-1": "km h-1",
"km/h": "km h-1",
"kilometers_per_hour": "km h-1",
"kilometres_per_hour": "km h-1",
"ft/s": "ft s-1",
"ft/sec": "ft s-1",
"fps": "ft s-1",
"fs-1": "ft s-1",
"feet_per_second": "ft s-1",
"pascal": "pa",
"pascals": "pa",
"hecto_pascal": "hpa",
"hecto_pascals": "hpa",
"millibar": "mb",
"millibars": "mb",
"mbar": "mb",
"kelvin": "k",
"degree_kelvin": "k",
"degrees_kelvin": "k",
"degree_k": "k",
"degrees_k": "k",
"degreek": "k",
"degreesk": "k",
"degk": "k",
"degsk": "k",
"deg_k": "k",
"degs_k": "k",
"deg k": "k",
"degs k": "k",
"celsius": "c",
"degree_celsius": "c",
"degrees_celsius": "c",
"degree_c": "c",
"degrees_c": "c",
"degreec": "c",
"degreesc": "c",
"degc": "c",
"degsc": "c",
"deg_c": "c",
"degs_c": "c",
"deg c": "c",
"degs c": "c",
"fahrenheit": "f",
"degree_fahrenheit": "f",
"degrees_fahrenheit": "f",
"degree_f": "f",
"degrees_f": "f",
"degreef": "f",
"degreesf": "f",
"degf": "f",
"degsf": "f",
"deg_f": "f",
"degs_f": "f",
"deg f": "f",
"degs f": "f",
"meter": "m",
"meters": "m",
"metre": "m",
"metres": "m",
"kilometer": "km",
"kilometers": "km",
"dekameter": "dm",
"dekameters": "dm",
"decameter": "dm",
"decameters": "dm",
"dekametre": "dm",
"dekametres": "dm",
"decametre": "dm",
"decametres": "dm",
"dam": "dm",
"dkm": "dm",
"feet": "ft",
"foot": "ft",
"mile": "mi",
"miles": "mi"
}
# A mapping of unit types to the avaible units
_VALID_UNITS = {"wind" : ["m s-1", "kt", "mi h-1", "km h-1", "ft s-1"],
"pressure" : ["pa", "hpa", "mb", "torr", "mmhg", "atm"],
"temp" : ["k", "f", "c"],
"height" : ["m", "km", "dm", "ft", "mi"]
}
_VALID_UNITS = {"wind": ["m s-1", "kt", "mi h-1", "km h-1", "ft s-1"],
"pressure": ["pa", "hpa", "mb", "torr", "mmhg", "atm"],
"temp": ["k", "f", "c"],
"height": ["m", "km", "dm", "ft", "mi"]
}
# Conversion factor map for wind from base units
_WIND_BASE_FACTORS = {"kt" : ConversionFactors.MPS_TO_KTS,
"km h-1" : ConversionFactors.MPS_TO_KMPH,
"mi h-1" : ConversionFactors.MPS_TO_MPH,
"ft s-1" : ConversionFactors.MPS_TO_FPS
}
_WIND_BASE_FACTORS = {"kt": ConversionFactors.MPS_TO_KTS,
"km h-1": ConversionFactors.MPS_TO_KMPH,
"mi h-1": ConversionFactors.MPS_TO_MPH,
"ft s-1": ConversionFactors.MPS_TO_FPS
}
# Conversion factor map to base units
_WIND_TOBASE_FACTORS = {"kt" : 1.0/ConversionFactors.MPS_TO_KTS,
"km h-1" : 1.0/ConversionFactors.MPS_TO_KMPH,
"mi h-1" : 1.0/ConversionFactors.MPS_TO_MPH,
"ft s-1" : 1.0/ConversionFactors.MPS_TO_FPS
_WIND_TOBASE_FACTORS = {"kt": 1.0/ConversionFactors.MPS_TO_KTS,
"km h-1": 1.0/ConversionFactors.MPS_TO_KMPH,
"mi h-1": 1.0/ConversionFactors.MPS_TO_MPH,
"ft s-1": 1.0/ConversionFactors.MPS_TO_FPS
}
# Conversion factor map for pressure from base units
_PRES_BASE_FACTORS = {"hpa" : ConversionFactors.PA_TO_HPA,
"mb" : ConversionFactors.PA_TO_HPA,
"torr" : ConversionFactors.PA_TO_TORR,
"mmhg" : ConversionFactors.PA_TO_MMHG,
"atm" : ConversionFactors.PA_TO_ATM
_PRES_BASE_FACTORS = {"hpa": ConversionFactors.PA_TO_HPA,
"mb": ConversionFactors.PA_TO_HPA,
"torr": ConversionFactors.PA_TO_TORR,
"mmhg": ConversionFactors.PA_TO_MMHG,
"atm": ConversionFactors.PA_TO_ATM
}
# Conversion factor map for pressure to base units
_PRES_TOBASE_FACTORS = {"hpa" : 1.0/ConversionFactors.PA_TO_HPA,
"mb" : 1.0/ConversionFactors.PA_TO_HPA,
"torr" : 1.0/ConversionFactors.PA_TO_TORR,
"mmhg" : 1.0/ConversionFactors.PA_TO_MMHG,
"atm" : 1.0/ConversionFactors.PA_TO_ATM
_PRES_TOBASE_FACTORS = {"hpa": 1.0/ConversionFactors.PA_TO_HPA,
"mb": 1.0/ConversionFactors.PA_TO_HPA,
"torr": 1.0/ConversionFactors.PA_TO_TORR,
"mmhg": 1.0/ConversionFactors.PA_TO_MMHG,
"atm": 1.0/ConversionFactors.PA_TO_ATM
}
# Conversion factor map for height from base units
_HEIGHT_BASE_FACTORS = {"km" : ConversionFactors.M_TO_KM,
"dm" : ConversionFactors.M_TO_DM,
"ft" : ConversionFactors.M_TO_FT,
"mi" : ConversionFactors.M_TO_MILES
_HEIGHT_BASE_FACTORS = {"km": ConversionFactors.M_TO_KM,
"dm": ConversionFactors.M_TO_DM,
"ft": ConversionFactors.M_TO_FT,
"mi": ConversionFactors.M_TO_MILES
}
# Conversion factor map for height to base units
_HEIGHT_TOBASE_FACTORS = {"km" : 1.0/ConversionFactors.M_TO_KM,
"dm" : 1.0/ConversionFactors.M_TO_DM,
"ft" : 1.0/ConversionFactors.M_TO_FT,
"mi" : 1.0/ConversionFactors.M_TO_MILES
}
_HEIGHT_TOBASE_FACTORS = {"km": 1.0/ConversionFactors.M_TO_KM,
"dm": 1.0/ConversionFactors.M_TO_DM,
"ft": 1.0/ConversionFactors.M_TO_FT,
"mi": 1.0/ConversionFactors.M_TO_MILES
}
# Mapping of unit type to base unit type
_BASE_UNITS = {"wind" : "m s-1",
"pressure" : "pa",
"temp" : "k",
"height" : "m"
_BASE_UNITS = {"wind": "m s-1",
"pressure": "pa",
"temp": "k",
"height": "m"
}
# A mapping of unit type to a mapping of to/from base conversion factors
_CONV_FACTORS = {"wind" : {"to_dest" : _WIND_BASE_FACTORS,
"to_base" : _WIND_TOBASE_FACTORS},
"pressure" : {"to_dest" : _PRES_BASE_FACTORS,
"to_base" : _PRES_TOBASE_FACTORS},
"height" : {"to_dest" : _HEIGHT_BASE_FACTORS,
"to_base" : _HEIGHT_TOBASE_FACTORS}
_CONV_FACTORS = {"wind": {"to_dest": _WIND_BASE_FACTORS,
"to_base": _WIND_TOBASE_FACTORS},
"pressure": {"to_dest": _PRES_BASE_FACTORS,
"to_base": _PRES_TOBASE_FACTORS},
"height": {"to_dest": _HEIGHT_BASE_FACTORS,
"to_base": _HEIGHT_TOBASE_FACTORS}
}
# A mapping of temperature type to the conversion function
_TEMP_CONV_METHODS = {"c" : _k_to_c,
"f" : _k_to_f
_TEMP_CONV_METHODS = {"c": _k_to_c,
"f": _k_to_f
}
def dealias_and_clean_unit(unit):
"""Return the properly cleaned and dealiased unit name.
Args:
unit (:obj:`str`): The unit name.
Returns:
:obj:`str`: A unit name suitable for dictionary key lookups.
"""
cleaned_unit = " ".join(unit.lower().split())
dealiased = _UNIT_ALIASES.get(cleaned_unit, None)
return cleaned_unit if dealiased is None else dealiased
def check_units(unit, unit_type):
"""Raise an exception if the unit name is invalid.
Args:
unit (:obj:`str`): The unit name.
unit_type (:obj:`str`): The type of unit.
Returns:
None
Raises:
:class:`ValueError`: Raised when the unit name is invalid.
"""
u_cleaned = dealias_and_clean_unit(unit)
if u_cleaned not in _VALID_UNITS[unit_type]:
raise ValueError("invalid unit type '%s'" % unit)
raise ValueError("invalid unit type '{}'".format(unit))
def do_conversion(var, vartype, var_unit, dest_unit):
"""Return the variable converted to different units.
Args:
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
variable.
vartype (:obj:`str`): The type of variable. Choices are: 'wind',
vartype (:obj:`str`): The type of variable. Choices are: 'wind',
'pressure', 'temp', or 'height'.
var_unit (:obj:`str`): The variable's current units.
dest_unit (:obj:`str`): The desired units.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The variable in
the desired units.
the desired units.
"""
u_cleaned = dealias_and_clean_unit(dest_unit)
u_cleaned = dealias_and_clean_unit(dest_unit)
if vartype != "temp":
return _apply_conv_fact(var, vartype, var_unit.lower(), u_cleaned)
else:
return _apply_temp_conv(var, var_unit.lower(), u_cleaned)

3505
src/wrf/util.py

File diff suppressed because it is too large Load Diff

1
src/wrf/version.py

@ -1,2 +1 @@ @@ -1,2 +1 @@
__version__ = "1.3.1"

Loading…
Cancel
Save