diff --git a/doc/source/api.rst b/doc/source/api.rst new file mode 100644 index 0000000..a205c49 --- /dev/null +++ b/doc/source/api.rst @@ -0,0 +1,9 @@ +API Reference +============= + + +.. toctree:: + :maxdepth: 1 + + user_api/index.rst + internal_api/index.rst diff --git a/doc/source/api/generated/README b/doc/source/api/generated/README deleted file mode 100644 index 4d0652a..0000000 --- a/doc/source/api/generated/README +++ /dev/null @@ -1 +0,0 @@ -This location contains the RST files created by Sphinx AutoSummary for the API. diff --git a/doc/source/api/index.rst b/doc/source/api/index.rst deleted file mode 100644 index 25a5967..0000000 --- a/doc/source/api/index.rst +++ /dev/null @@ -1,55 +0,0 @@ -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 - - - \ No newline at end of file diff --git a/doc/source/index.rst b/doc/source/index.rst index ed8c07a..cf1cd92 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -11,7 +11,7 @@ Contents: .. toctree:: :maxdepth: 1 - api/index + ./api diff --git a/doc/source/internal_api/index.rst b/doc/source/internal_api/index.rst new file mode 100644 index 0000000..cc2aed6 --- /dev/null +++ b/doc/source/internal_api/index.rst @@ -0,0 +1,74 @@ +Internal API +============= + +Algorithm Decorators +-------------------- + +The decorators below are used for performing common operations related to +diagnostic and interpolation calculations. + +.. autosummary:: + :nosignatures: + :toctree: ./generated/ + + wrf.convert_units + wrf.left_iteration + wrf.cast_type + wrf.extract_and_transpose + wrf.check_args + wrf.uvmet_left_iter + wrf.cape_left_iter + wrf.cloudfrac_left_iter + + +Metadata Decorators +-------------------- + +The decorators below are used for performing common operations related to +setting metadata. + +.. autosummary:: + :nosignatures: + :toctree: ./generated/ + + wrf.copy_and_set_metadata + wrf.set_wind_metadata + wrf.set_cape_metadata + wrf.set_cloudfrac_metadata + wrf.set_latlon_metadata + wrf.set_height_metadata + wrf.set_interp_metadata + wrf.set_alg_metadata + wrf.set_uvmet_alg_metadata + wrf.set_cape_alg_metadata + wrf.set_cloudfrac_alg_metadata + wrf.set_destag_metadata + + +Decorator Utilities +-------------------- + +The routines below are used within decorators. + +.. autosummary:: + :nosignatures: + :toctree: ./generated/ + + wrf.either + wrf.combine_dims + wrf.from_var + wrf.from_args + wrf.args_to_list + wrf.arg_location + +Miscellaneous Classes +---------------------- + + +.. autosummary:: + :nosignatures: + :toctree: ./generated/ + + wrf.IterWrapper + + diff --git a/doc/source/user_api/index.rst b/doc/source/user_api/index.rst new file mode 100644 index 0000000..acf174d --- /dev/null +++ b/doc/source/user_api/index.rst @@ -0,0 +1,158 @@ +User API +============= + +Diagnostic Routine +------------------- + +The routine below is the primary routine for extracting variables from a +WRF-ARW NetCDF file (or sequence of files) and performing diagnostic +calculations. + +.. autosummary:: + :nosignatures: + :toctree: ./generated/ + + wrf.getvar + + +Interpolation Routines +---------------------- + +The routines below are the primary routines used for performing interpolation +calculations. + +.. autosummary:: + :nosignatures: + :toctree: ./generated/ + + wrf.interplevel + wrf.vertcross + wrf.interpline + wrf.vinterp + + +Numpy Extraction Routine +-------------------------- + +The routine below is used to extract a :class:`numpy.ndarray` from a +:class:`xarray.DataArray`. This routine must be used before passing +the array object to a compiled extension. Otherwise, unusually crashes +may occur. + +.. autosummary:: + :nosignatures: + :toctree: ./generated/ + + wrf.npvalues + + +Variable Extraction Routines +----------------------------- + +The routines below are primarily used internally by :meth:`wrf.getvar`, but +some users may find them useful to manually extract variables from a +WRF NetCDF file (or a sequence of NetCDF files). + +.. autosummary:: + :nosignatures: + :toctree: ./generated/ + + wrf.extract_vars + wrf.combine_files + wrf.extract_dim + wrf.extract_extract_global_attrs + wrf.extract_times + + + +Raw Diagnostic Routines +------------------------ + +The routines below can be used when working with variables that are not +contained in a WRF-ARW NetCDF file. They can also be used with non-WRF data. +However, if you are working with WRF-ARW NetCDF files, +use :meth:`wrf.getvar` instead. + +Keep in mind that these routines were developed for WRF-ARW, so your mileage +may vary when working with non-WRF data. Also, the vast majority of these +routines do not allow for missing values in any of the input arrays, so make +sure they are removed before calling these routines. + + + +.. autosummary:: + :nosignatures: + :toctree: ./generated/ + + wrf.xy + wrf.interp1d + wrf.interp2dxy + wrf.interpz3d + wrf.slp + wrf.temp + wrf.tk + wrf.td + wrf.rh + wrf.uvmet + wrf.smooth2d + wrf.cape_2d + wrf.cape_3d + wrf.cloudfrac + wrf.ctt + wrf.dbz + wrf.srhel + wrf.udhel + wrf.avo + wrf.pvo + wrf.eth + wrf.wetbulb + wrf.tvirtual + wrf.omega + wrf.pw + + +CoordPair Class +---------------------- + +The class below is used for coordinate metadata. + +.. autosummary:: + :nosignatures: + :toctree: ./generated/ + + wrf.CoordPair + + +Miscellaneous Routines +----------------------- + +The routines below are primarily used internally, but some users may find +them helpful. + +.. autosummary:: + :nosignatures: + :toctree: ./generated/ + + wrf.is_time_coord_var + wrf.get_coord_pairs + wrf.is_multi_time_req + wrf.is_multi_file + wrf.has_time_coord + wrf.is_mapping + wrf.latlon_coordvars + wrf.is_coordvar + wrf.get_iterable + wrf.is_moving_domain + wrf.npbytes_to_str + wrf.is_standard_wrf_var + wrf.is_staggered + wrf.get_left_indexes + wrf.iter_left_indexes + wrf.get_right_slices + wrf.get_proj_params + wrf.psafilepath + wrf.get_id + + + + \ No newline at end of file diff --git a/src/wrf/api.py b/src/wrf/api.py index a5ed04b..b42f1ba 100644 --- a/src/wrf/api.py +++ b/src/wrf/api.py @@ -13,11 +13,26 @@ from .interp import (interplevel, vertcross, interpline, vinterp) from .latlon import (xy_to_ll, ll_to_xy, xy_to_ll_proj, ll_to_xy_proj) from .py3compat import (viewitems, viewkeys, viewvalues, isstr, py2round, py3range, ucode) -from .util import (npvalues, extract_global_attrs, - extract_dim, extract_vars, extract_times, combine_files, - is_staggered, get_left_indexes, iter_left_indexes, - get_right_slices, get_proj_params) +from .util import (npvalues, extract_global_attrs, is_standard_wrf_var, + extract_dim, extract_vars, extract_times, combine_files, + extract_times, npbytes_to_str, is_moving_domain, + is_staggered, get_left_indexes, iter_left_indexes, + get_right_slices, get_proj_params, from_args, + args_to_list, arg_location, psafilepath, get_id, + from_var, combine_dims, either, get_iterable, + IterWrapper, is_coordvar, latlon_coordvars, is_mapping, + has_time_coord, is_multi_file, is_multi_time_req, + get_coord_pairs, is_time_coord_var) from .coordpair import CoordPair +from decorators import (convert_units, left_iteration, cast_type, + extract_and_transpose, check_args) +from specialdec import (uvmet_left_iter, cape_left_iter, cloudfrac_left_iter) +from metadecorators import (copy_and_set_metadata, set_wind_metadata, + set_cloudfrac_metadata, set_latlon_metadata, + set_height_metadata, set_interp_metadata, + set_alg_metadata, set_uvmet_alg_metadata, + set_cape_alg_metadata, set_cloudfrac_alg_metadata, + set_destag_metadata) from .version import __version__ __all__ = [] @@ -36,10 +51,25 @@ __all__ += ["interplevel", "vertcross", "interpline", "vinterp"] __all__ += ["xy_to_ll", "ll_to_xy", "xy_to_ll_proj", "ll_to_xy_proj"] __all__ += ["viewitems", "viewkeys", "viewvalues", "isstr", "py2round", "py3range", "ucode"] -__all__ += ["npvalues", "extract_global_attrs", - "extract_dim", "extract_vars", "extract_times", "combine_files", +__all__ += ["npvalues", "extract_global_attrs", "is_standard_wrf_var", + "extract_dim", "extract_vars", "extract_times", "combine_files", + "extract_times", "npbytes_to_str", "is_moving_domain", "is_staggered", "get_left_indexes", "iter_left_indexes", - "get_right_slices", "get_proj_params"] + "get_right_slices", "get_proj_params", "from_args", + "args_to_list", "arg_location", "psafilepath", "get_id", + "from_var", "combine_dims", "either", "get_iterable", + "IterWrapper", "is_coordvar", "latlon_coordvars", "is_mapping", + "has_time_coord", "is_multi_file", "is_multi_time_req", + "get_coord_pairs", "is_time_coord_var"] +__all__ += ["convert_units", "left_iteration", "cast_type", + "extract_and_transpose", "check_args"] +__all__ += ["uvmet_left_iter", "cape_left_iter", "cloudfrac_left_iter"] +__all__ += ["copy_and_set_metadata", "set_wind_metadata", + "set_cloudfrac_metadata", "set_latlon_metadata", + "set_height_metadata", "set_interp_metadata", + "set_alg_metadata", "set_uvmet_alg_metadata", + "set_cape_alg_metadata", "set_cloudfrac_alg_metadata", + "set_destag_metadata"] __all__ += ["CoordPair"] __all__ += ["__version__"] diff --git a/src/wrf/computation.py b/src/wrf/computation.py index 27c8984..88549d2 100644 --- a/src/wrf/computation.py +++ b/src/wrf/computation.py @@ -440,7 +440,7 @@ def temp(pres, theta, meta=True, units="K"): def tk(pres, theta, meta=True): """Return the temperature in Kelvin. - This is an alias for :meth:`wrf.temp(pres, theta, meta, units='K'). This + This is an alias for *wrf.temp(pres, theta, meta, units='K')*. This function is here for users that are familiar with NCL's wrf_tk. This is the raw computational algorithm and does not extract any variables @@ -1181,7 +1181,7 @@ def dbz(pres, tkel, qv, qr, qs=None, qg=None, use_varint=False, in [K] with same dimensionality as *pres*. qv (:class:`xarray.DataArray` or :class:`numpy.ndarray`): Water vapor - mixing ratio in [kg/kg] with the same dimensionality as *pres_hpa*. + mixing ratio in [kg/kg] with the same dimensionality as *pres*. qr (:class:`xarray.DataArray` or :class:`numpy.ndarray`): Rain water vapor mixing ratio in [kg/kg] with the same dimensionality as diff --git a/src/wrf/constants.py b/src/wrf/constants.py index 50d0d9f..c8270db 100755 --- a/src/wrf/constants.py +++ b/src/wrf/constants.py @@ -6,6 +6,7 @@ import numpy as np from .py3compat import viewitems from wrf._wrffortran import wrf_constants +#: Indicates that all times should be used in a diagnostic routine. ALL_TIMES = None class Constants(object): diff --git a/src/wrf/decorators.py b/src/wrf/decorators.py index 25301e2..7add8b2 100644 --- a/src/wrf/decorators.py +++ b/src/wrf/decorators.py @@ -32,12 +32,11 @@ def convert_units(unit_type, alg_unit): Returns: :class:`numpy.ndarray`: The wrapped function's output in the desired - units. + units. """ @wrapt.decorator def func_wrapper(wrapped, instance, args, kwargs): - desired_units = from_args(wrapped, "units", *args, **kwargs)["units"] u_cleaned = dealias_and_clean_unit(desired_units) check_units(u_cleaned, unit_type) @@ -117,8 +116,8 @@ def left_iteration(ref_var_expected_dims, 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. + alg_dtype (:class:`numpy.dtype` or :obj:`str`): The numpy data type + used in the wrapped function. cast_output (:obj:`bool`): Set to True to cast the wrapped function's output to the same type as the reference variable. @@ -271,7 +270,7 @@ def cast_type(ref_idx=0, arg_idxs=None, karg_names=None, 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 + alg_dtype (:class:`numpy.dtype` or :obj:`str`): The numpy data type used in the wrapped function. outviews (:obj:`str` or a sequence): A single key or sequence of keys diff --git a/src/wrf/destag.py b/src/wrf/destag.py index 169481c..3d090ae 100755 --- a/src/wrf/destag.py +++ b/src/wrf/destag.py @@ -24,7 +24,7 @@ def destagger(var, stagger_dim, meta=False): meta (:obj:`bool`, optional): Set to False to disable metadata and return :class:`numpy.ndarray` instead of - :class:`xarray.DataArray`. Default is True. + :class:`xarray.DataArray`. Default is False. Returns: diff --git a/src/wrf/extension.py b/src/wrf/extension.py index 2781ddc..1a6e1ed 100755 --- a/src/wrf/extension.py +++ b/src/wrf/extension.py @@ -17,7 +17,7 @@ from .decorators import (left_iteration, cast_type, extract_and_transpose, check_args) from .util import combine_dims, npbytes_to_str, psafilepath from .py3compat import py3range -from .specialdec import (uvmet_left_iter_nocopy, cape_left_iter, +from .specialdec import (uvmet_left_iter, cape_left_iter, cloudfrac_left_iter) class FortranError(Exception): @@ -360,7 +360,7 @@ def _eth(qv, tk, p, outview=None): return result -@uvmet_left_iter_nocopy() +@uvmet_left_iter() @cast_type(arg_idxs=(0,1,2,3)) @extract_and_transpose() def _uvmet(u, v, lat, lon, cen_long, cone, isstag=0, has_missing=False, diff --git a/src/wrf/interp.py b/src/wrf/interp.py index dd76ea5..06ff1a1 100755 --- a/src/wrf/interp.py +++ b/src/wrf/interp.py @@ -90,7 +90,7 @@ def interplevel(field3d, vert, desiredlev, missing=Constants.DEFAULT_FILL, @set_interp_metadata("cross") -def vertcross(field3d, vert, missing=Constants.DEFAULT_FILL, +def vertcross(field3d, vert, levels=None, missing=Constants.DEFAULT_FILL, pivot_point=None, angle=None, start_point=None, end_point=None, latlon=False, cache=None, meta=True): @@ -101,10 +101,12 @@ def vertcross(field3d, vert, missing=Constants.DEFAULT_FILL, *pivot_point* and *angle* parameters, or the *start_point* and *end_point* 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 - maximum vertical distance from top to bottom. If all vertical levels are - desired, use the lower level :meth:`wrf.interp2dxy` function. + The vertical levels for the cross section are fixed if *levels* is not + specified, and are determined by dividing the vertical coordinate in to + grid boxes of roughly 1% of the maximum vertical distance from top to + bottom. Otherwise, the *levels*argument can be used to specify specific + vertical levels. If all vertical levels are desired, use the raw + :meth:`wrf.interp2dxy` function. See Also: @@ -121,6 +123,10 @@ def vertcross(field3d, vert, missing=Constants.DEFAULT_FILL, pressure or height. This array must have the same dimensionality as *field3d* + levels (sequence, optional): A sequence of :obj:`float` for the desired + vertical levels in the output array. If None, a fixed set of + vertical levels is provided. Default is None. + missing (:obj:`float`): The fill value to use for the output. Default is :data:`wrf.Constants.DEFAULT_FILL`. @@ -149,7 +155,7 @@ def vertcross(field3d, vert, missing=Constants.DEFAULT_FILL, two-dimensional latitude and longitude coordinates along the same horizontal line and include this information in the metadata (if enabled). This can be helpful for plotting. Default is False. - + 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 @@ -182,7 +188,8 @@ def vertcross(field3d, vert, missing=Constants.DEFAULT_FILL, z_var2d = cache["z_var2d"] except (KeyError, TypeError): xy, var2dz, z_var2d = get_xy_z_params(npvalues(vert), pivot_point, - angle, start_point, end_point) + angle, start_point, end_point, + levels) if not multi: result = _vertcross(field3d, xy, var2dz, z_var2d, missing) diff --git a/src/wrf/interputils.py b/src/wrf/interputils.py index a41d2b5..2f866bf 100644 --- a/src/wrf/interputils.py +++ b/src/wrf/interputils.py @@ -180,7 +180,8 @@ def _calc_xy(xdim, ydim, 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, + levels=None): """Return the cross section parameters. This function returns the xy horizontal cross section line coordinates, @@ -215,6 +216,10 @@ def get_xy_z_params(z, pivot_point=None, angle=None, [x, y] (or [west_east, south_north]), which indicates the end x,y location through which the plane will pass. + levels (sequence): A sequence of :obj:`float` for the desired + vertical levels in the output array. If None, a fixed set of + vertical levels is provided. Default is None. + Returns: :obj:`tuple`: A tuple containing the xy horizontal cross section @@ -234,22 +239,25 @@ def get_xy_z_params(z, pivot_point=None, angle=None, idx1 = tuple([0]*extra_dim_num + [0,0]) idx2 = tuple([0]*extra_dim_num + [-1,0]) - # interp to constant z grid - if(var2dz[idx1] > var2dz[idx2]): # monotonically decreasing coordinate - z_max = floor(np.amax(z)/10) * 10 # bottom value - z_min = ceil(np.amin(z)/10) * 10 # top value - dz = 10 - nlevels = int((z_max - z_min)/dz) - z_var2d = np.zeros((nlevels), dtype=z.dtype) - z_var2d[0] = z_max - dz = -dz + if levels is None: + # interp to constant z grid + if(var2dz[idx1] > var2dz[idx2]): # monotonically decreasing coordinate + z_max = floor(np.amax(z)/10) * 10 # bottom value + z_min = ceil(np.amin(z)/10) * 10 # top value + dz = 10 + nlevels = int((z_max - z_min)/dz) + z_var2d = np.zeros((nlevels), dtype=z.dtype) + z_var2d[0] = z_max + dz = -dz + else: + z_max = np.amax(z) + z_min = 0. + dz = 0.01*z_max + nlevels = int(z_max/dz) + z_var2d = np.zeros((nlevels), dtype=z.dtype) + z_var2d[0] = z_min else: - z_max = np.amax(z) - z_min = 0. - dz = 0.01*z_max - nlevels = int(z_max/dz) - z_var2d = np.zeros((nlevels), dtype=z.dtype) - z_var2d[0] = z_min + z_var2d = np.asarray(levels) for i in py3range(1,nlevels): z_var2d[i] = z_var2d[0] + i*dz diff --git a/src/wrf/specialdec.py b/src/wrf/specialdec.py index cb553ad..15536aa 100644 --- a/src/wrf/specialdec.py +++ b/src/wrf/specialdec.py @@ -13,7 +13,7 @@ if xarray_enabled(): from xarray import DataArray -def uvmet_left_iter_nocopy(alg_dtype=np.float64): +def uvmet_left_iter(alg_dtype=np.float64): """A decorator to handle iterating over the leftmost dimensions for the uvmet diagnostic. diff --git a/src/wrf/util.py b/src/wrf/util.py index 79df6b3..8f3a7ac 100644 --- a/src/wrf/util.py +++ b/src/wrf/util.py @@ -81,7 +81,7 @@ def get_coord_pairs(coord_varname): Args: - coord_varname (:obj:`strq): The coordinate variable name. + coord_varname (:obj:`str`): The coordinate variable name. Returns: @@ -1980,17 +1980,17 @@ def combine_files(wrfin, varname, timeidx, is_moving=None, Two aggregation methodologies are available to combine the sequence: - 'cat': Concatenate the files along the 'Time' dimension. The Time - dimension will be the leftmost dimension. No sorting is performed, - so files must be properly ordered in the sequence prior to calling this - function. + dimension will be the leftmost dimension. No sorting is performed, + so files must be properly ordered in the sequence prior to calling + this function. - 'join': Join the files by creating a new leftmost dimension for the - file index. In situations where there are multiple files with - multiple times, and the last file contains less times than the previous - files, the remaining arrays will be arrays filled with missing values. - There are checks in place within the wrf-python algorithms to look for - these missing arrays, but be careful when calling compiled routines - outside of wrf-python. + file index. In situations where there are multiple files with + multiple times, and the last file contains less times than the + previous files, the remaining arrays will be arrays filled with + missing values. There are checks in place within the wrf-python + algorithms to look for these missing arrays, but be careful when + calling compiled routines outside of wrf-python. Args: @@ -2506,13 +2506,13 @@ def get_left_indexes(var, expected_dims): if (extra_dim_num == 0): return [] - return tuple([var.shape[x] for x in py3range(extra_dim_num)]) + return var.shape[0:extra_dim_num] def iter_left_indexes(dims): """Yield the iteration tuples for a sequence of dimensions sizes. - For example, if *dims* is (3,3), then this will yield: + For example, if *dims* is (2,2), then this will yield: (0,0), (0,1), (1,0), (1,1) @@ -2526,7 +2526,6 @@ def iter_left_indexes(dims): :obj:`tuple`: The leftmost indexing iteration sizes. - """ arg = [py3range(dim) for dim in dims] for idxs in product(*arg): @@ -2620,16 +2619,16 @@ def get_proj_params(wrfin, timeidx=0, varname=None): def from_args(func, argnames, *args, **kwargs): """Return a mapping of argument name to value for the called function. - This function parses the function *args and **kwargs to obtain the desired - argument value. If the argument has not been passed in, the value is taken - from the default keyword argument value. + This function parses the function \*args and \*\*kwargs to obtain the \ + desired argument value. If the argument has not been passed in, the value + is taken from the default keyword argument value. This func is usually called from within a decorator. Note: This function currently does not work with functions that contain - *args or **kwargs arguments. + \*args or \*\*kwargs arguments. Args: @@ -2745,11 +2744,12 @@ def _args_to_list3(func, args, kwargs): def args_to_list(func, args, kwargs): """Return all of the function arguments, including defaults, as a list. - The result can then be passed to the function via *result. + The result can then be passed to the function via *result*. + Note: This function currently does not work with functions that contain - *args or **kwargs arguments. + \*args or \*\*kwargs arguments. Args: