diff --git a/wrf_open/src/python/wrf/decorators.py b/wrf_open/src/python/wrf/decorators.py index 7aaa6a6..a93ec1f 100644 --- a/wrf_open/src/python/wrf/decorators.py +++ b/wrf_open/src/python/wrf/decorators.py @@ -8,7 +8,7 @@ import numpy as np import numpy.ma as ma from .units import do_conversion, check_units -from .util import (iter_left_indexes, viewitems, from_args, npvalues) +from .util import (iter_left_indexes, viewitems, from_args, npvalues, range2) from .config import xarray_enabled if xarray_enabled(): @@ -86,7 +86,7 @@ def handle_left_iter(ref_var_expected_dims, ref_var_idx=-1, return wrapped(*args, **kwargs) # Start by getting the left-most 'extra' dims - extra_dims = [ref_var_shape[x] for x in xrange(extra_dim_num)] + extra_dims = [ref_var_shape[x] for x in range2(extra_dim_num)] out_inited = False for left_idxs in iter_left_indexes(extra_dims): @@ -135,14 +135,14 @@ def handle_left_iter(ref_var_expected_dims, ref_var_idx=-1, outdims = _calc_out_dims(res[0], extra_dims) if not isinstance(res[0], ma.MaskedArray): output = [np.empty(outdims, ref_var.dtype) - for i in xrange(len(res))] + for i in range2(len(res))] masked = False else: output = [ma.MaskedArray( np.zeros(outdims, ref_var.dtype), mask=np.zeros(outdims, np.bool_), fill_value=res[0].fill_value) - for i in xrange(len(res))] + for i in range2(len(res))] masked = True out_inited = True diff --git a/wrf_open/src/python/wrf/extension.py b/wrf_open/src/python/wrf/extension.py index c324d38..7f1164d 100755 --- a/wrf_open/src/python/wrf/extension.py +++ b/wrf_open/src/python/wrf/extension.py @@ -16,6 +16,7 @@ from ._wrfext import (f_interpz3d, f_interp2dxy,f_interp1d, from ._wrfcape import f_computecape from .decorators import (handle_left_iter, handle_casting, handle_extract_transpose) +from .util import range2 from .uvdecorator import uvmet_left_iter __all__ = ["FortranException", "computeslp", "computetk", "computetd", @@ -67,7 +68,7 @@ def computevertcross(field3d, xy, var2dz, z_var2d, missingval): var2d = np.empty((z_var2d.size, xy.shape[0]), dtype=var2dz.dtype) var2dtmp = interp2dxy(field3d, xy) - for i in xrange(xy.shape[0]): + for i in range2(xy.shape[0]): var2d[:,i] = interp1d(var2dtmp[:,i], var2dz[:,i], z_var2d, missingval) return var2d diff --git a/wrf_open/src/python/wrf/interputils.py b/wrf_open/src/python/wrf/interputils.py index afddc73..57e0c27 100644 --- a/wrf_open/src/python/wrf/interputils.py +++ b/wrf_open/src/python/wrf/interputils.py @@ -6,6 +6,7 @@ from math import floor, ceil import numpy as np from .extension import interp2dxy +from .util import range2 __all__ = ["to_positive_idxs", "calc_xy", "get_xy_z_params", "get_xy"] @@ -118,7 +119,7 @@ def calc_xy(xdim, ydim, pivot_point=None, angle=None, dx = dx/npts dy = dy/npts - for i in xrange(npts): + for i in range2(npts): xy[i,0] = x0 + i*dx xy[i,1] = y0 + i*dy @@ -153,7 +154,7 @@ def get_xy_z_params(z, pivot_point=None, angle=None, z_var2d = np.zeros((nlevels), dtype=z.dtype) z_var2d[0] = z_min - for i in xrange(1,nlevels): + for i in range2(1,nlevels): z_var2d[i] = z_var2d[0] + i*dz return xy, var2dz, z_var2d diff --git a/wrf_open/src/python/wrf/metadecorators.py b/wrf_open/src/python/wrf/metadecorators.py index 5499358..8f80a07 100644 --- a/wrf_open/src/python/wrf/metadecorators.py +++ b/wrf_open/src/python/wrf/metadecorators.py @@ -9,7 +9,7 @@ import numpy.ma as ma from .util import (viewkeys, viewitems, extract_vars, combine_with, either, from_args, arg_location, - _is_coord_var, CoordPair, npvalues) + _is_coord_var, CoordPair, npvalues, range2, ucode) from .interputils import get_xy_z_params, get_xy from .latlonutils import ij_to_ll, ll_to_ij from .config import xarray_enabled @@ -87,7 +87,7 @@ def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None, outattrs = OrderedDict() if copy_varname is not None: - outname = unicode(var_to_copy.name) + outname = ucode(var_to_copy.name) if dimnames is not None: if isinstance(dimnames, combine_with): @@ -458,15 +458,15 @@ def _set_cross_meta(wrapped, instance, args, kwargs): outattrs = OrderedDict() outdimnames = list(field3d.dims) outcoords.update(field3d.coords) - for i in xrange(-3,0,1): + for i in range2(-3,0,1): outdimnames.remove(field3d.dims[i]) del outcoords[field3d.dims[i]] # Delete any lat,lon coords - for key in viewkeys(outcoords): - if _is_coord_var(key): - del outcoords[key] + delkeys = [key for key in viewkeys(outcoords) if _is_coord_var(key)] + for key in delkeys: + del outcoords[key] outdimnames.append("vertical") outdimnames.append("xy") @@ -481,7 +481,7 @@ def _set_cross_meta(wrapped, instance, args, kwargs): pass outcoords["xy_loc"] = ("xy", [CoordPair(xy[i,0], xy[i,1]) - for i in xrange(xy.shape[-2])]) + for i in range2(xy.shape[-2])]) outcoords["vertical"] = z_var2d[:] @@ -549,14 +549,14 @@ def _set_line_meta(wrapped, instance, args, kwargs): outattrs = OrderedDict() outdimnames = list(field2d.dims) outcoords.update(field2d.coords) - for i in xrange(-2,0,1): + for i in range2(-2,0,1): outdimnames.remove(field2d.dims[i]) del outcoords[field2d.dims[i]] # Delete any lat,lon coords - for key in viewkeys(outcoords): - if _is_coord_var(key): - del outcoords[key] + delkeys = [key for key in viewkeys(outcoords) if _is_coord_var(key)] + for key in delkeys: + del outcoords[key] outdimnames.append("xy") outattrs.update(field2d.attrs) @@ -570,7 +570,7 @@ def _set_line_meta(wrapped, instance, args, kwargs): pass outcoords["xy_loc"] = ("xy", [CoordPair(xy[i,0], xy[i,1]) - for i in xrange(xy.shape[-2])]) + for i in range2(xy.shape[-2])]) else: outname = "field2d_line" @@ -652,7 +652,7 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs): outattrs = OrderedDict() outdimnames = list(field3d.dims) outcoords.update(field3d.coords) - for i in xrange(-2,0,1): + for i in range2(-2,0,1): outdimnames.remove(field3d.dims[i]) del outcoords[field3d.dims[i]] @@ -662,7 +662,7 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs): outname = "{0}_xy".format(field3d.name) outcoords["xy_loc"] = ("xy", [CoordPair(xy[i,0], xy[i,1]) - for i in xrange(xy.shape[-2])]) + for i in range2(xy.shape[-2])]) for key in ("MemoryOrder",): try: diff --git a/wrf_open/src/python/wrf/routines.py b/wrf_open/src/python/wrf/routines.py index f7abbd1..096cbd4 100644 --- a/wrf_open/src/python/wrf/routines.py +++ b/wrf_open/src/python/wrf/routines.py @@ -1,6 +1,6 @@ -from .util import _get_iterable, is_standard_wrf_var, extract_vars +from .util import _get_iterable, is_standard_wrf_var, extract_vars, viewkeys from .cape import get_2dcape, get_3dcape from .ctt import get_ctt from .dbz import get_dbz, get_max_dbz @@ -143,7 +143,7 @@ def _undo_alias(alias): return actual def _check_kargs(var, kargs): - for arg in kargs.iterkeys(): + for arg in viewkeys(kargs): if arg not in _VALID_KARGS[var]: raise ArgumentError("'%s' is an invalid keyword " "argument for '%s'" % (arg, var)) diff --git a/wrf_open/src/python/wrf/util.py b/wrf_open/src/python/wrf/util.py index 3e2c3b3..c15b512 100644 --- a/wrf_open/src/python/wrf/util.py +++ b/wrf_open/src/python/wrf/util.py @@ -8,13 +8,17 @@ from itertools import product from types import GeneratorType import datetime as dt from math import floor, copysign + from inspect import getmodule try: from inspect import signature except ImportError: - from inspect import getargspec, getargvalues - + from inspect import getargspec +try: + from inspect import getargvalues +except ImportError: + from inspect import getgeneratorlocals import numpy as np import numpy.ma as ma @@ -81,7 +85,10 @@ def _is_mapping(wrfnc): def _generator_copy(gen): funcname = gen.__name__ - argvals = getargvalues(gen.gi_frame) + try: + argvals = getargvalues(gen.gi_frame) + except NameError: + argvals = getgeneratorlocals(gen) module = getmodule(gen.gi_frame) if module is not None: @@ -177,17 +184,33 @@ def isstr(s): except NameError: return isinstance(s, str) + # Python 2 rounding behavior def _round2(x, d=0): p = 10 ** d return float(floor((x * p) + copysign(0.5, x)))/p + def py2round(x, d=0): if version_info >= (3,): return _round2(x, d) return round(x, d) + + +def range2(*args): + if version_info >= (3,): + return range(*args) + return xrange(*args) + + +def ucode(*args, **kwargs): + if version_info >= (3, ): + return str(*args, **kwargs) + + return unicode(*args, **kwargs) + # Helper to extract masked arrays from DataArrays that convert to NaN def npvalues(da): @@ -262,7 +285,7 @@ def _corners_moved(wrfnc, first_ll_corner, first_ur_corner, latvar, lonvar): lons = wrfnc.variables[lonvar] # Need to check all times - for i in xrange(lats.shape[-3]): + for i in range2(lats.shape[-3]): start_idxs = [0]*len(lats.shape) # PyNIO does not support ndim start_idxs[-3] = i start_idxs = tuple(start_idxs) @@ -459,7 +482,7 @@ def _combine_dict(wrfdict, varname, timeidx, method, meta): idx += 1 if xarray_enabled() and meta: - outname = unicode(first_array.name) + outname = str(first_array.name) # Note: assumes that all entries in dict have same coords outcoords = OrderedDict(first_array.coords) outdims = ["key"] + list(first_array.dims) @@ -580,7 +603,7 @@ def _build_data_array(wrfnc, varname, timeidx, is_moving_domain): varname) proj = [getproj(lats=lats[i,:], lons=lons[i,:], - **proj_params) for i in xrange(lats.shape[0])] + **proj_params) for i in range2(lats.shape[0])] if time_coord is not None: coords[time_coord] = (lon_coord_var.dimensions[0], @@ -778,14 +801,14 @@ def _cat_files(wrfseq, varname, timeidx, is_moving, squeeze, meta): varname) projs = [getproj(lats=lats[i,:], lons=lons[i,:], - **proj_params) for i in xrange(lats.shape[0])] + **proj_params) for i in range2(lats.shape[0])] outprojs[startidx:endidx] = np.asarray(projs, np.object)[:] startidx = endidx if xarray_enabled() and meta: - outname = unicode(first_var.name) + outname = ucode(first_var.name) outattrs = OrderedDict(first_var.attrs) outcoords = OrderedDict(first_var.coords) outdimnames = list(first_var.dims) @@ -939,7 +962,7 @@ def _join_files(wrfseq, varname, timeidx, is_moving, meta): varname) projs = [getproj(lats=lats[i,:], lons=lons[i,:], - **proj_params) for i in xrange(lats.shape[0])] + **proj_params) for i in range2(lats.shape[0])] outprojs[file_idx, 0:numtimes] = ( np.asarray(projs, np.object)[:]) @@ -954,12 +977,12 @@ def _join_files(wrfseq, varname, timeidx, is_moving, meta): outdata = np.ma.masked_values(outdata, Constants.DEFAULT_FILL) if xarray_enabled() and meta: - outname = unicode(first_var.name) + outname = ucode(first_var.name) outcoords = OrderedDict(first_var.coords) outattrs = OrderedDict(first_var.attrs) # New dimensions outdimnames = ["file"] + list(first_var.dims) - outcoords["file"] = [i for i in xrange(numfiles)] + outcoords["file"] = [i for i in range2(numfiles)] # Time needs to be multi dimensional, so use the default dimension del outcoords["Time"] @@ -1085,14 +1108,20 @@ def extract_vars(wrfnc, timeidx, varnames, method="cat", squeeze=True, method, squeeze, cache, meta) for var in varlist} +# Python 3 compatability +def _npbytes_to_str(var): + return (bytes(c).decode("utf-8") for c in var[:]) + + def _make_time(timearr): - return dt.datetime.strptime("".join(timearr[:]), "%Y-%m-%d_%H:%M:%S") + return dt.datetime.strptime("".join(_npbytes_to_str(timearr)), + "%Y-%m-%d_%H:%M:%S") def _file_times(wrfnc, timeidx): multitime = _is_multi_time_req(timeidx) if multitime: times = wrfnc.variables["Times"][:,:] - for i in xrange(times.shape[0]): + for i in range2(times.shape[0]): yield _make_time(times[i,:]) else: times = wrfnc.variables["Times"][timeidx,:] @@ -1148,7 +1177,7 @@ def get_left_indexes(ref_var, expected_dims): if (extra_dim_num == 0): return [] - return tuple([ref_var.shape[x] for x in xrange(extra_dim_num)]) + return tuple([ref_var.shape[x] for x in range2(extra_dim_num)]) def iter_left_indexes(dims): """A generator which yields the iteration tuples for a sequence of @@ -1163,7 +1192,7 @@ def iter_left_indexes(dims): - dims - a sequence of dimensions sizes (e.g. ndarry.shape) """ - arg = [xrange(dim) for dim in dims] + arg = [range2(dim) for dim in dims] for idxs in product(*arg): yield idxs @@ -1236,26 +1265,26 @@ class CoordPair(object): def from_args(func, argnames, *args, **kwargs): - """Parses the function args and kargs looking for the desired argument - value. Otherwise, the value is taken from the default keyword argument - using the arg spec. + """Parses the function args and kargs looking for the desired argument + value. Otherwise, the value is taken from the default keyword argument + using the arg spec. + + """ + if isstr(argnames): + arglist = [argnames] + else: + arglist = argnames + + result = {} + for argname in arglist: + arg_loc = arg_location(func, argname, args, kwargs) - """ - if isstr(argnames): - arglist = [argnames] + if arg_loc is not None: + result[argname] = arg_loc[0][arg_loc[1]] else: - arglist = argnames - - result = {} - for argname in arglist: - arg_loc = arg_location(func, argname, args, kwargs) - - if arg_loc is not None: - result[argname] = arg_loc[0][arg_loc[1]] - else: - result[argname] = None - - return result + result[argname] = None + + return result def _args_to_list2(func, args, kwargs): argspec = getargspec(func) @@ -1281,7 +1310,7 @@ def _args_to_list3(func, args, kwargs): bound = sig.bind(*args, **kwargs) bound.apply_defaults() - return [x for x in bound.arguments.values] + return [x for x in bound.arguments.values()] def args_to_list(func, args, kwargs): @@ -1309,10 +1338,15 @@ def _arg_location2(func, argname, args, kwargs): def _arg_location3(func, argname, args, kwargs): sig = signature(func) - params = list(sig.params.keys()) + params = list(sig.parameters.keys()) + list_args = _args_to_list3(func, args, kwargs) - result_idx = params.index(argname) + try: + result_idx = params.index(argname) + except ValueError: + return None + return list_args, result_idx diff --git a/wrf_open/src/python/wrf/uvdecorator.py b/wrf_open/src/python/wrf/uvdecorator.py index 12d9b26..cc4ccc6 100644 --- a/wrf_open/src/python/wrf/uvdecorator.py +++ b/wrf_open/src/python/wrf/uvdecorator.py @@ -6,7 +6,7 @@ import numpy as np import wrapt from .destag import destagger -from .util import iter_left_indexes +from .util import iter_left_indexes, range2 __all__ = ["uvmet_left_iter"] @@ -53,13 +53,13 @@ def uvmet_left_iter(): return wrapped(u, v, lat, lon, cen_long, cone) # Start by getting the left-most 'extra' dims - outdims = [u.shape[x] for x in xrange(extra_dim_num)] + outdims = [u.shape[x] for x in range2(extra_dim_num)] extra_dims = list(outdims) # Copy the left-most dims for iteration # Append the right-most dimensions outdims += [2] # For u/v components - outdims += [u.shape[x] for x in xrange(-num_right_dims,0,1)] + outdims += [u.shape[x] for x in range2(-num_right_dims,0,1)] output = np.empty(outdims, u.dtype) diff --git a/wrf_open/test/ipynb/WRF_python_demo.ipynb b/wrf_open/test/ipynb/WRF_python_demo.ipynb index c5ed0a0..7e490e5 100644 --- a/wrf_open/test/ipynb/WRF_python_demo.ipynb +++ b/wrf_open/test/ipynb/WRF_python_demo.ipynb @@ -343,8 +343,8 @@ }, "outputs": [], "source": [ - "\n", - "for key in vard.keys():\n", + "keys = [x for x in vard.keys()]\n", + "for key in keys:\n", " del vard[key]" ] }, @@ -727,7 +727,7 @@ "fig = plt.figure(figsize=(20,8))\n", "ax = plt.axes([0.1,0.1,0.8,0.8])\n", "\n", - "p_vert.plot.contour(ax=ax, levels=[0 + 50*n for n in xrange(20)], cmap=get_cmap(\"viridis\"))\n", + "p_vert.plot.contour(ax=ax, levels=[0 + 50*n for n in range(20)], cmap=get_cmap(\"viridis\"))\n", "\n", "\n" ] @@ -885,21 +885,21 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python 3", "language": "python", - "name": "python2" + "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.11" + "pygments_lexer": "ipython3", + "version": "3.5.0rc4" } }, "nbformat": 4,