diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index 51adfb9d8d..79223944a2 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -125,6 +125,8 @@ This document explains the changes made to Iris for this release #. `@HGWright`_ fixed some typo's from Gitwash. (:pull:`5145`) +#. `@Esadek-MO`_ added notes to function docstrings to + to clarify if the function preserves laziness or not. (:pull:`5137`) 💼 Internal =========== diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py index 173487cfb0..9444d38199 100644 --- a/lib/iris/analysis/__init__.py +++ b/lib/iris/analysis/__init__.py @@ -2032,6 +2032,7 @@ def interp_order(length): result = cube.collapsed('longitude', iris.analysis.MEDIAN) + This aggregator handles masked data, but NOT lazy data. For lazy aggregation, please try :obj:`~.PERCENTILE`. diff --git a/lib/iris/pandas.py b/lib/iris/pandas.py index 417b6b11de..522c216432 100644 --- a/lib/iris/pandas.py +++ b/lib/iris/pandas.py @@ -159,6 +159,8 @@ def as_cube( as_cube(series, calendars={0: cf_units.CALENDAR_360_DAY}) as_cube(data_frame, calendars={1: cf_units.CALENDAR_STANDARD}) + Since this function converts to/from a Pandas object, laziness will not be preserved. + """ message = ( "iris.pandas.as_cube has been deprecated, and will be removed in a " @@ -240,6 +242,8 @@ def as_cubes( :class:`dask.dataframe.DataFrame`\\ s are not supported. + Since this function converts to/from a Pandas object, laziness will not be preserved. + Examples -------- >>> from iris.pandas import as_cubes @@ -599,6 +603,10 @@ def as_series(cube, copy=True): If you have a large array that cannot be copied, make sure it is not masked and use copy=False. + Notes + ------ + Since this function converts to/from a Pandas object, laziness will not be preserved. + """ message = ( "iris.pandas.as_series has been deprecated, and will be removed in a " @@ -809,6 +817,10 @@ def as_data_frame( 419903 298.995148 Name: surface_temperature, Length: 419904, dtype: float32 + Notes + ------ + Since this function converts to/from a Pandas object, laziness will not be preserved. + """ def merge_metadata(meta_var_list): diff --git a/lib/iris/plot.py b/lib/iris/plot.py index f87d74b020..47e345b83c 100644 --- a/lib/iris/plot.py +++ b/lib/iris/plot.py @@ -1112,6 +1112,11 @@ def contour(cube, *args, **kwargs): See :func:`matplotlib.pyplot.contour` for details of other valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ result = _draw_2d_from_points("contour", None, cube, *args, **kwargs) return result @@ -1136,6 +1141,11 @@ def contourf(cube, *args, **kwargs): See :func:`matplotlib.pyplot.contourf` for details of other valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ coords = kwargs.get("coords") kwargs.setdefault("antialiased", True) @@ -1200,6 +1210,11 @@ def default_projection(cube): import matplotlib.pyplot as plt ax = plt.ax(projection=default_projection(cube)) + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ # XXX logic seems flawed, but it is what map_setup did... cs = cube.coord_system("CoordSystem") @@ -1218,6 +1233,11 @@ def default_projection_extent(cube, mode=iris.coords.POINT_MODE): points, or the limits of the cell's bounds. The default is iris.coords.POINT_MODE. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ extents = cartography._xy_range(cube, mode) xlim = extents[0] @@ -1255,7 +1275,13 @@ def _fill_orography(cube, coords, mode, vert_plot, horiz_plot, style_args): def orography_at_bounds(cube, facecolor="#888888", coords=None, axes=None): - """Plots orography defined at cell boundaries from the given Cube.""" + """Plots orography defined at cell boundaries from the given Cube. + + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ # XXX Needs contiguous orography corners to work. raise NotImplementedError( @@ -1288,7 +1314,13 @@ def horiz_plot(v_coord, orography, style_args): def orography_at_points(cube, facecolor="#888888", coords=None, axes=None): - """Plots orography defined at sample points from the given Cube.""" + """Plots orography defined at sample points from the given Cube. + + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ style_args = {"facecolor": facecolor} @@ -1334,6 +1366,11 @@ def outline(cube, coords=None, color="k", linewidth=None, axes=None): The axes to use for drawing. Defaults to the current axes if none provided. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ result = _draw_2d_from_bounds( "pcolormesh", @@ -1376,6 +1413,11 @@ def pcolor(cube, *args, **kwargs): See :func:`matplotlib.pyplot.pcolor` for details of other valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ kwargs.setdefault("antialiased", True) kwargs.setdefault("snap", False) @@ -1410,6 +1452,11 @@ def pcolormesh(cube, *args, **kwargs): See :func:`matplotlib.pyplot.pcolormesh` for details of other valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ result = _draw_2d_from_bounds("pcolormesh", cube, *args, **kwargs) return result @@ -1435,6 +1482,11 @@ def points(cube, *args, **kwargs): See :func:`matplotlib.pyplot.scatter` for details of other valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ def _scatter_args(u, v, data, *args, **kwargs): @@ -1526,6 +1578,11 @@ def barbs(u_cube, v_cube, *args, **kwargs): See :func:`matplotlib.pyplot.barbs` for details of other valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ # # TODO: check u + v cubes for compatibility. @@ -1576,6 +1633,11 @@ def quiver(u_cube, v_cube, *args, **kwargs): See :func:`matplotlib.pyplot.quiver` for details of other valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ # # TODO: check u + v cubes for compatibility. @@ -1622,6 +1684,11 @@ def plot(*args, **kwargs): See :func:`matplotlib.pyplot.plot` for details of additional valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ if "coords" in kwargs: raise TypeError( @@ -1654,6 +1721,11 @@ def scatter(x, y, *args, **kwargs): See :func:`matplotlib.pyplot.scatter` for details of additional valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ # here we are more specific about argument types than generic 1d plotting if not isinstance(x, (iris.cube.Cube, iris.coords.Coord)): @@ -1689,6 +1761,11 @@ def fill_between(x, y1, y2, *args, **kwargs): See :func:`matplotlib.pyplot.fill_between` for details of additional valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ # here we are more specific about argument types than generic 1d plotting if not isinstance(x, (iris.cube.Cube, iris.coords.Coord)): @@ -1721,6 +1798,11 @@ def hist(x, *args, **kwargs): See :func:`matplotlib.pyplot.hist` for details of additional valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ if isinstance(x, iris.cube.Cube): data = x.data @@ -1767,6 +1849,11 @@ def symbols(x, y, symbols, size, axes=None, units="inches"): * units: ['inches', 'points'] The unit for the symbol size. + Notes + ------ + This function does maintain laziness when called; it doesn't realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ if axes is None: axes = plt.gca() @@ -1892,6 +1979,11 @@ def animate(cube_iterator, plot_func, fig=None, **kwargs): >>> ani = iplt.animate(cube_iter, qplt.contourf) >>> iplt.show() + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ kwargs.setdefault("interval", 100) coords = kwargs.pop("coords", None) diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index c992cfdbf0..9209d4b3b7 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -174,6 +174,11 @@ def contour(cube, *args, **kwargs): See :func:`iris.plot.contour` for details of valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ coords = kwargs.get("coords") axes = kwargs.get("axes") @@ -201,6 +206,10 @@ def contourf(cube, *args, **kwargs): See :func:`iris.plot.contourf` for details of valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. """ coords = kwargs.get("coords") axes = kwargs.get("axes") @@ -229,6 +238,11 @@ def outline(cube, coords=None, color="k", linewidth=None, axes=None): The width of the lines showing the cell outlines. If None, the default width in patch.linewidth in matplotlibrc is used. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ result = iplt.outline( cube, color=color, linewidth=linewidth, coords=coords, axes=axes @@ -244,6 +258,10 @@ def pcolor(cube, *args, **kwargs): See :func:`iris.plot.pcolor` for details of valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. """ coords = kwargs.get("coords") axes = kwargs.get("axes") @@ -258,6 +276,11 @@ def pcolormesh(cube, *args, **kwargs): See :func:`iris.plot.pcolormesh` for details of valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ coords = kwargs.get("coords") axes = kwargs.get("axes") @@ -272,6 +295,11 @@ def points(cube, *args, **kwargs): See :func:`iris.plot.points` for details of valid keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ coords = kwargs.get("coords") axes = kwargs.get("axes") @@ -288,6 +316,11 @@ def plot(*args, **kwargs): See :func:`iris.plot.plot` for details of valid arguments and keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ axes = kwargs.get("axes") result = iplt.plot(*args, **kwargs) @@ -303,6 +336,11 @@ def scatter(x, y, *args, **kwargs): See :func:`iris.plot.scatter` for details of valid arguments and keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ axes = kwargs.get("axes") result = iplt.scatter(x, y, *args, **kwargs) @@ -317,6 +355,10 @@ def fill_between(x, y1, y2, *args, **kwargs): See :func:`iris.plot.fill_between` for details of valid arguments and keyword arguments. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. """ axes = kwargs.get("axes") result = iplt.fill_between(x, y1, y2, *args, **kwargs) @@ -330,6 +372,11 @@ def hist(x, *args, **kwargs): See :func:`iris.plot.hist` for details of valid arguments and keyword arguments. + + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. """ axes = kwargs.get("axes") result = iplt.hist(x, *args, **kwargs) diff --git a/lib/iris/util.py b/lib/iris/util.py index d2af4c1085..7900b734a8 100644 --- a/lib/iris/util.py +++ b/lib/iris/util.py @@ -70,6 +70,11 @@ def broadcast_to_shape(array, shape, dim_map): # a is an array of shape (48, 96) result = broadcast_to_shape(a, (96, 48, 12), (1, 0)) + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ if len(dim_map) != array.ndim: # We must check for this condition here because we cannot rely on @@ -142,6 +147,11 @@ def delta(ndarray, dimension, circular=False): >>> iris.util.delta(original, 0, circular=360) array([90, 90, 90, 90]) + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ if circular is not False: _delta = np.roll(ndarray, -1, axis=dimension) @@ -192,6 +202,11 @@ def describe_diff(cube_a, cube_b, output_file=None): two cubes will merge requires additional logic that is beyond the scope of this function. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ if output_file is None: @@ -244,6 +259,11 @@ def guess_coord_axis(coord): Returns: 'T', 'Z', 'Y', 'X', or None. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ axis = None @@ -305,6 +325,11 @@ def rolling_window(a, window=1, step=1, axis=-1): array([[ 1., 2., 3.], [ 6., 7., 8.]]) + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ # NOTE: The implementation of this function originates from # https://github.com/numpy/numpy/pull/31#issuecomment-1304851 04/08/2011 @@ -359,6 +384,10 @@ def array_equal(array1, array2, withnans=False): This provides much the same functionality as :func:`numpy.array_equal`, but with additional support for arrays of strings and NaN-tolerant operation. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ def normalise_array(array): @@ -407,6 +436,11 @@ def approx_equal(a, b, max_absolute_error=1e-10, max_relative_error=1e-10): if the actual error equals the maximum, whereas :func:`util.approx_equal` will return False. + Notes + ------ + This function does maintain laziness when called; it doesn't realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ wmsg = ( "iris.util.approx_equal has been deprecated and will be removed, " @@ -456,6 +490,11 @@ def between(lh, rh, lh_inclusive=True, rh_inclusive=True): for i in range(10): print(i, between_3_and_6(i)) + Notes + ------ + This function does maintain laziness when called; it doesn't realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ if lh_inclusive and rh_inclusive: return lambda c: lh <= c <= rh @@ -510,6 +549,11 @@ def reverse(cube_or_array, coords_or_dims): [19 18 17 16] [15 14 13 12]]] + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ from iris.cube import Cube @@ -588,6 +632,11 @@ def monotonic(array, strict=False, return_direction=False): ``(monotonic_status, direction)`` + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ if array.ndim != 1 or len(array) <= 1: raise ValueError( @@ -640,6 +689,11 @@ def column_slices_generator(full_slice, ndims): This method was developed as numpy does not support the direct approach of [(3, 5), : , (1, 6, 8)] for column based indexing. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ list_of_slices = [] @@ -1035,6 +1089,10 @@ def clip_string(the_str, clip_length=70, rider="..."): If the clip length was greater than the original string, the original string is returned unaltered. + Notes + ------ + This function does maintain laziness when called; it doesn't realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ if clip_length >= len(the_str) or clip_length <= 0: @@ -1065,6 +1123,11 @@ def format_array(arr): For customisations, use the :mod:`numpy.core.arrayprint` directly. + Notes + ------ + This function does maintain laziness when called; it doesn't realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ summary_threshold = 85 @@ -1095,7 +1158,7 @@ def format_array(arr): return result -def new_axis(src_cube, scalar_coord=None, expand_extras=()): +def new_axis(src_cube, scalar_coord=None, expand_extras=()): # maybe not lazy """ Create a new axis as the leading dimension of the cube, promoting a scalar coordinate if specified. @@ -1128,6 +1191,11 @@ def new_axis(src_cube, scalar_coord=None, expand_extras=()): >>> ncube = iris.util.new_axis(cube, 'time') >>> ncube.shape (1, 360, 360) + + Notes + ------ + This function does maintain laziness when called; it doesn't realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ def _reshape_data_array(data_manager): @@ -1245,6 +1313,11 @@ def squeeze(cube): >>> ncube.shape (360, 360) + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ slices = [ @@ -1314,7 +1387,14 @@ def file_is_newer_than(result_path, source_paths): def is_regular(coord): - """Determine if the given coord is regular.""" + """ + Determine if the given coord is regular. + + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ try: regular_step(coord) except iris.exceptions.CoordinateNotRegularError: @@ -1325,7 +1405,15 @@ def is_regular(coord): def regular_step(coord): - """Return the regular step from a coord or fail.""" + """ + Return the regular step from a coord or fail. + + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + + """ if coord.ndim != 1: raise iris.exceptions.CoordinateMultiDimError("Expected 1D coord") if coord.shape[0] < 2: @@ -1356,6 +1444,10 @@ def regular_points(zeroth, step, count): count : number The number of point values. + Notes + ------ + This function does maintain laziness when called; it doesn't realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ points = (zeroth + step) + step * np.arange(count, dtype=np.float32) _, regular = iris.util.points_step(points) @@ -1376,6 +1468,12 @@ def points_step(points): ------- numeric, bool A tuple containing the average difference between values, and whether the difference is regular. + + + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # Calculations only make sense with multiple points points = np.asanyarray(points) @@ -1405,6 +1503,11 @@ def unify_time_units(cubes): * cubes: An iterable containing :class:`iris.cube.Cube` instances. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ epochs = {} @@ -1545,6 +1648,12 @@ def promote_aux_coord_to_dim_coord(cube, name_or_coord): forecast_period x - - time x - - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + + """ from iris.coords import Coord, DimCoord @@ -1671,6 +1780,12 @@ def demote_dim_coord_to_aux_coord(cube, name_or_coord): time x - - year x - - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + + """ from iris.coords import Coord @@ -1762,6 +1877,12 @@ def find_discontiguities(cube, rel_tol=1e-5, abs_tol=1e-8): # Plot the masked cube slice: iplt.pcolormesh(masked_cube_slice) + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + + """ lats_and_lons = [ "latitude", @@ -1903,6 +2024,10 @@ def mask_cube(cube, points_to_mask, in_place=False, dim=None): If either ``cube`` or ``points_to_mask`` is lazy, the result will be lazy. + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + + """ if in_place and not cube.has_lazy_data(): # Ensure cube data is masked type so we can work on it in-place. @@ -1949,6 +2074,11 @@ def equalise_attributes(cubes): * removed (list): A list of dicts holding the removed attributes. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ removed = [] # Work out which attributes are identical across all the cubes. @@ -1992,6 +2122,12 @@ def is_masked(array): bool Whether or not the array has any masks. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + + """ if is_lazy_data(array): result = da.ma.getmaskarray(array).any().compute() @@ -2008,7 +2144,6 @@ def _strip_metadata_from_dims(cube, dims): To be used by operations that modify or remove dimensions. Note: does nothing to (aux)-coordinates. Those would be handled explicitly by the calling operation. - """ reduced_cube = cube.copy()