Browse Source

Added new unit aliases to better match udunits, if we ever go down that route. Changed temperature to use Kelvin as base unit, so speed should improve. Added unit test for units to make sure they all run

main
Bill Ladwig 9 years ago
parent
commit
c2fa5405fb
  1. 17
      src/wrf/cape.py
  2. 12
      src/wrf/computation.py
  3. 2
      src/wrf/ctt.py
  4. 4
      src/wrf/dbz.py
  5. 5
      src/wrf/decorators.py
  6. 4
      src/wrf/dewpoint.py
  7. 4
      src/wrf/helicity.py
  8. 6
      src/wrf/metadecorators.py
  9. 2
      src/wrf/omega.py
  10. 4
      src/wrf/pressure.py
  11. 4
      src/wrf/rh.py
  12. 2
      src/wrf/slp.py
  13. 16
      src/wrf/temp.py
  14. 173
      src/wrf/units.py
  15. 12
      src/wrf/uvmet.py
  16. 20
      src/wrf/wind.py
  17. 56
      test/test_units.py

17
src/wrf/cape.py

@ -4,22 +4,12 @@ from __future__ import (absolute_import, division, print_function,
import numpy as np import numpy as np
import numpy.ma as ma import numpy.ma as ma
#from .extension import computetk,computecape
from .extension import _tk, _cape from .extension import _tk, _cape
from .destag import destagger from .destag import destagger
from .constants import Constants, ConversionFactors from .constants import Constants, ConversionFactors
from .util import extract_vars from .util import extract_vars
from .metadecorators import set_cape_metadata from .metadecorators import set_cape_metadata
#@copy_and_set_metadata(copy_varname="T",
# name="cape_2d",
# dimnames=combine_with("T", remove_dims=("bottom_top",),
# insert_before="south_north",
# new_dimnames=["mcape_mcin_lcl_lfc"]),
# description="mcape ; mcin ; lcl ; lfc",
# units="J/kg ; J/kg ; m ; m",
# MemoryOrder="XY")
@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(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None, missing=Constants.DEFAULT_FILL): meta=True, _key=None, missing=Constants.DEFAULT_FILL):
@ -74,13 +64,6 @@ def get_2dcape(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None,
return ma.masked_values(result, missing) return ma.masked_values(result, missing)
#@copy_and_set_metadata(copy_varname="T", name="cape_3d",
# dimnames=combine_with("T",
# insert_before="bottom_top",
# new_dimnames=["cape_cin"]),
# description="cape ; cin",
# units="J kg-1 ; J kg-1",
# MemoryOrder="XY")
@set_cape_metadata(is2d=False) @set_cape_metadata(is2d=False)
def get_3dcape(wrfnc, timeidx=0, method="cat", def get_3dcape(wrfnc, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, squeeze=True, cache=None, meta=True,

12
src/wrf/computation.py

@ -38,7 +38,7 @@ def interpz3d(field3d, z, desiredloc, missingval=Constants.DEFAULT_FILL,
return _interpz3d(field3d, z, desiredloc, missingval) return _interpz3d(field3d, z, desiredloc, missingval)
@set_alg_metadata(2, "pres", refvarndims=3, units="hpa", @set_alg_metadata(2, "pres", refvarndims=3, units="hPa",
description="sea level pressure") description="sea level pressure")
def slp(height, tkel, pres, qv, meta=True): def slp(height, tkel, pres, qv, meta=True):
return _slp(height, tkel, pres, qv) return _slp(height, tkel, pres, qv)
@ -139,8 +139,8 @@ def ctt(pres_hpa, tkel, qv, qcld, height, terrain, qice=None, meta=True):
@set_alg_metadata(3, "pres", units="dBZ", @set_alg_metadata(3, "pres", units="dBZ",
description="radar reflectivity") description="radar reflectivity")
def dbz(pres, tkel, qv, qr, qs=None, qg=None, use_varint=False, use_liqskin=False, def dbz(pres, tkel, qv, qr, qs=None, qg=None, use_varint=False,
meta=True): use_liqskin=False, meta=True):
if qs is None: if qs is None:
qs = np.zeros(qv.shape, qv.dtype) qs = np.zeros(qv.shape, qv.dtype)
@ -155,7 +155,7 @@ def dbz(pres, tkel, qv, qr, qs=None, qg=None, use_varint=False, use_liqskin=Fals
return _dbz(pres, tkel, qv, qr, qs, qg, sn0, ivarint, iliqskin) return _dbz(pres, tkel, qv, qr, qs, qg, sn0, ivarint, iliqskin)
@set_alg_metadata(2, "terrain", units="m-2/s-2", @set_alg_metadata(2, "terrain", units="m2 s-2",
description="storm relative helicity") description="storm relative helicity")
def srhel(u, v, z, terrain, top=3000.0, meta=True): def srhel(u, v, z, terrain, top=3000.0, meta=True):
# u, v get swapped in vertical # u, v get swapped in vertical
@ -166,7 +166,7 @@ def srhel(u, v, z, terrain, top=3000.0, meta=True):
return _srhel(_u, _v, _z, terrain, top) return _srhel(_u, _v, _z, terrain, top)
@set_alg_metadata(2, "u", refvarndims=3, units="m-2/s-2", @set_alg_metadata(2, "u", refvarndims=3, units="m2 s-2",
description="updraft helicity") description="updraft helicity")
def udhel(zstag, mapfct, u, v, wstag, dx, dy, bottom=2000.0, top=5000.0, def udhel(zstag, mapfct, u, v, wstag, dx, dy, bottom=2000.0, top=5000.0,
meta=True): meta=True):
@ -205,7 +205,7 @@ def tvirtual(tkel, qv, meta=True):
return _tv(tkel, qv) return _tv(tkel, qv)
@set_alg_metadata(3, "qv", units="Pa/s", @set_alg_metadata(3, "qv", units="Pa s-1",
description="omega") description="omega")
def omega(qv, tkel, w, pres, meta=True): def omega(qv, tkel, w, pres, meta=True):
return _omega(qv, tkel, w, pres) return _omega(qv, tkel, w, pres)

2
src/wrf/ctt.py

@ -19,7 +19,7 @@ from .util import extract_vars
@convert_units("temp", "c") @convert_units("temp", "c")
def get_ctt(wrfnc, timeidx=0, method="cat", def get_ctt(wrfnc, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None, squeeze=True, cache=None, meta=True, _key=None,
units="c"): units="degC"):
"""Return the cloud top temperature. """Return the cloud top temperature.
""" """

4
src/wrf/dbz.py

@ -12,7 +12,7 @@ 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(wrfnc, 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):
@ -68,7 +68,7 @@ def get_dbz(wrfnc, timeidx=0, method="cat",
@copy_and_set_metadata(copy_varname="T", name="max_dbz", @copy_and_set_metadata(copy_varname="T", name="max_dbz",
remove_dims=("bottom_top",), remove_dims=("bottom_top",),
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(wrfnc, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None, squeeze=True, cache=None, meta=True, _key=None,

5
src/wrf/decorators.py

@ -7,7 +7,7 @@ import wrapt
import numpy as np import numpy as np
import numpy.ma as ma import numpy.ma as ma
from .units import do_conversion, check_units from .units import do_conversion, check_units, dealias_and_clean_unit
from .util import iter_left_indexes, from_args, npvalues, combine_dims from .util import iter_left_indexes, from_args, npvalues, combine_dims
from .py3compat import viewitems, viewvalues, isstr from .py3compat import viewitems, viewvalues, isstr
from .config import xarray_enabled from .config import xarray_enabled
@ -29,7 +29,8 @@ def convert_units(unit_type, alg_unit):
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
desired_units = from_args(wrapped, "units", *args, **kwargs)["units"] desired_units = from_args(wrapped, "units", *args, **kwargs)["units"]
check_units(desired_units, unit_type) u_cleaned = dealias_and_clean_unit(desired_units)
check_units(u_cleaned, unit_type)
# Unit conversion done here # Unit conversion done here
return do_conversion(wrapped(*args, **kwargs), unit_type, return do_conversion(wrapped(*args, **kwargs), unit_type,

4
src/wrf/dewpoint.py

@ -12,7 +12,7 @@ from .util import extract_vars
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(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, units="c"): cache=None, meta=True, _key=None, units="degC"):
varnames=("P", "PB", "QVAPOR") varnames=("P", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache,
@ -33,7 +33,7 @@ def get_dp(wrfnc, timeidx=0, method="cat", squeeze=True,
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(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, units="c"): cache=None, meta=True, _key=None, units="degC"):
varnames=("PSFC", "Q2") varnames=("PSFC", "Q2")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)

4
src/wrf/helicity.py

@ -11,7 +11,7 @@ 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="m-2/s-2") units="m2 s-2")
def get_srh(wrfnc, timeidx=0, method="cat", squeeze=True, def get_srh(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, top=3000.0): cache=None, meta=True, _key=None, top=3000.0):
# 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)
@ -51,7 +51,7 @@ 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="m-2/s-2") units="m2 s-2")
def get_uh(wrfnc, timeidx=0, method="cat", squeeze=True, def get_uh(wrfnc, 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):

6
src/wrf/metadecorators.py

@ -286,7 +286,7 @@ def set_cape_metadata(is2d):
outdimnames[0] = "mcape_mcin_lcl_lfc" outdimnames[0] = "mcape_mcin_lcl_lfc"
outattrs["description"] = "mcape ; mcin ; lcl ; lfc" outattrs["description"] = "mcape ; mcin ; lcl ; lfc"
outattrs["MemoryOrder"] = "XY" outattrs["MemoryOrder"] = "XY"
outattrs["units"] = "J/kg ; J/kg ; m ; m" outattrs["units"] = "J kg-1 ; J kg-1 ; m ; m"
outname = "cape_2d" outname = "cape_2d"
else: else:
# Right dims # Right dims
@ -1215,7 +1215,7 @@ def set_alg_metadata(alg_ndims, refvarname,
return func_wrapper return func_wrapper
def set_uvmet_alg_metadata(units="mps", description="earth rotated u,v", def set_uvmet_alg_metadata(units="m s-1", description="earth rotated u,v",
latarg="lat", windarg="u"): latarg="lat", windarg="u"):
@wrapt.decorator @wrapt.decorator
@ -1287,7 +1287,7 @@ def set_cape_alg_metadata(is2d, copyarg="pres_hpa"):
if is2d: if is2d:
outname = "cape_2d" outname = "cape_2d"
outattrs["description"] = "mcape ; mcin ; lcl ; lfc" outattrs["description"] = "mcape ; mcin ; lcl ; lfc"
outattrs["units"] = "J/kg ; J/kg ; m ; m" outattrs["units"] = "J kg-1 ; J kg-1 ; m ; m"
outattrs["MemoryOrder"] = "XY" outattrs["MemoryOrder"] = "XY"
else: else:
outname = "cape_3d" outname = "cape_3d"

2
src/wrf/omega.py

@ -10,7 +10,7 @@ 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") units="Pa s-1")
def get_omega(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_omega(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
varnames=("T", "P", "W", "PB", "QVAPOR") varnames=("T", "P", "W", "PB", "QVAPOR")

4
src/wrf/pressure.py

@ -11,7 +11,7 @@ from .util import extract_vars, either
@convert_units("pressure", "pa") @convert_units("pressure", "pa")
def get_pressure(wrfnc, timeidx=0, method="cat", squeeze=True, def get_pressure(wrfnc, 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) varname = either("P", "PRES")(wrfnc)
if varname == "P": if varname == "P":
@ -30,7 +30,7 @@ def get_pressure(wrfnc, timeidx=0, method="cat", squeeze=True,
def get_pressure_hpa(wrfnc, timeidx=0, method="cat", squeeze=True, def get_pressure_hpa(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="hpa"): units="hPa"):
return get_pressure(wrfnc, timeidx, method, squeeze, cache, meta, _key, return get_pressure(wrfnc, timeidx, method, squeeze, cache, meta, _key,
units) units)

4
src/wrf/rh.py

@ -10,7 +10,7 @@ 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",
delete_attrs=("units",)) units="%")
def get_rh(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_rh(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
varnames=("T", "P", "PB", "QVAPOR") varnames=("T", "P", "PB", "QVAPOR")
@ -32,7 +32,7 @@ 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",
delete_attrs=("units",)) units="%")
def get_rh_2m(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_rh_2m(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None): meta=True, _key=None):
varnames=("T2", "PSFC", "Q2") varnames=("T2", "PSFC", "Q2")

2
src/wrf/slp.py

@ -17,7 +17,7 @@ from .util import extract_vars
@convert_units("pressure", "hpa") @convert_units("pressure", "hpa")
def get_slp(wrfnc, timeidx=0, method="cat", squeeze=True, def get_slp(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="hpa"): units="hPa"):
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(wrfnc, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)

16
src/wrf/temp.py

@ -13,7 +13,7 @@ from .util import extract_vars
@convert_units("temp", "k") @convert_units("temp", "k")
def get_theta(wrfnc, timeidx=0, method="cat", squeeze=True, def get_theta(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="k"): units="K"):
varnames = ("T",) varnames = ("T",)
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache, ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache,
@ -29,7 +29,7 @@ def get_theta(wrfnc, timeidx=0, method="cat", squeeze=True,
@convert_units("temp", "k") @convert_units("temp", "k")
def get_temp(wrfnc, timeidx=0, method="cat", squeeze=True, def get_temp(wrfnc, 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 Kelvin or Celsius"""
varnames=("T", "P", "PB") varnames=("T", "P", "PB")
@ -48,10 +48,10 @@ 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(wrfnc, 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 equivalent potential temperature (Theta-e) in Kelvin"
varnames=("T", "P", "PB", "QVAPOR") varnames=("T", "P", "PB", "QVAPOR")
@ -76,7 +76,7 @@ def get_eth(wrfnc, timeidx=0, method="cat", squeeze=True,
@convert_units("temp", "k") @convert_units("temp", "k")
def get_tv(wrfnc, timeidx=0, method="cat", squeeze=True, def get_tv(wrfnc, 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 (tv) in Kelvin or Celsius"
varnames=("T", "P", "PB", "QVAPOR") varnames=("T", "P", "PB", "QVAPOR")
@ -102,7 +102,7 @@ def get_tv(wrfnc, timeidx=0, method="cat", squeeze=True,
@convert_units("temp", "k") @convert_units("temp", "k")
def get_tw(wrfnc, timeidx=0, method="cat", squeeze=True, def get_tw(wrfnc, 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 (tw)"
varnames=("T", "P", "PB", "QVAPOR") varnames=("T", "P", "PB", "QVAPOR")
@ -125,13 +125,13 @@ def get_tw(wrfnc, timeidx=0, method="cat", squeeze=True,
def get_tk(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, def get_tk(wrfnc, 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 get_temp(wrfnc, 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(wrfnc, 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 get_temp(wrfnc, timeidx, method, squeeze, cache, meta, _key,
units="c") units="degC")

173
src/wrf/units.py

@ -12,7 +12,7 @@ def _apply_conv_fact(var, vartype, var_unit, dest_unit):
# Note, case where var_unit and dest_unit are base unit, should be # Note, case where var_unit and dest_unit are base unit, should be
# handled above # handled above
if var_unit == _BASE_UNITS[vartype]: if var_unit == _BASE_UNITS[vartype]:
return var * _CONV_FACTORS[vartype]["to_dest"][dest_unit] return var*(_CONV_FACTORS[vartype]["to_dest"][dest_unit])
else: else:
if dest_unit == _BASE_UNITS[vartype]: if dest_unit == _BASE_UNITS[vartype]:
return var*(_CONV_FACTORS[vartype]["to_base"][var_unit]) return var*(_CONV_FACTORS[vartype]["to_base"][var_unit])
@ -21,51 +21,149 @@ def _apply_conv_fact(var, vartype, var_unit, dest_unit):
_CONV_FACTORS[vartype]["to_dest"][dest_unit]) _CONV_FACTORS[vartype]["to_dest"][dest_unit])
def _to_celsius(var, var_unit): def _to_kelvin(var, var_unit):
if var_unit == "k": if var_unit == "c":
return var - Constants.CELKEL return var + Constants.CELKEL
elif var_unit == "f": elif var_unit == "f":
return (var - 32.0) * (5.0/9.0) return (var - 32.0) * (5.0/9.0) + Constants.CELKEL
def _c_to_k(var): def _k_to_c(var):
return var + Constants.TCK0 return var - Constants.CELKEL
def _c_to_f(var): def _k_to_f(var):
return 1.8 * var + 32.0 return 1.8 * _k_to_c(var) + 32.0
# Temperature is a more complicated operation so requres functions # 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):
if dest_unit == var_unit: if dest_unit == var_unit:
return var return var
if var_unit != _BASE_UNITS["temp"]: if var_unit != _BASE_UNITS["temp"]:
tc = _to_celsius(var, var_unit) tk = _to_kelvin(var, var_unit)
if dest_unit == _BASE_UNITS["temp"]: if dest_unit == _BASE_UNITS["temp"]:
return tc return tk
else: else:
return (_TEMP_CONV_METHODS[dest_unit])(tc) return (_TEMP_CONV_METHODS[dest_unit])(tk)
else: else:
return (_TEMP_CONV_METHODS[dest_unit])(var) return (_TEMP_CONV_METHODS[dest_unit])(var)
_UNIT_ALIASES = {"mps" : "m s-1",
"m/s" : "m s-1",
"ms-1" : "m s-1",
"meters_per_second" : "m s-1",
"metres_per_second" : "m s-1",
"knots" : "kt",
"knot" : "kt",
"kts" : "kt",
"kn" : "kt",
"miles_per_hour" : "mi h-1",
"mih-1" : "mi h-1",
"mph" : "mi h-1",
"mi/h" : "mi h-1",
"kmph" : "km h-1",
"kmh-1" : "km h-1",
"km/h" : "km h-1",
"kilometers_per_hour" : "km h-1",
"kilometres_per_hour" : "km h-1",
"ft/s" : "ft s-1",
"ft/sec" : "ft s-1",
"fps" : "ft s-1",
"fs-1" : "ft s-1",
"feet_per_second" : "ft s-1",
"pascal" : "pa",
"pascals" : "pa",
"hecto_pascal" : "hpa",
"hecto_pascals" : "hpa",
"millibar" : "mb",
"millibars" : "mb",
"mbar" : "mb",
"kelvin" : "k",
"degree_kelvin" : "k",
"degrees_kelvin" : "k",
"degree_k" : "k",
"degrees_k" : "k",
"degreek" : "k",
"degreesk" : "k",
"degk" : "k",
"degsk" : "k",
"deg_k" : "k",
"degs_k" : "k",
"deg k" : "k",
"degs k" : "k",
"celsius" : "c",
"degree_celsius" : "c",
"degrees_celsius" : "c",
"degree_c" : "c",
"degrees_c" : "c",
"degreec" : "c",
"degreesc" : "c",
"degc" : "c",
"degsc" : "c",
"deg_c" : "c",
"degs_c" : "c",
"deg c" : "c",
"degs c" : "c",
"fahrenheit" : "f",
"degree_fahrenheit" : "f",
"degrees_fahrenheit" : "f",
"degree_f" : "f",
"degrees_f" : "f",
"degreef" : "f",
"degreesf" : "f",
"degf" : "f",
"degsf" : "f",
"deg_f" : "f",
"degs_f" : "f",
"deg f" : "f",
"degs f" : "f",
"meter" : "m",
"meters" : "m",
"metre" : "m",
"metres" : "m",
"kilometer" : "km",
"kilometers" : "km",
"dekameter" : "dm",
"dekameters" : "dm",
"decameter" : "dm",
"decameters" : "dm",
"dekametre" : "dm",
"dekametres" : "dm",
"decametre" : "dm",
"decametres" : "dm",
"dam" : "dm",
"dkm" : "dm",
"feet" : "ft",
"foot" : "ft",
"mile" : "mi",
"miles" : "mi"
}
_VALID_UNITS = {"wind" : ["mps", "kts", "mph", "kmph", "fps"], _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", "miles"] "height" : ["m", "km", "dm", "ft", "mi"]
} }
_WIND_BASE_FACTORS = {"kts" : ConversionFactors.MPS_TO_KTS, _WIND_BASE_FACTORS = {"kt" : ConversionFactors.MPS_TO_KTS,
"kmph" : ConversionFactors.MPS_TO_KMPH, "km h-1" : ConversionFactors.MPS_TO_KMPH,
"mph" : ConversionFactors.MPS_TO_MPH, "mi h-1" : ConversionFactors.MPS_TO_MPH,
"fps" : ConversionFactors.MPS_TO_FPS "ft s-1" : ConversionFactors.MPS_TO_FPS
} }
_WIND_TOBASE_FACTORS = {"kts" : 1.0/ConversionFactors.MPS_TO_KTS, _WIND_TOBASE_FACTORS = {"kt" : 1.0/ConversionFactors.MPS_TO_KTS,
"kmph" : 1.0/ConversionFactors.MPS_TO_KMPH, "km h-1" : 1.0/ConversionFactors.MPS_TO_KMPH,
"mph" : 1.0/ConversionFactors.MPS_TO_MPH, "mi h-1" : 1.0/ConversionFactors.MPS_TO_MPH,
"fps" : 1.0/ConversionFactors.MPS_TO_FPS "ft s-1" : 1.0/ConversionFactors.MPS_TO_FPS
} }
_PRES_BASE_FACTORS = {"hpa" : ConversionFactors.PA_TO_HPA, _PRES_BASE_FACTORS = {"hpa" : ConversionFactors.PA_TO_HPA,
@ -85,19 +183,18 @@ _PRES_TOBASE_FACTORS = {"hpa" : 1.0/ConversionFactors.PA_TO_HPA,
_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,
"miles" : ConversionFactors.M_TO_MILES "mi" : ConversionFactors.M_TO_MILES
} }
_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,
"miles" : 1.0/ConversionFactors.M_TO_MILES "mi" : 1.0/ConversionFactors.M_TO_MILES
} }
_BASE_UNITS = {"wind" : "mps", _BASE_UNITS = {"wind" : "m s-1",
"pressure" : "pa", "pressure" : "pa",
"temp" : "c", "temp" : "k",
"height" : "m" "height" : "m"
} }
@ -109,23 +206,29 @@ _CONV_FACTORS = {"wind" : {"to_dest" : _WIND_BASE_FACTORS,
"to_base" : _HEIGHT_TOBASE_FACTORS} "to_base" : _HEIGHT_TOBASE_FACTORS}
} }
_TEMP_CONV_METHODS = {"k" : _c_to_k, _TEMP_CONV_METHODS = {"c" : _k_to_c,
"f" : _c_to_f "f" : _k_to_f
} }
def dealias_and_clean_unit(unit):
cleaned_unit = " ".join(unit.lower().split())
dealiased = _UNIT_ALIASES.get(cleaned_unit, None)
return cleaned_unit if dealiased is None else dealiased
def check_units(unit, unit_type): def check_units(unit, unit_type):
unitl = unit.lower() u_cleaned = dealias_and_clean_unit(unit)
if unitl 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):
u_cleaned = dealias_and_clean_unit(dest_unit)
if vartype != "temp": if vartype != "temp":
return _apply_conv_fact(var, vartype, return _apply_conv_fact(var, vartype, var_unit.lower(), u_cleaned)
var_unit.lower(), dest_unit.lower())
else: else:
return _apply_temp_conv(var, var_unit.lower(), dest_unit.lower()) return _apply_temp_conv(var, var_unit.lower(), u_cleaned)

12
src/wrf/uvmet.py

@ -15,10 +15,10 @@ from .metadecorators import set_wind_metadata
from .util import extract_vars, extract_global_attrs, either from .util import extract_vars, extract_global_attrs, either
@convert_units("wind", "mps") @convert_units("wind", "m s-1")
def _get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True, def _get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
ten_m=False, units ="mps"): ten_m=False, units ="m s-1"):
""" Return a tuple of u,v with the winds rotated in to earth space""" """ Return a tuple of u,v with the winds rotated in to earth space"""
if not ten_m: if not ten_m:
@ -135,7 +135,7 @@ def _get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True,
wspd_wdir=False) wspd_wdir=False)
def get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True, def get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="mps"): units="m s-1"):
return _get_uvmet(wrfnc, timeidx, method, squeeze, cache, meta, _key, return _get_uvmet(wrfnc, timeidx, method, squeeze, cache, meta, _key,
False, units) False, units)
@ -148,7 +148,7 @@ def get_uvmet(wrfnc, timeidx=0, method="cat", squeeze=True,
wspd_wdir=False) wspd_wdir=False)
def get_uvmet10(wrfnc, timeidx=0, method="cat", squeeze=True, def get_uvmet10(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="mps"): units="m s-1"):
return _get_uvmet(wrfnc, timeidx, method, squeeze, cache, meta, _key, return _get_uvmet(wrfnc, timeidx, method, squeeze, cache, meta, _key,
True, units) True, units)
@ -161,7 +161,7 @@ def get_uvmet10(wrfnc, timeidx=0, method="cat", squeeze=True,
wspd_wdir=True) wspd_wdir=True)
def get_uvmet_wspd_wdir(wrfnc, timeidx=0, method="cat", squeeze=True, def get_uvmet_wspd_wdir(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="mps"): units="m s-1"):
uvmet = _get_uvmet(wrfnc, timeidx, method, squeeze, uvmet = _get_uvmet(wrfnc, timeidx, method, squeeze,
cache, meta, _key, False, units) cache, meta, _key, False, units)
@ -177,7 +177,7 @@ def get_uvmet_wspd_wdir(wrfnc, timeidx=0, method="cat", squeeze=True,
wspd_wdir=True) wspd_wdir=True)
def get_uvmet10_wspd_wdir(wrfnc, timeidx=0, method="cat", squeeze=True, def get_uvmet10_wspd_wdir(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="mps"): units="m s-1"):
uvmet10 = _get_uvmet(wrfnc, timeidx, method, squeeze, cache, meta, _key, uvmet10 = _get_uvmet(wrfnc, timeidx, method, squeeze, cache, meta, _key,
True, units) True, units)

20
src/wrf/wind.py

@ -10,8 +10,8 @@ from .decorators import convert_units
from .metadecorators import set_wind_metadata from .metadecorators import set_wind_metadata
@convert_units("wind", "mps") @convert_units("wind", "m s-1")
def _calc_wspd(u, v, units="mps"): def _calc_wspd(u, v, units="m s-1"):
return np.sqrt(u**2 + v**2) return np.sqrt(u**2 + v**2)
@ -50,10 +50,10 @@ def _calc_wspd_wdir(u, v, two_d, units):
wind_ncvar=True, wind_ncvar=True,
two_d=False, two_d=False,
wspd_wdir=False) wspd_wdir=False)
@convert_units("wind", "mps") @convert_units("wind", "m s-1")
def get_u_destag(wrfnc, timeidx=0, method="cat", squeeze=True, def get_u_destag(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="mps"): units="m s-1"):
varname = either("U", "UU")(wrfnc) varname = either("U", "UU")(wrfnc)
u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
@ -68,10 +68,10 @@ def get_u_destag(wrfnc, timeidx=0, method="cat", squeeze=True,
two_d=False, two_d=False,
wind_ncvar=True, wind_ncvar=True,
wspd_wdir=False) wspd_wdir=False)
@convert_units("wind", "mps") @convert_units("wind", "m s-1")
def get_v_destag(wrfnc, timeidx=0, method="cat", squeeze=True, def get_v_destag(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="mps"): units="m s-1"):
varname = either("V", "VV")(wrfnc) varname = either("V", "VV")(wrfnc)
v_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, v_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
@ -86,10 +86,10 @@ def get_v_destag(wrfnc, timeidx=0, method="cat", squeeze=True,
two_d=False, two_d=False,
wind_ncvar=True, wind_ncvar=True,
wspd_wdir=False) wspd_wdir=False)
@convert_units("wind", "mps") @convert_units("wind", "m s-1")
def get_w_destag(wrfnc, timeidx=0, method="cat", squeeze=True, def get_w_destag(wrfnc, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
units="mps"): units="m s-1"):
w_vars = extract_vars(wrfnc, timeidx, "W", method, squeeze, cache, w_vars = extract_vars(wrfnc, 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)
@ -103,7 +103,7 @@ def get_w_destag(wrfnc, timeidx=0, method="cat", squeeze=True,
wspd_wdir=True) wspd_wdir=True)
def get_destag_wspd_wdir(wrfnc, timeidx=0, method="cat", def get_destag_wspd_wdir(wrfnc, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None, squeeze=True, cache=None, meta=True, _key=None,
units="mps"): units="m s-1"):
varname = either("U", "UU")(wrfnc) varname = either("U", "UU")(wrfnc)
u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key) meta=False, _key=_key)
@ -124,7 +124,7 @@ def get_destag_wspd_wdir(wrfnc, timeidx=0, method="cat",
wspd_wdir=True) wspd_wdir=True)
def get_destag_wspd_wdir10(wrfnc, timeidx=0, method="cat", def get_destag_wspd_wdir10(wrfnc, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None, squeeze=True, cache=None, meta=True, _key=None,
units="mps"): units="m s-1"):
varname = either("U10", "UU")(wrfnc) varname = either("U10", "UU")(wrfnc)
u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, u_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache,

56
test/test_units.py

@ -0,0 +1,56 @@
import sys
import unittest as ut
import numpy.testing as nt
import numpy as np
import numpy.ma as ma
from netCDF4 import Dataset as nc
from wrf import getvar
TEST_FILE = "/Users/ladwig/Documents/wrf_files/wrfout_d01_2010-06-13_21:00:00"
# Python 3
if sys.version_info > (3,):
xrange = range
class TestUnits(ut.TestCase):
longMessage = True
def test_temp_units(self):
wrfnc = nc(TEST_FILE)
for units in ("K", "degC", "degF"):
var = getvar(wrfnc, "temp", units=units)
self.assertEqual(var.attrs["units"], units)
def test_wind_units(self):
wrfnc = nc(TEST_FILE)
for units in ("m s-1", "kt", "mi h-1", "km h-1", "ft s-1"):
var = getvar(wrfnc, "uvmet", units=units)
self.assertEqual(var.attrs["units"], units)
def test_pres_units(self):
wrfnc = nc(TEST_FILE)
for units in ("Pa", "hPa", "mb", "torr", "mmHg", "atm"):
var = getvar(wrfnc, "slp", units=units)
self.assertEqual(var.attrs["units"], units)
def test_height_units(self):
wrfnc = nc(TEST_FILE)
for units in ("m", "km", "dam", "ft", "mi"):
var = getvar(wrfnc, "z", units=units)
self.assertEqual(var.attrs["units"], units)
if __name__ == "__main__":
ut.main()
Loading…
Cancel
Save