Browse Source

Added docstrings to all functions. Modified some argument names for better consistency. Added unit support to raw computational algorithms. Modified setup.py to work with readthedocs. Modifyied conf.py to use mocks for readthedocs. Modified gitignore to ignore the generated documentation folder.

main
Bill Ladwig 9 years ago
parent
commit
49092f6ac1
  1. 1
      .gitignore
  2. 238
      doc/source/_templates/product_table.txt
  3. 32
      doc/source/_templates/wrf_class.rst
  4. 1
      doc/source/api/generated/README
  5. 55
      doc/source/api/index.rst
  6. 63
      doc/source/conf.py
  7. 20
      doc/source/index.rst
  8. 74
      ncl_reference/getvar_table.txt
  9. 77
      ncl_reference/product_table.txt
  10. 26
      setup.py
  11. 9
      src/wrf/__init__.py
  12. 71
      src/wrf/cache.py
  13. 135
      src/wrf/cape.py
  14. 64
      src/wrf/cloudfrac.py
  15. 1751
      src/wrf/computation.py
  16. 56
      src/wrf/config.py
  17. 139
      src/wrf/coordpair.py
  18. 61
      src/wrf/ctt.py
  19. 149
      src/wrf/dbz.py
  20. 231
      src/wrf/decorators.py
  21. 33
      src/wrf/destag.py
  22. 120
      src/wrf/dewpoint.py
  23. 171
      src/wrf/extension.py
  24. 203
      src/wrf/geoht.py
  25. 145
      src/wrf/helicity.py
  26. 456
      src/wrf/interp.py
  27. 141
      src/wrf/interputils.py
  28. 430
      src/wrf/latlon.py
  29. 323
      src/wrf/latlonutils.py
  30. 630
      src/wrf/metadecorators.py
  31. 56
      src/wrf/omega.py
  32. 10
      src/wrf/precip.py
  33. 128
      src/wrf/pressure.py
  34. 461
      src/wrf/projection.py
  35. 56
      src/wrf/pw.py
  36. 108
      src/wrf/py3compat.py
  37. 112
      src/wrf/rh.py
  38. 241
      src/wrf/routines.py
  39. 62
      src/wrf/slp.py
  40. 67
      src/wrf/specialdec.py
  41. 416
      src/wrf/temp.py
  42. 63
      src/wrf/terrain.py
  43. 113
      src/wrf/times.py
  44. 141
      src/wrf/units.py
  45. 1617
      src/wrf/util.py
  46. 383
      src/wrf/uvmet.py
  47. 2
      src/wrf/version.py
  48. 118
      src/wrf/vorticity.py
  49. 398
      src/wrf/wind.py
  50. 34
      test/reduce_file.py

1
.gitignore vendored

@ -43,5 +43,6 @@ Thumbs.db
*.project *.project
*.pydevproject *.pydevproject
doc/build doc/build
doc/source/api/generated
test/ipynb/.ipynb_checkpoints test/ipynb/.ipynb_checkpoints

238
doc/source/_templates/product_table.txt

@ -0,0 +1,238 @@
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| Variable Name | Description | Available Units | Additional Keyword Arguments |
+====================+===============================================================+=============================+===============================================================================================+
| avo | Absolute Vorticity | 10-5 s-1 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| eth/theta_e | Equivalent Potential Temperature | K | **units** (str) : Set to desired units. Default is *'K'*. |
| | | | |
| | | degC | |
| | | | |
| | | degF | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| cape_2d | 2D cape (mcape/mcin/lcl/lfc) | J kg-1 ; J kg-1 ; m ; m | **missing** (float): Fill value for output only |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| cape_3d | 3D cape and cin | J kg-1 | **missing** (float): Fill value for output only |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| ctt | Cloud Top Temperature | degC | **units** (str) : Set to desired units. Default is *'degC'*. |
| | | | |
| | | K | |
| | | | |
| | | degF | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| cloudfrac | Cloud Fraction | % | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| dbz | Reflectivity | dBZ | **do_variant** (boolean): Set to True to enable variant calculation. Default is *False*. |
| | | | |
| | | | **do_liqskin** (boolean): Set to True to enable liquid skin calculation. Default is *False*. |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| mdbz | Maximum Reflectivity | dBZ | **do_variant** (boolean): Set to True to enable variant calculation. Default is *False*. |
| | | | |
| | | | **do_liqskin** (boolean): Set to True to enable liquid skin calculation. Default is *False*. |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| geopt/geopotential | Full Model Geopotential | m2 s-2 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| helicity | Storm Relative Helicity | m2 s-2 | **top** (float): The top level for the calculation in meters. Default is *3000.0*. |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| lat | Latitude | decimal degrees | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| lon | Longitude | decimal degrees | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| omg/omega | Omega | Pa s-1 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| p/pres | Full Model Pressure | Pa | **units** (str) : Set to desired units. Default is *'Pa'*. |
| | | | |
| | (in specified units) | hPa | |
| | | | |
| | | mb | |
| | | | |
| | | torr | |
| | | | |
| | | mmhg | |
| | | | |
| | | atm | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| pressure | Full Model Pressure (hPa) | hPa | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| pvo | Potential Vorticity | PVU | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| pw | Precipitable Water | kg m-2 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| rh2 | 2m Relative Humidity | % | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| slp | Sea Level Pressure | hPa | **units** (str) : Set to desired units. Default is *'hPa'*. |
| | | | |
| | | hPa | |
| | | | |
| | | mb | |
| | | | |
| | | torr | |
| | | | |
| | | mmhg | |
| | | | |
| | | atm | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| ter | Model Terrain Height | m | **units** (str) : Set to desired units. Default is *'m'*. |
| | | | |
| | | km | |
| | | | |
| | | dm | |
| | | | |
| | | ft | |
| | | | |
| | | mi | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| td2 | 2m Dew Point Temperature | degC | **units** (str) : Set to desired units. Default is *'degC'*. |
| | | | |
| | | K | |
| | | | |
| | | degF | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| td | Dew Point Temperature | degC | **units** (str) : Set to desired units. Default is *'degC'*. |
| | | | |
| | | K | |
| | | | |
| | | degF | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| tc | Temperature in Celsius | degC | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| th/theta | Potential Temperature | K | **units** (str) : Set to desired units. Default is *'K'*. |
| | | | |
| | | degC | |
| | | | |
| | | degF | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| temp | Temperature (in specified units) | K | **units** (str) : Set to desired units. Default is *'K'*. |
| | | | |
| | | degC | |
| | | | |
| | | degF | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| tk | Temperature in Kelvin | K | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| times | Times in the File or Sequence | | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| xtimes | XTIME Coordinate | minutes since | |
| | | | |
| | (if applicable) | start of | |
| | | | |
| | | model run | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| tv | Virtual Temperature | K | **units** (str) : Set to desired units. Default is *'K'*. |
| | | | |
| | | degC | |
| | | | |
| | | degF | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| twb | Wet Bulb Temperature | K | **units** (str) : Set to desired units. Default is *'K'*. |
| | | | |
| | | degC | |
| | | | |
| | | degF | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| updraft_helicity | Updraft Helicity | m2 s-2 | **bottom** (float): The bottom level for the calculation in meters. Default is *2000.0*. |
| | | | |
| | | | **top** (float): The top level for the calculation in meters. Default is *5000.0*. |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| ua | U-component of Wind on Mass Points | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | |
| | | km h-1 | |
| | | | |
| | | mi h-1 | |
| | | | |
| | | kt | |
| | | | |
| | | ft s-1 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| va | V-component of Wind on Mass Points | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | |
| | | km h-1 | |
| | | | |
| | | mi h-1 | |
| | | | |
| | | kt | |
| | | | |
| | | ft s-1 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| wa | W-component of Wind on Mass Points | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | |
| | | km h-1 | |
| | | | |
| | | mi h-1 | |
| | | | |
| | | kt | |
| | | | |
| | | ft s-1 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| uvmet10 | 10 m U and V Components of Wind | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | |
| | Rotated to Earth Coordinates | km h-1 | |
| | | | |
| | | mi h-1 | |
| | | | |
| | | kt | |
| | | | |
| | | ft s-1 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| uvmet | U and V Components of Wind | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | |
| | Rotated to Earth Coordinates | km h-1 | |
| | | | |
| | | mi h-1 | |
| | | | |
| | | kt | |
| | | | |
| | | ft s-1 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| wspd_wdir | Wind Speed and Direction | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | |
| | in Grid Coordinates | km h-1 | |
| | | | |
| | | mi h-1 | |
| | | | |
| | | kt | |
| | | | |
| | | ft s-1 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| wspd_wdir10 | 10m Wind Speed and Direction | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | |
| | in Grid Coordinates | km h-1 | |
| | | | |
| | | mi h-1 | |
| | | | |
| | | kt | |
| | | | |
| | | ft s-1 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| uvmet_wspd_wdir | Wind Speed and Direction | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | |
| | Rotated to Earth Coordinates | km h-1 | |
| | | | |
| | | mi h-1 | |
| | | | |
| | | kt | |
| | | | |
| | | ft s-1 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| uvmet10_wspd_wdir | 10m Wind Speed and Direction | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | |
| | Rotated to Earth Coordinates | km h-1 | |
| | | | |
| | | mi h-1 | |
| | | | |
| | | kt | |
| | | | |
| | | ft s-1 | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+
| z/height | Full Model Height | m | **msl** (boolean): Set to False to return AGL values. True is for MSL. Default is *True*. |
| | | | |
| | | km | **units** (str) : Set to desired units. Default is *'m'*. |
| | | | |
| | | dm | |
| | | | |
| | | ft | |
| | | | |
| | | mi | |
+--------------------+---------------------------------------------------------------+-----------------------------+-----------------------------------------------------------------------------------------------+

32
doc/source/_templates/wrf_class.rst

@ -0,0 +1,32 @@
{{ fullname }}
{{ underline }}
.. currentmodule:: {{ module }}
.. autoclass:: {{ objname }}
{% block methods %}
{% if methods %}
.. rubric:: Methods
.. autosummary::
{% for item in methods %}
{% if item != '__init__' %}
~{{ name }}.{{ item }}
{% endif %}
{%- endfor %}
{% endif %}
{% endblock %}
{% block attributes %}
{% if attributes %}
.. rubric:: Attributes
.. autosummary::
{% for item in attributes %}
~{{ name }}.{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

1
doc/source/api/generated/README

@ -0,0 +1 @@
This location contains the RST files created by Sphinx AutoSummary for the API.

55
doc/source/api/index.rst

@ -0,0 +1,55 @@
API Reference
=============
Diagnostic Routines
-------------------
.. autosummary::
:nosignatures:
:toctree: generated/
wrf.getvar
Interpolation Routines
----------------------
.. autosummary::
:nosignatures:
:toctree: generated/
wrf.interplevel
wrf.vertcross
wrf.interpline
wrf.vinterp
Extraction Routines
-------------------
.. autosummary::
:nosignatures:
:toctree: generated/
wrf.npvalues
wrf.util.either
wrf.util.is_moving_domain
Raw Computation Routines
------------------------
.. autosummary::
:nosignatures:
:toctree: generated/
wrf.xy
wrf.interp1d
wrf.interp2dxy
wrf.slp
wrf.uvmet
wrf.cape_2d
wrf.cape_3d

63
doc/source/conf.py

@ -15,6 +15,36 @@
import sys import sys
import os import os
try:
from unittest.mock import MagicMock
except ImportError:
from mock import Mock as MagicMock
class Mock(MagicMock):
@classmethod
def __getattr__(cls, name):
return Mock()
MOCK_MODULES = ["numpy", "numpy.ma", "xarray",
"pandas", "matplotlib", "netCDF4", "mpl_toolkits.basemap",
"wrf._wrffortran"]
sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
consts = {"DEFAULT_FILL" : 9.9692099683868690E36}
class MockWrfConstants(object):
def __init__(self):
self.__dict__ = consts
def mock_asscalar(val):
return float(val)
sys.modules["wrf._wrffortran"].wrf_constants = MockWrfConstants()
sys.modules["numpy"].asscalar = mock_asscalar
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
@ -29,9 +59,26 @@ import os
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones. # ones.
extensions = [ extensions = [
'sphinx.ext.autodoc', 'sphinx.ext.napoleon' 'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.autosummary',
'sphinx.ext.intersphinx',
] ]
intersphinx_mapping = {
'matplotlib': ('http://matplotlib.org/', None),
'python': ('http://docs.python.org/3/', None),
'numpy': ('http://docs.scipy.org/doc/numpy/', None),
'xarray': ('http://xarray.pydata.org/en/stable/', None),
'wrapt': ('http://wrapt.readthedocs.io/en/latest/',
None)
}
napoleon_use_admonition_for_examples = True
napoleon_include_special_with_doc = True
autosummary_generate = True
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ['_templates']
@ -48,7 +95,7 @@ master_doc = 'index'
# General information about the project. # General information about the project.
project = u'wrf-python' project = u'wrf-python'
copyright = u'2016, UCAR' copyright = u'2016, University Corporation for Atmospheric Research'
author = u'Bill Ladwig' author = u'Bill Ladwig'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
@ -56,9 +103,10 @@ author = u'Bill Ladwig'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = u'0.0.1' import wrf
version = wrf.__version__
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = u'0.0.1' release = wrf.__version__
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
@ -110,7 +158,12 @@ todo_include_todos = False
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
html_theme = 'alabaster' import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
#html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme # Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the # further. For a list of options available for each theme, see the

20
doc/source/index.rst

@ -3,28 +3,16 @@
You can adapt this file completely to your liking, but it should at least You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive. contain the root `toctree` directive.
Welcome to wrf-python's documentation! User Guide for wrf-python
====================================== ==========================
Contents: Contents:
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 1
Extraction Routine api/index
------------------
.. autofunction:: wrf.getvar
Interpolation Routines
----------------------
.. autofunction:: wrf.interplevel
.. autofunction:: wrf.vertcross
.. autofunction:: wrf.interpline
.. autofunction:: wrf.vinterp
Indices and tables Indices and tables

74
ncl_reference/getvar_table.txt

@ -1,74 +0,0 @@
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| Variable Name | Description | Units | Additional Keyword Arguments |
+====================+===============================================================+=====================+===============================================================================================+
| avo | Absolute Vorticity | 10-5 s-1 | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| eth/theta_e | Equivalent Potential Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| cape_2d | 2D cape (mcape/mcin/lcl/lfc) | J/kg / J/kg / m / m | missing: Fill value for output only (float) |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| cape_3d | 3D cape and cin | J/kg | missing: Fill value for output only (float) |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| ctt | Cloud Top Temperature | C | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| dbz | Reflectivity | dBz | do_variant: Set to True to enable variant calculation. Default is False. |
| | | | do_liqskin : Set to True to enable liquid skin calculation. Default is False. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| mdbz | Maximum Reflectivity | dBz | do_variant: Set to True to enable variant calculation. Default is False. |
| | | | do_liqskin: Set to True to enable liquid skin calculation. Default is False. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| geopt/geopotential | Full Model Geopotential | m2 s-2 | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| helicity | Storm Relative Helicity | m-2/s-2 | top: The top level for the calculation in meters (float). Default is 3000.0. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| lat | Latitude | decimal degrees | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| lon | Longitude | decimal degrees | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| omg/omega | Omega | Pa/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| p/pres | Full Model Pressure | Pa | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| pressure | Full Model Pressure | hPa | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| pvo | Potential Vorticity | PVU | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| pw | Precipitable Water | kg m-2 | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| rh2 | 2m Relative Humidity | % | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| slp | Sea Level Pressure | hPa | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| ter | Model Terrain Height | m | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| td2 | 2m Dew Point Temperature | C | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| td | Dew Point Temperature | C | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| tc | Temperature | C | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| th/theta | Potential Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| tk | Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| times | Times in the File or Sequence | | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| tv | Virtual Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| twb | Wet Bulb Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| updraft_helicity | Updraft Helicity | m-2/s-2 | bottom: The bottom level for the calculation in meters (float). Default is 2000.0. |
| | | | top: The top level for the calculation in meters (float). Default is 5000.0. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| ua | U-component of Wind on Mass Points | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| va | V-component of Wind on Mass Points | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| wa | W-component of Wind on Mass Points | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| uvmet10 | 10 m U and V Components of Wind Rotated to Earth Coordinates | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| uvmet | U and V Components of Wind Rotated to Earth Coordinates | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| z/height | Full Model Height | m | msl: Set to False to return AGL values. Otherwise, MSL. Default is True. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+

77
ncl_reference/product_table.txt

@ -0,0 +1,77 @@
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| Variable Name | Description | Units | Additional Keyword Arguments |
+====================+===============================================================+=====================+===============================================================================================+
| avo | Absolute Vorticity | 10-5 s-1 | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| eth/theta_e | Equivalent Potential Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| cape_2d | 2D cape (mcape/mcin/lcl/lfc) | J/kg / J/kg / m / m | missing: Fill value for output only (float) |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| cape_3d | 3D cape and cin | J/kg | missing: Fill value for output only (float) |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| ctt | Cloud Top Temperature | C | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| cloudfrac | Cloud Fraction | % | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| dbz | Reflectivity | dBz | do_variant: Set to True to enable variant calculation. Default is False. |
| | | | do_liqskin : Set to True to enable liquid skin calculation. Default is False. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| mdbz | Maximum Reflectivity | dBz | do_variant: Set to True to enable variant calculation. Default is False. |
| | | | do_liqskin: Set to True to enable liquid skin calculation. Default is False. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| geopt/geopotential | Full Model Geopotential | m2 s-2 | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| helicity | Storm Relative Helicity | m2 s-2 | top: The top level for the calculation in meters (float). Default is 3000.0. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| lat | Latitude | decimal degrees | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| lon | Longitude | decimal degrees | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| omg/omega | Omega | Pa/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| p/pres | Full Model Pressure | Pa | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| pressure | Full Model Pressure | hPa | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| pvo | Potential Vorticity | PVU | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| pw | Precipitable Water | kg m-2 | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| rh2 | 2m Relative Humidity | % | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| slp | Sea Level Pressure | hPa | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| ter | Model Terrain Height | m | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| td2 | 2m Dew Point Temperature | C | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| td | Dew Point Temperature | C | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| tc | Temperature | C | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| th/theta | Potential Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| tk | Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| times | Times in the File or Sequence | | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| tv | Virtual Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| twb | Wet Bulb Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| updraft_helicity | Updraft Helicity | m2 s-2 | bottom: The bottom level for the calculation in meters (float). Default is 2000.0. |
| | | | top: The top level for the calculation in meters (float). Default is 5000.0. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| ua | U-component of Wind on Mass Points | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| va | V-component of Wind on Mass Points | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| wa | W-component of Wind on Mass Points | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| uvmet10 | 10 m U and V Components of Wind Rotated to Earth Coordinates | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| uvmet | U and V Components of Wind Rotated to Earth Coordinates | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| z/height | Full Model Height | m | msl: Set to False to return AGL values. Otherwise, MSL. Default is True. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+

26
setup.py

@ -1,3 +1,5 @@
import os
import sys
import setuptools import setuptools
import numpy.distutils.core import numpy.distutils.core
@ -25,10 +27,24 @@ ext1 = numpy.distutils.core.Extension(
with open("src/wrf/version.py") as f: with open("src/wrf/version.py") as f:
exec(f.read()) exec(f.read())
requirements = [ on_rtd = os.environ.get("READTHEDOCS", None) == "True"
"numpy>=1.9.0", #on_rtd=True
"wrapt>=1.10" if on_rtd:
] if sys.version_info < (3,3):
requirements = ["mock"] # for python2 and python < 3.3
else:
requirements = [] # for >= python3.3
ext_modules = []
else:
# Place install_requires into the text file "requirements.txt"
with open("requirements.txt") as f2:
requirements = f2.read().strip().splitlines()
#if sys.version_info < (3,3):
# requirements.append("mock")
ext_modules = [ext1]
numpy.distutils.core.setup( numpy.distutils.core.setup(
author = "Bill Ladwig", author = "Bill Ladwig",
@ -61,7 +77,7 @@ numpy.distutils.core.setup(
name = "wrf", name = "wrf",
version = __version__, version = __version__,
packages = setuptools.find_packages("src"), packages = setuptools.find_packages("src"),
ext_modules = [ext1], ext_modules = ext_modules,
package_dir = {"" : "src"}, package_dir = {"" : "src"},
#namespace_packages=["wrf"], #namespace_packages=["wrf"],
# Note: If this doesn't work, you need to add the file to MANIFEST # Note: If this doesn't work, you need to add the file to MANIFEST

9
src/wrf/__init__.py

@ -6,12 +6,3 @@ from .api import *
__all__ = [] __all__ = []
__all__.extend(api.__all__) __all__.extend(api.__all__)

71
src/wrf/cache.py

@ -9,6 +9,38 @@ from .config import get_cache_size
_local_storage = local() _local_storage = local()
def cache_item(key, product, value): def cache_item(key, product, value):
"""Store an item in the 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
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 thread that cached them.
Args:
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
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 global _local_storage
if key is None: if key is None:
@ -32,6 +64,36 @@ def cache_item(key, product, value):
def get_cached_item(key, product): def get_cached_item(key, product):
"""Return an item from the 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
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 thread that cached them.
Args:
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
string for the product type.
Returns:
:obj:`object`: The cached object.
See Also:
:meth:`cache_item`
"""
if key is None: if key is None:
return None return None
@ -50,6 +112,15 @@ def get_cached_item(key, product):
return result return result
def _get_cache(): def _get_cache():
"""Return the cache.
This is primarily used for testing.
Returns:
:class:`threading.local`
"""
return getattr(_local_storage, "cache", None) return getattr(_local_storage, "cache", None)

135
src/wrf/cape.py

@ -11,12 +11,75 @@ from .util import extract_vars
from .metadecorators import set_cape_metadata from .metadecorators import set_cape_metadata
@set_cape_metadata(is2d=True) @set_cape_metadata(is2d=True)
def get_2dcape(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_2dcape(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None, missing=Constants.DEFAULT_FILL): meta=True, _key=None, missing=Constants.DEFAULT_FILL):
"""Return the 2d fields of cape, cin, lcl, and lfc""" """Return the 2d fields of CAPE, CIN, LCL, and LFC.
The leftmost dimension of the returned array represents four different
quantities:
- return_val[0,...] will contain CAPE [J kg-1]
- return_val[1,...] will contain CIN [J kg-1]
- return_val[2,...] will contain LCL [m]
- return_val[3,...] will contain LFC [m]
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): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
missing (:obj:`float`): The fill value to use for the output.
Default is :data:`wrf.Constants.DEFAULT_FILL`.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cape, cin, lcl, and lfc values as an array whose
leftmost dimension is 4 (0=CAPE, 1=CIN, 2=LCL, 3=LFC).
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", "HGT", "PSFC") varnames = ("T", "P", "PB", "QVAPOR", "PH","PHB", "HGT", "PSFC")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]
@ -65,12 +128,72 @@ def get_2dcape(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None,
@set_cape_metadata(is2d=False) @set_cape_metadata(is2d=False)
def get_3dcape(wrfnc, timeidx=0, method="cat", def get_3dcape(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, squeeze=True, cache=None, meta=True,
_key=None, missing=Constants.DEFAULT_FILL): _key=None, missing=Constants.DEFAULT_FILL):
"""Return the 3d fields of cape and cin""" """Return the three-dimensional CAPE and CIN.
The leftmost dimension of the returned array represents two different
quantities:
- return_val[0,...] will contain CAPE [J kg-1]
- return_val[1,...] will contain CIN [J kg-1]
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): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
missing (:obj:`float`): The fill value to use for the output.
Default is :data:`wrf.Constants.DEFAULT_FILL`.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
CAPE and CIN as an array whose leftmost dimension is 2 (0=CAPE, 1=CIN).
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", "HGT", "PSFC") varnames = ("T", "P", "PB", "QVAPOR", "PH", "PHB", "HGT", "PSFC")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]
p = ncvars["P"] p = ncvars["P"]

64
src/wrf/cloudfrac.py

@ -7,10 +7,70 @@ from .metadecorators import set_cloudfrac_metadata
from .util import extract_vars from .util import extract_vars
@set_cloudfrac_metadata() @set_cloudfrac_metadata()
def get_cloudfrac(wrfnc, timeidx=0, method="cat", squeeze=True, def get_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None): cache=None, meta=True, _key=None):
"""Return the cloud fraction.
ncvars = extract_vars(wrfnc, timeidx, ("P", "PB", "QVAPOR", "T"), 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
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): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
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
be a :class:`numpy.ndarray` object with no metadata.
"""
ncvars = extract_vars(wrfin, timeidx, ("P", "PB", "QVAPOR", "T"),
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)

1751
src/wrf/computation.py

File diff suppressed because it is too large Load Diff

56
src/wrf/config.py

@ -32,70 +32,126 @@ except ImportError:
def xarray_enabled(): def xarray_enabled():
"""Return True if xarray is installed and enabled.
Returns:
:obj:`bool`: True if xarray is installed and enabled.
"""
global _local_config global _local_config
return _local_config.xarray_enabled return _local_config.xarray_enabled
def disable_xarray(): def disable_xarray():
"""Disable xarray."""
global _local_config global _local_config
_local_config.xarray_enabled = False _local_config.xarray_enabled = False
def enable_xarray(): def enable_xarray():
"""Enable xarray."""
global _local_config global _local_config
_local_config.xarray_enabled = True _local_config.xarray_enabled = True
def cartopy_enabled(): def cartopy_enabled():
"""Return True if cartopy is installed and enabled.
Returns:
:obj:`bool`: True if cartopy is installed and enabled.
"""
global _local_config global _local_config
return _local_config.cartopy_enabled return _local_config.cartopy_enabled
def enable_cartopy(): def enable_cartopy():
"""Enable cartopy."""
global _local_config global _local_config
_local_config.cartopy_enabled = True _local_config.cartopy_enabled = True
def disable_cartopy(): def disable_cartopy():
"""Disable cartopy."""
global _local_config global _local_config
_local_config.cartopy_enabled = True _local_config.cartopy_enabled = True
def basemap_enabled(): def basemap_enabled():
"""Return True if basemap is installed and enabled.
Returns:
:obj:`bool`: True if basemap is installed and enabled.
"""
global _local_config global _local_config
return _local_config.basemap_enabled return _local_config.basemap_enabled
def enable_basemap(): def enable_basemap():
"""Enable basemap."""
global _local_config global _local_config
_local_config.basemap_enabled = True _local_config.basemap_enabled = True
def disable_basemap(): def disable_basemap():
"""Disable basemap."""
global _local_config global _local_config
_local_config.basemap_enabled = True _local_config.basemap_enabled = True
def pyngl_enabled(): def pyngl_enabled():
"""Return True if pyngl is installed and enabled.
Returns:
:obj:`bool`: True if pyngl is installed and enabled.
"""
global _local_config global _local_config
return _local_config.pyngl_enabled return _local_config.pyngl_enabled
def enable_pyngl(): def enable_pyngl():
"""Enable pyngl."""
global _local_config global _local_config
_local_config.pyngl_enabled = True _local_config.pyngl_enabled = True
def disable_pyngl(): def disable_pyngl():
"""Disable pyngl."""
global _local_config global _local_config
_local_config.pyngl_enabled = True _local_config.pyngl_enabled = True
def set_cache_size(size): def set_cache_size(size):
"""Set the maximum number of items that the threadsafe 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 global _local_config
_local_config.cache_size = size _local_config.cache_size = size
def get_cache_size(): def get_cache_size():
"""Return the maximum number of items that the threadsafe cache can retain.
Returns:
:obj:`int`: The maximum number of items the cache can retain.
"""
global _local_config global _local_config
return int(_local_config.cache_size) return int(_local_config.cache_size)

139
src/wrf/coordpair.py

@ -5,7 +5,36 @@ from .py3compat import py2round
def _binary_operator(operator): 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): def func(self, other):
"""Operator implementation.
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
attributes with the scalar value.
Args:
other (:class:`CoordPair` or scalar): A separate :class:`CoordPair`
object or scalar value.
Returns:
:class:`CoordPair`: A new :class:`CoordPair` object that is the
result of the operator action.
"""
if isinstance(other, CoordPair): if isinstance(other, CoordPair):
args = [ args = [
None if getattr(self, attr) is None or getattr(other, attr) is None None if getattr(self, attr) is None or getattr(other, attr) is None
@ -23,7 +52,28 @@ def _binary_operator(operator):
def _unary_operator(operator): 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): def func(self):
"""Operator implementation.
Operator action is performed across all class attributes.
Returns:
:class:`CoordPair`: A new :class:`CoordPair` object that is the
result of the operator action.
"""
args = [None if getattr(self, attr) is None 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")] for attr in ("x", "y", "lat", "lon")]
@ -34,7 +84,30 @@ def _unary_operator(operator):
def _cmp_operator(operator): 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): 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.
Returns:
:obj:`boot`: Returns True if all comparisons across class
attributes returns True, otherwise False.
"""
vals = [getattr(getattr(self, attr), operator)(getattr(other, attr)) 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] if getattr(self, attr) is not None]
@ -45,7 +118,35 @@ def _cmp_operator(operator):
class CoordPair(object): class CoordPair(object):
"""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.
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): 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.x = x
self.y = y self.y = y
self.lat = lat self.lat = lat
@ -72,6 +173,17 @@ class CoordPair(object):
def xy_str(self, fmt="{:.4f}, {:.4f}"): 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: if self.x is None or self.y is None:
return None return None
@ -79,15 +191,38 @@ class CoordPair(object):
def latlon_str(self, fmt="{:.4f}, {:.4f}"): 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: if self.lat is None or self.lon is None:
return None return None
return fmt.format(self.lat, self.lon) return fmt.format(self.lat, self.lon)
def __round__(self, d=None): 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 args = [None if getattr(self, attr) is None
else py2round(getattr(self, attr), d) else py2round(getattr(self, attr), ndigits)
for attr in ("x", "y", "lat", "lon")] for attr in ("x", "y", "lat", "lon")]
return CoordPair(*args) return CoordPair(*args)

61
src/wrf/ctt.py

@ -17,14 +17,67 @@ from .util import extract_vars
description="cloud top temperature", description="cloud top temperature",
MemoryOrder="XY") MemoryOrder="XY")
@convert_units("temp", "c") @convert_units("temp", "c")
def get_ctt(wrfnc, timeidx=0, method="cat", def get_ctt(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None, squeeze=True, cache=None, meta=True, _key=None,
units="degC"): units="degC"):
"""Return the cloud top temperature. """Return the cloud top temperature.
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): Input 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
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.
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
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.
Default is None.
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
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 'ctt'. Default
is 'degC'.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
""" """
varnames = ("T", "P", "PB", "PH", "PHB", "HGT", "QVAPOR") varnames = ("T", "P", "PB", "PH", "PHB", "HGT", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]
p = ncvars["P"] p = ncvars["P"]
@ -36,7 +89,7 @@ def get_ctt(wrfnc, timeidx=0, method="cat",
haveqci = 1 haveqci = 1
try: try:
icevars = extract_vars(wrfnc, timeidx, "QICE", icevars = extract_vars(wrfin, timeidx, "QICE",
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)
except KeyError: except KeyError:
@ -46,7 +99,7 @@ def get_ctt(wrfnc, timeidx=0, method="cat",
qice = icevars["QICE"] * 1000.0 #g/kg qice = icevars["QICE"] * 1000.0 #g/kg
try: try:
cldvars = extract_vars(wrfnc, timeidx, "QCLOUD", cldvars = extract_vars(wrfin, timeidx, "QCLOUD",
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)
except KeyError: except KeyError:

149
src/wrf/dbz.py

@ -13,21 +13,75 @@ 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", description="radar reflectivity",
units="dBZ") units="dBZ")
def get_dbz(wrfnc, timeidx=0, method="cat", def get_dbz(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None, squeeze=True, cache=None, meta=True, _key=None,
use_varint=False, use_liqskin=False): use_varint=False, use_liqskin=False):
""" Return the dbz """Return the simulated radar reflectivity.
use_varint - do variable intercept (if False, constants are used. Otherwise, This functions extracts the necessary variables from the NetCDF file
intercepts are calculated using a technique from Thompson, Rasmussen, object in order to perform the calculation.
and Manning (2004, Monthly Weather Review, Vol. 132, No. 2, pp. 519-542.)
use_liqskin - do liquid skin for snow (frozen particles above freezing scatter Args:
as liquid)
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): Input 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
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.
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
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.
Default is None.
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
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
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
be a :class:`numpy.ndarray` object with no metadata.
""" """
varnames = ("T", "P", "PB", "QVAPOR", "QRAIN") varnames = ("T", "P", "PB", "QVAPOR", "QRAIN")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]
p = ncvars["P"] p = ncvars["P"]
@ -36,7 +90,7 @@ def get_dbz(wrfnc, timeidx=0, method="cat",
qr = ncvars["QRAIN"] qr = ncvars["QRAIN"]
try: try:
snowvars = extract_vars(wrfnc, timeidx, "QSNOW", snowvars = extract_vars(wrfin, timeidx, "QSNOW",
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)
except KeyError: except KeyError:
@ -45,7 +99,7 @@ def get_dbz(wrfnc, timeidx=0, method="cat",
qs = snowvars["QSNOW"] qs = snowvars["QSNOW"]
try: try:
graupvars = extract_vars(wrfnc, timeidx, "QGRAUP", graupvars = extract_vars(wrfin, timeidx, "QGRAUP",
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)
except KeyError: except KeyError:
@ -70,10 +124,77 @@ def get_dbz(wrfnc, timeidx=0, method="cat",
description="maximum radar reflectivity", description="maximum radar reflectivity",
units="dBZ", units="dBZ",
MemoryOrder="XY") MemoryOrder="XY")
def get_max_dbz(wrfnc, timeidx=0, method="cat", def get_max_dbz(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None, squeeze=True, cache=None, meta=True, _key=None,
do_varint=False, do_liqskin=False): use_varint=False, use_liqskin=False):
return np.amax(get_dbz(wrfnc, timeidx, method, squeeze, cache, meta, """Return the maximum simulated radar reflectivity.
_key, do_varint, do_liqskin),
This function returns the maximum reflectivity found in the column for
each grid point.
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): Input 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
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.
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
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.
Default is None.
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
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
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
be a :class:`numpy.ndarray` object with no metadata.
"""
return np.amax(get_dbz(wrfin, timeidx, method, squeeze, cache, meta,
_key, use_varint, use_liqskin),
axis=-3) axis=-3)

231
src/wrf/decorators.py

@ -17,12 +17,22 @@ if xarray_enabled():
from xarray import DataArray from xarray import DataArray
def convert_units(unit_type, alg_unit): def convert_units(unit_type, alg_unit):
"""A decorator that applies unit conversion to a function's output array. """A decorator that converts the units from the wrapped function's output.
Arguments: The desired units are determined from the wrapped function's arguments.
- unit_type - the unit type category (wind, pressure, etc) Args:
- alg_unit - the units that the function returns by default
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,
which is usually the units returned by the Fortran routine.
Returns:
:class:`numpy.ndarray`: The wrapped function's output in the desired
units.
""" """
@wrapt.decorator @wrapt.decorator
@ -39,10 +49,15 @@ def convert_units(unit_type, alg_unit):
return func_wrapper return func_wrapper
def _calc_out_dims(outvar, left_dims): #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 # """
# #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, def left_iteration(ref_var_expected_dims,
@ -55,33 +70,63 @@ def left_iteration(ref_var_expected_dims,
outviews="outview", outviews="outview",
alg_dtype=np.float64, alg_dtype=np.float64,
cast_output=True): cast_output=True):
"""Decorator to handle iterating over leftmost dimensions when using """A decorator to handle iterating over the leftmost dimensions.
multiple files and/or multiple times.
For example, if a wrapped function works with three-dimensional arrays, but
Arguments: the variables include a 4th leftmost dimension for 'Time', this decorator
- ref_var_expected_dims - the number of dimensions that the Fortran will iterate over all times, call the 3D Fortran routine, and aggregate the
algorithm is expecting for the reference variable results in to a 4D output array.
- ref_var_right_ndims - the number of dims from the right to keep for
the reference variable when making the output. Can also be a It is also important to note that the final output array is allocated
combine_dims instance if the sizes are determined from multiple first, and then views are passed to the wrapped function so that values
variables. do not need to get copied in to the final output array.
- insert_dims - a sequence of dimensions to insert between the left
dimenions (e.g. time) and the kept right dimensions Args:
- ref_var_idx - the index in args used as the reference variable for
calculating leftmost dimensions ref_var_expected_dims (:obj:`int`): The number of dimensions that the
- ref_var_name - the keyword argument name for kwargs used as the Fortran routine is expecting for the reference variable.
reference varible for calculating leftmost dimensions
- alg_out_fixed_dims - additional fixed dimension sizes for the ref_var_right_ndims (:obj:`int`): The number of dimensions from the
numerical algorithm (e.g. uvmet has a fixed left dimsize of 2) right to keep for the reference variable when making the output.
- ignore_args - indexes of any arguments which should be passed Can also be a :class:`combine_dims` object if the sizes are
directly without any slicing determined from multiple variables.
- ignore_kargs - keys of any keyword arguments which should be passed
directly without slicing insert_dims (sequence of :obj:`int`, optional): A sequence of
- outviews - a single key or sequence of keys indicating the keyword dimensions to insert between the left dimensions (e.g. time) and
argument used as the output variable(s) the kept right dimensions. Default is None.
- algtype - the data type used in the numerical routine
- cast_output - cast the final output to the ref_var data type 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
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
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
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
as the output variable(s) in the wrapped function.
alg_dtype (:class:`np.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
output to the same type as the reference variable.
Returns:
:class:`numpy.ndarray`: The aggregated output array that includes
all extra leftmost dimensions found in the reference variable.
""" """
@wrapt.decorator @wrapt.decorator
@ -204,10 +249,39 @@ def left_iteration(ref_var_expected_dims,
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, alg_dtype=np.float64, outviews="outview"):
outviews="outview"): """A decorator to handle type casting.
"""Decorator to handle casting to/from required dtype used in
numerical routine. 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
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
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.
Default is None.
alg_dtype (:class:`np.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
same :class:`numpy.dtype` as the reference variable.
""" """
@wrapt.decorator @wrapt.decorator
@ -255,6 +329,27 @@ def cast_type(ref_idx=0, arg_idxs=None, karg_names=None,
def _extract_and_transpose(arg, do_transpose): def _extract_and_transpose(arg, do_transpose):
"""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
*arg* is returned.
Args:
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,
the numpy array will also be a Fortran contiguous view.
"""
if xarray_enabled(): if xarray_enabled():
if isinstance(arg, DataArray): if isinstance(arg, DataArray):
@ -269,8 +364,25 @@ def _extract_and_transpose(arg, do_transpose):
def extract_and_transpose(do_transpose=True, outviews="outview"): def extract_and_transpose(do_transpose=True, outviews="outview"):
"""Decorator to extract the data array from a DataArray and also """A decorator to extract the data array from a :class:`xarray.DataArray`
transposes the view of the data if the data is not fortran contiguous.
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
as the output variable(s) in the wrapped function.
Returns:
:class:`numpy.ndarray`: A numpy array. If *do_transpose* is True,
the numpy array will also be a Fortran contiguous view.
""" """
@wrapt.decorator @wrapt.decorator
@ -311,16 +423,37 @@ def extract_and_transpose(do_transpose=True, outviews="outview"):
def check_args(refvaridx, refvarndim, rightdims, stagger=None, def check_args(refvaridx, refvarndim, rightdims, stagger=None,
refstagdim=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
index to use as the reference variable.
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
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
staggering for that argument. Default is None.
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.
refvaridx - reference variable to check for presence of left dimensions
refvarndim - the number of dimensions for the references variable
expected by the fortran routine
rightdims - the expected number of right dimensions for each argument
stagger - the dimension which is staggered for each argument. Use
None to indicate no staggering.
refstagdim - If the reference variable is staggered, indicate the dim that
is staggered
""" """
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):

33
src/wrf/destag.py

@ -8,14 +8,31 @@ from .metadecorators import set_destag_metadata
@set_destag_metadata() @set_destag_metadata()
@extract_and_transpose(do_transpose=False) @extract_and_transpose(do_transpose=False)
def destagger(var, stagger_dim, meta=False): def destagger(var, stagger_dim, meta=False):
""" De-stagger the variable. """Return the variable on the unstaggered grid.
Arguments: This function destaggers the variable by taking the average of the
- var is a numpy array for the variable values located on either side of the grid box.
- stagger_dim is the dimension of the numpy array to de-stagger
(e.g. 0, 1, 2). Note: negative values are acceptable to choose Args:
a dimensions from the right hand side (e.g. -1, -2, -3)
- meta - set to True to include 'var' metadata 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
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
:class:`xarray.DataArray`. Default is True.
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
:class:`numpy.ndarray` object with no metadata.
""" """
var_shape = var.shape var_shape = var.shape

120
src/wrf/dewpoint.py

@ -11,11 +11,67 @@ 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") description="dew point temperature")
@convert_units("temp", "c") @convert_units("temp", "c")
def get_dp(wrfnc, timeidx=0, method="cat", squeeze=True, def get_dp(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, units="degC"): cache=None, meta=True, _key=None, units="degC"):
"""Return the dewpoint temperature.
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): Input 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
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.
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
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.
Default is None.
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
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
is 'degC'.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("P", "PB", "QVAPOR") varnames=("P", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
p = ncvars["P"] p = ncvars["P"]
@ -32,10 +88,66 @@ def get_dp(wrfnc, timeidx=0, method="cat", squeeze=True,
@copy_and_set_metadata(copy_varname="Q2", name="td2", @copy_and_set_metadata(copy_varname="Q2", name="td2",
description="2m dew point temperature") description="2m dew point temperature")
@convert_units("temp", "c") @convert_units("temp", "c")
def get_dp_2m(wrfnc, 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"): cache=None, meta=True, _key=None, units="degC"):
"""Return the 2m dewpoint temperature.
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): Input 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
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.
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
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.
Default is None.
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
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
is 'degC'.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("PSFC", "Q2") varnames=("PSFC", "Q2")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
# Algorithm requires hPa # Algorithm requires hPa

171
src/wrf/extension.py

@ -21,25 +21,52 @@ from .specialdec import (uvmet_left_iter_nocopy, cape_left_iter,
cloudfrac_left_iter) cloudfrac_left_iter)
class FortranError(Exception): class FortranError(Exception):
"""Raised when an error occurs in a Fortran routine."""
def __init__(self, message=None): def __init__(self, message=None):
"""Initialize a :class:`wrf.FortranError` objection.
Args:
message (:obj:`str`): The error message.
"""
self._msg = message self._msg = message
def __str__(self): def __str__(self):
return self._msg return self._msg
def __call__(self, message): def __call__(self, message):
"""Callable method to make the exception object raise itself.
This allows the exception to be thrown from inside Fortran routines
by using f2py's callback mechanism. This is no longer used within
wrf-python, but may be useful to other users.
See Also:
`f2py doc <http://docs.scipy.org/doc/numpy-1.11.0/f2py/>`_
"""
raise self.__class__(message) raise self.__class__(message)
# The routines below are thin wrappers around the Fortran functions. These
# are not meant to be called by end users. Use the public API instead for
# that purpose.
# IMPORTANT! Unless otherwise noted, all variables used in the routines # IMPORTANT! Unless otherwise noted, all variables used in the routines
# below assume that fortran-ordered views are being used. This allows # below assume that Fortran-ordered views are being used. This allows
# f2py to pass the array pointers directly to the fortran routine. # f2py to pass the array pointers directly to the Fortran routine.
@check_args(0, 3, (3, 3, None, None)) @check_args(0, 3, (3, 3, None, None))
@left_iteration(3, 2, ref_var_idx=0, ignore_args=(2,3)) @left_iteration(3, 2, ref_var_idx=0, ignore_args=(2,3))
@cast_type(arg_idxs=(0,1)) @cast_type(arg_idxs=(0,1))
@extract_and_transpose() @extract_and_transpose()
def _interpz3d(field3d, z, desiredloc, missingval, outview=None): def _interpz3d(field3d, z, desiredloc, missingval, outview=None):
"""Wrapper for dinterp3dz.
Located in wrf_user.f90.
"""
if outview is None: if outview is None:
outview = np.empty(field3d.shape[0:2], np.float64, order="F") outview = np.empty(field3d.shape[0:2], np.float64, order="F")
@ -57,6 +84,11 @@ def _interpz3d(field3d, z, desiredloc, missingval, outview=None):
@cast_type(arg_idxs=(0,1)) @cast_type(arg_idxs=(0,1))
@extract_and_transpose() @extract_and_transpose()
def _interp2dxy(field3d, xy, outview=None): def _interp2dxy(field3d, xy, outview=None):
"""Wrapper for dinterp2dxy.
Located in wrf_user.f90.
"""
if outview is None: if outview is None:
outview = np.empty((xy.shape[-1], field3d.shape[-1]), np.float64, outview = np.empty((xy.shape[-1], field3d.shape[-1]), np.float64,
order="F") order="F")
@ -72,7 +104,11 @@ def _interp2dxy(field3d, xy, outview=None):
@cast_type(arg_idxs=(0,1,2)) @cast_type(arg_idxs=(0,1,2))
@extract_and_transpose() @extract_and_transpose()
def _interp1d(v_in, z_in, z_out, missingval, outview=None): def _interp1d(v_in, z_in, z_out, missingval, outview=None):
"""Wrapper for dinterp1d.
Located in wrf_user.f90.
"""
if outview is None: if outview is None:
outview = np.empty_like(z_out) outview = np.empty_like(z_out)
@ -90,6 +126,14 @@ def _interp1d(v_in, z_in, z_out, missingval, outview=None):
@cast_type(arg_idxs=(0,)) @cast_type(arg_idxs=(0,))
@extract_and_transpose(do_transpose=False) @extract_and_transpose(do_transpose=False)
def _vertcross(field3d, xy, var2dz, z_var2d, missingval, outview=None): def _vertcross(field3d, xy, var2dz, z_var2d, missingval, outview=None):
"""Return the vertical cross section.
This routine was originally written in scripted NCL code and doesn't
directly wrap a Fortran routine.
Located in WRFUserARW.ncl.
"""
# Note: This is using C-ordering # Note: This is using C-ordering
if outview is None: if outview is None:
outview = np.empty((z_var2d.shape[0], xy.shape[0]), dtype=var2dz.dtype) outview = np.empty((z_var2d.shape[0], xy.shape[0]), dtype=var2dz.dtype)
@ -107,6 +151,14 @@ def _vertcross(field3d, xy, var2dz, z_var2d, missingval, outview=None):
@cast_type(arg_idxs=(0,)) @cast_type(arg_idxs=(0,))
@extract_and_transpose(do_transpose=False) @extract_and_transpose(do_transpose=False)
def _interpline(field2d, xy, outview=None): def _interpline(field2d, xy, outview=None):
"""Return the two-dimensional field interpolated to a line.
This routine was originally written in scripted NCL code and doesn't
directly wrap a Fortran routine.
Located in WRFUserARW.ncl.
"""
# Note: This is using C-ordering # Note: This is using C-ordering
if outview is None: if outview is None:
outview = np.empty(xy.shape[0], dtype=field2d.dtype) outview = np.empty(xy.shape[0], dtype=field2d.dtype)
@ -127,7 +179,11 @@ def _interpline(field2d, xy, outview=None):
@cast_type(arg_idxs=(0,1,2,3)) @cast_type(arg_idxs=(0,1,2,3))
@extract_and_transpose() @extract_and_transpose()
def _slp(z, t, p, q, outview=None): def _slp(z, t, p, q, outview=None):
"""Wrapper for dcomputeseaprs.
Located in wrf_user.f90.
"""
t_surf = np.zeros(z.shape[0:2], np.float64, order="F") t_surf = np.zeros(z.shape[0:2], np.float64, order="F")
t_sea_level = np.zeros(z.shape[0:2], np.float64, order="F") t_sea_level = np.zeros(z.shape[0:2], np.float64, order="F")
level = np.zeros(z.shape[0:2], np.int32, order="F") level = np.zeros(z.shape[0:2], np.int32, order="F")
@ -160,6 +216,11 @@ def _slp(z, t, p, q, outview=None):
@cast_type(arg_idxs=(0,1)) @cast_type(arg_idxs=(0,1))
@extract_and_transpose() @extract_and_transpose()
def _tk(pressure, theta, outview=None): def _tk(pressure, theta, outview=None):
"""Wrapper for dcomputetk.
Located in wrf_user.f90.
"""
# No need to transpose here since operations on 1D array # No need to transpose here since operations on 1D array
shape = pressure.shape shape = pressure.shape
if outview is None: if outview is None:
@ -177,6 +238,11 @@ def _tk(pressure, theta, outview=None):
@cast_type(arg_idxs=(0,1)) @cast_type(arg_idxs=(0,1))
@extract_and_transpose() @extract_and_transpose()
def _td(pressure, qv_in, outview=None): def _td(pressure, qv_in, outview=None):
"""Wrapper for dcomputetd.
Located in wrf_user.f90.
"""
shape = pressure.shape shape = pressure.shape
if outview is None: if outview is None:
outview = np.empty_like(pressure) outview = np.empty_like(pressure)
@ -194,6 +260,11 @@ def _td(pressure, qv_in, outview=None):
@cast_type(arg_idxs=(0,1,2)) @cast_type(arg_idxs=(0,1,2))
@extract_and_transpose() @extract_and_transpose()
def _rh(qv, q, t, outview=None): def _rh(qv, q, t, outview=None):
"""Wrapper for dcomputerh.
Located in wrf_user.f90.
"""
shape = qv.shape shape = qv.shape
if outview is None: if outview is None:
outview = np.empty_like(qv) outview = np.empty_like(qv)
@ -216,6 +287,11 @@ def _rh(qv, q, t, outview=None):
@cast_type(arg_idxs=(0,1,2,3,4,5)) @cast_type(arg_idxs=(0,1,2,3,4,5))
@extract_and_transpose() @extract_and_transpose()
def _avo(u, v, msfu, msfv, msfm, cor, dx, dy, outview=None): def _avo(u, v, msfu, msfv, msfm, cor, dx, dy, outview=None):
"""Wrapper for dcomputeabsvort.
Located in wrf_pvo.f90.
"""
if outview is None: if outview is None:
outshape = (v.shape[0],) + u.shape[1:] outshape = (v.shape[0],) + u.shape[1:]
outview = np.empty(outshape, np.float64, order="F") outview = np.empty(outshape, np.float64, order="F")
@ -240,6 +316,11 @@ def _avo(u, v, msfu, msfv, msfm, cor, dx, dy, outview=None):
@cast_type(arg_idxs=(0,1,2,3,4,5,6,7)) @cast_type(arg_idxs=(0,1,2,3,4,5,6,7))
@extract_and_transpose() @extract_and_transpose()
def _pvo(u, v, theta, prs, msfu, msfv, msfm, cor, dx, dy, outview=None): def _pvo(u, v, theta, prs, msfu, msfv, msfm, cor, dx, dy, outview=None):
"""Wrapper for dcomputepv.
Located in wrf_pvo.f90.
"""
if outview is None: if outview is None:
outview = np.empty_like(prs) outview = np.empty_like(prs)
@ -263,6 +344,11 @@ def _pvo(u, v, theta, prs, msfu, msfv, msfm, cor, dx, dy, outview=None):
@cast_type(arg_idxs=(0,1,2)) @cast_type(arg_idxs=(0,1,2))
@extract_and_transpose() @extract_and_transpose()
def _eth(qv, tk, p, outview=None): def _eth(qv, tk, p, outview=None):
"""Wrapper for deqthecalc.
Located in eqthecalc.f90.
"""
if outview is None: if outview is None:
outview = np.empty_like(qv) outview = np.empty_like(qv)
@ -280,6 +366,11 @@ def _eth(qv, tk, p, outview=None):
def _uvmet(u, v, lat, lon, cen_long, cone, isstag=0, has_missing=False, def _uvmet(u, v, lat, lon, cen_long, cone, isstag=0, has_missing=False,
umissing=Constants.DEFAULT_FILL, vmissing=Constants.DEFAULT_FILL, umissing=Constants.DEFAULT_FILL, vmissing=Constants.DEFAULT_FILL,
uvmetmissing=Constants.DEFAULT_FILL, outview=None): uvmetmissing=Constants.DEFAULT_FILL, outview=None):
"""Wrapper for dcomputeuvmet.
Located in wrf_user.f90.
"""
longca = np.zeros(lat.shape[0:2], np.float64, order="F") longca = np.zeros(lat.shape[0:2], np.float64, order="F")
longcb = np.zeros(lon.shape[0:2], np.float64, order="F") longcb = np.zeros(lon.shape[0:2], np.float64, order="F")
rpd = Constants.PI/180. rpd = Constants.PI/180.
@ -312,6 +403,11 @@ def _uvmet(u, v, lat, lon, cen_long, cone, isstag=0, has_missing=False,
@cast_type(arg_idxs=(0,1,2,3)) @cast_type(arg_idxs=(0,1,2,3))
@extract_and_transpose() @extract_and_transpose()
def _omega(qv, tk, w, p, outview=None): def _omega(qv, tk, w, p, outview=None):
"""Wrapper for omgcalc.
Located in wrf_rip_phys_routines.f90.
"""
if outview is None: if outview is None:
outview = np.empty_like(qv) outview = np.empty_like(qv)
@ -329,6 +425,11 @@ def _omega(qv, tk, w, p, outview=None):
@cast_type(arg_idxs=(0,1)) @cast_type(arg_idxs=(0,1))
@extract_and_transpose() @extract_and_transpose()
def _tv(tk, qv, outview=None): def _tv(tk, qv, outview=None):
"""Wrapper for virtual_temp.
Located in wrf_rip_phys_routines.f90.
"""
if outview is None: if outview is None:
outview = np.empty_like(tk) outview = np.empty_like(tk)
@ -344,6 +445,11 @@ def _tv(tk, qv, outview=None):
@cast_type(arg_idxs=(0,1,2)) @cast_type(arg_idxs=(0,1,2))
@extract_and_transpose() @extract_and_transpose()
def _wetbulb(p, tk, qv, psafile=psafilepath(), outview=None): def _wetbulb(p, tk, qv, psafile=psafilepath(), outview=None):
"""Wrapper for wetbulbcalc.
Located in wrf_rip_phys_routines.f90.
"""
if outview is None: if outview is None:
outview = np.empty_like(p) outview = np.empty_like(p)
@ -369,6 +475,11 @@ def _wetbulb(p, tk, qv, psafile=psafilepath(), outview=None):
@cast_type(arg_idxs=(0,1,2,3)) @cast_type(arg_idxs=(0,1,2,3))
@extract_and_transpose() @extract_and_transpose()
def _srhel(u, v, z, ter, top, outview=None): def _srhel(u, v, z, ter, top, outview=None):
"""Wrapper for dcalrelhl.
Located in wrf_relhl.f90.
"""
if outview is None: if outview is None:
outview = np.empty_like(ter) outview = np.empty_like(ter)
@ -387,6 +498,11 @@ def _srhel(u, v, z, ter, top, outview=None):
@cast_type(arg_idxs=(0,1,2,3,4)) @cast_type(arg_idxs=(0,1,2,3,4))
@extract_and_transpose() @extract_and_transpose()
def _udhel(zstag, mapfct, u, v, wstag, dx, dy, bottom, top, outview=None): def _udhel(zstag, mapfct, u, v, wstag, dx, dy, bottom, top, outview=None):
"""Wrapper for dcalcuh.
Located in calc_uh.f90.
"""
if outview is None: if outview is None:
outview = np.empty_like(mapfct) outview = np.empty_like(mapfct)
@ -416,7 +532,11 @@ def _udhel(zstag, mapfct, u, v, wstag, dx, dy, bottom, top, outview=None):
@cast_type(arg_idxs=(0,1,2,3)) @cast_type(arg_idxs=(0,1,2,3))
@extract_and_transpose() @extract_and_transpose()
def _pw(p, tv, qv, ht, outview=None): def _pw(p, tv, qv, ht, outview=None):
"""Wrapper for dcomputepw.
Located in wrf_pw.f90.
"""
if outview is None: if outview is None:
outview = np.empty(p.shape[0:2], p.dtype, order="F") outview = np.empty(p.shape[0:2], p.dtype, order="F")
@ -434,6 +554,11 @@ def _pw(p, tv, qv, ht, outview=None):
@cast_type(arg_idxs=(0,1,2,3,4,5)) @cast_type(arg_idxs=(0,1,2,3,4,5))
@extract_and_transpose() @extract_and_transpose()
def _dbz(p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin, outview=None): def _dbz(p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin, outview=None):
"""Wrapper for calcdbz.
Located in wrf_user_dbz.f90.
"""
if outview is None: if outview is None:
outview = np.empty_like(p) outview = np.empty_like(p)
@ -457,7 +582,11 @@ def _dbz(p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin, outview=None):
@extract_and_transpose(outviews=("capeview", "cinview")) @extract_and_transpose(outviews=("capeview", "cinview"))
def _cape(p_hpa, tk, qv, ht, ter, sfp, missing, i3dflag, ter_follow, def _cape(p_hpa, tk, qv, ht, ter, sfp, missing, i3dflag, ter_follow,
psafile=psafilepath(), capeview=None, cinview=None): psafile=psafilepath(), capeview=None, cinview=None):
"""Wrapper for dcapecalc3d.
Located in rip_cape.f90.
"""
if capeview is None: if capeview is None:
capeview = np.zeros(p_hpa.shape[0:3], p_hpa.dtype, order="F") capeview = np.zeros(p_hpa.shape[0:3], p_hpa.dtype, order="F")
@ -493,7 +622,11 @@ def _cape(p_hpa, tk, qv, ht, ter, sfp, missing, i3dflag, ter_follow,
@cast_type(arg_idxs=(0, 1), outviews=("lowview", "medview", "highview")) @cast_type(arg_idxs=(0, 1), outviews=("lowview", "medview", "highview"))
@extract_and_transpose(outviews=("lowview", "medview", "hightview")) @extract_and_transpose(outviews=("lowview", "medview", "hightview"))
def _cloudfrac(p, rh, lowview=None, medview=None, highview=None): def _cloudfrac(p, rh, lowview=None, medview=None, highview=None):
"""Wrapper for dcloudfrace.
Located in wrf_cloud_fracf.f90.
"""
if lowview is None: if lowview is None:
lowview = np.zeros(p.shape[0:2], p.dtype, order="F") lowview = np.zeros(p.shape[0:2], p.dtype, order="F")
@ -516,7 +649,11 @@ def _lltoxy(map_proj, truelat1, truelat2, stdlon,
lat1, lon1, pole_lat, pole_lon, lat1, lon1, pole_lat, pole_lon,
known_x, known_y, dx, dy, latinc, loninc, lat, lon, known_x, known_y, dx, dy, latinc, loninc, lat, lon,
outview=None): outview=None):
"""Wrapper for dlltoij.
Located in wrf_user_latlon_routines.f90.
"""
if outview is None: if outview is None:
outview = np.zeros((2), dtype=np.float64, order="F") outview = np.zeros((2), dtype=np.float64, order="F")
@ -552,7 +689,11 @@ def _lltoxy(map_proj, truelat1, truelat2, stdlon,
def _xytoll(map_proj, truelat1, truelat2, stdlon, lat1, lon1, def _xytoll(map_proj, truelat1, truelat2, stdlon, lat1, lon1,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc, pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc, x, y, outview=None): loninc, x, y, outview=None):
"""Wrapper for dijtoll.
Located in wrf_user_latlon_routines.f90.
"""
if outview is None: if outview is None:
outview = np.zeros((2), dtype=np.float64, order="F") outview = np.zeros((2), dtype=np.float64, order="F")
@ -590,6 +731,11 @@ def _xytoll(map_proj, truelat1, truelat2, stdlon, lat1, lon1,
@cast_type(arg_idxs=(0,1,2,3,4,5,6)) @cast_type(arg_idxs=(0,1,2,3,4,5,6))
@extract_and_transpose() @extract_and_transpose()
def _ctt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci, outview=None): def _ctt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci, outview=None):
"""Wrapper for wrfcttcalc.
Located in wrf_fctt.f90.
"""
if outview is None: if outview is None:
outview = np.empty_like(ter) outview = np.empty_like(ter)
@ -611,6 +757,11 @@ def _ctt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci, outview=None):
@cast_type(arg_idxs=(0,)) @cast_type(arg_idxs=(0,))
@extract_and_transpose() @extract_and_transpose()
def _smooth2d(field, passes, outview=None): def _smooth2d(field, passes, outview=None):
"""Wrapper for dfilter2d.
Located in wrf_user.f90.
"""
# Unlike NCL, this routine will not modify the values in place, but # Unlike NCL, this routine will not modify the values in place, but
# copies the original data before modifying it. # copies the original data before modifying it.
@ -639,6 +790,11 @@ def _smooth2d(field, passes, outview=None):
@cast_type(arg_idxs=(0,1,2)) @cast_type(arg_idxs=(0,1,2))
@extract_and_transpose() @extract_and_transpose()
def _monotonic(var, lvprs, coriolis, idir, delta, icorsw, outview=None): def _monotonic(var, lvprs, coriolis, idir, delta, icorsw, outview=None):
"""Wrapper for wrf_monotonic.
Located in wrf_vinterp.f90.
"""
# If icorsw is not 0, then the input variable might get modified by the # If icorsw is not 0, then the input variable might get modified by the
# fortran routine. We don't want this, so make a copy and pass that on. # fortran routine. We don't want this, so make a copy and pass that on.
var = var.copy(order="A") if icorsw != 0 else var var = var.copy(order="A") if icorsw != 0 else var
@ -667,7 +823,11 @@ def _monotonic(var, lvprs, coriolis, idir, delta, icorsw, outview=None):
def _vintrp(field, pres, tk, qvp, ght, terrain, sfp, smsfp, def _vintrp(field, pres, tk, qvp, ght, terrain, sfp, smsfp,
vcarray, interp_levels, icase, extrap, vcor, logp, vcarray, interp_levels, icase, extrap, vcor, logp,
missing, outview=None): missing, outview=None):
"""Wrapper for wrf_vintrp.
Located in wrf_vinterp.f90.
"""
if outview is None: if outview is None:
outdims = field.shape[0:2] + interp_levels.shape outdims = field.shape[0:2] + interp_levels.shape
outview = np.empty(outdims, field.dtype, order="F") outview = np.empty(outdims, field.dtype, order="F")
@ -700,10 +860,3 @@ def _vintrp(field, pres, tk, qvp, ght, terrain, sfp, smsfp,
return result return result

203
src/wrf/geoht.py

@ -7,19 +7,79 @@ from .decorators import convert_units
from .metadecorators import set_height_metadata from .metadecorators import set_height_metadata
from .util import extract_vars, either from .util import extract_vars, either
def _get_geoht(wrfnc, timeidx, method="cat", squeeze=True, def _get_geoht(wrfin, timeidx, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
height=True, msl=True): height=True, msl=True):
"""Return the geopotential in units of m2 s-2 if height is False, """Return the geopotential or geopotential height.
otherwise return the geopotential height in meters. If height is True,
then if msl is True the result will be in MSL, otherwise AGL (the terrain If *height* is False, then geopotential is returned in units of
height is subtracted). [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
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
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
the terrain height. Default is True.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
""" """
varname = either("PH", "GHT")(wrfnc) varname = either("PH", "GHT")(wrfin)
if varname == "PH": if varname == "PH":
ph_vars = extract_vars(wrfnc, timeidx, ("PH", "PHB", "HGT"), ph_vars = extract_vars(wrfin, timeidx, ("PH", "PHB", "HGT"),
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)
ph = ph_vars["PH"] ph = ph_vars["PH"]
@ -28,7 +88,7 @@ def _get_geoht(wrfnc, timeidx, method="cat", squeeze=True,
geopt = ph + phb geopt = ph + phb
geopt_unstag = destagger(geopt, -3) geopt_unstag = destagger(geopt, -3)
else: else:
ght_vars = extract_vars(wrfnc, timeidx, ("GHT", "HGT_M"), ght_vars = extract_vars(wrfin, timeidx, ("GHT", "HGT_M"),
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)
geopt_unstag = ght_vars["GHT"] * Constants.G geopt_unstag = ght_vars["GHT"] * Constants.G
@ -51,18 +111,137 @@ def _get_geoht(wrfnc, timeidx, method="cat", squeeze=True,
@set_height_metadata(geopt=True) @set_height_metadata(geopt=True)
def get_geopt(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_geopt(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
return _get_geoht(wrfnc, timeidx, method, squeeze, cache, meta, _key, """Return the geopotential.
The geopotential is returned in units of [m2 s-2].
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): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
return _get_geoht(wrfin, timeidx, method, squeeze, cache, meta, _key,
False, True) False, True)
@set_height_metadata(geopt=False) @set_height_metadata(geopt=False)
@convert_units("height", "m") @convert_units("height", "m")
def get_height(wrfnc, timeidx=0, method="cat", squeeze=True, def get_height(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
msl=True, units="m"): 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
Above Ground Level (AGL) by subtracting the terrain height.
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): Input 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
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.
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
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.
Default is None.
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
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
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
is 'm'.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
return _get_geoht(wrfnc, timeidx, method, squeeze, cache, meta, _key, return _get_geoht(wrfin, timeidx, method, squeeze, cache, meta, _key,
True, msl) True, msl)

145
src/wrf/helicity.py

@ -12,11 +12,68 @@ from .metadecorators import copy_and_set_metadata
@copy_and_set_metadata(copy_varname="HGT", name="srh", @copy_and_set_metadata(copy_varname="HGT", name="srh",
description="storm relative helicity", description="storm relative helicity",
units="m2 s-2") units="m2 s-2")
def get_srh(wrfnc, 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): 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
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
top (:obj:`float`, optional): The top of the integration in [m].
Default is 3000.0.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
# Top can either be 3000 or 1000 (for 0-1 srh or 0-3 srh) # Top can either be 3000 or 1000 (for 0-1 srh or 0-3 srh)
ncvars = extract_vars(wrfnc, timeidx, ("HGT", "PH", "PHB"), ncvars = extract_vars(wrfin, timeidx, ("HGT", "PH", "PHB"),
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)
@ -25,13 +82,13 @@ def get_srh(wrfnc, timeidx=0, method="cat", squeeze=True,
phb = ncvars["PHB"] phb = ncvars["PHB"]
# As coded in NCL, but not sure this is possible # As coded in NCL, but not sure this is possible
varname = either("U", "UU")(wrfnc) varname = either("U", "UU")(wrfin)
u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, u_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
u = destagger(u_vars[varname], -1) u = destagger(u_vars[varname], -1)
varname = either("V", "VV")(wrfnc) varname = either("V", "VV")(wrfin)
v_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, v_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
v = destagger(v_vars[varname], -2) v = destagger(v_vars[varname], -2)
@ -52,11 +109,73 @@ def get_srh(wrfnc, timeidx=0, method="cat", squeeze=True,
@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", description="updraft helicity",
units="m2 s-2") units="m2 s-2")
def get_uh(wrfnc, timeidx=0, method="cat", squeeze=True, def get_uh(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
bottom=2000.0, top=5000.0): bottom=2000.0, top=5000.0):
ncvars = extract_vars(wrfnc, timeidx, ("W", "PH", "PHB", "MAPFAC_M"), """Return the updraft helicity.
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
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
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].
Default is 5000.0.
Returns:
: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
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=None) method, squeeze, cache, meta=False, _key=None)
wstag = ncvars["W"] wstag = ncvars["W"]
@ -64,18 +183,18 @@ def get_uh(wrfnc, timeidx=0, method="cat", squeeze=True,
phb = ncvars["PHB"] phb = ncvars["PHB"]
mapfct = ncvars["MAPFAC_M"] mapfct = ncvars["MAPFAC_M"]
attrs = extract_global_attrs(wrfnc, attrs=("DX", "DY")) attrs = extract_global_attrs(wrfin, attrs=("DX", "DY"))
dx = attrs["DX"] dx = attrs["DX"]
dy = attrs["DY"] dy = attrs["DY"]
# As coded in NCL, but not sure this is possible # As coded in NCL, but not sure this is possible
varname = either("U", "UU")(wrfnc) varname = either("U", "UU")(wrfin)
u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, u_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
u = destagger(u_vars[varname], -1) u = destagger(u_vars[varname], -1)
varname = either("V", "VV")(wrfnc) varname = either("V", "VV")(wrfin)
v_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, v_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
v = destagger(v_vars[varname], -2) v = destagger(v_vars[varname], -2)

456
src/wrf/interp.py

@ -20,135 +20,169 @@ from .pressure import get_pressure
# Note: Extension decorator is good enough to handle left dims # Note: Extension decorator is good enough to handle left dims
@set_interp_metadata("horiz") @set_interp_metadata("horiz")
def interplevel(field3d, z, desiredlev, missing=Constants.DEFAULT_FILL, def interplevel(field3d, vert, desiredlev, missing=Constants.DEFAULT_FILL,
meta=True): meta=True):
"""Interpolates a three-dimensional field specified pressure or """Return the three-dimensional field horizontally interpolated to a
height level. specified vertical level.
Parameters Args:
----------
field3d : `xarray.DataArray` or `numpy.ndarray` field3d (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
A three-dimensional field. three-dimensional field to interpolate, with the rightmost
dimensions of nz x ny x nx.
z : `xarray.DataArray` or `numpy.ndarray`
A three-dimensional array for the vertical coordinate, typically vert (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
pressure or height. three-dimensional array for the vertical coordinate, typically
pressure or height. This array must have the same dimensionality
desiredlev : float as *field3d*.
The desired vertical level. Must be in the same units as the `z`
parameter. desiredlev (:obj:`float`): The desired vertical level.
Must be in the same units as the *vert* parameter.
missing : float
The fill value to use for the output. missing (:obj:`float`): The fill value to use for the output.
`Default is wrf.Constants.DEFAULT_FILL`. Default is :data:`wrf.Constants.DEFAULT_FILL`.
meta : {True, False} meta (:obj:`bool`): Set to False to disable metadata and return
Set to False to disable metadata and return `numpy.ndarray` instead of :class:`numpy.ndarray` instead of
`xarray.DataArray`. Default is True. :class:`xarray.DataArray`. Default is True.
Returns Returns:
-------
`xarray.DataArray` or `numpy.ndarray` :class:`xarray.DataArray` or :class:`numpy.ndarray`: The
Returns the interpolated variable. If xarray is enabled and interpolated variable. If xarray is enabled and
the meta parameter is True, then the result will be an the *meta* parameter is True, then the result will be an
`xarray.DataArray` object. Otherwise, the result will be a :class:`xarray.DataArray` object. Otherwise, the result will
`numpy.ndarray` object with no metadata. be a :class:`numpy.ndarray` object with no metadata.
Example:
Interpolate Geopotential Height to 500 hPa
.. code-block:: python
from netCDF4 import Dataset
from wrf import getvar, interplevel
wrfin = Dataset("wrfout_d02_2010-06-13_21:00:00")
p = getvar(wrfin, "pressure")
ht = getvar(wrfin, "z", units="dm")
ht_500 = interplevel(ht, p, 500.0)
""" """
# Some fields like uvmet have an extra left dimension for the product # Some fields like uvmet have an extra left dimension for the product
# type, we'll handle that iteration here. # type, we'll handle that iteration here.
multi = True if field3d.ndim - z.ndim == 1 else False multi = True if field3d.ndim - vert.ndim == 1 else False
if not multi: if not multi:
result = _interpz3d(field3d, z, desiredlev, missing) result = _interpz3d(field3d, vert, desiredlev, missing)
else: else:
outshape = field3d.shape[0:-3] + field3d.shape[-2:] outshape = field3d.shape[0:-3] + field3d.shape[-2:]
result = np.empty(outshape, dtype=field3d.dtype) result = np.empty(outshape, dtype=field3d.dtype)
for i in py3range(field3d.shape[0]): for i in py3range(field3d.shape[0]):
result[i,:] = ( result[i,:] = (
_interpz3d(field3d[i,:], z, desiredlev, missing)[:]) _interpz3d(field3d[i,:], vert, desiredlev, missing)[:])
return ma.masked_values (result, missing) return ma.masked_values (result, missing)
@set_interp_metadata("cross") @set_interp_metadata("cross")
def vertcross(field3d, z, missing=Constants.DEFAULT_FILL, def vertcross(field3d, vert, missing=Constants.DEFAULT_FILL,
pivot_point=None, angle=None, pivot_point=None, angle=None,
start_point=None, end_point=None, start_point=None, end_point=None,
latlon=False, cache=None, meta=True): latlon=False, cache=None, meta=True):
"""Return the vertical cross section for a 3D field, interpolated """Return the vertical cross section for a three-dimensional field.
to a vertical plane defined by a horizontal line.
The cross section is defined by a horizontal line through the domain.
The horizontal line is defined by either including the This horizontal line is defined by either including the
`pivot_point` and `angle` parameters, or the `start_point` and *pivot_point* and *angle* parameters, or the *start_point* and
`end_point` parameters. *end_point* parameters.
Parameters The vertical levels for the cross section are fixed, and are determined by
---------- dividing the vertical coordinate in to grid boxes of roughly 1% of the
field3d : `xarray.DataArray` or `numpy.ndarray` maximum vertical distance from top to bottom. If all vertical levels are
A three-dimensional field. desired, use the lower level :meth:`wrf.interp2dxy` function.
z : `xarray.DataArray` or `numpy.ndarray` See Also:
A three-dimensional array for the vertical coordinate, typically
pressure or height :meth:`wrf.interp2dxy`
pivot_point : tuple or list, optional Args:
A tuple or list with two entries, in the form of [x, y]
(or [west_east, south_north]), which indicates the x,y location field3d (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
through which the plane will pass. Must also specify `angle`. three-dimensional field to interpolate, whose
rightmost dimensions are nz x ny x nx.
angle : float, optional
Only valid for cross sections where a plane will be plotted through vert (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
a given point on the model domain. 0.0 represents a S-N cross section three-dimensional variable for the vertical coordinate, typically
and 90.0 a W-E cross section. pressure or height. This array must have the same dimensionality
as *field3d*
start_point : tuple or list, optional
A tuple or list with two entries, in the form of [x, y] missing (:obj:`float`): The fill value to use for the output.
(or [west_east, south_north]), which indicates the start x,y location Default is :data:`wrf.Constants.DEFAULT_FILL`.
through which the plane will pass.
pivot_point (:obj:`tuple` or :obj:`list`, optional): A
end_point : tuple or list, optional :obj:`tuple` or :obj:`list` with two entries,
A tuple or list with two entries, in the form of [x, y] in the form of [x, y] (or [west_east, south_north]), which
(or [west_east, south_north]), which indicates the end x,y location indicates the x,y location through which the plane will pass.
through which the plane will pass. Must also specify `angle`.
latlon : {True, False}, optional angle (:obj:`float`, optional): Only valid for cross sections where
Set to True to also interpolate the two-dimensional latitude and a plane will be plotted through
longitude coordinates along the same horizontal line and include a given point on the model domain. 0.0 represents a S-N cross
this information in the metadata (if enabled). This can be section. 90.0 is a W-E cross section.
helpful for plotting. Default is False.
start_point (:obj:`tuple` or :obj:`list`, optional): A
cache : dict, optional :obj:`tuple` or :obj:`list` with two entries, in the form of
A dictionary of (varname, numpy.ndarray) pairs which can be used to [x, y] (or [west_east, south_north]), which indicates the start
supply pre-extracted NetCDF variables to the computational routines. x,y location through which the plane will pass.
This can be used to prevent the repeated variable extraction from large
sequences of data files. Default is None. end_point (:obj:`tuple` or :obj:`list`, optional): A
:obj:`tuple` or :obj:`list` with two entries, in the form of
meta : {True, False}, optional [x, y] (or [west_east, south_north]), which indicates the end x,y
Set to False to disable metadata and return `numpy.ndarray` instead of location through which the plane will pass.
`xarray.DataArray`. Default is True.
latlon (:obj:`bool`, optional): Set to True to also interpolate the
Returns two-dimensional latitude and longitude coordinates along the same
------- horizontal line and include this information in the metadata
`xarray.DataArray` or `numpy.ndarray` (if enabled). This can be helpful for plotting. Default is False.
Returns the interpolated variable. If xarray is enabled and
the meta parameter is True, then the result will be an cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
`xarray.DataArray` object. Otherwise, the result will be a that can be used to supply pre-extracted NetCDF variables to the
`numpy.ndarray` object with no metadata. 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
:class:`xarray.DataArray`. Default is True.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`:
The interpolated 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.
""" """
# Some fields like uvmet have an extra left dimension for the product # Some fields like uvmet have an extra left dimension for the product
# type, we'll handle that iteration here. # type, we'll handle that iteration here.
multi = True if field3d.ndim - z.ndim == 1 else False multi = True if field3d.ndim - vert.ndim == 1 else False
try: try:
xy = cache["xy"] xy = cache["xy"]
var2dz = cache["var2dz"] var2dz = cache["var2dz"]
z_var2d = cache["z_var2d"] z_var2d = cache["z_var2d"]
except (KeyError, TypeError): except (KeyError, TypeError):
xy, var2dz, z_var2d = get_xy_z_params(npvalues(z), pivot_point, angle, xy, var2dz, z_var2d = get_xy_z_params(npvalues(vert), pivot_point,
start_point, end_point) angle, start_point, end_point)
if not multi: if not multi:
result = _vertcross(field3d, xy, var2dz, z_var2d, missing) result = _vertcross(field3d, xy, var2dz, z_var2d, missing)
@ -170,55 +204,59 @@ def interpline(field2d, pivot_point=None,
cache=None, meta=True): cache=None, meta=True):
"""Return the two-dimensional field interpolated along a line. """Return the two-dimensional field interpolated along a line.
Parameters Args:
----------
field2d : `xarray.DataArray` or `numpy.ndarray` field2d (:class:`xarray.DataArray` or :class:`numpy.ndarray`):
A two-dimensional field. A two-dimensional field.
pivot_point : tuple or list, optional pivot_point (:obj:`tuple` or :obj:`list`, optional): A
A tuple or list with two entries, in the form of [x, y] :obj:`tuple` or :obj:`list` with two entries,
(or [west_east, south_north]), which indicates the x,y location in the form of [x, y] (or [west_east, south_north]), which
through which the plane will pass. Must also specify `angle`. indicates the x,y location through which the plane will pass.
Must also specify `angle`.
angle : float, optional
Only valid for cross sections where a plane will be plotted through angle (:obj:`float`, optional): Only valid for cross sections where
a given point on the model domain. 0.0 represents a S-N cross section a plane will be plotted through
and 90.0 a W-E cross section. 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 : tuple or list, optional
A tuple or list with two entries, in the form of [x, y] start_point (:obj:`tuple` or :obj:`list`, optional): A
(or [west_east, south_north]), which indicates the start x,y location :obj:`tuple` or :obj:`list` with two entries, in the form of
through which the plane will pass. [x, y] (or [west_east, south_north]), which indicates the start
x,y location through which the plane will pass.
end_point : tuple or list, optional
A tuple or list with two entries, in the form of [x, y] end_point (:obj:`tuple` or :obj:`list`, optional): A
(or [west_east, south_north]), which indicates the end x,y location :obj:`tuple` or :obj:`list` with two entries, in the form of
through which the plane will pass. [x, y] (or [west_east, south_north]), which indicates the end x,y
location through which the plane will pass.
latlon : {True, False}, optional
Set to True to also interpolate the two-dimensional latitude and latlon (:obj:`bool`, optional): Set to True to also interpolate the
longitude coordinates along the same horizontal line and include two-dimensional latitude and longitude coordinates along the same
this information in the metadata (if enabled). This can be horizontal line and include this information in the metadata
helpful for plotting. Default is False. (if enabled). This can be helpful for plotting. Default is False.
cache : dict, optional cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
A dictionary of (varname, numpy.ndarray) pairs which can be used to that can be used to supply pre-extracted NetCDF variables to the
supply pre-extracted NetCDF variables to the computational routines. computational routines. It is primarily used for internal
This can be used to prevent the repeated variable extraction from large purposes, but can also be used to improve performance by
sequences of data files. Default is None. eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
meta : {True, False}, optional large sequences of files.
Set to False to disable metadata and return `numpy.ndarray` instead of Default is None.
`xarray.DataArray`. Default is True.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
Returns :class:`xarray.DataArray`. Default is True.
-------
`xarray.DataArray` or `numpy.ndarray`
Returns the interpolated variable. If xarray is enabled and Returns:
the meta parameter is True, then the result will be an
`xarray.DataArray` object. Otherwise, the result will be a :class:`xarray.DataArray` or :class:`numpy.ndarray`:
`numpy.ndarray` object with no metadata. The interpolated 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.
""" """
@ -231,80 +269,92 @@ def interpline(field2d, pivot_point=None,
@set_interp_metadata("vinterp") @set_interp_metadata("vinterp")
def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False, def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
field_type=None, log_p=False, timeidx=0, method="cat", field_type=None, log_p=False, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True): squeeze=True, cache=None, meta=True):
"""Return the field vertically interpolated to the given the type of """Return the field vertically interpolated to the given the type of
surface and a set of new levels. surface and a set of new levels.
Parameters Args:
---------- wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`,\
wrfnc : `netCD4F.Dataset`, `Nio.NioFile`, or a sequence or an iterable):
Input WRF ARW NetCDF data as a `netCDF4.Dataset`, `Nio.NioFile` or an Input WRF ARW NetCDF data as a :class:`netCDF4.Dataset`,
iterable sequence of the aforementioned types. :class:`Nio.NioFile` or an iterable sequence of the
aforementioned types.
field : `xarray.DataArray` or `numpy.ndarray` field (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
A three-dimensional field. three-dimensional field.
vert_coord : {'pressure', 'pres', 'p', 'ght_msl', 'ght_agl', 'theta', 'th', 'theta-e', 'thetae', 'eth'} vert_coord (:obj:`str`): A string indicating the vertical coordinate
A string indicating the vertical coordinate type to interpolate to. type to interpolate to.
Valid strings are: Valid strings are:
* 'pressure', 'pres', 'p': pressure [hPa] * 'pressure', 'pres', 'p': pressure [hPa]
* 'ght_msl': grid point height msl [km] * 'ght_msl': grid point height msl [km]
* 'ght_agl': grid point height agl [km] * 'ght_agl': grid point height agl [km]
* 'theta', 'th': potential temperature [K] * 'theta', 'th': potential temperature [K]
* 'theta-e', 'thetae', 'eth': equivalent potential temperature [K] * 'theta-e', 'thetae', 'eth': equivalent potential temperature \
[K]
interp_levels : sequence interp_levels (sequence): A 1D sequence of vertical levels to
A 1D sequence of vertical levels to interpolate to. interpolate to.
extrapolate : {True, False}, optional extrapolate (:obj:`bool`, optional): Set to True to extrapolate
Set to True to extrapolate values below ground. Default is False. values below ground. Default is False.
field_type : {'none', 'pressure', 'pres', 'p', 'z', 'tc', 'tk', 'theta', 'th', 'theta-e', 'thetae', 'eth', 'ght'}, optional field_type (:obj:`str`, optional):
The type of field. Default is None. The type of field. Default is None.
log_p : {True, False} Valid strings are:
Use the log of the pressure for interpolation instead of just pressure. * 'none': None
Default is False. * 'pressure', 'pres', 'p': pressure
* 'z', 'ght': geopotential height
* 'tc': temperature [degC]
* 'tk': temperature [K]
* 'theta', 'th': potential temperature [K]
* 'theta-e', 'thetae', 'eth': equivalent potential temperature
timeidx : int, optional log_p (:obj:`bool`, optional): Use the log of the pressure for
interpolation instead of pressure. Default is False.
timeidx (:obj:`int`, optional):
The time index to use when extracting auxiallary variables used in The time index to use when extracting auxiallary variables used in
the interpolation. This value must be set to match the same value the interpolation. This value must be set to match the same value
used when the `field` variable was extracted. Default is 0. used when the `field` variable was extracted. Default is 0.
method : {'cat', 'join'}, optional method (:obj:`str`, optional): The aggregation method to use for
The aggregation method to use for sequences, either 'cat' or 'join'. sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time index. 'join' is creates a new 'cat' combines the data along the Time dimension.
index for the file. This must be set to the same method used when 'join' creates a new dimension for the file index.
extracting the `field` variable. The default is 'cat'. The default is 'cat'.
squeeze : {True, False}, optional squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
Set to False to prevent dimensions with a size of 1 from being removed with a size of 1 from being automatically removed from the shape
from the shape of the output. Default is True. of the output. Default is True.
cache : dict, optional cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
A dictionary of (varname, ndarray) which can be used to supply that can be used to supply pre-extracted NetCDF variables to the
pre-extracted NetCDF variables to the computational routines. This can computational routines. It is primarily used for internal
be used to prevent the repeated variable extraction from large purposes, but can also be used to improve performance by
sequences of data files. Default is None. eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
meta : {True, False}, optional large sequences of files.
Set to False to disable metadata and return `numpy.ndarray` instead of Default is None.
`xarray.DataArray`. Default is True.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
Returns :class:`xarray.DataArray`. Default is True.
-------
`xarray.DataArray` or `numpy.ndarray` Returns:
Returns the interpolated variable. If xarray is enabled and
the meta parameter is True, then the result will be an :class:`xarray.DataArray` or :class:`numpy.ndarray`:
`xarray.DataArray` object. Otherwise, the result will be a The interpolated variable. If xarray is enabled and
`numpy.ndarray` object with no metadata. 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.
""" """
_key = get_id(wrfnc) _key = get_id(wrfin)
# Remove case sensitivity # Remove case sensitivity
field_type = field_type.lower() if field_type is not None else "none" field_type = field_type.lower() if field_type is not None else "none"
@ -341,7 +391,7 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False,
interp_levels = np.asarray(interp_levels, np.float64) interp_levels = np.asarray(interp_levels, np.float64)
# TODO: Check if field is staggered # TODO: Check if field is staggered
if is_staggered(field, wrfnc): if is_staggered(wrfin, field):
raise RuntimeError("Please unstagger field in the vertical") raise RuntimeError("Please unstagger field in the vertical")
# Check for valid coord # Check for valid coord
@ -364,29 +414,29 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False,
# Extract vriables # Extract vriables
#timeidx = -1 # Should this be an argument? #timeidx = -1 # Should this be an argument?
ncvars = extract_vars(wrfnc, timeidx, ("PSFC", "QVAPOR", "F"), ncvars = extract_vars(wrfin, timeidx, ("PSFC", "QVAPOR", "F"),
method, squeeze, cache, meta=False, _key=_key) method, squeeze, cache, meta=False, _key=_key)
sfp = ncvars["PSFC"] * ConversionFactors.PA_TO_HPA sfp = ncvars["PSFC"] * ConversionFactors.PA_TO_HPA
qv = ncvars["QVAPOR"] qv = ncvars["QVAPOR"]
coriolis = ncvars["F"] coriolis = ncvars["F"]
terht = get_terrain(wrfnc, timeidx, units="m", terht = get_terrain(wrfin, timeidx, units="m",
method=method, squeeze=squeeze, cache=cache, method=method, squeeze=squeeze, cache=cache,
meta=False, _key=_key) meta=False, _key=_key)
t = get_theta(wrfnc, timeidx, units="k", t = get_theta(wrfin, timeidx, units="k",
method=method, squeeze=squeeze, cache=cache, method=method, squeeze=squeeze, cache=cache,
meta=False, _key=_key) meta=False, _key=_key)
tk = get_temp(wrfnc, timeidx, units="k", tk = get_temp(wrfin, timeidx, units="k",
method=method, squeeze=squeeze, cache=cache, method=method, squeeze=squeeze, cache=cache,
meta=False, _key=_key) meta=False, _key=_key)
p = get_pressure(wrfnc, timeidx, units="pa", p = get_pressure(wrfin, timeidx, units="pa",
method=method, squeeze=squeeze, cache=cache, method=method, squeeze=squeeze, cache=cache,
meta=False, _key=_key) meta=False, _key=_key)
ght = get_height(wrfnc, timeidx, msl=True, units="m", ght = get_height(wrfin, timeidx, msl=True, units="m",
method=method, squeeze=squeeze, cache=cache, method=method, squeeze=squeeze, cache=cache,
meta=False, _key=_key) meta=False, _key=_key)
ht_agl = get_height(wrfnc, timeidx, msl=False, units="m", ht_agl = get_height(wrfin, timeidx, msl=False, units="m",
method=method, squeeze=squeeze, cache=cache, method=method, squeeze=squeeze, cache=cache,
meta=False, _key=_key) meta=False, _key=_key)
@ -427,7 +477,7 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False,
idir = 1 idir = 1
delta = 0.01 delta = 0.01
eth = get_eth(wrfnc, timeidx, method=method, squeeze=squeeze, eth = get_eth(wrfin, timeidx, method=method, squeeze=squeeze,
cache=cache, meta=False, _key=_key) cache=cache, meta=False, _key=_key)
p_hpa = p * ConversionFactors.PA_TO_HPA p_hpa = p * ConversionFactors.PA_TO_HPA

141
src/wrf/interputils.py

@ -10,26 +10,65 @@ from .py3compat import py3range
def to_positive_idxs(shape, coord): 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): if (coord[-2] >= 0 and coord[-1] >= 0):
return coord 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, def _calc_xy(xdim, ydim, pivot_point=None, angle=None,
start_point=None, end_point=None): start_point=None, end_point=None):
"""Returns the x,y points for the horizontal cross section line. """Return the x,y points for the horizontal cross section line.
xdim - maximum x-dimension Args:
ydim - maximum y-dimension
pivot_point - a pivot point of (south_north, west_east)
(must be used with angle)
angle - the angle through the pivot point in degrees
start_point - a start_point sequence of (x, y)
end_point - an end point sequence of (x, y)
""" 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.
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
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
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
having two values for the x and y coordinates [0=X, 1=Y].
"""
# Have a pivot point with an angle to find cross section # Have a pivot point with an angle to find cross section
if pivot_point is not None and angle is not None: if pivot_point is not None and angle is not None:
xp = pivot_point[-2] xp = pivot_point[-2]
@ -139,8 +178,52 @@ def calc_xy(xdim, ydim, pivot_point=None, angle=None,
return xy return xy
def get_xy_z_params(z, pivot_point=None, angle=None, def get_xy_z_params(z, pivot_point=None, angle=None,
start_point=None, end_point=None): start_point=None, end_point=None):
"""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
line, and the fixed vertical levels to be used by the cross section
algorithm (at ~1% increments for the minimum to maximum vertical
span).
Args:
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.
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
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
location through which the plane will pass.
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
vertical span.
"""
xy = get_xy(z, pivot_point, angle, start_point, end_point) xy = get_xy(z, pivot_point, angle, start_point, end_point)
@ -173,8 +256,44 @@ def get_xy_z_params(z, pivot_point=None, angle=None,
return xy, var2dz, z_var2d 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): 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.
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
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
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
having two values for the x and y coordinates [0=X, 1=Y].
"""
if pivot_point is not None: if pivot_point is not None:
pos_pivot = to_positive_idxs(var.shape[-2:], pivot_point) pos_pivot = to_positive_idxs(var.shape[-2:], pivot_point)
else: else:
@ -193,6 +312,6 @@ def get_xy(var, pivot_point=None, angle=None,
xdim = var.shape[-1] xdim = var.shape[-1]
ydim = var.shape[-2] ydim = var.shape[-2]
xy = calc_xy(xdim, ydim, pos_pivot, angle, pos_start, pos_end) xy = _calc_xy(xdim, ydim, pos_pivot, angle, pos_start, pos_end)
return xy return xy

430
src/wrf/latlon.py

@ -6,37 +6,218 @@ from .latlonutils import (_lat_varname, _lon_varname, _ll_to_xy, _xy_to_ll)
from .metadecorators import set_latlon_metadata from .metadecorators import set_latlon_metadata
def get_lat(wrfnc, timeidx=0, method="cat", squeeze=True, def get_lat(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
stagger=None): stagger=None):
"""Return the two dimensional latitude coordinate variable.
varname = _lat_varname(wrfnc, stagger) This functions extracts the necessary variables from the NetCDF file
lat_var = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
stagger (:obj:`str`): By default, the latitude is 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,
which has a staggered west_east (x) dimension.
- 'v': Use the same staggered grid as the v wind component,
which has a staggered south_north (y) dimension.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
two dimensional latitude coordinate 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.
"""
varname = _lat_varname(wrfin, stagger)
lat_var = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta, _key) meta, _key)
return lat_var[varname] return lat_var[varname]
def get_lon(wrfnc, timeidx=0, method="cat", squeeze=True, def get_lon(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
stagger=None): stagger=None):
"""Return the two dimensional longitude coordinate variable.
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): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
stagger (:obj:`str`): By default, the longitude is 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,
which has a staggered west_east (x) dimension.
- 'v': Use the same staggered grid as the v wind component,
which has a staggered south_north (y) dimension.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
two dimensional longitude coordinate 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.
"""
varname = _lon_varname(wrfnc, stagger) varname = _lon_varname(wrfin, stagger)
lon_var = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, lon_var = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta, _key) meta, _key)
return lon_var[varname] return lon_var[varname]
# TODO: Do we need the user to know about method, squeeze, cache for this? # TODO: Do we need the user to know about method, squeeze, cache for this?
# Can either use wrfnc as a single file or sequence, or provide
# projection parameters (which don't allow for moving domains)
@set_latlon_metadata(xy=True) @set_latlon_metadata(xy=True)
def ll_to_xy(wrfnc, latitude, longitude, timeidx=0, stagger=None, method="cat", def ll_to_xy(wrfin, latitude, longitude, timeidx=0,
squeeze=True, cache=None, meta=True, as_int=True): squeeze=True, meta=True, stagger=None, as_int=True):
_key = get_id(wrfnc) """Return the x,y coordinates for a specified latitude and longitude.
return _ll_to_xy(latitude, longitude, wrfnc, timeidx, stagger, method,
squeeze, cache, _key, as_int, **{}) 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
quantities:
- return_val[0,...] will contain the X (west_east) values.
- return_val[1,...] will contain the Y (south_north) values.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): Input WRF ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
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
of latitude values to be converted.
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.
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.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
stagger (:obj:`str`): By default, the latitude is 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,
which has a staggered west_east (x) dimension.
- 'v': Use the same staggered grid as the v wind component,
which has a staggered south_north (y) dimension.
as_int (:obj:`bool`): Set to True to return the x,y values as
:obj:`int`, otherwise they will be returned as :obj:`float`.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
_key = get_id(wrfin)
return _ll_to_xy(latitude, longitude, wrfin, timeidx, stagger, "cat",
squeeze, None, _key, as_int, **{})
@set_latlon_metadata(xy=True) @set_latlon_metadata(xy=True)
@ -45,7 +226,84 @@ def ll_to_xy_proj(latitude, longitude, meta=True, squeeze=True, as_int=True,
ref_lat=None, ref_lon=None, pole_lat=None, pole_lon=None, ref_lat=None, ref_lon=None, pole_lat=None, pole_lon=None,
known_x=None, known_y=None, dx=None, dy=None, known_x=None, known_y=None, dx=None, dy=None,
latinc=None, loninc=None): latinc=None, loninc=None):
"""Return the x, y coordinates for a specified latitude and longitude.
The *latitude* and *longitude* arguments can be a single value or a
sequence of values. This version of the ll_to_xy routine allows users
to manually specify projection parameters.
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
of latitude values to be converted.
longitude (:obj:`float` or sequence): A single longitude or a sequence
of latitude values to be converted.
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.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
as_int (:obj:`bool`): Set to True to return the x,y values as
:obj:`int`, otherwise they will be returned as :obj:`float`.
map_proj (:obj:`int`): Model projection [1=Lambert Conformal,
2=Polar Stereographic, 3=Mercator, 6=Lat-Lon]. Required.
truelat1 (:obj:`float`): True latitude 1. Required for
map_proj = 1, 2, 3 (defaults to 0 otherwise).
truelat2 (:obj:`float`): True latitude 2. Optional for
map_proj = 1 (defaults to 0 otherwise).
stand_lon (:obj:`float`): Standard longitude. Required.
ref_lat (:obj:`float`): A reference latitude. Required.
ref_lon (:obj:`float`): A reference longitude. Required.
known_x (:obj:`float`): The known x-coordinate associated with
*ref_lon*. Required.
known_y (:obj:`float`): The known y-coordinate associated with
*ref_lat*. Required.
pole_lat (:obj:`float`): Pole latitude. Optional for
*map_proj* = 6 (defaults to 90 otherwise).
pole_lon (:obj:`float`): Pole longitude. Optional for
*map_proj* = 6 (defaults to 0 otherwise).
dx (:obj:`float`): The x spacing in meters at the true latitude.
Required for *map_proj* = 1, 2, 3 (defaults to 0 otherwise).
dy (:obj:`float`) - The y spacing in meters at the true latitude.
Required for *map_proj* = 1, 2, 3 (defaults to 0 otherwise).
latinc (:obj:`float`): The lower left corner latitude at (0,0).
Required for *map_proj* = 6.
loninc (:obj:`float`) - The lower left corner longitude at (0,0).
Required for *map_proj* = 6.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
loc = locals() loc = locals()
projparams = {name : loc[name] for name in ("map_proj", "truelat1", projparams = {name : loc[name] for name in ("map_proj", "truelat1",
"truelat2", "stand_lon", "ref_lat", "truelat2", "stand_lon", "ref_lat",
@ -53,15 +311,73 @@ def ll_to_xy_proj(latitude, longitude, meta=True, squeeze=True, as_int=True,
"known_x", "known_y", "dx", "dy", "known_x", "known_y", "dx", "dy",
"latinc", "loninc")} "latinc", "loninc")}
return _ll_to_xy(latitude, longitude, None, 0, squeeze, "cat", True, None, return _ll_to_xy(latitude, longitude, None, 0, True, "cat", squeeze, None,
None, as_int, **projparams) None, as_int, **projparams)
@set_latlon_metadata(xy=False) @set_latlon_metadata(xy=False)
def xy_to_ll(wrfnc, x, y, timeidx=0, stagger=None, method="cat", squeeze=True, def xy_to_ll(wrfin, x, y, timeidx=0, stagger=None, squeeze=True, meta=True):
cache=None, meta=True): """Return the latitude and longitude for specified x,y coordinates.
_key = get_id(wrfnc)
return _xy_to_ll(x, y, wrfnc, timeidx, stagger, method, squeeze, cache, 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
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): Input 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
of x-coordinate values to be converted.
y (:obj:`float` or sequence): A single y-coordinate or a sequence
of y-coordinate values to be converted.
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.
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.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
stagger (:obj:`str`): By default, the latitude is 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,
which has a staggered west_east (x) dimension.
- 'v': Use the same staggered grid as the v wind component,
which has a staggered south_north (y) dimension.
as_int (:obj:`bool`): Set to True to return the x,y values as
:obj:`int`, otherwise they will be returned as :obj:`float`.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
_key = get_id(wrfin)
return _xy_to_ll(x, y, wrfin, timeidx, stagger, "cat", True, None,
_key, **{}) _key, **{})
@ -70,6 +386,84 @@ def xy_to_ll_proj(x, y, meta=True, squeeze=True, map_proj=None, truelat1=None,
truelat2=None, stand_lon=None, ref_lat=None, ref_lon=None, truelat2=None, stand_lon=None, ref_lat=None, ref_lon=None,
pole_lat=None, pole_lon=None, known_x=None, known_y=None, pole_lat=None, pole_lon=None, known_x=None, known_y=None,
dx=None, dy=None, latinc=None, loninc=None): dx=None, dy=None, latinc=None, loninc=None):
"""Return the latitude and longitude for the specified x,y coordinates.
The *x* and *y* arguments can be a single value or a
sequence of values. This version of the xy_to_ll routine allows users
to manually specify map projection parameters.
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:
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
of y-coordinate values to be converted.
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.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
as_int (:obj:`bool`): Set to True to return the x,y values as
:obj:`int`, otherwise they will be returned as :obj:`float`.
map_proj (:obj:`int`): Model projection [1=Lambert Conformal,
2=Polar Stereographic, 3=Mercator, 6=Lat-Lon]. Required.
truelat1 (:obj:`float`): True latitude 1. Required for
map_proj = 1, 2, 3 (defaults to 0 otherwise).
truelat2 (:obj:`float`): True latitude 2. Optional for
map_proj = 1 (defaults to 0 otherwise).
stand_lon (:obj:`float`): Standard longitude. Required.
ref_lat (:obj:`float`): A reference latitude. Required.
ref_lon (:obj:`float`): A reference longitude. Required.
known_x (:obj:`float`): The known x-coordinate associated with
*ref_lon*. Required.
known_y (:obj:`float`): The known y-coordinate associated with
*ref_lat*. Required.
pole_lat (:obj:`float`): Pole latitude. Optional for
*map_proj* = 6 (defaults to 90 otherwise).
pole_lon (:obj:`float`): Pole longitude. Optional for
*map_proj* = 6 (defaults to 0 otherwise).
dx (:obj:`float`): The x spacing in meters at the true latitude.
Required for *map_proj* = 1, 2, 3 (defaults to 0 otherwise).
dy (:obj:`float`) - The y spacing in meters at the true latitude.
Required for *map_proj* = 1, 2, 3 (defaults to 0 otherwise).
latinc (:obj:`float`): The lower left corner latitude at (0,0).
Required for *map_proj* = 6.
loninc (:obj:`float`) - The lower left corner longitude at (0,0).
Required for *map_proj* = 6.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
loc = locals() loc = locals()
projparams = {name : loc[name] for name in ("map_proj", "truelat1", projparams = {name : loc[name] for name in ("map_proj", "truelat1",
"truelat2", "stand_lon", "ref_lat", "truelat2", "stand_lon", "ref_lat",

323
src/wrf/latlonutils.py

@ -12,9 +12,32 @@ from .util import (extract_vars, extract_global_attrs,
iter_left_indexes, is_mapping, is_multi_file) iter_left_indexes, is_mapping, is_multi_file)
from .py3compat import viewkeys, viewitems from .py3compat import viewkeys, viewitems
def _lat_varname(wrfnc, stagger): 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): Input 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
following:
- 'm': Use the mass grid (default).
- '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,
which has a staggered south_north (y) dimension.
Returns:
:obj:`str`: The latitude variable name.
"""
if stagger is None or stagger.lower() == "m": if stagger is None or stagger.lower() == "m":
varname = either("XLAT", "XLAT_M")(wrfnc) varname = either("XLAT", "XLAT_M")(wrfin)
elif stagger.lower() == "u" or stagger.lower() == "v": elif stagger.lower() == "u" or stagger.lower() == "v":
varname = "XLAT_{}".format(stagger.upper()) varname = "XLAT_{}".format(stagger.upper())
else: else:
@ -22,9 +45,32 @@ def _lat_varname(wrfnc, stagger):
return varname return varname
def _lon_varname(wrfnc, stagger): 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): Input 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
following:
- 'm': Use the mass grid (default).
- '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,
which has a staggered south_north (y) dimension.
Returns:
:obj:`str`: The latitude variable name.
"""
if stagger is None or stagger.lower() == "m": if stagger is None or stagger.lower() == "m":
varname = either("XLONG", "XLONG_M")(wrfnc) varname = either("XLONG", "XLONG_M")(wrfin)
elif stagger.lower() == "u" or stagger.lower() == "v": elif stagger.lower() == "u" or stagger.lower() == "v":
varname = "XLONG_{}".format(stagger.upper()) varname = "XLONG_{}".format(stagger.upper())
else: else:
@ -32,11 +78,61 @@ def _lon_varname(wrfnc, stagger):
return varname return varname
def _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, cache, _key): 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): Input 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
all times in the file or sequence. The default is 0.
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,
which has a staggered west_east (x) dimension.
- '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.
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
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.
Default is None.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
Returns:
"""
if timeidx < 0: if timeidx < 0:
raise ValueError("'timeidx' must be greater than 0") raise ValueError("'timeidx' must be greater than 0")
attrs = extract_global_attrs(wrfnc, attrs=("MAP_PROJ", "TRUELAT1", attrs = extract_global_attrs(wrfin, attrs=("MAP_PROJ", "TRUELAT1",
"TRUELAT2", "STAND_LON", "TRUELAT2", "STAND_LON",
"DX", "DY")) "DX", "DY"))
map_proj = attrs["MAP_PROJ"] map_proj = attrs["MAP_PROJ"]
@ -47,7 +143,7 @@ def _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, cache, _key):
dy = attrs["DY"] dy = attrs["DY"]
if map_proj == ProjectionTypes.LAT_LON: if map_proj == ProjectionTypes.LAT_LON:
pole_attrs = extract_global_attrs(wrfnc, attrs=("POLE_LAT", pole_attrs = extract_global_attrs(wrfin, attrs=("POLE_LAT",
"POLE_LON")) "POLE_LON"))
pole_lat = pole_attrs["POLE_LAT"] pole_lat = pole_attrs["POLE_LAT"]
pole_lon = pole_attrs["POLE_LON"] pole_lon = pole_attrs["POLE_LON"]
@ -59,31 +155,32 @@ def _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, cache, _key):
latinc = 0.0 latinc = 0.0
loninc = 0.0 loninc = 0.0
latvar = _lat_varname(wrfnc, stagger) latvar = _lat_varname(wrfin, stagger)
lonvar = _lon_varname(wrfnc, stagger) lonvar = _lon_varname(wrfin, stagger)
lat_timeidx = timeidx lat_timeidx = timeidx
is_moving = is_moving_domain(wrfnc, 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 # Only need one file and one time if the domain is not moving
if not is_moving: if not is_moving:
if is_multi_time_req(timeidx): if is_multi_time_req(timeidx):
lat_timeidx = 0 lat_timeidx = 0
if is_multi_file(wrfnc): if is_multi_file(wrfin):
if not is_mapping(wrfnc): if not is_mapping(wrfin):
wrfnc = next(iter(wrfnc)) # only need one file wrfin = next(iter(wrfin)) # only need one file
else: else:
first_entry = next(iter(viewkeys(wrfnc))) first_entry = next(iter(viewkeys(wrfin)))
wrfnc = wrfnc[first_entry] wrfin = wrfin[first_entry]
key = _key[first_entry] key = _key[first_entry]
return _get_proj_params(wrfnc, timeidx, stagger, return _get_proj_params(wrfin, timeidx, stagger,
method, squeeze, cache, key) method, squeeze, cache, key)
xlat = extract_vars(wrfnc, lat_timeidx, (latvar,), method, squeeze, cache, xlat = extract_vars(wrfin, lat_timeidx, (latvar,), method, squeeze, cache,
meta=False, _key=_key)[latvar] meta=False, _key=_key)[latvar]
xlon = extract_vars(wrfnc, lat_timeidx, (lonvar,), method, squeeze, cache, 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_lat = np.ravel(xlat[..., 0, 0])
@ -98,10 +195,35 @@ def _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, cache, _key):
def _dict_keys_to_upper(d): 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)}
# known_x and known_y are 0-based # known_x and known_y are 0-based
def _kwarg_proj_params(**projparams): def _kwarg_proj_params(**projparams):
"""Return the map projection parameters.
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) projparams = _dict_keys_to_upper(projparams)
map_proj = projparams.get("MAP_PROJ") map_proj = projparams.get("MAP_PROJ")
@ -169,14 +291,89 @@ def _kwarg_proj_params(**projparams):
# Will return 0-based indexes # Will return 0-based indexes
def _ll_to_xy(latitude, longitude, wrfnc=None, timeidx=0, def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0,
stagger=None, method="cat", squeeze=True, cache=None, stagger=None, method="cat", squeeze=True, cache=None,
_key=None, as_int=True, **projparams): _key=None, as_int=True, **projparams):
"""Return the x,y coordinates for a specified latitude and longitude.
if wrfnc is not None: 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
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
of latitude values to be converted.
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): Input 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
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
with the following options:
- 'm': Use the mass grid (default).
- '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,
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.
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
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.
Default is None.
_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
: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
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
be a :class:`numpy.ndarray` object with no metadata.
"""
if wrfin is not None:
(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc, pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc) = _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, loninc) = _get_proj_params(wrfin, timeidx, stagger, method, squeeze,
cache, _key) cache, _key)
else: else:
(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon,
@ -255,14 +452,92 @@ def _ll_to_xy(latitude, longitude, wrfnc=None, timeidx=0,
return result return result
# X and Y should be 0-based # X and Y should be 0-based
def _xy_to_ll(x, y, wrfnc=None, timeidx=0, stagger=None, def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None,
method="cat", squeeze=True, cache=None, _key=None, method="cat", squeeze=True, cache=None, _key=None,
**projparams): **projparams):
if wrfnc is not None: """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
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): Input 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
of x-coordinate values to be converted.
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): Input 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
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
with the following options:
- 'm': Use the mass grid (default).
- '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,
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.
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
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.
Default is None.
_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
(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
be a :class:`numpy.ndarray` object with no metadata.
"""
if wrfin is not None:
(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc, pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc) = _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, loninc) = _get_proj_params(wrfin, timeidx, stagger, method, squeeze,
cache, _key) cache, _key)
else: else:
(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon,

630
src/wrf/metadecorators.py

@ -7,7 +7,7 @@ import numpy as np
import numpy.ma as ma import numpy.ma as ma
from .extension import _interpline from .extension import _interpline
from .util import (extract_vars, combine_with, either, from_args, arg_location, from .util import (extract_vars, either, from_args, arg_location,
is_coordvar, latlon_coordvars, npvalues, is_coordvar, latlon_coordvars, npvalues,
from_var, iter_left_indexes) from_var, iter_left_indexes)
from .coordpair import CoordPair from .coordpair import CoordPair
@ -22,11 +22,58 @@ if xarray_enabled():
def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None, def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None,
remove_dims=None, dimnames=None, remove_dims=None, dimnames=None,
coords=None, **fixed_attrs): coords=None, **fixed_attrs):
"""Decorator to set the metadata for a WRF method. """A decorator that sets the metadata for a wrapped function's output.
Generally, the metadata is copied from the variable specified by
*copy_varname*, with other fixed fields set by the other decorator
arguments.
The *cache* argument used by most diagnostic routines is supplied by
this decorator when the *copy_varname* variable is extracted, in order
to prevent the variable from being extracted again by the wrapped function.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
copy_varname (:obj:`str`, optional): The NetCDF variable name to copy.
Default is None.
delete_attrs (sequence of :obj:`str`, optional): A sequence of key
names to remove from the :attr:`xarray.DataArray.attrs` attribute
in the wrapped function output (after being copied from
*copy_varname*). Default is None.
name (:obj:`str`): The name to use for the
:attr:`xarray.DataArray.name` attribute.
remove_dims (sequence of :obj:`int`, optional): A sequence of dimension
indexes to be removed from the wrapped function output (after being
copied from *copy_varname*). This is useful when the copy
variable is three dimensional but the wrapped function output
is two dimensional, and you still want to keep the names of
the rightmost two dimensions. Default is None.
dimnames (sequence of :obj:`str`, optional): A sequence of dimension
names in order to manually set the
:attr:`xarray.DataArray.dims` attribute. Default is None.
coords (:obj:`dict`): A mapping of coordinate name to coordinate
value to manually specify the :attr:`xarray.DataArray.coords`
attribute. Default is None.
**fixed_attrs: These keyword arguments are added to the
:attr:`xarray.DataArray.attrs` attribute.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
function output with or without metadata. 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.
A cache is inserted/updated to include the extracted variable that will
have its metadata copied. This prevents the variable being extracted more
than once. This extraction can be slow with sequences of large files.
""" """
@wrapt.decorator @wrapt.decorator
@ -39,12 +86,12 @@ def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None,
if not xarray_enabled() or not do_meta: if not xarray_enabled() or not do_meta:
return wrapped(*args, **kwargs) return wrapped(*args, **kwargs)
argvars = from_args(wrapped, ("wrfnc", "timeidx", "method", argvars = from_args(wrapped, ("wrfin", "timeidx", "method",
"squeeze", "cache", "units", "meta", "squeeze", "cache", "units", "meta",
"_key"), "_key"),
*args, **kwargs) *args, **kwargs)
wrfnc = argvars["wrfnc"] wrfin = argvars["wrfin"]
timeidx = argvars["timeidx"] timeidx = argvars["timeidx"]
units = argvars["units"] units = argvars["units"]
method = argvars["method"] method = argvars["method"]
@ -56,7 +103,7 @@ def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None,
# Note: can't modify nonlocal var # Note: can't modify nonlocal var
if (callable(copy_varname)): if (callable(copy_varname)):
_copy_varname = copy_varname(wrfnc) _copy_varname = copy_varname(wrfin)
else: else:
_copy_varname = copy_varname _copy_varname = copy_varname
@ -66,7 +113,7 @@ def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None,
if var_to_copy is None: if var_to_copy is None:
var_to_copy = extract_vars(wrfnc, timeidx, (_copy_varname,), var_to_copy = extract_vars(wrfin, timeidx, (_copy_varname,),
method, squeeze, cache, method, squeeze, cache,
meta=True, _key=_key)[_copy_varname] meta=True, _key=_key)[_copy_varname]
@ -90,9 +137,6 @@ def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None,
outname = ucode(var_to_copy.name) outname = ucode(var_to_copy.name)
if dimnames is not None: if dimnames is not None:
if isinstance(dimnames, combine_with):
outdimnames, outcoords = dimnames(var_to_copy)
else:
outdimnames = dimnames outdimnames = dimnames
outcoords = coords outcoords = coords
else: else:
@ -140,6 +184,49 @@ def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None,
def set_wind_metadata(copy_varname, name, description, def set_wind_metadata(copy_varname, name, description,
wind_ncvar=False, wind_ncvar=False,
two_d=False, wspd_wdir=False): two_d=False, wspd_wdir=False):
"""A decorator that sets the metadata for a wrapped wind function's output.
This is a special metadata decorator for working with wind functions, which
include wind extraction routines, uvmet routines, and
wind speed / wind direction routines.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
copy_varname (:obj:`str`, optional): The NetCDF variable name to copy.
Default is None.
name (:obj:`str`): The name to use for the
:attr:`xarray.DataArray.name` attribute.
description (:obj:`str`): The description to use for the 'description'
key in the :attr:`xarray.DataArray.attrs` attribute.
wind_ncvar (:obj:`bool`, optional): Set to True when the wrapped
function is simply extracting a wind variable (U, V, W) from the
NetCDF file. Set to False for other types of wind algorithms
(uvmet, wspd_wdir, etc). Default is False.
two_d (:obj:`bool`, optional): Set to True if the wind field is
two-dimensional. Set to False for a three-dimensional wind field.
Default is False.
wspd_wdir (:obj:`bool`): Set to True if the wrapped function is a
wind speed / wind direction algorithm. Otherwise, set to False.
Default is False.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
wind function output with or without metadata. 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.
"""
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"]
@ -150,11 +237,11 @@ def set_wind_metadata(copy_varname, name, description,
if not xarray_enabled() or not do_meta: if not xarray_enabled() or not do_meta:
return wrapped(*args, **kwargs) return wrapped(*args, **kwargs)
argvars = from_args(wrapped, ("wrfnc", "timeidx", "units", argvars = from_args(wrapped, ("wrfin", "timeidx", "units",
"method", "squeeze", "ten_m", "cache", "method", "squeeze", "ten_m", "cache",
"_key"), "_key"),
*args, **kwargs) *args, **kwargs)
wrfnc = argvars["wrfnc"] wrfin = argvars["wrfin"]
timeidx = argvars["timeidx"] timeidx = argvars["timeidx"]
units = argvars["units"] units = argvars["units"]
method = argvars["method"] method = argvars["method"]
@ -166,11 +253,11 @@ def set_wind_metadata(copy_varname, name, description,
cache = {} cache = {}
if isinstance(copy_varname, either): if isinstance(copy_varname, either):
_copy_varname = copy_varname(wrfnc) _copy_varname = copy_varname(wrfin)
else: else:
_copy_varname = copy_varname _copy_varname = copy_varname
copy_var = extract_vars(wrfnc, timeidx, _copy_varname, copy_var = extract_vars(wrfin, timeidx, _copy_varname,
method, squeeze, cache, method, squeeze, cache,
meta=True, _key=_key)[_copy_varname] meta=True, _key=_key)[_copy_varname]
@ -236,6 +323,28 @@ def set_wind_metadata(copy_varname, name, description,
return func_wrapper return func_wrapper
def set_cape_metadata(is2d): def set_cape_metadata(is2d):
"""A decorator that sets the metadata for a wrapped CAPE function's output.
This is a special metadata decorator for working with CAPE functions.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
is2d (:obj:`bool`): Set to True if the wrapped function is for a
two-dimensional CAPE routine. Set to False for a
three-dimensional CAPE routine.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
CAPE function output with or without metadata. 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.
"""
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"]
@ -246,10 +355,10 @@ def set_cape_metadata(is2d):
if not xarray_enabled() or not do_meta: if not xarray_enabled() or not do_meta:
return wrapped(*args, **kwargs) return wrapped(*args, **kwargs)
argvars = from_args(wrapped, ("wrfnc", "timeidx", "method", "squeeze", argvars = from_args(wrapped, ("wrfin", "timeidx", "method", "squeeze",
"cache", "_key", "missing"), "cache", "_key", "missing"),
*args, **kwargs) *args, **kwargs)
wrfnc = argvars["wrfnc"] wrfin = argvars["wrfin"]
timeidx = argvars["timeidx"] timeidx = argvars["timeidx"]
method = argvars["method"] method = argvars["method"]
squeeze = argvars["squeeze"] squeeze = argvars["squeeze"]
@ -260,7 +369,7 @@ def set_cape_metadata(is2d):
cache = {} cache = {}
_copy_varname = "P" _copy_varname = "P"
copy_var = extract_vars(wrfnc, timeidx, _copy_varname, method, squeeze, copy_var = extract_vars(wrfin, timeidx, _copy_varname, method, squeeze,
cache, meta=True, _key=_key)[_copy_varname] cache, meta=True, _key=_key)[_copy_varname]
# Make a copy so we don't modify a user supplied cache # Make a copy so we don't modify a user supplied cache
@ -330,6 +439,24 @@ def set_cape_metadata(is2d):
def set_cloudfrac_metadata(): def set_cloudfrac_metadata():
"""A decorator that sets the metadata for a wrapped cloud fraction
function's output.
This is a special metadata decorator for working with cloud fraction
functions.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
cloud fraction function output with or without metadata. 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.
"""
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"]
@ -340,10 +467,10 @@ def set_cloudfrac_metadata():
if not xarray_enabled() or not do_meta: if not xarray_enabled() or not do_meta:
return wrapped(*args, **kwargs) return wrapped(*args, **kwargs)
argvars = from_args(wrapped, ("wrfnc", "timeidx", "method", "squeeze", argvars = from_args(wrapped, ("wrfin", "timeidx", "method", "squeeze",
"cache", "_key"), "cache", "_key"),
*args, **kwargs) *args, **kwargs)
wrfnc = argvars["wrfnc"] wrfin = argvars["wrfin"]
timeidx = argvars["timeidx"] timeidx = argvars["timeidx"]
method = argvars["method"] method = argvars["method"]
squeeze = argvars["squeeze"] squeeze = argvars["squeeze"]
@ -353,7 +480,7 @@ def set_cloudfrac_metadata():
cache = {} cache = {}
_copy_varname = "P" _copy_varname = "P"
copy_var = extract_vars(wrfnc, timeidx, _copy_varname, method, squeeze, copy_var = extract_vars(wrfin, timeidx, _copy_varname, method, squeeze,
cache, meta=True, _key=_key)[_copy_varname] cache, meta=True, _key=_key)[_copy_varname]
# Make a copy so we don't modify a user supplied cache # Make a copy so we don't modify a user supplied cache
@ -403,6 +530,29 @@ def set_cloudfrac_metadata():
return func_wrapper return func_wrapper
def set_latlon_metadata(xy=False): def set_latlon_metadata(xy=False):
"""A decorator that sets the metadata for a wrapped latlon function's
output.
This is a special metadata decorator for working with latlon functions.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
xy (:obj:`bool`, optional): Set to True if the wrapped function returns
xy values (ll_to_xy). Set to False if the wrapped function returns
latlon values (xy_to_ll). Default is False.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
latlon function output with or without metadata. 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.
"""
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
@ -465,6 +615,29 @@ def set_latlon_metadata(xy=False):
return func_wrapper return func_wrapper
def set_height_metadata(geopt=False): def set_height_metadata(geopt=False):
"""A decorator that sets the metadata for a wrapped height function's
output.
This is a special metadata decorator for working with height functions.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
geopt (:obj:`bool`, optional): Set to True if the wrapped function
returns geopotential. Set to True if the wrapped function
returns geopotential height. Default is False.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
height function output with or without metadata. 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.
"""
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"]
@ -475,11 +648,11 @@ def set_height_metadata(geopt=False):
if not xarray_enabled() or not do_meta: if not xarray_enabled() or not do_meta:
return wrapped(*args, **kwargs) return wrapped(*args, **kwargs)
argvars = from_args(wrapped, ("wrfnc", "timeidx", "method", argvars = from_args(wrapped, ("wrfin", "timeidx", "method",
"squeeze", "units", "msl", "cache", "squeeze", "units", "msl", "cache",
"_key"), "_key"),
*args, **kwargs) *args, **kwargs)
wrfnc = argvars["wrfnc"] wrfin = argvars["wrfin"]
timeidx = argvars["timeidx"] timeidx = argvars["timeidx"]
units = argvars["units"] units = argvars["units"]
method = argvars["method"] method = argvars["method"]
@ -493,8 +666,8 @@ def set_height_metadata(geopt=False):
# For height, either copy the met_em GHT variable or copy and modify # For height, either copy the met_em GHT variable or copy and modify
# pressure (which has the same dims as destaggered height) # pressure (which has the same dims as destaggered height)
ht_metadata_varname = either("P", "GHT")(wrfnc) ht_metadata_varname = either("P", "GHT")(wrfin)
ht_var = extract_vars(wrfnc, timeidx, ht_metadata_varname, ht_var = extract_vars(wrfin, timeidx, ht_metadata_varname,
method, squeeze, cache, meta=True, method, squeeze, cache, meta=True,
_key=_key) _key=_key)
ht_metadata_var = ht_var[ht_metadata_varname] ht_metadata_var = ht_var[ht_metadata_varname]
@ -532,12 +705,45 @@ def set_height_metadata(geopt=False):
return func_wrapper return func_wrapper
def _set_horiz_meta(wrapped, instance, args, kwargs): def _set_horiz_meta(wrapped, instance, args, kwargs):
argvars = from_args(wrapped, ("field3d", "z", "desiredlev", """A decorator implementation that sets the metadata for a wrapped
horizontal interpolation function.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
wrapped: The wrapped function which in turns needs to be called by your
wrapper function.
instance: The object to which the wrapped function was bound when it
was called.
args: The list of positional arguments supplied when the decorated
function was called.
kwargs: The dictionary of keyword arguments supplied when the decorated
function was called.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
horiztontal interpolation function output with or without metadata.
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.
See Also:
:mod:`wrapt`
"""
argvars = from_args(wrapped, ("field3d", "vert", "desiredlev",
"missing"), "missing"),
*args, **kwargs) *args, **kwargs)
field3d = argvars["field3d"] field3d = argvars["field3d"]
z = argvars["z"] z = argvars["vert"]
desiredloc = argvars["desiredlev"] desiredloc = argvars["desiredlev"]
missingval = argvars["missing"] missingval = argvars["missing"]
@ -591,14 +797,47 @@ def _set_horiz_meta(wrapped, instance, args, kwargs):
coords=outcoords, attrs=outattrs) coords=outcoords, attrs=outattrs)
def _set_cross_meta(wrapped, instance, args, kwargs): def _set_cross_meta(wrapped, instance, args, kwargs):
argvars = from_args(wrapped, ("field3d", "z", "latlon", "missing", """A decorator implementation that sets the metadata for a wrapped cross \
section interpolation function.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
wrapped: The wrapped function which in turns needs to be called by your
wrapper function.
instance: The object to which the wrapped function was bound when it
was called.
args: The list of positional arguments supplied when the decorated
function was called.
kwargs: The dictionary of keyword arguments supplied when the decorated
function was called.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
cross section interpolation function output with or without metadata.
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.
See Also:
:mod:`wrapt`
"""
argvars = from_args(wrapped, ("field3d", "vert", "latlon", "missing",
"pivot_point", "angle", "pivot_point", "angle",
"start_point", "end_point", "start_point", "end_point",
"cache"), "cache"),
*args, **kwargs) *args, **kwargs)
field3d = argvars["field3d"] field3d = argvars["field3d"]
z = argvars["z"] z = argvars["vert"]
inc_latlon = argvars["latlon"] inc_latlon = argvars["latlon"]
missingval = argvars["missing"] missingval = argvars["missing"]
pivot_point = argvars["pivot_point"] pivot_point = argvars["pivot_point"]
@ -737,6 +976,39 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
def _set_line_meta(wrapped, instance, args, kwargs): def _set_line_meta(wrapped, instance, args, kwargs):
"""A decorator implementation that sets the metadata for a wrapped line
interpolation function.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
wrapped: The wrapped function which in turns needs to be called by your
wrapper function.
instance: The object to which the wrapped function was bound when it
was called.
args: The list of positional arguments supplied when the decorated
function was called.
kwargs: The dictionary of keyword arguments supplied when the decorated
function was called.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
line interpolation function output with or without metadata.
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.
See Also:
:mod:`wrapt`
"""
argvars = from_args(wrapped, ("field2d", "pivot_point", "angle", argvars = from_args(wrapped, ("field2d", "pivot_point", "angle",
"start_point", "end_point", "latlon", "start_point", "end_point", "latlon",
"cache"), "cache"),
@ -871,7 +1143,41 @@ def _set_line_meta(wrapped, instance, args, kwargs):
def _set_vinterp_meta(wrapped, instance, args, kwargs): def _set_vinterp_meta(wrapped, instance, args, kwargs):
argvars = from_args(wrapped, ("wrfnc", "field", "vert_coord", """A decorator implementation that sets the metadata for a wrapped
vertical coordinate interpolation function.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
wrapped: The wrapped function which in turns needs to be called by your
wrapper function.
instance: The object to which the wrapped function was bound when it
was called.
args: The list of positional arguments supplied when the decorated
function was called.
kwargs: The dictionary of keyword arguments supplied when the decorated
function was called.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
vertical coordinate interpolation function output with or without
metadata.
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.
See Also:
:mod:`wrapt`
"""
argvars = from_args(wrapped, ("wrfin", "field", "vert_coord",
"interp_levels", "extrapolate", "interp_levels", "extrapolate",
"field_type", "log_p", "field_type", "log_p",
"timeidx", "method", "squeeze", "timeidx", "method", "squeeze",
@ -917,6 +1223,40 @@ def _set_vinterp_meta(wrapped, instance, args, kwargs):
def _set_2dxy_meta(wrapped, instance, args, kwargs): def _set_2dxy_meta(wrapped, instance, args, kwargs):
"""A decorator implementation that sets the metadata for a wrapped line
cross section interpolation function.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
wrapped: The wrapped function which in turns needs to be called by your
wrapper function.
instance: The object to which the wrapped function was bound when it
was called.
args: The list of positional arguments supplied when the decorated
function was called.
kwargs: The dictionary of keyword arguments supplied when the decorated
function was called.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
line cross section interpolation function output with or without
metadata.
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.
See Also:
:mod:`wrapt`
"""
argvars = from_args(wrapped, ("field3d", "xy"), *args, **kwargs) argvars = from_args(wrapped, ("field3d", "xy"), *args, **kwargs)
field3d = argvars["field3d"] field3d = argvars["field3d"]
@ -989,6 +1329,39 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs):
def _set_1d_meta(wrapped, instance, args, kwargs): def _set_1d_meta(wrapped, instance, args, kwargs):
"""A decorator implementation that sets the metadata for a wrapped 1D
interpolation function.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
wrapped: The wrapped function which in turns needs to be called by your
wrapper function.
instance: The object to which the wrapped function was bound when it
was called.
args: The list of positional arguments supplied when the decorated
function was called.
kwargs: The dictionary of keyword arguments supplied when the decorated
function was called.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
1D interpolation function output with or without metadata.
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.
See Also:
:mod:`wrapt`
"""
argvars = from_args(wrapped, ("field", "z_in", "z_out", "missingval"), argvars = from_args(wrapped, ("field", "z_in", "z_out", "missingval"),
*args, **kwargs) *args, **kwargs)
@ -1042,6 +1415,39 @@ def _set_1d_meta(wrapped, instance, args, kwargs):
def _set_xy_meta(wrapped, instance, args, kwargs): def _set_xy_meta(wrapped, instance, args, kwargs):
"""A decorator implementation that sets the metadata for a wrapped xy line
interpolation function.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
wrapped: The wrapped function which in turns needs to be called by your
wrapper function.
instance: The object to which the wrapped function was bound when it
was called.
args: The list of positional arguments supplied when the decorated
function was called.
kwargs: The dictionary of keyword arguments supplied when the decorated
function was called.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
xy line interpolation function output with or without metadata.
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.
See Also:
:mod:`wrapt`
"""
argvars = from_args(wrapped, ("field", "pivot_point", "angle", argvars = from_args(wrapped, ("field", "pivot_point", "angle",
"start_point", "end_point"), "start_point", "end_point"),
*args, **kwargs) *args, **kwargs)
@ -1078,6 +1484,27 @@ def _set_xy_meta(wrapped, instance, args, kwargs):
def set_interp_metadata(interp_type): def set_interp_metadata(interp_type):
"""A decorator that sets the metadata for a wrapped interpolation
function.
If the wrapped function's *meta* argument is False, then this decorator
returns the wrapped function output without applying the metadata.
Args:
interp_type (:obj:`str`): The type of interpolation routine. Choices
are: 'horiz', 'cross', 'line', 'vinterp', '2dxy', '1d',
'xy'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
interpolation function output with or without metadata.
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.
"""
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"]
@ -1110,19 +1537,51 @@ def set_alg_metadata(alg_ndims, refvarname,
refvarndims=None, missingarg=None, refvarndims=None, missingarg=None,
stagdim=None, stagsubvar=None, stagdim=None, stagsubvar=None,
units=None, description=None): units=None, description=None):
""" """A decorator that sets the metadata for a wrapped raw diagnostic
alg_ndims: number of dimensions returned by the algorithm function.
refvarndims: number of right dimensions for the refernce var, used
when the result has less dimensions than reference
refvarname: argument name for the reference variable
missingarg: argument name for the missing value
stagdim: staggered dimension in reference
stagsubvar: the variable name to use to supply the unstaggered
dimension size
Args:
""" alg_ndims (:obj:`int`): The number of dimensions returned by the
wrapped function.
refvarname (:obj:`str`): The wrapped function argument name for the
reference variable.
refvarndims (:obj:`int`, optional): The number of right dimensions for
the reference variable. This paramter is required when the
wrapped function result has less dimensions than reference.
Default is None.
missingarg (:obj:`str`, optional): The wrapped function argument name
for the missing value variable. Default is None.
stagdim (:obj`int`, optional): The staggered dimension for the
reference. This is only needed if the reference variable is
on a staggered grid. Default is None.
stagsubvar (:obj:`str`, optional): The wrapped function argument name
to use to supply the unstaggered dimension name for the staggered
dimension in the reference. This is needed if *stagdim* is not
None. It is primarily used for absolute vorticity. Default is None.
units (:obj:`str`, optional): The units to use if if there is no
'units' argument for the wrapped function. Default is None.
description (:obj:`str`, optional): A description for the wrapped
algorithm, which is stored in the :attr:`xarray.DataArray.attrs`
attribute under the 'description' key. Default is None.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
numerical function output with or without metadata.
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.
"""
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"]
@ -1161,6 +1620,13 @@ def set_alg_metadata(alg_ndims, refvarname,
else: else:
outattrs["units"] = units outattrs["units"] = units
else:
# Check for a units argument, if not, just ignore
_units = from_args(wrapped, ("units",), *args, **kwargs)["units"]
if _units is not None:
outattrs["units"] = _units
if description is not None: if description is not None:
if isinstance(description, from_var): if isinstance(description, from_var):
desc = description(wrapped, *args, **kwargs) desc = description(wrapped, *args, **kwargs)
@ -1224,9 +1690,35 @@ def set_alg_metadata(alg_ndims, refvarname,
return func_wrapper return func_wrapper
def set_uvmet_alg_metadata(units="m s-1", description="earth rotated u,v", def set_uvmet_alg_metadata(units=None, description="earth rotated u,v",
latarg="lat", windarg="u"): latarg="lat", windarg="u"):
"""A decorator that sets the metadata for the wrapped raw UVMET diagnostic
function.
Args:
units (:obj:`str`, optional): The units to use if if there is no
'units' argument for the wrapped function. Default is None.
description (:obj:`str`, optional): A description for the wrapped
algorithm, which is stored in the :attr:`xarray.DataArray.attrs`
attribute under the 'description' key. Default is None.
latarg (:obj:'str`, optional): The wrapped function argument name for
latitude. Default is 'lat'.
windarg (:obj:`str`, optional): The wrapped function argument name for
the u wind component. Default is 'u'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
UVMET function output with or without metadata.
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.
"""
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"]
@ -1247,6 +1739,10 @@ def set_uvmet_alg_metadata(units="m s-1", description="earth rotated u,v",
if units is not None: if units is not None:
outattrs["units"] = units outattrs["units"] = units
else:
_units = from_args(wrapped, ("units",), *args, **kwargs)["units"]
if _units is not None:
outattrs["units"] = _units
if description is not None: if description is not None:
outattrs["description"] = description outattrs["description"] = description
@ -1254,7 +1750,7 @@ def set_uvmet_alg_metadata(units="m s-1", description="earth rotated u,v",
latvar = from_args(wrapped, latarg, *args, **kwargs)[latarg] latvar = from_args(wrapped, latarg, *args, **kwargs)[latarg]
uvar = from_args(wrapped, windarg, *args, **kwargs)[windarg] uvar = from_args(wrapped, windarg, *args, **kwargs)[windarg]
if isinstance(uvar, DataArray): if isinstance(uvar, DataArray) and isinstance(latvar, DataArray):
# Right dims come from latvar # Right dims come from latvar
outdims[-2:] = latvar.dims[-2:] outdims[-2:] = latvar.dims[-2:]
@ -1275,7 +1771,26 @@ def set_uvmet_alg_metadata(units="m s-1", description="earth rotated u,v",
def set_cape_alg_metadata(is2d, copyarg="pres_hpa"): def set_cape_alg_metadata(is2d, copyarg="pres_hpa"):
"""A decorator that sets the metadata for the wrapped raw CAPE diagnostic
function.
Args:
is2d (:obj:`bool`): Set to True for the two-dimensional CAPE
calculation, False for three-dimensional CAPE.
copyarg (:obj:`str`): The wrapped function argument to use for
copying dimension names. Default is 'pres_hpa'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
CAPE function output with or without metadata.
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.
"""
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"]
@ -1342,6 +1857,23 @@ def set_cape_alg_metadata(is2d, copyarg="pres_hpa"):
def set_cloudfrac_alg_metadata(copyarg="pres"): def set_cloudfrac_alg_metadata(copyarg="pres"):
"""A decorator that sets the metadata for the wrapped raw cloud fraction
diagnostic function.
Args:
copyarg (:obj:`str`): The wrapped function argument to use for
copying dimension names. Default is 'pres'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
cloud fraction function output with or without metadata.
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.
"""
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
@ -1389,6 +1921,18 @@ def set_cloudfrac_alg_metadata(copyarg="pres"):
def set_destag_metadata(): def set_destag_metadata():
"""A decorator that sets the metadata for the wrapped raw destaggering
function.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wrapped
destaggering function output with or without metadata.
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.
"""
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):

56
src/wrf/omega.py

@ -11,10 +11,62 @@ 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", description="omega",
units="Pa s-1") units="Pa s-1")
def get_omega(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_omega(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
"""Return Omega.
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): Input 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
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.
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
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.
Default is None.
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
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:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "W", "PB", "QVAPOR") varnames=("T", "P", "W", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]
p = ncvars["P"] p = ncvars["P"]

10
src/wrf/precip.py

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

128
src/wrf/pressure.py

@ -9,30 +9,140 @@ 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") description="pressure")
@convert_units("pressure", "pa") @convert_units("pressure", "pa")
def get_pressure(wrfnc, timeidx=0, method="cat", squeeze=True, def get_pressure(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="Pa"): units="Pa"):
varname = either("P", "PRES")(wrfnc) """Return the pressure in the specified units.
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): Input 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
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.
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
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.
Default is None.
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
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
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:`numpy.ndarray` object with no metadata.
"""
varname = either("P", "PRES")(wrfin)
if varname == "P": if varname == "P":
p_vars = extract_vars(wrfnc, timeidx, ("P", "PB"), p_vars = extract_vars(wrfin, timeidx, ("P", "PB"),
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)
p = p_vars["P"] p = p_vars["P"]
pb = p_vars["PB"] pb = p_vars["PB"]
pres = p + pb pres = p + pb
else: else:
pres = extract_vars(wrfnc, timeidx, "PRES", pres = extract_vars(wrfin, timeidx, "PRES",
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key)["PRES"] _key=_key)["PRES"]
return pres return pres
def get_pressure_hpa(wrfnc, timeidx=0, method="cat", squeeze=True, def get_pressure_hpa(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None):
units="hPa"): """Return the pressure in [hPa].
return get_pressure(wrfnc, timeidx, method, squeeze, cache, meta, _key,
units) 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): Input 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
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.
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
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.
Default is None.
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
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:`numpy.ndarray` object with no metadata.
"""
return get_pressure(wrfin, timeidx, method, squeeze, cache, meta, _key,
units="hPa")

461
src/wrf/projection.py

@ -18,11 +18,39 @@ if pyngl_enabled():
if cartopy_enabled(): if cartopy_enabled():
class MercatorWithLatTS(crs.Mercator): class MercatorWithLatTS(crs.Mercator):
"""A :class:`cartopy.crs.Mercator` subclass that adds support for
a latitude of true scale parameter.
See Also:
:class:`cartopy.crs.Mercator`
"""
def __init__(self, central_longitude=0.0, def __init__(self, central_longitude=0.0,
latitude_true_scale=0.0, latitude_true_scale=0.0,
min_latitude=-80.0, min_latitude=-80.0,
max_latitude=84.0, max_latitude=84.0,
globe=None): globe=None):
"""Initialize a :class:`wrf.MercatorWithLatTS` object.
Args:
central_longitude (:obj:`float`, optional): The central
longitude. Default is 0.0.
latitude_true_scale (:obj:`float`, optional): The latitude
of true scale. Default is 0.0.
min_latitude (:obj:`float`, optional): The maximum southerly
extent of the projection. Default is -80.0.
max_latitude (:obj:`float`, optional): The maximum northerly
extent of the projection. Default is 84.0..
globe (:class:`cartopy.crs.Globe`, optional): A globe object.
If omitted, a default globe is created.
"""
proj4_params = [("proj", "merc"), proj4_params = [("proj", "merc"),
("lon_0", central_longitude), ("lon_0", central_longitude),
("lat_ts", latitude_true_scale), ("lat_ts", latitude_true_scale),
@ -51,11 +79,83 @@ if cartopy_enabled():
self._threshold = np.diff(self.x_limits)[0] / 720 self._threshold = np.diff(self.x_limits)[0] / 720
def _ismissing(val): def _ismissing(val):
"""Return True if a value is None, greater than 90.0, or less than -90.
This function is used to check for invalid latitude values.
Args:
val (numeric): A numeric value.
Returns:
:obj:`bool`: True if the value is None, greater than 90.0, or less
than -90.0. Otherwise, False is returned.
"""
return val is None or val > 90. or val < -90. return val is None or val > 90. or val < -90.
class WrfProj(object): class WrfProj(object):
"""A base class for storing map projection information from WRF data.
Subclasses of this type will be stored in the 'projection' attribute
entry within a :attr:`xarray.DataArray.attrs` dictionary. This base class
contains the methods required to extract the appropriate projection class
for PyNGL, matplotlib basemap, and cartopy.
Attributes:
ll_lat (:obj:`float): Lower left corner latitude.
ll_lat (:obj:`float): Lower left corner longitude.
ur_lat (:obj:`float): Upper right corner latitude.
ur_lon (:obj:`float): Upper right corner longitude.
bottom_left (indexable sequence): A pair of (ll_lat, ll_lon).
top_right (indexable sequence): A pair of (ur_lat, ur_lon).
"""
def __init__(self, bottom_left=None, top_right=None, def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params): lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.WrfProj` object.
Args:
bottom_left (indexable sequence, optional): The lower left corner
as a (latitude, longitude) pair. Must also specify *top_right*
if used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
- 'MAP_PROJ': The map projection type as an integer.
- 'CEN_LAT': Center latitude.
- 'CEN_LON': Center longitude.
- 'TRUELAT1': True latitude 1.
- 'TRUELAT2': True latitude 2.
- 'MOAD_CEN_LAT': Mother of all domains center latitude.
- 'STAND_LON': Standard longitude.
- 'POLE_LAT': Pole latitude.
- 'POLE_LON': Pole longitude.
"""
if bottom_left is not None and top_right is not None: if bottom_left is not None and top_right is not None:
self.ll_lat = bottom_left[0] self.ll_lat = bottom_left[0]
self.ll_lon = bottom_left[1] self.ll_lon = bottom_left[1]
@ -119,11 +219,31 @@ class WrfProj(object):
semiminor_axis=Constants.WRF_EARTH_RADIUS)) semiminor_axis=Constants.WRF_EARTH_RADIUS))
def cartopy_xlim(self): def cartopy_xlim(self):
"""Return the x extents in projected coordinates (for cartopy)""" """Return the x extents in projected coordinates for cartopy.
Returns:
:obj:`list`: A pair of [xmin, xmax].
See Also:
:mod:`cartopy`, :mod:`matplotlib`
"""
return self._cart_extents()[0] return self._cart_extents()[0]
def cartopy_ylim(self): def cartopy_ylim(self):
"""Return the y extents in projected coordinates (for cartopy)""" """Return the y extents in projected coordinates for cartopy.
Returns:
:obj:`list`: A pair of [ymin, ymax].
See Also:
:mod:`cartopy`, :mod:`matplotlib`
"""
return self._cart_extents()[1] return self._cart_extents()[1]
def __repr__(self): def __repr__(self):
@ -138,41 +258,102 @@ class WrfProj(object):
return "{}({})".format(self.__class__.__name__, args) return "{}({})".format(self.__class__.__name__, args)
def basemap(self, resolution='l'): def basemap(self, resolution='l'):
"""Return a mpl_toolkits.basemap.Basemap instance for the """Return a :class:`matplotlib.mpl_toolkits.basemap.Basemap` object
projection""" for the map projection.
Arguments:
resolution (:obj:`str`): The map resolution type.
Returns:
:class:`matplotlib.mpl_toolkits.basemap.Basemap`: A Basemap
object for the projection.
See Also:
:class:`matplotlib.mpl_toolkits.basemap.Basemap`
"""
if not basemap_enabled(): if not basemap_enabled():
raise RuntimeError("'mpl_toolkits.basemap' is not " raise RuntimeError("'mpl_toolkits.basemap' is not "
"installed or is disabled") "installed or is disabled")
return self._basemap(resolution) return self._basemap(resolution)
def cartopy(self): def cartopy(self):
"""Return a cartopy.crs.Projection subclass for the """Return a :class:`cartopy.crs.Projection` subclass for the
projection""" map projection.
Returns:
:class:`cartopy.crs.Projection`: A Projection subclass for the
map projection.
See Also:
:class:`cartopy.crs.Projection`
"""
if not cartopy_enabled(): if not cartopy_enabled():
raise RuntimeError("'cartopy' is not " raise RuntimeError("'cartopy' is not "
"installed or is disabled") "installed or is disabled")
return self._cartopy() return self._cartopy()
def pyngl(self): def pyngl(self):
"""Return the PyNGL resources for the projection""" """Return a :class:`Ngl.Resources` object for the map projection.
Returns:
:class:`Ngl.Resources`: A dict-like object that contains the
PyNGL resources for the map projection.
See Also:
`PyNGL <https://www.pyngl.ucar.edu/>`_
"""
if not pyngl_enabled(): if not pyngl_enabled():
raise RuntimeError("'pyngl' is not " raise RuntimeError("'pyngl' is not "
"installed or is disabled") "installed or is disabled")
return self._pyngl() return self._pyngl()
def proj4(self): def proj4(self):
"""Return the proj4 string for the map projection""" """Return the PROJ.4 string for the map projection.
Returns:
:obj:`str`: A string suitable for use with the PROJ.4 library.
See Also:
PROJ.4 <https://trac.osgeo.org/proj/>`_
"""
return self._proj4() return self._proj4()
def cf(self): def cf(self):
"""Return a dictionary with the NetCDF CF parameters for the """Return a dictionary with the NetCDF CF parameters for the
projection""" projection.
Returns:
:obj:`dict`: A dictionary with the NetCDF CF parameter names and
projection parameter values.
"""
return self._cf_params() return self._cf_params()
# Used for 'missing' projection values during the 'join' method # Used for 'missing' projection values during the 'join' method
class NullProjection(WrfProj): class NullProjection(WrfProj):
"""A :class:`wrf.WrfProj` subclass for empty projections.
The :class:`NullProjection` is primarily used for creating missing
projections when using the 'join' method.
"""
def __init__(self): def __init__(self):
"""Initialize a :class:`wrf.NullProjection` object."""
pass pass
def __repr__(self): def __repr__(self):
@ -180,8 +361,51 @@ class NullProjection(WrfProj):
class LambertConformal(WrfProj): class LambertConformal(WrfProj):
"""A :class:`wrf.WrfProj` subclass for Lambert Conformal Conic projections.
See Also:
:class:`wrf.WrfProj`, :class:`wrf.LatLon`,
:class:`wrf.PolarStereographic`,
:class:`Mercator`, :class:`RotatedLatLon`
"""
def __init__(self, bottom_left=None, top_right=None, def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params): lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.LambertConformal` object.
Args:
bottom_left (indexable sequence, optional): The lower left corner
as a (latitude, longitude) pair. Must also specify *top_right*
if used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
- 'CEN_LAT': Center latitude.
- 'CEN_LON': Center longitude.
- 'TRUELAT1': True latitude 1.
- 'TRUELAT2': True latitude 2.
- 'MOAD_CEN_LAT': Mother of all domains center latitude.
- 'STAND_LON': Standard longitude.
- 'POLE_LAT': Pole latitude.
- 'POLE_LON': Pole longitude.
"""
super(LambertConformal, self).__init__(bottom_left, super(LambertConformal, self).__init__(bottom_left,
top_right, lats, lons, **proj_params) top_right, lats, lons, **proj_params)
@ -283,8 +507,51 @@ class LambertConformal(WrfProj):
return _proj4 return _proj4
class Mercator(WrfProj): class Mercator(WrfProj):
"""A :class:`wrf.WrfProj` subclass for Mercator projections.
See Also:
:class:`wrf.WrfProj`, :class:`wrf.LatLon`,
:class:`wrf.PolarStereographic`,
:class:`RotatedLatLon`, :class:`LambertConformal`
"""
def __init__(self, bottom_left=None, top_right=None, def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params): lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.Mercator` object.
Args:
bottom_left (indexable sequence, optional): The lower left corner
as a (latitude, longitude) pair. Must also specify *top_right*
if used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
- 'CEN_LAT': Center latitude.
- 'CEN_LON': Center longitude.
- 'TRUELAT1': True latitude 1.
- 'TRUELAT2': True latitude 2.
- 'MOAD_CEN_LAT': Mother of all domains center latitude.
- 'STAND_LON': Standard longitude.
- 'POLE_LAT': Pole latitude.
- 'POLE_LON': Pole longitude.
"""
super(Mercator, self).__init__(bottom_left, top_right, super(Mercator, self).__init__(bottom_left, top_right,
lats, lons, **proj_params) lats, lons, **proj_params)
@ -383,8 +650,52 @@ class Mercator(WrfProj):
return _proj4 return _proj4
class PolarStereographic(WrfProj): class PolarStereographic(WrfProj):
"""A :class:`wrf.WrfProj` subclass for Polar Stereographic projections.
See Also:
:class:`wrf.WrfProj`, :class:`wrf.LatLon`,
:class:`wrf.RotatedLatLon`,
:class:`Mercator`, :class:`LambertConformal`
"""
def __init__(self, bottom_left=None, top_right=None, def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params): lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.PolarStereographic` object.
Args:
bottom_left (indexable sequence, optional): The lower left corner
as a (latitude, longitude) pair. Must also specify *top_right*
if used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
- 'CEN_LAT': Center latitude.
- 'CEN_LON': Center longitude.
- 'TRUELAT1': True latitude 1.
- 'TRUELAT2': True latitude 2.
- 'MOAD_CEN_LAT': Mother of all domains center latitude.
- 'STAND_LON': Standard longitude.
- 'POLE_LAT': Pole latitude.
- 'POLE_LON': Pole longitude.
"""
super(PolarStereographic, self).__init__(bottom_left, super(PolarStereographic, self).__init__(bottom_left,
top_right, lats, lons, **proj_params) top_right, lats, lons, **proj_params)
self._hemi = -90. if self.truelat1 < 0 else 90. self._hemi = -90. if self.truelat1 < 0 else 90.
@ -482,8 +793,51 @@ class PolarStereographic(WrfProj):
class LatLon(WrfProj): class LatLon(WrfProj):
"""A :class:`wrf.WrfProj` subclass for Lat Lon projections.
See Also:
:class:`wrf.WrfProj`, :class:`wrf.RotatedLatLon`,
:class:`wrf.PolarStereographic`,
:class:`Mercator`, :class:`LambertConformal`
"""
def __init__(self, bottom_left=None, top_right=None, def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params): lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.LatLon` object.
Args:
bottom_left (indexable sequence, optional): The lower left corner
as a (latitude, longitude) pair. Must also specify *top_right*
if used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
- 'CEN_LAT': Center latitude.
- 'CEN_LON': Center longitude.
- 'TRUELAT1': True latitude 1.
- 'TRUELAT2': True latitude 2.
- 'MOAD_CEN_LAT': Mother of all domains center latitude.
- 'STAND_LON': Standard longitude.
- 'POLE_LAT': Pole latitude.
- 'POLE_LON': Pole longitude.
"""
super(LatLon, self).__init__(bottom_left, top_right, super(LatLon, self).__init__(bottom_left, top_right,
lats, lons, **proj_params) lats, lons, **proj_params)
@ -563,8 +917,7 @@ class LatLon(WrfProj):
# 4) In basemap, lon_0 should be set to the central (standard) longitude. # 4) In basemap, lon_0 should be set to the central (standard) longitude.
# 5) In either cartopy, basemap or pyngl, I'm not sure that projections with # 5) In either cartopy, basemap or pyngl, I'm not sure that projections with
# a pole_lon not equal to 0 or 180 can be plotted. Hopefully people # a pole_lon not equal to 0 or 180 can be plotted. Hopefully people
# follow the WPS instructions, otherwise I need to see a sample file and # follow the WPS instructions, otherwise I need to see a sample file.
# a lot of rum.
# 6) For items in 3 - 4, the "longitude" (lon_0 or pole_longitude) is # 6) For items in 3 - 4, the "longitude" (lon_0 or pole_longitude) is
# determined by WRF's # determined by WRF's
# STAND_LON values, with the following calculations based on hemisphere: # STAND_LON values, with the following calculations based on hemisphere:
@ -583,8 +936,51 @@ class LatLon(WrfProj):
# to keep things in the -180 to 180, -90 to 90 range. # to keep things in the -180 to 180, -90 to 90 range.
# 12) This projection makes me sad. # 12) This projection makes me sad.
class RotatedLatLon(WrfProj): class RotatedLatLon(WrfProj):
"""A :class:`wrf.WrfProj` subclass for Rotated Lat Lon projections.
See Also:
:class:`wrf.WrfProj`, :class:`wrf.LatLon`,
:class:`wrf.PolarStereographic`,
:class:`Mercator`, :class:`LambertConformal`
"""
def __init__(self, bottom_left=None, top_right=None, def __init__(self, bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params): lats=None, lons=None, **proj_params):
"""Initialize a :class:`wrf.RotatedLatLon` object.
Args:
bottom_left (indexable sequence, optional): The lower left corner
as a (latitude, longitude) pair. Must also specify *top_right*
if used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
- 'CEN_LAT': Center latitude.
- 'CEN_LON': Center longitude.
- 'TRUELAT1': True latitude 1.
- 'TRUELAT2': True latitude 2.
- 'MOAD_CEN_LAT': Mother of all domains center latitude.
- 'STAND_LON': Standard longitude.
- 'POLE_LAT': Pole latitude.
- 'POLE_LON': Pole longitude.
"""
super(RotatedLatLon, self).__init__(bottom_left, top_right, super(RotatedLatLon, self).__init__(bottom_left, top_right,
lats, lons, **proj_params) lats, lons, **proj_params)
@ -717,6 +1113,49 @@ class RotatedLatLon(WrfProj):
def getproj(bottom_left=None, top_right=None, def getproj(bottom_left=None, top_right=None,
lats=None, lons=None, **proj_params): lats=None, lons=None, **proj_params):
"""Return a :class:`wrf.WrfProj` subclass.
This functions serves as a factory function for returning a
:class:`wrf.WrfProj` subclass from the specified map projection parameters.
Args:
bottom_left (indexable sequence, optional): The lower left corner as
a (latitude, longitude) pair. Must also specify *top_right* if
used. Default is None.
top_right (indexable sequence): The upper right corner as a
(latitude, longitude) pair. Must also specify *bottom_left*
if used. Default is None.
lats (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the latitude values. Must
also specify *lons* if used. Default is None.
lons (:class:`numpy.ndarray`, optional): An array of at least
two dimensions containing all of the longitude values. Must
also specify *lats* if used. Default is None.
**proj_params: Map projection optional keyword arguments, that
have the same names as found in WRF output NetCDF global
attributes:
- 'MAP_PROJ': The map projection type as an integer.
- 'CEN_LAT': Center latitude.
- 'CEN_LON': Center longitude.
- 'TRUELAT1': True latitude 1.
- 'TRUELAT2': True latitude 2.
- 'MOAD_CEN_LAT': Mother of all domains center latitude.
- 'STAND_LON': Standard longitude.
- 'POLE_LAT': Pole latitude.
- 'POLE_LON': Pole longitude.
Returns:
:class:`wrf.WrfProj`: A :class:`wrf.WrfProj` subclass for the
specified map projection parameters.
"""
proj_type = proj_params.get("MAP_PROJ", 0) proj_type = proj_params.get("MAP_PROJ", 0)
if proj_type == ProjectionTypes.LAMBERT_CONFORMAL: if proj_type == ProjectionTypes.LAMBERT_CONFORMAL:

56
src/wrf/pw.py

@ -13,10 +13,62 @@ from .metadecorators import copy_and_set_metadata
description="precipitable water", description="precipitable water",
MemoryOrder="XY", MemoryOrder="XY",
units="kg m-2") units="kg m-2")
def get_pw(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_pw(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
"""Return the preciptiable water.
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): Input 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
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.
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
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.
Default is None.
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
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:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "PH", "PHB", "QVAPOR") varnames=("T", "P", "PB", "PH", "PHB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]

108
src/wrf/py3compat.py

@ -6,6 +6,17 @@ from math import floor, copysign
# Dictionary python 2-3 compatibility stuff # Dictionary python 2-3 compatibility stuff
def viewitems(d): 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) func = getattr(d, "viewitems", None)
if func is None: if func is None:
func = d.items func = d.items
@ -13,6 +24,17 @@ def viewitems(d):
def viewkeys(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) func = getattr(d, "viewkeys", None)
if func is None: if func is None:
func = d.keys func = d.keys
@ -20,12 +42,34 @@ def viewkeys(d):
def viewvalues(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) func = getattr(d, "viewvalues", None)
if func is None: if func is None:
func = d.values func = d.values
return func() return func()
def isstr(s): 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: try:
return isinstance(s, basestring) return isinstance(s, basestring)
except NameError: except NameError:
@ -34,12 +78,48 @@ def isstr(s):
# Python 2 rounding behavior # Python 2 rounding behavior
def _round2(x, d=None): def _round2(x, d=None):
"""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
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,
which indicates the nearest integer.
Returns:
:obj:`float`: The rounded number.
"""
d = 0 if d is None else d d = 0 if d is None else d
p = 10 ** d p = 10 ** d
return float(floor((x * p) + copysign(0.5, x)))/p return float(floor((x * p) + copysign(0.5, x)))/p
def py2round(x, d=None): def py2round(x, d=None):
"""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
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,
which indicates the nearest integer.
Returns:
:obj:`float`: The rounded number.
"""
if version_info >= (3,): if version_info >= (3,):
return _round2(x, d) return _round2(x, d)
@ -47,6 +127,19 @@ def py2round(x, d=None):
def py3range(*args): 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,): if version_info >= (3,):
return range(*args) return range(*args)
@ -54,6 +147,21 @@ def py3range(*args):
def ucode(*args, **kwargs): 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, ): if version_info >= (3, ):
return str(*args, **kwargs) return str(*args, **kwargs)

112
src/wrf/rh.py

@ -11,10 +11,62 @@ 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", description="relative humidity",
units="%") units="%")
def get_rh(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_rh(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
"""Return the relative humidity.
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): Input 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
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.
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
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.
Default is None.
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
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:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR") varnames=("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]
p = ncvars["P"] p = ncvars["P"]
@ -33,10 +85,62 @@ def get_rh(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None,
@copy_and_set_metadata(copy_varname="T2", name="rh2", @copy_and_set_metadata(copy_varname="T2", name="rh2",
description="2m relative humidity", description="2m relative humidity",
units="%") units="%")
def get_rh_2m(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_rh_2m(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
"""Return the 2m relative humidity.
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): Input 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
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.
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
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.
Default is None.
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
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
:class:`numpy.ndarray` object with no metadata.
"""
varnames=("T2", "PSFC", "Q2") varnames=("T2", "PSFC", "Q2")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t2 = ncvars["T2"] t2 = ncvars["T2"]
psfc = ncvars["PSFC"] psfc = ncvars["PSFC"]

241
src/wrf/routines.py

@ -65,8 +65,8 @@ _FUNC_MAP = {"cape2d" : get_2dcape,
"pres" : get_pressure, "pres" : get_pressure,
"wspd_wdir" : get_destag_wspd_wdir, "wspd_wdir" : get_destag_wspd_wdir,
"wspd_wdir10" : get_destag_wspd_wdir10, "wspd_wdir10" : get_destag_wspd_wdir10,
"wspd_wdir_uvmet" : get_uvmet_wspd_wdir, "uvmet_wspd_wdir" : get_uvmet_wspd_wdir,
"wspd_wdir_uvmet10" : get_uvmet10_wspd_wdir, "uvmet10_wspd_wdir" : get_uvmet10_wspd_wdir,
"ctt" : get_ctt, "ctt" : get_ctt,
"cloudfrac" : get_cloudfrac "cloudfrac" : get_cloudfrac
} }
@ -108,8 +108,8 @@ _VALID_KARGS = {"cape2d" : ["missing"],
"pressure" : ["units"], "pressure" : ["units"],
"wspd_wdir" : ["units"], "wspd_wdir" : ["units"],
"wspd_wdir10" : ["units"], "wspd_wdir10" : ["units"],
"wspd_wdir_uvmet" : ["units"], "uvmet_wspd_wdir" : ["units"],
"wspd_wdir_uvmet10" : ["units"], "uvmet10_wspd_wdir" : ["units"],
"ctt" : [], "ctt" : [],
"cloudfrac" : [], "cloudfrac" : [],
"default" : [] "default" : []
@ -131,7 +131,9 @@ _ALIASES = {"cape_2d" : "cape2d",
"updraft_helicity" : "uhel", "updraft_helicity" : "uhel",
"td" : "dp", "td" : "dp",
"td2" : "dp2m", "td2" : "dp2m",
"cfrac" : "cloudfrac" "cfrac" : "cloudfrac",
"wspd_wdir_uvmet" : "uvmet_wspd_wdir",
"wspd_wdir_uvmet10" : "uvmet10_wspd_wdir"
} }
class ArgumentError(Exception): class ArgumentError(Exception):
@ -151,155 +153,134 @@ def _undo_alias(alias):
def _check_kargs(var, kargs): def _check_kargs(var, kargs):
for arg in viewkeys(kargs): for arg in viewkeys(kargs):
if arg not in _VALID_KARGS[var]: if arg not in _VALID_KARGS[var]:
raise ArgumentError("'%s' is an invalid keyword " raise ValueError("'%s' is an invalid keyword "
"argument for '%s'" % (arg, var)) "argument for '%s'" % (arg, var))
def getvar(wrfnc, varname, timeidx=0, def getvar(wrfin, varname, timeidx=0,
method="cat", squeeze=True, cache=None, meta=True, method="cat", squeeze=True, cache=None, meta=True,
**kargs): **kwargs):
"""Returns basic diagnostics from the WRF ARW model output. """Returns basic diagnostics from the WRF ARW model output.
Below is a table of available diagnostics. A table of all available diagnostics is below.
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+ .. include:: ../../_templates/product_table.txt
| Variable Name | Description | Units | Additional Keyword Arguments |
+====================+===============================================================+=====================+===============================================================================================+ Args:
| avo | Absolute Vorticity | 10-5 s-1 | | wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+ iterable): Input WRF ARW NetCDF
| eth/theta_e | Equivalent Potential Temperature | K | | data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+ or an iterable sequence of the aforementioned types.
| cape_2d | 2D cape (mcape/mcin/lcl/lfc) | J/kg / J/kg / m / m | missing: Fill value for output only (float) |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+ varname (:obj:`str`) : The variable name.
| cape_3d | 3D cape and cin | J/kg | missing: Fill value for output only (float) |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+ timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
| ctt | Cloud Top Temperature | C | | desired time index. This value can be a positive integer,
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+ negative integer, or
| cloudfrac | Cloud Fraction | % | | :data:`wrf.ALL_TIMES` (an alias for None) to return
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| dbz | Reflectivity | dBz | do_variant: Set to True to enable variant calculation. Default is False. |
| | | | do_liqskin : Set to True to enable liquid skin calculation. Default is False. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| mdbz | Maximum Reflectivity | dBz | do_variant: Set to True to enable variant calculation. Default is False. |
| | | | do_liqskin: Set to True to enable liquid skin calculation. Default is False. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| geopt/geopotential | Full Model Geopotential | m2 s-2 | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| helicity | Storm Relative Helicity | m-2/s-2 | top: The top level for the calculation in meters (float). Default is 3000.0. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| lat | Latitude | decimal degrees | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| lon | Longitude | decimal degrees | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| omg/omega | Omega | Pa/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| p/pres | Full Model Pressure | Pa | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| pressure | Full Model Pressure | hPa | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| pvo | Potential Vorticity | PVU | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| pw | Precipitable Water | kg m-2 | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| rh2 | 2m Relative Humidity | % | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| slp | Sea Level Pressure | hPa | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| ter | Model Terrain Height | m | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| td2 | 2m Dew Point Temperature | C | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| td | Dew Point Temperature | C | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| tc | Temperature | C | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| th/theta | Potential Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| tk | Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| times | Times in the File or Sequence | | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| tv | Virtual Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| twb | Wet Bulb Temperature | K | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| updraft_helicity | Updraft Helicity | m-2/s-2 | bottom: The bottom level for the calculation in meters (float). Default is 2000.0. |
| | | | top: The top level for the calculation in meters (float). Default is 5000.0. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| ua | U-component of Wind on Mass Points | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| va | V-component of Wind on Mass Points | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| wa | W-component of Wind on Mass Points | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| uvmet10 | 10 m U and V Components of Wind Rotated to Earth Coordinates | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| uvmet | U and V Components of Wind Rotated to Earth Coordinates | m/s | |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
| z/height | Full Model Height | m | msl: Set to False to return AGL values. Otherwise, MSL. Default is True. |
+--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+
Parameters
----------
wrfnc : `netCD4F.Dataset`, `Nio.NioFile`, or a sequence
Input WRF ARW NetCDF data as a `netCDF4.Dataset`, `Nio.NioFile` or an
iterable sequence of the aforementioned types.
varname : str
The variable name.
timeidx : int or `wrf.ALL_TIMES`, optional
The desired time index. This value can be a positive integer,
negative integer, or `wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0. all times in the file or sequence. The default is 0.
method : {'cat', 'join'}, optional method (:obj:`str`, optional): The aggregation method to use for
The aggregation method to use for sequences, either 'cat' or 'join'. sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time index. 'join' is creates a new 'cat' combines the data along the Time dimension.
index for the file. The default is 'cat'. '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
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.
Default is None.
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.
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:`numpy.ndarray` object with no metadata.
Raises:
: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.
squeeze : {True, False}, optional See Also:
Set to False to prevent dimensions with a size of 1 from being removed
from the shape of the output. Default is True.
cache : dict, optional :class:`numpy.ndarray`, :class:`xarray.DataArray`
A dictionary of (varname, ndarray) which can be used to supply
pre-extracted NetCDF variables to the computational routines. This can
be used to prevent the repeated variable extraction from large
sequences of data files. Default is None.
meta : {True, False}, optional
Set to False to disable metadata and return `numpy.ndarray` instead of
`xarray.DataArray`. Default is True.
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)
if f.startswith("wrfout_d02_")]
uvmet = getvar(wrfin, "uvmet", timeidx=3, units="kt")
Returns
-------
`xarray.DataArray` or `numpy.ndarray`
Returns the specified diagnostics output. If xarray is enabled and
the meta parameter is True, then the result will be an
`xarray.DataArray` object. Otherwise, the result will be a
`numpy.ndarray` object with no metadata.
""" """
_key = get_id(wrfnc) _key = get_id(wrfin)
wrfnc = get_iterable(wrfnc) wrfin = get_iterable(wrfin)
if is_standard_wrf_var(wrfnc, varname) and varname != "Times": if is_standard_wrf_var(wrfin, varname) and varname != "Times":
return extract_vars(wrfnc, timeidx, varname, return extract_vars(wrfin, timeidx, varname,
method, squeeze, cache, meta, _key)[varname] method, squeeze, cache, meta, _key)[varname]
elif varname == "Times": elif varname == "Times":
varname = "times" # Diverting to the get_times routine varname = "times" # Diverting to the get_times routine
actual_var = _undo_alias(varname) actual_var = _undo_alias(varname)
if actual_var not in _VALID_KARGS: if actual_var not in _VALID_KARGS:
raise ArgumentError("'%s' is not a valid variable name" % (varname)) raise ValueError("'%s' is not a valid variable name" % (varname))
_check_kargs(actual_var, kwargs)
_check_kargs(actual_var, kargs) return _FUNC_MAP[actual_var](wrfin, timeidx, method, squeeze, cache,
return _FUNC_MAP[actual_var](wrfnc, timeidx, method, squeeze, cache, meta, _key, **kwargs)
meta, _key, **kargs)

62
src/wrf/slp.py

@ -15,11 +15,69 @@ from .util import extract_vars
description="sea level pressure", description="sea level pressure",
MemoryOrder="XY") MemoryOrder="XY")
@convert_units("pressure", "hpa") @convert_units("pressure", "hpa")
def get_slp(wrfnc, timeidx=0, method="cat", squeeze=True, def get_slp(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="hPa"): units="hPa"):
"""Return the sea level pressure in the specified units.
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): Input 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
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.
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
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.
Default is None.
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
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
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:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR", "PH", "PHB") varnames=("T", "P", "PB", "QVAPOR", "PH", "PHB")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]

67
src/wrf/specialdec.py

@ -14,8 +14,27 @@ if xarray_enabled():
def uvmet_left_iter_nocopy(alg_dtype=np.float64): def uvmet_left_iter_nocopy(alg_dtype=np.float64):
"""Decorator to handle iterating over leftmost dimensions when using """A decorator to handle iterating over the leftmost dimensions for the
multiple files and/or multiple times with the uvmet product. 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
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
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
in the wrapped function.
Returns:
:class:`numpy.ndarray`: The aggregated uvmet output array that includes
all extra leftmost dimensions.
""" """
@wrapt.decorator @wrapt.decorator
@ -159,9 +178,27 @@ def uvmet_left_iter_nocopy(alg_dtype=np.float64):
def cape_left_iter(alg_dtype=np.float64): def cape_left_iter(alg_dtype=np.float64):
"""Decorator to handle iterating over leftmost dimensions when using """A decorator to handle iterating over the leftmost dimensions for the
multiple files and/or multiple times with the cape product. 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
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
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
in the wrapped function.
Returns:
:class:`numpy.ndarray`: The aggregated cape output array that includes
all extra leftmost dimensions.
""" """
@wrapt.decorator @wrapt.decorator
@ -289,9 +326,27 @@ def cape_left_iter(alg_dtype=np.float64):
return func_wrapper return func_wrapper
def cloudfrac_left_iter(alg_dtype=np.float64): def cloudfrac_left_iter(alg_dtype=np.float64):
"""Decorator to handle iterating over leftmost dimensions when using """A decorator to handle iterating over the leftmost dimensions for the
multiple files and/or multiple times with the cloudfrac product. 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
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
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
in the wrapped function.
Returns:
:class:`numpy.ndarray`: The aggregated cloud fraction output array
that includes all extra leftmost dimensions.
""" """
@wrapt.decorator @wrapt.decorator

416
src/wrf/temp.py

@ -11,12 +11,68 @@ 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") description="potential temperature")
@convert_units("temp", "k") @convert_units("temp", "k")
def get_theta(wrfnc, timeidx=0, method="cat", squeeze=True, def get_theta(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="K"): units="K"):
"""Return the potential temperature.
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): Input 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
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.
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
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.
Default is None.
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
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
is 'K'.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames = ("T",) varnames = ("T",)
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]
full_t = t + Constants.T_BASE full_t = t + Constants.T_BASE
@ -27,13 +83,68 @@ def get_theta(wrfnc, timeidx=0, method="cat", squeeze=True,
@copy_and_set_metadata(copy_varname="T", name="temp", @copy_and_set_metadata(copy_varname="T", name="temp",
description="temperature") description="temperature")
@convert_units("temp", "k") @convert_units("temp", "k")
def get_temp(wrfnc, timeidx=0, method="cat", squeeze=True, def get_temp(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="K"): units="K"):
"""Return the temperature in Kelvin or Celsius""" """Return the temperature in the specified units.
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): Input 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
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.
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
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.
Default is None.
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
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
is 'K'.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB") varnames=("T", "P", "PB")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]
p = ncvars["P"] p = ncvars["P"]
@ -49,13 +160,68 @@ def get_temp(wrfnc, timeidx=0, method="cat", squeeze=True,
@copy_and_set_metadata(copy_varname="T", name="theta_e", @copy_and_set_metadata(copy_varname="T", name="theta_e",
description="equivalent potential temperature") description="equivalent potential temperature")
@convert_units("temp", "K") @convert_units("temp", "K")
def get_eth(wrfnc, timeidx=0, method="cat", squeeze=True, def get_eth(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="K"): units="K"):
"Return equivalent potential temperature (Theta-e) in Kelvin" """Return the equivalent potential temperature.
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): Input 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
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.
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
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.
Default is None.
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
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
is 'K'.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR") varnames=("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]
p = ncvars["P"] p = ncvars["P"]
@ -74,13 +240,68 @@ def get_eth(wrfnc, timeidx=0, method="cat", squeeze=True,
@copy_and_set_metadata(copy_varname="T", name="tv", @copy_and_set_metadata(copy_varname="T", name="tv",
description="virtual temperature") description="virtual temperature")
@convert_units("temp", "k") @convert_units("temp", "k")
def get_tv(wrfnc, timeidx=0, method="cat", squeeze=True, def get_tv(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="K"): units="K"):
"Return the virtual temperature (tv) in Kelvin or Celsius" """Return the virtual temperature.
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): Input 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
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.
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
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.
Default is None.
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
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
is 'K'.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR") varnames=("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]
@ -100,13 +321,68 @@ def get_tv(wrfnc, timeidx=0, method="cat", squeeze=True,
@copy_and_set_metadata(copy_varname="T", name="twb", @copy_and_set_metadata(copy_varname="T", name="twb",
description="wetbulb temperature") description="wetbulb temperature")
@convert_units("temp", "k") @convert_units("temp", "k")
def get_tw(wrfnc, timeidx=0, method="cat", squeeze=True, def get_tw(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="K"): units="K"):
"Return the wetbulb temperature (tw)" """Return the wetbulb temperature.
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): Input 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
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.
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
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.
Default is None.
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
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
is 'K'.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR") varnames=("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
t = ncvars["T"] t = ncvars["T"]
p = ncvars["P"] p = ncvars["P"]
@ -122,15 +398,119 @@ def get_tw(wrfnc, timeidx=0, method="cat", squeeze=True,
return tw return tw
def get_tk(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_tk(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
return get_temp(wrfnc, timeidx, method, squeeze, cache, meta, _key, """Return the temperature in [K].
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): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
return get_temp(wrfin, timeidx, method, squeeze, cache, meta, _key,
units="K") units="K")
def get_tc(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_tc(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
return get_temp(wrfnc, timeidx, method, squeeze, cache, meta, _key, """Return the temperature in [degC].
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): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
Returns:
: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
be a :class:`numpy.ndarray` object with no metadata.
"""
return get_temp(wrfin, timeidx, method, squeeze, cache, meta, _key,
units="degC") units="degC")

63
src/wrf/terrain.py

@ -10,11 +10,68 @@ from .util import extract_vars, 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") description="terrain height")
@convert_units("height", "m") @convert_units("height", "m")
def get_terrain(wrfnc, timeidx=0, method="cat", squeeze=True, def get_terrain(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=False, _key=None, units="m"): cache=None, meta=False, _key=None, units="m"):
varname = either("HGT", "HGT_M")(wrfnc) """Return the terrain height in the specified units.
return extract_vars(wrfnc, timeidx, varname, 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): Input 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
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.
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
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.
Default is None.
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
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
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:`numpy.ndarray` object with no metadata.
"""
varname = either("HGT", "HGT_M")(wrfin)
return extract_vars(wrfin, timeidx, varname,
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key)[varname] _key=_key)[varname]

113
src/wrf/times.py

@ -4,14 +4,119 @@ from __future__ import (absolute_import, division, print_function,
from .util import extract_times from .util import extract_times
def get_times(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_times(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
return extract_times(wrfnc, timeidx, method, squeeze, cache, """Return a sequence of time objects.
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): Input 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
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.
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
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.
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
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:`numpy.ndarray`.
"""
return extract_times(wrfin, timeidx, method, squeeze, cache,
meta=meta, do_xtime=False) meta=meta, do_xtime=False)
def get_xtimes(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_xtimes(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
return extract_times(wrfnc, timeidx, method, squeeze, cache, """Return a sequence of time 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): Input 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
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.
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
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.
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
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:`numpy.ndarray`.
Raises:
:class:`KeyError`: Raised if the 'XTIME' variable is not present
in the NetCDF file.
"""
return extract_times(wrfin, timeidx, method, squeeze, cache,
meta=meta, do_xtime=True) meta=meta, do_xtime=True)

141
src/wrf/units.py

@ -4,8 +4,28 @@ from __future__ import (absolute_import, division, print_function,
from .constants import Constants, ConversionFactors from .constants import Constants, ConversionFactors
# Handles unit conversions that only differ by multiplication factors
def _apply_conv_fact(var, vartype, var_unit, dest_unit): def _apply_conv_fact(var, vartype, var_unit, dest_unit):
"""Return the variable converted to different units using a conversion
factor.
Args:
var (:class:`xarray.DataArray` or :class:`numpy.ndarray`): A
variable.
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.
"""
if var_unit == dest_unit: if var_unit == dest_unit:
return var return var
@ -22,6 +42,21 @@ def _apply_conv_fact(var, vartype, var_unit, dest_unit):
def _to_kelvin(var, var_unit): def _to_kelvin(var, var_unit):
"""Return the variable in Kelvin.
Args:
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
Kelvin.
"""
if var_unit == "c": if var_unit == "c":
return var + Constants.CELKEL return var + Constants.CELKEL
elif var_unit == "f": elif var_unit == "f":
@ -29,15 +64,58 @@ def _to_kelvin(var, var_unit):
def _k_to_c(var): def _k_to_c(var):
"""Return the variable in Celsius.
Args:
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
Celsius.
"""
return var - Constants.CELKEL return var - Constants.CELKEL
def _k_to_f(var): def _k_to_f(var):
"""Return the variable in Fahrenheit.
Args:
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
Fahrenheit.
"""
return 1.8 * _k_to_c(var) + 32.0 return 1.8 * _k_to_c(var) + 32.0
# Temperature is a more complicated operation so requires functions
def _apply_temp_conv(var, var_unit, dest_unit): 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
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.
"""
if dest_unit == var_unit: if dest_unit == var_unit:
return var return var
@ -51,6 +129,7 @@ def _apply_temp_conv(var, var_unit, dest_unit):
return (_TEMP_CONV_METHODS[dest_unit])(var) return (_TEMP_CONV_METHODS[dest_unit])(var)
# A mapping of unit names to their dictionary key names
_UNIT_ALIASES = {"mps" : "m s-1", _UNIT_ALIASES = {"mps" : "m s-1",
"m/s" : "m s-1", "m/s" : "m s-1",
"ms-1" : "m s-1", "ms-1" : "m s-1",
@ -148,24 +227,28 @@ _UNIT_ALIASES = {"mps" : "m s-1",
} }
# 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"], _VALID_UNITS = {"wind" : ["m s-1", "kt", "mi h-1", "km h-1", "ft s-1"],
"pressure" : ["pa", "hpa", "mb", "torr", "mmhg", "atm"], "pressure" : ["pa", "hpa", "mb", "torr", "mmhg", "atm"],
"temp" : ["k", "f", "c"], "temp" : ["k", "f", "c"],
"height" : ["m", "km", "dm", "ft", "mi"] "height" : ["m", "km", "dm", "ft", "mi"]
} }
# Conversion factor map for wind from base units
_WIND_BASE_FACTORS = {"kt" : ConversionFactors.MPS_TO_KTS, _WIND_BASE_FACTORS = {"kt" : ConversionFactors.MPS_TO_KTS,
"km h-1" : ConversionFactors.MPS_TO_KMPH, "km h-1" : ConversionFactors.MPS_TO_KMPH,
"mi h-1" : ConversionFactors.MPS_TO_MPH, "mi h-1" : ConversionFactors.MPS_TO_MPH,
"ft s-1" : ConversionFactors.MPS_TO_FPS "ft s-1" : ConversionFactors.MPS_TO_FPS
} }
# Conversion factor map to base units
_WIND_TOBASE_FACTORS = {"kt" : 1.0/ConversionFactors.MPS_TO_KTS, _WIND_TOBASE_FACTORS = {"kt" : 1.0/ConversionFactors.MPS_TO_KTS,
"km h-1" : 1.0/ConversionFactors.MPS_TO_KMPH, "km h-1" : 1.0/ConversionFactors.MPS_TO_KMPH,
"mi h-1" : 1.0/ConversionFactors.MPS_TO_MPH, "mi h-1" : 1.0/ConversionFactors.MPS_TO_MPH,
"ft s-1" : 1.0/ConversionFactors.MPS_TO_FPS "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, _PRES_BASE_FACTORS = {"hpa" : ConversionFactors.PA_TO_HPA,
"mb" : ConversionFactors.PA_TO_HPA, "mb" : ConversionFactors.PA_TO_HPA,
"torr" : ConversionFactors.PA_TO_TORR, "torr" : ConversionFactors.PA_TO_TORR,
@ -173,6 +256,7 @@ _PRES_BASE_FACTORS = {"hpa" : ConversionFactors.PA_TO_HPA,
"atm" : ConversionFactors.PA_TO_ATM "atm" : ConversionFactors.PA_TO_ATM
} }
# Conversion factor map for pressure to base units
_PRES_TOBASE_FACTORS = {"hpa" : 1.0/ConversionFactors.PA_TO_HPA, _PRES_TOBASE_FACTORS = {"hpa" : 1.0/ConversionFactors.PA_TO_HPA,
"mb" : 1.0/ConversionFactors.PA_TO_HPA, "mb" : 1.0/ConversionFactors.PA_TO_HPA,
"torr" : 1.0/ConversionFactors.PA_TO_TORR, "torr" : 1.0/ConversionFactors.PA_TO_TORR,
@ -180,24 +264,28 @@ _PRES_TOBASE_FACTORS = {"hpa" : 1.0/ConversionFactors.PA_TO_HPA,
"atm" : 1.0/ConversionFactors.PA_TO_ATM "atm" : 1.0/ConversionFactors.PA_TO_ATM
} }
# Conversion factor map for height from base units
_HEIGHT_BASE_FACTORS = {"km" : ConversionFactors.M_TO_KM, _HEIGHT_BASE_FACTORS = {"km" : ConversionFactors.M_TO_KM,
"dm" : ConversionFactors.M_TO_DM, "dm" : ConversionFactors.M_TO_DM,
"ft" : ConversionFactors.M_TO_FT, "ft" : ConversionFactors.M_TO_FT,
"mi" : ConversionFactors.M_TO_MILES "mi" : ConversionFactors.M_TO_MILES
} }
# Conversion factor map for height to base units
_HEIGHT_TOBASE_FACTORS = {"km" : 1.0/ConversionFactors.M_TO_KM, _HEIGHT_TOBASE_FACTORS = {"km" : 1.0/ConversionFactors.M_TO_KM,
"dm" : 1.0/ConversionFactors.M_TO_DM, "dm" : 1.0/ConversionFactors.M_TO_DM,
"ft" : 1.0/ConversionFactors.M_TO_FT, "ft" : 1.0/ConversionFactors.M_TO_FT,
"mi" : 1.0/ConversionFactors.M_TO_MILES "mi" : 1.0/ConversionFactors.M_TO_MILES
} }
# Mapping of unit type to base unit type
_BASE_UNITS = {"wind" : "m s-1", _BASE_UNITS = {"wind" : "m s-1",
"pressure" : "pa", "pressure" : "pa",
"temp" : "k", "temp" : "k",
"height" : "m" "height" : "m"
} }
# A mapping of unit type to a mapping of to/from base conversion factors
_CONV_FACTORS = {"wind" : {"to_dest" : _WIND_BASE_FACTORS, _CONV_FACTORS = {"wind" : {"to_dest" : _WIND_BASE_FACTORS,
"to_base" : _WIND_TOBASE_FACTORS}, "to_base" : _WIND_TOBASE_FACTORS},
"pressure" : {"to_dest" : _PRES_BASE_FACTORS, "pressure" : {"to_dest" : _PRES_BASE_FACTORS,
@ -206,11 +294,23 @@ _CONV_FACTORS = {"wind" : {"to_dest" : _WIND_BASE_FACTORS,
"to_base" : _HEIGHT_TOBASE_FACTORS} "to_base" : _HEIGHT_TOBASE_FACTORS}
} }
# A mapping of temperature type to the conversion function
_TEMP_CONV_METHODS = {"c" : _k_to_c, _TEMP_CONV_METHODS = {"c" : _k_to_c,
"f" : _k_to_f "f" : _k_to_f
} }
def dealias_and_clean_unit(unit): 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()) cleaned_unit = " ".join(unit.lower().split())
dealiased = _UNIT_ALIASES.get(cleaned_unit, None) dealiased = _UNIT_ALIASES.get(cleaned_unit, None)
@ -218,12 +318,49 @@ def dealias_and_clean_unit(unit):
def check_units(unit, unit_type): 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) u_cleaned = dealias_and_clean_unit(unit)
if u_cleaned not in _VALID_UNITS[unit_type]: if u_cleaned not in _VALID_UNITS[unit_type]:
raise ValueError("invalid unit type '%s'" % unit) raise ValueError("invalid unit type '%s'" % unit)
def do_conversion(var, vartype, var_unit, dest_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
variable.
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.
"""
u_cleaned = dealias_and_clean_unit(dest_unit) u_cleaned = dealias_and_clean_unit(dest_unit)
if vartype != "temp": if vartype != "temp":
return _apply_conv_fact(var, vartype, var_unit.lower(), u_cleaned) return _apply_conv_fact(var, vartype, var_unit.lower(), u_cleaned)

1617
src/wrf/util.py

File diff suppressed because it is too large Load Diff

383
src/wrf/uvmet.py

@ -16,36 +16,101 @@ from .util import extract_vars, extract_global_attrs, either
@convert_units("wind", "m s-1") @convert_units("wind", "m s-1")
def _get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True, def _get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
ten_m=False, units ="m s-1"): ten_m=False, units ="m s-1"):
""" Return a tuple of u,v with the winds rotated in to earth space""" """Return the u,v wind components rotated to earth coordinates.
The leftmost dimension of the returned array represents two different
quantities:
- return_val[0,...] will contain U_EARTH
- return_val[1,...] will contain V_EARTH
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): Input 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
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.
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
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.
Default is None.
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
purposes only. Default is None.
ten_m (:obj:`bool`, optional): Set to True to use the 10m surface
winds, rather than the three-dimensional wind field. Default is
False.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'uvmet'. Default
is 'm s-1'.
Returns:
:class:`numpy.ndarray`: The u,v components of the wind rotated to
earth coordinates, whose leftmost dimensions is 2 (0=U, 1=V). The
*meta* parameter is ignored for this function, so only a
:class:`numpy.ndarray` is returned.
"""
if not ten_m: if not ten_m:
varname = either("U", "UU")(wrfnc) varname = either("U", "UU")(wrfin)
u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, u_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
u = destagger(u_vars[varname], -1) u = destagger(u_vars[varname], -1)
varname = either("V", "VV")(wrfnc) varname = either("V", "VV")(wrfin)
v_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, v_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
v = destagger(v_vars[varname], -2) v = destagger(v_vars[varname], -2)
else: else:
varname = either("U10", "UU")(wrfnc) varname = either("U10", "UU")(wrfin)
u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, u_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
u = (u_vars[varname] if varname == "U10" else u = (u_vars[varname] if varname == "U10" else
destagger(u_vars[varname][...,0,:,:], -1)) destagger(u_vars[varname][...,0,:,:], -1))
varname = either("V10", "VV")(wrfnc) varname = either("V10", "VV")(wrfin)
v_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, v_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
v = (v_vars[varname] if varname == "V10" else v = (v_vars[varname] if varname == "V10" else
destagger(v_vars[varname][...,0,:,:], -2)) destagger(v_vars[varname][...,0,:,:], -2))
map_proj_attrs = extract_global_attrs(wrfnc, attrs="MAP_PROJ") map_proj_attrs = extract_global_attrs(wrfin, attrs="MAP_PROJ")
map_proj = map_proj_attrs["MAP_PROJ"] map_proj = map_proj_attrs["MAP_PROJ"]
# 1 - Lambert # 1 - Lambert
@ -75,7 +140,7 @@ def _get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True,
return result return result
elif map_proj in (1,2): elif map_proj in (1,2):
lat_attrs = extract_global_attrs(wrfnc, attrs=("TRUELAT1", lat_attrs = extract_global_attrs(wrfin, attrs=("TRUELAT1",
"TRUELAT2")) "TRUELAT2"))
radians_per_degree = Constants.PI/180.0 radians_per_degree = Constants.PI/180.0
# Rotation needed for Lambert and Polar Stereographic # Rotation needed for Lambert and Polar Stereographic
@ -83,10 +148,10 @@ def _get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True,
true_lat2 = lat_attrs["TRUELAT2"] true_lat2 = lat_attrs["TRUELAT2"]
try: try:
lon_attrs = extract_global_attrs(wrfnc, attrs="STAND_LON") lon_attrs = extract_global_attrs(wrfin, attrs="STAND_LON")
except AttributeError: except AttributeError:
try: try:
cen_lon_attrs = extract_global_attrs(wrfnc, attrs="CEN_LON") cen_lon_attrs = extract_global_attrs(wrfin, attrs="CEN_LON")
except AttributeError: except AttributeError:
raise RuntimeError("longitude attributes not found in NetCDF") raise RuntimeError("longitude attributes not found in NetCDF")
else: else:
@ -95,14 +160,14 @@ def _get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True,
cen_lon = lon_attrs["STAND_LON"] cen_lon = lon_attrs["STAND_LON"]
varname = either("XLAT_M", "XLAT")(wrfnc) varname = either("XLAT_M", "XLAT")(wrfin)
xlat_var = extract_vars(wrfnc, timeidx, varname, xlat_var = extract_vars(wrfin, timeidx, varname,
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)
lat = xlat_var[varname] lat = xlat_var[varname]
varname = either("XLONG_M", "XLONG")(wrfnc) varname = either("XLONG_M", "XLONG")(wrfin)
xlon_var = extract_vars(wrfnc, timeidx, varname, xlon_var = extract_vars(wrfin, timeidx, varname,
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)
lon = xlon_var[varname] lon = xlon_var[varname]
@ -133,11 +198,75 @@ def _get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True,
description="earth rotated u,v", description="earth rotated u,v",
two_d=False, two_d=False,
wspd_wdir=False) wspd_wdir=False)
def get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True, def get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="m s-1"): units="m s-1"):
"""Return the u,v wind components rotated to earth coordinates.
return _get_uvmet(wrfnc, timeidx, method, squeeze, cache, meta, _key, The leftmost dimension of the returned array represents two different
quantities:
- return_val[0,...] will contain U_EARTH
- return_val[1,...] will contain V_EARTH
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): Input 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
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.
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
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.
Default is None.
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
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 'uvmet'. Default
is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The u,v components
of the wind rotated to earth coordinates, whose leftmost dimensions is
2 (0=U_EARTH, 1=V_EARTH).
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_uvmet(wrfin, timeidx, method, squeeze, cache, meta, _key,
False, units) False, units)
@ -146,11 +275,77 @@ def get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True,
description="10m earth rotated u,v", description="10m earth rotated u,v",
two_d=True, two_d=True,
wspd_wdir=False) wspd_wdir=False)
def get_uvmet10(wrfnc, timeidx=0, method="cat", squeeze=True, def get_uvmet10(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="m s-1"): units="m s-1"):
"""Return the u,v components for the 10m winds rotated to earth
return _get_uvmet(wrfnc, timeidx, method, squeeze, cache, meta, _key, coordinates.
The leftmost dimension of the returned array represents two different
quantities:
- return_val[0,...] will contain U10_EARTH
- return_val[1,...] will contain V10_EARTH
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): Input 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
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.
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
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.
Default is None.
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
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 'uvmet10'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The u,v components
of the 10m wind rotated to earth coordinates, whose leftmost dimensions
is 2 (0=U10_EARTH, 1=V10_EARTH).
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_uvmet(wrfin, timeidx, method, squeeze, cache, meta, _key,
True, units) True, units)
@ -159,11 +354,78 @@ def get_uvmet10(wrfnc, timeidx=0, method="cat", squeeze=True,
description="earth rotated wspd,wdir", description="earth rotated wspd,wdir",
two_d=False, two_d=False,
wspd_wdir=True) wspd_wdir=True)
def get_uvmet_wspd_wdir(wrfnc, timeidx=0, method="cat", squeeze=True, def get_uvmet_wspd_wdir(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="m s-1"): units="m s-1"):
"""Return the wind speed and wind direction for the wind rotated to
earth coordinates.
uvmet = _get_uvmet(wrfnc, timeidx, method, squeeze, This function should be used when comparing with observations.
The leftmost dimension of the returned array represents two different
quantities:
- return_val[0,...] will contain WSPD_EARTH
- return_val[1,...] will contain WDIR_EARTH
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): Input 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
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.
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
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.
Default is None.
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
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 'uvmet_wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind speed and
wind direction for the wind rotated to earth coordinates, whose
leftmost dimensions is 2 (0=WSPD_EARTH, 1=WDIR_EARTH). 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.
"""
uvmet = _get_uvmet(wrfin, timeidx, method, squeeze,
cache, meta, _key, False, units) cache, meta, _key, False, units)
return _calc_wspd_wdir(uvmet[0,...,:,:,:], uvmet[1,...,:,:,:], return _calc_wspd_wdir(uvmet[0,...,:,:,:], uvmet[1,...,:,:,:],
@ -175,11 +437,78 @@ def get_uvmet_wspd_wdir(wrfnc, timeidx=0, method="cat", squeeze=True,
description="10m earth rotated wspd,wdir", description="10m earth rotated wspd,wdir",
two_d=True, two_d=True,
wspd_wdir=True) wspd_wdir=True)
def get_uvmet10_wspd_wdir(wrfnc, timeidx=0, method="cat", squeeze=True, def get_uvmet10_wspd_wdir(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="m s-1"): units="m s-1"):
"""Return the wind speed and wind direction for the 10m wind rotated to
earth coordinates.
This function should be used when comparing with observations.
The leftmost dimension of the returned array represents two different
quantities:
- return_val[0,...] will contain WSPD10_EARTH
- return_val[1,...] will contain WDIR10_EARTH
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): Input 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
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.
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
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.
Default is None.
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
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
'uvmet10_wspd_wdir'. Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind speed and
wind direction for the 10m wind rotated to earth coordinates, whose
leftmost dimensions is 2 (0=WSPD10_EARTH, 1=WDIR10_EARTH). 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.
"""
uvmet10 = _get_uvmet(wrfnc, timeidx, method, squeeze, cache, meta, _key, uvmet10 = _get_uvmet(wrfin, timeidx, method, squeeze, cache, meta, _key,
True, units) True, units)
return _calc_wspd_wdir(uvmet10[0,...,:,:], uvmet10[1,...,:,:], True, units) return _calc_wspd_wdir(uvmet10[0,...,:,:], uvmet10[1,...,:,:], True, units)

2
src/wrf/version.py

@ -1,2 +1,2 @@
__version__ = "1.0a2" __version__ = "1.0a3"

118
src/wrf/vorticity.py

@ -9,14 +9,67 @@ 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", description="absolute vorticity",
units="10-5 s-1") units="10-5 s-1")
def get_avo(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_avo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
ncvars = extract_vars(wrfnc, timeidx, ("U", "V", "MAPFAC_U", """Return the absolute vorticity.
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): Input 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
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.
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
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.
Default is None.
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
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:`numpy.ndarray` object with no metadata.
"""
ncvars = extract_vars(wrfin, timeidx, ("U", "V", "MAPFAC_U",
"MAPFAC_V", "MAPFAC_M", "MAPFAC_V", "MAPFAC_M",
"F"), "F"),
method, squeeze, cache, meta=False, _key=_key) method, squeeze, cache, meta=False, _key=_key)
attrs = extract_global_attrs(wrfnc, attrs=("DX", "DY")) attrs = extract_global_attrs(wrfin, attrs=("DX", "DY"))
u = ncvars["U"] u = ncvars["U"]
v = ncvars["V"] v = ncvars["V"]
msfu = ncvars["MAPFAC_U"] msfu = ncvars["MAPFAC_U"]
@ -33,14 +86,67 @@ def get_avo(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None,
@copy_and_set_metadata(copy_varname="T", name="pvo", @copy_and_set_metadata(copy_varname="T", name="pvo",
description="potential vorticity", description="potential vorticity",
units="PVU") units="PVU")
def get_pvo(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_pvo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
ncvars = extract_vars(wrfnc, timeidx, ("U", "V", "T", "P", """Return the potential vorticity.
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): Input 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
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.
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
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.
Default is None.
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
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:`numpy.ndarray` object with no metadata.
"""
ncvars = extract_vars(wrfin, timeidx, ("U", "V", "T", "P",
"PB", "MAPFAC_U", "PB", "MAPFAC_U",
"MAPFAC_V", "MAPFAC_M", "MAPFAC_V", "MAPFAC_M",
"F"), "F"),
method, squeeze, cache, meta=False, _key=_key) method, squeeze, cache, meta=False, _key=_key)
attrs = extract_global_attrs(wrfnc, attrs=("DX", "DY")) attrs = extract_global_attrs(wrfin, attrs=("DX", "DY"))
u = ncvars["U"] u = ncvars["U"]
v = ncvars["V"] v = ncvars["V"]

398
src/wrf/wind.py

@ -12,15 +12,73 @@ from .metadecorators import set_wind_metadata
@convert_units("wind", "m s-1") @convert_units("wind", "m s-1")
def _calc_wspd(u, v, units="m s-1"): def _calc_wspd(u, v, units="m s-1"):
"""Return the wind speed.
Args:
u (:class:`numpy.ndarray`): The u component of the wind.
v (:class:`numpy.ndarray`): The v component of the wind.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'uvmet_wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`numpy.ndarray`: The wind speed.
"""
return np.sqrt(u**2 + v**2) return np.sqrt(u**2 + v**2)
def _calc_wdir(u, v): def _calc_wdir(u, v):
"""Return the wind direction.
Args:
u (:class:`numpy.ndarray`): The u component of the wind.
v (:class:`numpy.ndarray`): The v component of the wind.
Returns:
:class:`numpy.ndarray`: The wind direction.
"""
wdir = 270.0 - np.arctan2(v,u) * (180.0/Constants.PI) wdir = 270.0 - np.arctan2(v,u) * (180.0/Constants.PI)
return np.remainder(wdir, 360.0) return np.remainder(wdir, 360.0)
def _calc_wspd_wdir(u, v, two_d, units): def _calc_wspd_wdir(u, v, two_d, units):
"""Return the wind speed and wind direction.
The leftmost dimension of the returned array represents two different
quantities:
- return_val[0,...] will contain WSPD
- return_val[1,...] will contain WDIR
Args:
u (:class:`numpy.ndarray`): The u component of the wind.
v (:class:`numpy.ndarray`): The v component of the wind.
two_d (:obj:`bool`): Set to True if the u,v wind components are
for a two-dimensional array (no height dimension). Otherwise,
set to False.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'uvmet_wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`numpy.ndarray`: The wind speed and wind direction, whose
leftmost dimension is 2 (0=WSPD, 1=WDIR).
"""
wspd = _calc_wspd(u, v, units) wspd = _calc_wspd(u, v, units)
wdir = _calc_wdir(u, v) wdir = _calc_wdir(u, v)
@ -51,11 +109,65 @@ def _calc_wspd_wdir(u, v, two_d, units):
two_d=False, two_d=False,
wspd_wdir=False) wspd_wdir=False)
@convert_units("wind", "m s-1") @convert_units("wind", "m s-1")
def get_u_destag(wrfnc, timeidx=0, method="cat", squeeze=True, def get_u_destag(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="m s-1"): units="m s-1"):
varname = either("U", "UU")(wrfnc) """Return the u-component of the wind on mass points.
u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache,
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): Input 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
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.
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
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.
Default is None.
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
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 'wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The u-component
of the wind.
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("U", "UU")(wrfin)
u_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
u = destagger(u_vars[varname], -1) u = destagger(u_vars[varname], -1)
@ -69,11 +181,65 @@ def get_u_destag(wrfnc, timeidx=0, method="cat", squeeze=True,
wind_ncvar=True, wind_ncvar=True,
wspd_wdir=False) wspd_wdir=False)
@convert_units("wind", "m s-1") @convert_units("wind", "m s-1")
def get_v_destag(wrfnc, timeidx=0, method="cat", squeeze=True, def get_v_destag(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="m s-1"): units="m s-1"):
varname = either("V", "VV")(wrfnc) """Return the v-component of the wind on mass points.
v_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache,
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): Input 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
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.
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
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.
Default is None.
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
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 'wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The v-component
of the wind.
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("V", "VV")(wrfin)
v_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
v = destagger(v_vars[varname], -2) v = destagger(v_vars[varname], -2)
@ -87,10 +253,64 @@ def get_v_destag(wrfnc, timeidx=0, method="cat", squeeze=True,
wind_ncvar=True, wind_ncvar=True,
wspd_wdir=False) wspd_wdir=False)
@convert_units("wind", "m s-1") @convert_units("wind", "m s-1")
def get_w_destag(wrfnc, timeidx=0, method="cat", squeeze=True, def get_w_destag(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="m s-1"): units="m s-1"):
w_vars = extract_vars(wrfnc, timeidx, "W", method, squeeze, cache, """Return the w-component of the wind on mass points.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): Input 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
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.
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
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.
Default is None.
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
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 'wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The w-component
of the wind.
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.
"""
w_vars = extract_vars(wrfin, timeidx, "W", method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
w = destagger(w_vars["W"], -3) w = destagger(w_vars["W"], -3)
return w return w
@ -101,16 +321,86 @@ def get_w_destag(wrfnc, timeidx=0, method="cat", squeeze=True,
description="wspd,wdir in projection space", description="wspd,wdir in projection space",
two_d=False, two_d=False,
wspd_wdir=True) wspd_wdir=True)
def get_destag_wspd_wdir(wrfnc, timeidx=0, method="cat", def get_destag_wspd_wdir(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None, squeeze=True, cache=None, meta=True, _key=None,
units="m s-1"): units="m s-1"):
varname = either("U", "UU")(wrfnc) """Return the wind speed and wind direction for the wind in the projected
u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, coordinate space.
The wind speed and direction from this function will be relative to the
grid. This function should not be used to compare with observations,
instead use :meth:`wrf.uvmet10_wspd_wdir` to get the earth relative wind
speed and direction.
The leftmost dimension of the returned array represents two different
quantities:
- return_val[0,...] will contain WSPD
- return_val[1,...] will contain WDIR
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): Input 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
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.
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
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.
Default is None.
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
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 'wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind speed and
wind direction for the wind in projected space, whose
leftmost dimensions is 2 (0=WSPD, 1=WDIR). 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("U", "UU")(wrfin)
u_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
u = destagger(u_vars[varname], -1) u = destagger(u_vars[varname], -1)
varname = either("V", "VV")(wrfnc) varname = either("V", "VV")(wrfin)
v_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, v_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
v = destagger(v_vars[varname], -2) v = destagger(v_vars[varname], -2)
@ -122,18 +412,88 @@ def get_destag_wspd_wdir(wrfnc, timeidx=0, method="cat",
description="10m wspd,wdir in projection space", description="10m wspd,wdir in projection space",
two_d=False, two_d=False,
wspd_wdir=True) wspd_wdir=True)
def get_destag_wspd_wdir10(wrfnc, timeidx=0, method="cat", def get_destag_wspd_wdir10(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None, squeeze=True, cache=None, meta=True, _key=None,
units="m s-1"): units="m s-1"):
"""Return the wind speed and wind direction for the 10m wind in
varname = either("U10", "UU")(wrfnc) projected coordinate space.
u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache,
The wind speed and direction from this function will be relative to the
grid. This function should not be used to compare with observations,
instead use :meth:`wrf.uvmet10_wspd_wdir` to get the earth relative wind
speed and direction.
The leftmost dimension of the returned array represents two different
quantities:
- return_val[0,...] will contain WSPD10
- return_val[1,...] will contain WDIR10
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): Input 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
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.
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
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.
Default is None.
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
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
'wspd_wdir10'. Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind speed and
wind direction for the 10m wind in projected space, whose
leftmost dimensions is 2 (0=WSPD10, 1=WDIR10). 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("U10", "UU")(wrfin)
u_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
u = (u_vars[varname] if varname == "U10" else u = (u_vars[varname] if varname == "U10" else
destagger(u_vars[varname][...,0,:,:], -1)) destagger(u_vars[varname][...,0,:,:], -1))
varname = either("V10", "VV")(wrfnc) varname = either("V10", "VV")(wrfin)
v_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, v_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
v = (v_vars[varname] if varname == "V10" else v = (v_vars[varname] if varname == "V10" else
destagger(v_vars[varname][...,0,:,:], -2)) destagger(v_vars[varname][...,0,:,:], -2))

34
test/reduce_file.py

@ -0,0 +1,34 @@
from netCDF4 import Dataset as NetCDF
f = "/Users/ladwig/Documents/wrf_files/wrfout_d01_2016-02-25_18_00_00"
outfilename = "/Users/ladwig/Documents/wrf_files/rotated_pole_test.nc"
in_nc = NetCDF(f, mode='r', format="NETCDF3_CLASSIC")
out_nc = NetCDF(outfilename, mode='w', format="NETCDF3_CLASSIC")
# Copy Global Attributes
for att_name in in_nc.ncattrs():
setattr(out_nc, att_name, getattr(in_nc, att_name))
# Copy Dimensions, but modify the vertical dimensions
for dimname, dim in in_nc.dimensions.iteritems():
out_nc.createDimension(dimname, len(dim))
# Copy Variables and their Attributes, using the reduced vertical dimension
for varname, var in in_nc.variables.iteritems():
if varname in ("T2", "XLAT", "XLONG", "XTIME"):
datatype = var.datatype
dimensions = var.dimensions
shape = var.shape
new_shape = shape
new_var = out_nc.createVariable(varname, datatype, dimensions)
new_var[:] = var[:]
for att_name in var.ncattrs():
setattr(new_var, att_name, getattr(var, att_name))
in_nc.close()
out_nc.close()
Loading…
Cancel
Save