From 12dd56a27dd4e31f3ad8dbb9baab8c6305694c71 Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Mon, 14 Nov 2022 17:04:02 +0000 Subject: [PATCH 01/11] cube and io lazy data notes added --- lib/iris/cube.py | 245 +++++++++++++++++++++++++++++++++++++++- lib/iris/io/__init__.py | 10 ++ 2 files changed, 250 insertions(+), 5 deletions(-) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index 9779558506..85274c76ab 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -234,6 +234,12 @@ def __setitem__(self, key, cube_or_sequence): def append(self, cube): """ Append a cube. + + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ self._assert_is_cube(cube) super(CubeList, self).append(cube) @@ -246,18 +252,38 @@ def extend(self, other_cubes): * other_cubes: A cubelist or other sequence of cubes. + + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ super(CubeList, self).extend(CubeList(other_cubes)) def insert(self, index, cube): """ Insert a cube before index. + + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ self._assert_is_cube(cube) super(CubeList, self).insert(index, cube) def xml(self, checksum=False, order=True, byteorder=True): - """Return a string of the XML that this list of cubes represents.""" + """ + Return a string of the XML that this list of cubes represents. + + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + + """ doc = Document() cubes_xml_element = doc.createElement("cubes") @@ -291,6 +317,12 @@ def extract(self, constraints): * constraints (:class:`~iris.Constraint` or iterable of constraints): A single constraint or an iterable. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ return self._extract_and_merge(self, constraints, strict=False) @@ -304,6 +336,12 @@ def extract_cube(self, constraint): * constraint (:class:`~iris.Constraint`): The constraint to extract with. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + .. see also:: :meth:`~iris.cube.CubeList.extract` @@ -325,6 +363,12 @@ def extract_cubes(self, constraints): * constraints (iterable of, or single, :class:`~iris.Constraint`): The constraints to extract with. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + .. see also:: :meth:`~iris.cube.CubeList.extract` @@ -384,6 +428,11 @@ def extract_overlapping(self, coord_names): A string or list of strings of the names of the coordinates over which to perform the extraction. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ if isinstance(coord_names, str): coord_names = [coord_names] @@ -427,6 +476,12 @@ def merge_cube(self): Coordinates in cube.dim_coords differ: z. Coordinate-to-dimension mapping differs for cube.dim_coords. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ if not self: raise ValueError("can't merge an empty CubeList") @@ -507,6 +562,10 @@ def merge(self, unique=True): :func:`iris.util.unify_time_units` to normalise the epochs of the time coordinates so that the cubes can be merged. + .. note:: + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # Register each of our cubes with its appropriate ProtoCube. proto_cubes_by_name = {} @@ -571,6 +630,11 @@ def concatenate_cube( Concatenation cannot occur along an anonymous dimension. + .. note:: + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ from iris._concatenate import concatenate @@ -709,6 +773,11 @@ def concatenate( Concatenation cannot occur along an anonymous dimension. + .. note:: + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ from iris._concatenate import concatenate @@ -749,6 +818,12 @@ def realise_data(self): def copy(self): """ Return a CubeList when CubeList.copy() is called. + + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ if type(self) == CubeList: return deepcopy(self) @@ -1107,7 +1182,11 @@ def convert_units(self, unit): celsius and subtract 273.15 from each value in :attr:`~iris.cube.Cube.data`. - This operation preserves lazy data. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # If the cube has units convert the data. @@ -1132,7 +1211,10 @@ def convert_units(self, unit): self.units = unit def add_cell_method(self, cell_method): - """Add a :class:`~iris.coords.CellMethod` to the Cube.""" + """ + Add a :class:`~iris.coords.CellMethod` to the Cube. + + """ self.cell_methods += (cell_method,) def add_aux_coord(self, coord, data_dims=None): @@ -1154,6 +1236,12 @@ def add_aux_coord(self, coord, data_dims=None): Raises a ValueError if a coordinate with identical metadata already exists on the cube. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + See also :meth:`Cube.remove_coord()`. """ @@ -1354,6 +1442,12 @@ def add_dim_coord(self, dim_coord, data_dim): exists on the cube or if a coord already exists for the given dimension. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + See also :meth:`Cube.remove_coord()`. """ @@ -1433,6 +1527,12 @@ def remove_coord(self, coord): * coord (string or coord) The (name of the) coordinate to remove from the cube. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + See also :meth:`Cube.add_dim_coord()` and :meth:`Cube.add_aux_coord()`. @@ -1501,6 +1601,12 @@ def replace_coord(self, new_coord): """ Replace the coordinate whose metadata matches the given coordinate. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ old_coord = self.coord(new_coord) dims = self.coord_dims(old_coord) @@ -1529,6 +1635,12 @@ def coord_dims(self, coord): * coord (string or coord) The (name of the) coord to look for. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ name_provided = False if isinstance(coord, str): @@ -1789,6 +1901,12 @@ def coords( A list containing zero or more coordinates matching the provided criteria. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ coords_and_factories = [] @@ -1965,6 +2083,11 @@ def coord( Returns: The coordinate that matches the provided criteria. + .. note:: + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ coords = self.coords( name_or_coord=name_or_coord, @@ -2024,6 +2147,12 @@ def coord_system(self, spec=None): Returns: The :class:`iris.coord_systems.CoordSystem` or None. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ if isinstance(spec, str) or spec is None: spec_name = spec @@ -2327,12 +2456,25 @@ def core_data(self): you can perform operations using this method that work equivalently on real or lazy data, and will maintain lazy data if present. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ return self._data_manager.core_data() @property def shape(self): - """The shape of the data of this cube.""" + """The shape of the data of this cube. + + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ return self._data_manager.shape @property @@ -2341,12 +2483,26 @@ def dtype(self): The data type of the values in the data array of this :class:`~iris.cube.Cube`. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ return self._data_manager.dtype @property def ndim(self): - """The number of dimensions in the data of this cube.""" + """ + The number of dimensions in the data of this cube. + + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ return self._data_manager.ndim def lazy_data(self): @@ -2385,6 +2541,11 @@ def data(self): To obtain the shape of the data without causing it to be loaded, use the Cube.shape attribute. + .. note:: + + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + Example:: >>> fname = iris.sample_data_path('air_temp.pp') >>> cube = iris.load_cube(fname, 'air_temperature') @@ -2403,6 +2564,8 @@ def data(self): >>> print(data.shape) (10, 20) + + """ return self._data_manager.data @@ -2434,6 +2597,10 @@ def dim_coords(self): dimension - instead use the :meth:`Cube.coord` method with the ``dimensions`` and ``dim_coords`` keyword arguments. + .. note:: + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ return tuple( ( @@ -2451,6 +2618,11 @@ def aux_coords(self): Return a tuple of all the auxiliary coordinates, ordered by dimension(s). + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ return tuple( ( @@ -2496,6 +2668,11 @@ def summary(self, shorten=False, name_padding=35): Control the *minimum* width of the cube name + units, i.e. the indent of the dimension map section. + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ from iris._representation.cube_printout import CubePrinter @@ -2646,6 +2823,12 @@ def subset(self, coord): coordinate. If the coordinate provided applies to the whole cube; the whole cube is returned. As such, the operation is not strict. + + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ if not isinstance(coord, iris.coords.Coord): raise ValueError("coord_to_extract must be a valid Coord.") @@ -2701,6 +2884,12 @@ def extract(self, constraint): Filter the cube by the given constraint using :meth:`iris.Constraint.extract` method. + + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # Cast the constraint into a proper constraint if it is not so already constraint = iris._constraints.as_constraint(constraint) @@ -2757,6 +2946,11 @@ def intersection(self, *args, **kwargs): range that covers the entire modulus, a split cell will preferentially be placed at the ``minimum`` end. + .. note:: + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + .. warning:: Currently this routine only works with "circular" @@ -3151,6 +3345,11 @@ def slices_over(self, ref_to_slice): the order of returned items in the iterator; instead the ordering is based on the fastest-changing dimension. + .. note:: + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ # Required to handle a mix between types. if _is_single_item(ref_to_slice): @@ -3208,6 +3407,11 @@ def slices(self, ref_to_slice, ordered=True): for sub_cube in cube.slices(['longitude', 'latitude']): print(sub_cube) + .. note:: + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + .. seealso:: :meth:`iris.cube.Cube.slices_over`. """ @@ -3273,6 +3477,11 @@ def transpose(self, new_order=None): .. note:: If defined, new_order must span all of the data dimensions. + .. note:: + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + Example usage:: # put the second dimension first, followed by the third dimension, @@ -3326,6 +3535,11 @@ def xml(self, checksum=False, order=True, byteorder=True): """ Returns a fully valid CubeML string representation of the Cube. + + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ doc = Document() @@ -3516,6 +3730,11 @@ def copy(self, data=None): Returns: A copy instance of the :class:`Cube`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ memo = {} cube = self._deepcopy(memo, data=data) @@ -3772,6 +3991,11 @@ def collapsed(self, coords, aggregator, **kwargs): cube.collapsed(['latitude', 'longitude'], iris.analysis.VARIANCE) + + .. note:: + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # Convert any coordinate names to coordinates coords = self._as_list_of_coords(coords) @@ -4002,6 +4226,12 @@ def aggregated_by( Conventions 'CF-1.5' STASH m01s00i024 + Notes + ------ + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ groupby_coords = [] dimension_to_groupby = None @@ -4259,6 +4489,11 @@ def rolling_window(self, coord, aggregator, window, **kwargs): This operation does not yet have support for lazy evaluation. + .. note:: + + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + For example: >>> import iris, iris.analysis diff --git a/lib/iris/io/__init__.py b/lib/iris/io/__init__.py index 4659f70ae3..5cec9b61a3 100644 --- a/lib/iris/io/__init__.py +++ b/lib/iris/io/__init__.py @@ -58,6 +58,11 @@ def run_callback(callback, cube, field, filename): It is possible that this function returns None for certain callbacks, the caller of this function should handle this case. + + .. note:: + + 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 @@ -424,6 +429,11 @@ def save(source, target, saver=None, **kwargs): >>> # Save a cube list to netCDF, using the NETCDF3_CLASSIC storage option >>> iris.save(my_cube_list, "myfile.nc", netcdf_format="NETCDF3_CLASSIC") + 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, CubeList From 2a3a7ae96e54d5900a199594022196178ce3d033 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Nov 2022 17:10:23 +0000 Subject: [PATCH 02/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- lib/iris/io/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/iris/io/__init__.py b/lib/iris/io/__init__.py index 5cec9b61a3..7dd08c723c 100644 --- a/lib/iris/io/__init__.py +++ b/lib/iris/io/__init__.py @@ -58,9 +58,9 @@ def run_callback(callback, cube, field, filename): It is possible that this function returns None for certain callbacks, the caller of this function should handle this case. - + .. note:: - + This function maintains laziness when called; it does not realise data. See more at :doc:`/userguide/real_and_lazy_data`. From 983b21291ad566de0311595587938327447c6fb4 Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Tue, 15 Nov 2022 19:18:32 +0000 Subject: [PATCH 03/11] Added comments within analysis, as well as palette and iterate, and what's new --- docs/src/whatsnew/latest.rst | 3 ++ lib/iris/analysis/__init__.py | 25 +++++++++------ lib/iris/analysis/calculus.py | 23 ++++++++++++++ lib/iris/analysis/cartography.py | 22 ++++++++++++++ lib/iris/analysis/maths.py | 52 ++++++++++++++++++++++++++++++++ lib/iris/analysis/trajectory.py | 4 +++ lib/iris/iterate.py | 4 +++ lib/iris/palette.py | 10 ++++++ 8 files changed, 133 insertions(+), 10 deletions(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index 770242d4ca..9a754e7964 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -194,6 +194,9 @@ This document explains the changes made to Iris for this release #. `@tkknight`_ updated the links for the Iris documentation to v2.4 and earlier to point to the archive of zip files instead. (:pull:`5064`) +#. `@Esadek-MO`_ added notes at the bottom of functions to + to clarify if the function preserves laziness or not. (:pull:`5066`) + 💼 Internal =========== diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py index 85b49ece4e..30a835e040 100644 --- a/lib/iris/analysis/__init__.py +++ b/lib/iris/analysis/__init__.py @@ -1778,7 +1778,7 @@ def interp_order(length): .. seealso:: The :func:`~iris.analysis.PROPORTION` aggregator. -This aggregator handles masked data. +This aggregator handles masked data and lazy data. """ @@ -1808,7 +1808,7 @@ def interp_order(length): result = precip_cube.collapsed('time', iris.analysis.MAX_RUN, function=lambda values: values > 10) -This aggregator handles masked data, which it treats as interrupting a run. +This aggregator handles masked data, which it treats as interrupting a run, and lazy data. """ MAX_RUN.name = lambda: "max_run" @@ -1826,7 +1826,7 @@ def interp_order(length): result = cube.collapsed('longitude', iris.analysis.GMEAN) -This aggregator handles masked data. +This aggregator handles masked data, but NOT lazy data. """ @@ -1848,7 +1848,7 @@ def interp_order(length): The harmonic mean is only valid if all data values are greater than zero. -This aggregator handles masked data. +This aggregator handles masked data, but NOT lazy data. """ @@ -1933,7 +1933,7 @@ def interp_order(length): result = cube.collapsed('longitude', iris.analysis.MIN) -This aggregator handles masked data. +This aggregator handles masked data and lazy data. """ @@ -1952,7 +1952,7 @@ def interp_order(length): result = cube.collapsed('longitude', iris.analysis.MAX) -This aggregator handles masked data. +This aggregator handles masked data and lazy data. """ @@ -1978,7 +1978,7 @@ def interp_order(length): result = cube.collapsed('time', iris.analysis.PEAK) -This aggregator handles masked data. +This aggregator handles masked data but NOT lazy data. """ @@ -2084,7 +2084,7 @@ def interp_order(length): result = cube.collapsed('longitude', iris.analysis.RMS) -This aggregator handles masked data. +This aggregator handles masked data and lazy data. """ @@ -2157,7 +2157,7 @@ def interp_order(length): result = cube.rolling_window('time', iris.analysis.SUM, len(weights), weights=weights) -This aggregator handles masked data. +This aggregator handles masked data and lazy data. """ @@ -2194,7 +2194,7 @@ def interp_order(length): Lazy operation is supported, via :func:`dask.array.var`. -This aggregator handles masked data. +This aggregator handles masked data and lazy data. """ @@ -2619,6 +2619,11 @@ def clear_phenomenon_identity(cube): Helper function to clear the standard_name, attributes, and cell_methods of a cube. + + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ cube.rename(None) cube.attributes.clear() diff --git a/lib/iris/analysis/calculus.py b/lib/iris/analysis/calculus.py index 4630f47967..c530dbd216 100644 --- a/lib/iris/analysis/calculus.py +++ b/lib/iris/analysis/calculus.py @@ -147,6 +147,12 @@ def cube_delta(cube, coord): .. note:: Missing data support not yet implemented. + .. note:: + + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + + """ # handle the case where a user passes a coordinate name if isinstance(coord, str): @@ -251,6 +257,11 @@ def differentiate(cube, coord_to_differentiate): .. note:: Spherical differentiation does not occur in this routine. + .. note:: + + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ # Get the delta cube in the required differential direction. # This operation results in a copy of the original cube. @@ -532,6 +543,12 @@ def curl(i_cube, j_cube, k_cube=None): where phi is longitude, theta is latitude. + .. note:: + + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + + """ # Get the vector quantity names. # (i.e. ['easterly', 'northerly', 'vertical']) @@ -741,6 +758,12 @@ def spatial_vectors_with_phenom_name(i_cube, j_cube, k_cube=None): #doctest: +SKIP (['u', 'v', 'w'], 'wind') + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + + """ directional_names = ( ("u", "v", "w"), diff --git a/lib/iris/analysis/cartography.py b/lib/iris/analysis/cartography.py index 8dbad9c4e9..09ae452a30 100644 --- a/lib/iris/analysis/cartography.py +++ b/lib/iris/analysis/cartography.py @@ -66,6 +66,10 @@ def wrap_lons(lons, base, period): >>> print(wrap_lons(np.array([185, 30, -200, 75]), -180, 360)) [-175. 30. 160. 75.] + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # It is important to use 64bit floating precision when changing a floats # numbers range. @@ -271,6 +275,10 @@ def get_xy_grids(cube): x, y = get_xy_grids(cube) + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ x_coord, y_coord = cube.coord(axis="X"), cube.coord(axis="Y") @@ -299,6 +307,11 @@ def get_xy_contiguous_bounded_grids(cube): xs, ys = get_xy_contiguous_bounded_grids(cube) + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ x_coord, y_coord = cube.coord(axis="X"), cube.coord(axis="Y") @@ -498,6 +511,10 @@ def cosine_latitude_weights(cube): cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) weights = np.sqrt(cosine_latitude_weights(cube)) + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # Find all latitude coordinates, we want one and only one. lat_coords = [ @@ -1075,6 +1092,11 @@ def rotate_winds(u_cube, v_cube, target_cs): The names of the output cubes are those of the inputs, prefixed with 'transformed\_' (e.g. 'transformed_x_wind'). + .. note:: + + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + .. warning:: Conversion between rotated-pole and non-rotated systems can be diff --git a/lib/iris/analysis/maths.py b/lib/iris/analysis/maths.py index 468847bca2..db889346de 100644 --- a/lib/iris/analysis/maths.py +++ b/lib/iris/analysis/maths.py @@ -115,6 +115,11 @@ def abs(cube, in_place=False): Returns: An instance of :class:`iris.cube.Cube`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ _assert_is_cube(cube) new_dtype = _output_dtype(np.abs, cube.dtype, in_place=in_place) @@ -160,6 +165,11 @@ def intersection_of_cubes(cube, other_cube): intersections = cubes.extract_overlapping(coords) cube1, cube2 = (intersections[0], intersections[1]) + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ wmsg = ( "iris.analysis.maths.intersection_of_cubes has been deprecated and will " @@ -243,6 +253,11 @@ def add(cube, other, dim=None, in_place=False): Returns: An instance of :class:`iris.cube.Cube`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ _assert_is_cube(cube) new_dtype = _output_dtype( @@ -292,6 +307,11 @@ def subtract(cube, other, dim=None, in_place=False): Returns: An instance of :class:`iris.cube.Cube`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ _assert_is_cube(cube) new_dtype = _output_dtype( @@ -383,6 +403,10 @@ def multiply(cube, other, dim=None, in_place=False): Returns: An instance of :class:`iris.cube.Cube`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ _assert_is_cube(cube) @@ -456,6 +480,10 @@ def divide(cube, other, dim=None, in_place=False): Returns: An instance of :class:`iris.cube.Cube`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ _assert_is_cube(cube) @@ -519,6 +547,10 @@ def exponentiate(cube, exponent, in_place=False): Returns: An instance of :class:`iris.cube.Cube`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ _assert_is_cube(cube) new_dtype = _output_dtype( @@ -567,6 +599,11 @@ def exp(cube, in_place=False): Returns: An instance of :class:`iris.cube.Cube`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ _assert_is_cube(cube) new_dtype = _output_dtype(np.exp, cube.dtype, in_place=in_place) @@ -593,6 +630,11 @@ def log(cube, in_place=False): Returns: An instance of :class:`iris.cube.Cube`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ _assert_is_cube(cube) new_dtype = _output_dtype(np.log, cube.dtype, in_place=in_place) @@ -623,6 +665,11 @@ def log2(cube, in_place=False): Returns: An instance of :class:`iris.cube.Cube`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ _assert_is_cube(cube) new_dtype = _output_dtype(np.log2, cube.dtype, in_place=in_place) @@ -649,6 +696,11 @@ def log10(cube, in_place=False): Returns: An instance of :class:`iris.cube.Cube`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ _assert_is_cube(cube) new_dtype = _output_dtype(np.log10, cube.dtype, in_place=in_place) diff --git a/lib/iris/analysis/trajectory.py b/lib/iris/analysis/trajectory.py index 946ae1cb2c..a7fd2abdc9 100644 --- a/lib/iris/analysis/trajectory.py +++ b/lib/iris/analysis/trajectory.py @@ -216,6 +216,10 @@ def interpolate(cube, sample_points, method=None): ('longitude', [-60, -50, -40])] interpolated_cube = interpolate(cube, sample_points) + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. """ from iris.analysis import Linear diff --git a/lib/iris/iterate.py b/lib/iris/iterate.py index 636635ee78..d6bac77d3b 100644 --- a/lib/iris/iterate.py +++ b/lib/iris/iterate.py @@ -58,6 +58,10 @@ def izip(*cubes, **kwargs): ... 'grid_longitude']): ... pass + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ if not cubes: raise TypeError("Expected one or more cubes.") diff --git a/lib/iris/palette.py b/lib/iris/palette.py index 5aa30a6b4e..05aa20b09b 100644 --- a/lib/iris/palette.py +++ b/lib/iris/palette.py @@ -48,6 +48,11 @@ def is_brewer(cmap): Returns: Boolean. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ result = False if cmap is not None: @@ -121,6 +126,11 @@ def cmap_norm(cube): Tuple of :class:`matplotlib.colors.LinearSegmentedColormap` and :class:`iris.palette.SymmetricNormalize` + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ args, kwargs = _default_cmap_norm((cube,), {}) return kwargs.get("cmap"), kwargs.get("norm") From f3ade9338d8dace848369c5f79d9cc4efb1112f1 Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Wed, 16 Nov 2022 16:40:08 +0000 Subject: [PATCH 04/11] fixed docstrings as requested in @trexfeathers review --- lib/iris/analysis/__init__.py | 9 +++++++-- lib/iris/analysis/_grid_angles.py | 5 +++++ lib/iris/analysis/cartography.py | 5 +++++ lib/iris/analysis/geometry.py | 5 +++++ lib/iris/analysis/maths.py | 6 ++++++ lib/iris/palette.py | 5 ----- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py index 30a835e040..6213fedd3e 100644 --- a/lib/iris/analysis/__init__.py +++ b/lib/iris/analysis/__init__.py @@ -1914,7 +1914,7 @@ def interp_order(length): result = cube.collapsed('longitude', iris.analysis.MEDIAN) -This aggregator handles masked data. +This aggregator handles masked data, but NOT lazy data. """ @@ -2058,7 +2058,7 @@ def interp_order(length): .. seealso:: The :func:`~iris.analysis.COUNT` aggregator. -This aggregator handles masked data. +This aggregator handles masked data, but NOT lazy data. """ @@ -2225,6 +2225,11 @@ def interp_order(length): Specifies the kind of interpolation used, see :func:`scipy.interpolate.interp1d` Defaults to "linear", which is equivalent to alphap=0.5, betap=0.5 in `iris.analysis.PERCENTILE` + +Notes +------ +This function does not maintain laziness when called; it realises data. +See more at :doc:`/userguide/real_and_lazy_data`. """ diff --git a/lib/iris/analysis/_grid_angles.py b/lib/iris/analysis/_grid_angles.py index 0b52f54568..4cb449ae51 100644 --- a/lib/iris/analysis/_grid_angles.py +++ b/lib/iris/analysis/_grid_angles.py @@ -449,6 +449,11 @@ def rotate_grid_vectors( Vector magnitudes will always be the same as the inputs. + .. note:: + + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ u_out, v_out = (cube.copy() for cube in (u_cube, v_cube)) if not grid_angles_cube: diff --git a/lib/iris/analysis/cartography.py b/lib/iris/analysis/cartography.py index 09ae452a30..a8e90a63ad 100644 --- a/lib/iris/analysis/cartography.py +++ b/lib/iris/analysis/cartography.py @@ -618,6 +618,11 @@ def project(cube, target_proj, nx=None, ny=None): resulting nearest neighbour values. If masked, the value in the resulting cube is set to 0. + .. note:: + + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + .. warning:: This function uses a nearest neighbour approach rather than any form diff --git a/lib/iris/analysis/geometry.py b/lib/iris/analysis/geometry.py index a412a26ebc..b246b518d4 100644 --- a/lib/iris/analysis/geometry.py +++ b/lib/iris/analysis/geometry.py @@ -160,6 +160,11 @@ def geometry_area_weights(cube, geometry, normalize=False): calculation might be wrong. In this case, a UserWarning will be issued. + .. note:: + + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. + Args: * cube (:class:`iris.cube.Cube`): diff --git a/lib/iris/analysis/maths.py b/lib/iris/analysis/maths.py index db889346de..09a02ad51c 100644 --- a/lib/iris/analysis/maths.py +++ b/lib/iris/analysis/maths.py @@ -755,6 +755,12 @@ def apply_ufunc( cube = apply_ufunc(numpy.sin, cube, in_place=True) + .. note:: + + This function maintains laziness when called; it does not realise data. This is dependent on `ufunc` argument + being a numpy operation that is compatible with lazy operation. + See more at :doc:`/userguide/real_and_lazy_data`. + """ if not isinstance(ufunc, np.ufunc): diff --git a/lib/iris/palette.py b/lib/iris/palette.py index 05aa20b09b..a1c0a1e878 100644 --- a/lib/iris/palette.py +++ b/lib/iris/palette.py @@ -48,11 +48,6 @@ def is_brewer(cmap): Returns: Boolean. - Notes - ------ - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ result = False if cmap is not None: From 7ad5126dae926aa87bf8147ce390962d12f949c1 Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Wed, 16 Nov 2022 16:46:43 +0000 Subject: [PATCH 05/11] reverted cube.py for time being --- lib/iris/cube.py | 245 +---------------------------------------------- 1 file changed, 5 insertions(+), 240 deletions(-) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index a86ba7389a..e45ac8ca2d 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -234,12 +234,6 @@ def __setitem__(self, key, cube_or_sequence): def append(self, cube): """ Append a cube. - - Notes - ------ - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ self._assert_is_cube(cube) super(CubeList, self).append(cube) @@ -252,38 +246,18 @@ def extend(self, other_cubes): * other_cubes: A cubelist or other sequence of cubes. - - Notes - ------ - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ super(CubeList, self).extend(CubeList(other_cubes)) def insert(self, index, cube): """ Insert a cube before index. - - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ self._assert_is_cube(cube) super(CubeList, self).insert(index, cube) def xml(self, checksum=False, order=True, byteorder=True): - """ - Return a string of the XML that this list of cubes represents. - - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - - """ + """Return a string of the XML that this list of cubes represents.""" doc = Document() cubes_xml_element = doc.createElement("cubes") @@ -317,12 +291,6 @@ def extract(self, constraints): * constraints (:class:`~iris.Constraint` or iterable of constraints): A single constraint or an iterable. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ return self._extract_and_merge(self, constraints, strict=False) @@ -336,12 +304,6 @@ def extract_cube(self, constraint): * constraint (:class:`~iris.Constraint`): The constraint to extract with. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - .. see also:: :meth:`~iris.cube.CubeList.extract` @@ -363,12 +325,6 @@ def extract_cubes(self, constraints): * constraints (iterable of, or single, :class:`~iris.Constraint`): The constraints to extract with. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - .. see also:: :meth:`~iris.cube.CubeList.extract` @@ -428,11 +384,6 @@ def extract_overlapping(self, coord_names): A string or list of strings of the names of the coordinates over which to perform the extraction. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ if isinstance(coord_names, str): coord_names = [coord_names] @@ -476,12 +427,6 @@ def merge_cube(self): Coordinates in cube.dim_coords differ: z. Coordinate-to-dimension mapping differs for cube.dim_coords. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ if not self: raise ValueError("can't merge an empty CubeList") @@ -562,10 +507,6 @@ def merge(self, unique=True): :func:`iris.util.unify_time_units` to normalise the epochs of the time coordinates so that the cubes can be merged. - .. note:: - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ # Register each of our cubes with its appropriate ProtoCube. proto_cubes_by_name = {} @@ -630,11 +571,6 @@ def concatenate_cube( Concatenation cannot occur along an anonymous dimension. - .. note:: - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ from iris._concatenate import concatenate @@ -773,11 +709,6 @@ def concatenate( Concatenation cannot occur along an anonymous dimension. - .. note:: - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ from iris._concatenate import concatenate @@ -818,12 +749,6 @@ def realise_data(self): def copy(self): """ Return a CubeList when CubeList.copy() is called. - - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ if type(self) == CubeList: return deepcopy(self) @@ -1182,11 +1107,7 @@ def convert_units(self, unit): celsius and subtract 273.15 from each value in :attr:`~iris.cube.Cube.data`. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. + This operation preserves lazy data. """ # If the cube has units convert the data. @@ -1211,10 +1132,7 @@ def convert_units(self, unit): self.units = unit def add_cell_method(self, cell_method): - """ - Add a :class:`~iris.coords.CellMethod` to the Cube. - - """ + """Add a :class:`~iris.coords.CellMethod` to the Cube.""" self.cell_methods += (cell_method,) def add_aux_coord(self, coord, data_dims=None): @@ -1236,12 +1154,6 @@ def add_aux_coord(self, coord, data_dims=None): Raises a ValueError if a coordinate with identical metadata already exists on the cube. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - See also :meth:`Cube.remove_coord()`. """ @@ -1442,12 +1354,6 @@ def add_dim_coord(self, dim_coord, data_dim): exists on the cube or if a coord already exists for the given dimension. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - See also :meth:`Cube.remove_coord()`. """ @@ -1527,12 +1433,6 @@ def remove_coord(self, coord): * coord (string or coord) The (name of the) coordinate to remove from the cube. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - See also :meth:`Cube.add_dim_coord()` and :meth:`Cube.add_aux_coord()`. @@ -1601,12 +1501,6 @@ def replace_coord(self, new_coord): """ Replace the coordinate whose metadata matches the given coordinate. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ old_coord = self.coord(new_coord) dims = self.coord_dims(old_coord) @@ -1635,12 +1529,6 @@ def coord_dims(self, coord): * coord (string or coord) The (name of the) coord to look for. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ name_provided = False if isinstance(coord, str): @@ -1901,12 +1789,6 @@ def coords( A list containing zero or more coordinates matching the provided criteria. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ coords_and_factories = [] @@ -2083,11 +1965,6 @@ def coord( Returns: The coordinate that matches the provided criteria. - .. note:: - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ coords = self.coords( name_or_coord=name_or_coord, @@ -2153,12 +2030,6 @@ def coord_system(self, spec=None): Returns: The :class:`iris.coord_systems.CoordSystem` or None. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ if isinstance(spec, str) or spec is None: spec_name = spec @@ -2475,25 +2346,12 @@ def core_data(self): you can perform operations using this method that work equivalently on real or lazy data, and will maintain lazy data if present. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ return self._data_manager.core_data() @property def shape(self): - """The shape of the data of this cube. - - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ + """The shape of the data of this cube.""" return self._data_manager.shape @property @@ -2502,26 +2360,12 @@ def dtype(self): The data type of the values in the data array of this :class:`~iris.cube.Cube`. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ return self._data_manager.dtype @property def ndim(self): - """ - The number of dimensions in the data of this cube. - - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ + """The number of dimensions in the data of this cube.""" return self._data_manager.ndim def lazy_data(self): @@ -2560,11 +2404,6 @@ def data(self): To obtain the shape of the data without causing it to be loaded, use the Cube.shape attribute. - .. note:: - - This function does not maintain laziness when called; it realises data. - See more at :doc:`/userguide/real_and_lazy_data`. - Example:: >>> fname = iris.sample_data_path('air_temp.pp') >>> cube = iris.load_cube(fname, 'air_temperature') @@ -2583,8 +2422,6 @@ def data(self): >>> print(data.shape) (10, 20) - - """ return self._data_manager.data @@ -2616,10 +2453,6 @@ def dim_coords(self): dimension - instead use the :meth:`Cube.coord` method with the ``dimensions`` and ``dim_coords`` keyword arguments. - .. note:: - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ return tuple( ( @@ -2637,11 +2470,6 @@ def aux_coords(self): Return a tuple of all the auxiliary coordinates, ordered by dimension(s). - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ return tuple( ( @@ -2687,11 +2515,6 @@ def summary(self, shorten=False, name_padding=35): Control the *minimum* width of the cube name + units, i.e. the indent of the dimension map section. - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ from iris._representation.cube_printout import CubePrinter @@ -2842,12 +2665,6 @@ def subset(self, coord): coordinate. If the coordinate provided applies to the whole cube; the whole cube is returned. As such, the operation is not strict. - - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ if not isinstance(coord, iris.coords.Coord): raise ValueError("coord_to_extract must be a valid Coord.") @@ -2903,12 +2720,6 @@ def extract(self, constraint): Filter the cube by the given constraint using :meth:`iris.Constraint.extract` method. - - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ # Cast the constraint into a proper constraint if it is not so already constraint = iris._constraints.as_constraint(constraint) @@ -2965,11 +2776,6 @@ def intersection(self, *args, **kwargs): range that covers the entire modulus, a split cell will preferentially be placed at the ``minimum`` end. - .. note:: - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - .. warning:: Currently this routine only works with "circular" @@ -3364,11 +3170,6 @@ def slices_over(self, ref_to_slice): the order of returned items in the iterator; instead the ordering is based on the fastest-changing dimension. - .. note:: - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ # Required to handle a mix between types. if _is_single_item(ref_to_slice): @@ -3426,11 +3227,6 @@ def slices(self, ref_to_slice, ordered=True): for sub_cube in cube.slices(['longitude', 'latitude']): print(sub_cube) - .. note:: - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - .. seealso:: :meth:`iris.cube.Cube.slices_over`. """ @@ -3496,11 +3292,6 @@ def transpose(self, new_order=None): .. note:: If defined, new_order must span all of the data dimensions. - .. note:: - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - Example usage:: # put the second dimension first, followed by the third dimension, @@ -3554,11 +3345,6 @@ def xml(self, checksum=False, order=True, byteorder=True): """ Returns a fully valid CubeML string representation of the Cube. - - Notes - ------ - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ doc = Document() @@ -3749,11 +3535,6 @@ def copy(self, data=None): Returns: A copy instance of the :class:`Cube`. - Notes - ------ - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ memo = {} cube = self._deepcopy(memo, data=data) @@ -4010,11 +3791,6 @@ def collapsed(self, coords, aggregator, **kwargs): cube.collapsed(['latitude', 'longitude'], iris.analysis.VARIANCE) - - .. note:: - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. """ # Convert any coordinate names to coordinates coords = self._as_list_of_coords(coords) @@ -4245,12 +4021,6 @@ def aggregated_by( Conventions 'CF-1.5' STASH m01s00i024 - Notes - ------ - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - """ groupby_coords = [] dimension_to_groupby = None @@ -4519,11 +4289,6 @@ def rolling_window(self, coord, aggregator, window, **kwargs): This operation does not yet have support for lazy evaluation. - .. note:: - - This function maintains laziness when called; it does not realise data. - See more at :doc:`/userguide/real_and_lazy_data`. - For example: >>> import iris, iris.analysis From 887515268055ff2959753c808134a70d8c7b1759 Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Wed, 16 Nov 2022 17:09:01 +0000 Subject: [PATCH 06/11] fixed flake8 issue --- lib/iris/analysis/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py index 6213fedd3e..c0f9b5b0f8 100644 --- a/lib/iris/analysis/__init__.py +++ b/lib/iris/analysis/__init__.py @@ -2225,7 +2225,7 @@ def interp_order(length): Specifies the kind of interpolation used, see :func:`scipy.interpolate.interp1d` Defaults to "linear", which is equivalent to alphap=0.5, betap=0.5 in `iris.analysis.PERCENTILE` - + Notes ------ This function does not maintain laziness when called; it realises data. From 9684e89c521572ca1a3b08d5c8a8e8f4acf98bb3 Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Mon, 9 Jan 2023 17:48:48 +0000 Subject: [PATCH 07/11] Lazy data second batch --- lib/iris/cube.py | 647 ++++++++++++++---------------------------- lib/iris/pandas.py | 12 + lib/iris/plot.py | 65 +++++ lib/iris/quickplot.py | 38 +++ lib/iris/util.py | 116 +++++++- 5 files changed, 437 insertions(+), 441 deletions(-) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index e45ac8ca2d..7d5f76591b 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -6,7 +6,6 @@ """ Classes for representing multi-dimensional data with metadata. - """ from collections import OrderedDict @@ -48,7 +47,6 @@ class _CubeFilter: """ A constraint, paired with a list of cubes matching that constraint. - """ def __init__(self, constraint, cubes=None): @@ -64,7 +62,6 @@ def add(self, cube): """ Adds the appropriate (sub)cube to the list of cubes where it matches the constraint. - """ sub_cube = self.constraint.extract(cube) if sub_cube is not None: @@ -74,13 +71,10 @@ def merged(self, unique=False): """ Returns a new :class:`_CubeFilter` by merging the list of cubes. - Kwargs: - * unique: If True, raises `iris.exceptions.DuplicateDataError` if duplicate cubes are detected. - """ return _CubeFilter(self.constraint, self.cubes.merge(unique)) @@ -88,7 +82,6 @@ def merged(self, unique=False): class _CubeFilterCollection: """ A list of _CubeFilter instances. - """ @staticmethod @@ -96,7 +89,6 @@ def from_cubes(cubes, constraints=None): """ Creates a new collection from an iterable of cubes, and some optional constraints. - """ constraints = iris._constraints.list_of_constraints(constraints) pairs = [_CubeFilter(constraint) for constraint in constraints] @@ -112,7 +104,6 @@ def add_cube(self, cube): """ Adds the given :class:`~iris.cube.Cube` to all of the relevant constraint pairs. - """ for pair in self.pairs: pair.add(cube) @@ -121,7 +112,6 @@ def cubes(self): """ Returns all the cubes in this collection concatenated into a single :class:`CubeList`. - """ result = CubeList() for pair in self.pairs: @@ -132,13 +122,10 @@ def merged(self, unique=False): """ Returns a new :class:`_CubeFilterCollection` by merging all the cube lists of this collection. - Kwargs: - * unique: If True, raises `iris.exceptions.DuplicateDataError` if duplicate cubes are detected. - """ return _CubeFilterCollection( [pair.merged(unique) for pair in self.pairs] @@ -149,7 +136,6 @@ class CubeList(list): """ All the functionality of a standard :class:`list` with added "Cube" context. - """ def __init__(self, *args, **kwargs): @@ -206,9 +192,7 @@ def __getitem__(self, keys): def __getslice__(self, start, stop): """ x.__getslice__(i, j) <==> x[i:j] - Use of negative indices is not supported. - """ result = super().__getslice__(start, stop) result = CubeList(result) @@ -234,6 +218,10 @@ def __setitem__(self, key, cube_or_sequence): def append(self, cube): """ Append a cube. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ self._assert_is_cube(cube) super(CubeList, self).append(cube) @@ -241,23 +229,35 @@ def append(self, cube): def extend(self, other_cubes): """ Extend cubelist by appending the cubes contained in other_cubes. - Args: - * other_cubes: A cubelist or other sequence of cubes. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ super(CubeList, self).extend(CubeList(other_cubes)) def insert(self, index, cube): """ Insert a cube before index. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ self._assert_is_cube(cube) super(CubeList, self).insert(index, cube) def xml(self, checksum=False, order=True, byteorder=True): - """Return a string of the XML that this list of cubes represents.""" + """ + Return a string of the XML that this list of cubes represents. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ doc = Document() cubes_xml_element = doc.createElement("cubes") @@ -280,17 +280,17 @@ def extract(self, constraints): """ Filter each of the cubes which can be filtered by the given constraints. - This method iterates over each constraint given, and subsets each of the cubes in this CubeList where possible. Thus, a CubeList of length **n** when filtered with **m** constraints can generate a maximum of **m * n** cubes. - Args: - * constraints (:class:`~iris.Constraint` or iterable of constraints): A single constraint or an iterable. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ return self._extract_and_merge(self, constraints, strict=False) @@ -298,15 +298,15 @@ def extract_cube(self, constraint): """ Extract a single cube from a CubeList, and return it. Raise an error if the extract produces no cubes, or more than one. - Args: - * constraint (:class:`~iris.Constraint`): The constraint to extract with. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. .. see also:: :meth:`~iris.cube.CubeList.extract` - """ # Just validate this, so we can accept strings etc, but not multiples. constraint = iris._constraints.as_constraint(constraint) @@ -319,15 +319,15 @@ def extract_cubes(self, constraints): Extract specific cubes from a CubeList, one for each given constraint. Each constraint must produce exactly one cube, otherwise an error is raised. - Args: - * constraints (iterable of, or single, :class:`~iris.Constraint`): The constraints to extract with. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. .. see also:: :meth:`~iris.cube.CubeList.extract` - """ return self._extract_and_merge( self, constraints, strict=True, return_single_cube=False @@ -377,13 +377,14 @@ def extract_overlapping(self, coord_names): Returns a :class:`CubeList` of cubes extracted over regions where the coordinates overlap, for the coordinates in coord_names. - Args: - * coord_names: A string or list of strings of the names of the coordinates over which to perform the extraction. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ if isinstance(coord_names, str): coord_names = [coord_names] @@ -407,13 +408,10 @@ def merge_cube(self): """ Return the merged contents of the :class:`CubeList` as a single :class:`Cube`. - If it is not possible to merge the `CubeList` into a single `Cube`, a :class:`~iris.exceptions.MergeError` will be raised describing the reason for the failure. - For example: - >>> cube_1 = iris.cube.Cube([1, 2]) >>> cube_1.add_aux_coord(iris.coords.AuxCoord(0, long_name='x')) >>> cube_2 = iris.cube.Cube([3, 4]) @@ -426,7 +424,10 @@ def merge_cube(self): iris.exceptions.MergeError: failed to merge into a single cube. Coordinates in cube.dim_coords differ: z. Coordinate-to-dimension mapping differs for cube.dim_coords. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ if not self: raise ValueError("can't merge an empty CubeList") @@ -444,18 +445,13 @@ def merge(self, unique=True): """ Returns the :class:`CubeList` resulting from merging this :class:`CubeList`. - Kwargs: - * unique: If True, raises `iris.exceptions.DuplicateDataError` if duplicate cubes are detected. - This combines cubes with different values of an auxiliary scalar coordinate, by constructing a new dimension. - .. testsetup:: - import iris c1 = iris.cube.Cube([0,1,2], long_name='some_parameter') xco = iris.coords.DimCoord([11, 12, 13], long_name='x_vals') @@ -463,9 +459,7 @@ def merge(self, unique=True): c1.add_aux_coord(iris.coords.AuxCoord([100], long_name='y_vals')) c2 = c1.copy() c2.coord('y_vals').points = [200] - For example:: - >>> print(c1) some_parameter / (unknown) (x_vals: 3) Dimension coordinates: @@ -488,25 +482,22 @@ def merge(self, unique=True): >>> print(new_cube.coord('y_vals').points) [100 200] >>> - Contrast this with :meth:`iris.cube.CubeList.concatenate`, which joins cubes along an existing dimension. - .. note:: - Cubes may contain additional dimensional elements such as auxiliary coordinates, cell measures or ancillary variables. A group of similar cubes can only merge to a single result if all such elements are identical in every input cube : they are then present, unchanged, in the merged output cube. - .. note:: - If time coordinates in the list of cubes have differing epochs then the cubes will not be able to be merged. If this occurs, use :func:`iris.util.unify_time_units` to normalise the epochs of the time coordinates so that the cubes can be merged. - + .. note:: + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # Register each of our cubes with its appropriate ProtoCube. proto_cubes_by_name = {} @@ -545,32 +536,27 @@ def concatenate_cube( """ Return the concatenated contents of the :class:`CubeList` as a single :class:`Cube`. - If it is not possible to concatenate the `CubeList` into a single `Cube`, a :class:`~iris.exceptions.ConcatenateError` will be raised describing the reason for the failure. - Kwargs: - * check_aux_coords Checks the auxiliary coordinates of the cubes match. This check is not applied to auxiliary coordinates that span the dimension the concatenation is occurring along. Defaults to True. - * check_cell_measures Checks the cell measures of the cubes match. This check is not applied to cell measures that span the dimension the concatenation is occurring along. Defaults to True. - * check_ancils Checks the ancillary variables of the cubes match. This check is not applied to ancillary variables that span the dimension the concatenation is occurring along. Defaults to True. - .. note:: - Concatenation cannot occur along an anonymous dimension. - + .. note:: + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ from iris._concatenate import concatenate @@ -615,34 +601,26 @@ def concatenate( ): """ Concatenate the cubes over their common dimensions. - Kwargs: - * check_aux_coords Checks the auxiliary coordinates of the cubes match. This check is not applied to auxiliary coordinates that span the dimension the concatenation is occurring along. Defaults to True. - * check_cell_measures Checks the cell measures of the cubes match. This check is not applied to cell measures that span the dimension the concatenation is occurring along. Defaults to True. - * check_ancils Checks the ancillary variables of the cubes match. This check is not applied to ancillary variables that span the dimension the concatenation is occurring along. Defaults to True. - Returns: A new :class:`iris.cube.CubeList` of concatenated :class:`iris.cube.Cube` instances. - This combines cubes with a common dimension coordinate, but occupying different regions of the coordinate value. The cubes are joined across that dimension. - .. testsetup:: - import iris import numpy as np xco = iris.coords.DimCoord([11, 12, 13, 14], long_name='x_vals') @@ -654,9 +632,7 @@ def concatenate( c2 = iris.cube.Cube(np.zeros((3,4)), long_name='some_parameter') c2.add_dim_coord(xco, 1) c2.add_dim_coord(yco2, 0) - For example:: - >>> print(c1) some_parameter / (unknown) (y_vals: 2; x_vals: 4) Dimension coordinates: @@ -681,12 +657,9 @@ def concatenate( >>> print(new_cube.coord('y_vals').points) [ 4 5 7 9 10] >>> - Contrast this with :meth:`iris.cube.CubeList.merge`, which makes a new dimension from values of an auxiliary scalar coordinate. - .. note:: - Cubes may contain 'extra' dimensional elements such as auxiliary coordinates, cell measures or ancillary variables. For a group of similar cubes to concatenate together into one output, all @@ -697,18 +670,16 @@ def concatenate( appear, concatenated, in the output cube. If any cubes in a group have dimensional elements which do not match correctly, the group will not concatenate to a single output cube. - .. note:: - If time coordinates in the list of cubes have differing epochs then the cubes will not be able to be concatenated. If this occurs, use :func:`iris.util.unify_time_units` to normalise the epochs of the time coordinates so that the cubes can be concatenated. - .. note:: - Concatenation cannot occur along an anonymous dimension. - + .. note:: + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ from iris._concatenate import concatenate @@ -722,33 +693,30 @@ def concatenate( def realise_data(self): """ Fetch 'real' data for all cubes, in a shared calculation. - This computes any lazy data, equivalent to accessing each `cube.data`. However, lazy calculations and data fetches can be shared between the computations, improving performance. - For example:: - # Form stats. a_std = cube_a.collapsed(['x', 'y'], iris.analysis.STD_DEV) b_std = cube_b.collapsed(['x', 'y'], iris.analysis.STD_DEV) ab_mean_diff = (cube_b - cube_a).collapsed(['x', 'y'], iris.analysis.MEAN) std_err = (a_std * a_std + b_std * b_std) ** 0.5 - # Compute these stats together (avoiding multiple data passes). CubeList([a_std, b_std, ab_mean_diff, std_err]).realise_data() - .. Note:: - Cubes with non-lazy data are not affected. - """ _lazy.co_realise_cubes(*self) def copy(self): """ Return a CubeList when CubeList.copy() is called. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ if type(self) == CubeList: return deepcopy(self) @@ -757,9 +725,7 @@ def copy(self): def _is_single_item(testee): """ Return whether this is a single item, rather than an iterable. - We count string types as 'single', also. - """ return isinstance(testee, str) or not isinstance(testee, Iterable) @@ -767,12 +733,9 @@ def _is_single_item(testee): class Cube(CFVariableMixin): """ A single Iris cube of data and metadata. - Typically obtained from :func:`iris.load`, :func:`iris.load_cube`, :func:`iris.load_cubes`, or from the manipulation of existing cubes. - For example: - >>> cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) >>> print(cube) air_temperature / (K) (latitude: 73; longitude: 96) @@ -792,10 +755,7 @@ class Cube(CFVariableMixin): Attributes: STASH m01s16i203 source 'Data from Met Office Unified Model' - - See the :doc:`user guide` for more information. - """ #: Indicates to client code that the object supports @@ -809,19 +769,14 @@ def _sort_xml_attrs(cls, doc): """ Takes an xml document and returns a copy with all element attributes sorted in alphabetical order. - This is a private utility method required by iris to maintain legacy xml behaviour beyond python 3.7. - Args: - * doc: The :class:`xml.dom.minidom.Document`. - Returns: The :class:`xml.dom.minidom.Document` with sorted element attributes. - """ from xml.dom.minidom import Document @@ -874,24 +829,17 @@ def __init__( ): """ Creates a cube with data and optional metadata. - Not typically used - normally cubes are obtained by loading data (e.g. :func:`iris.load`) or from manipulating existing cubes. - Args: - * data This object defines the shape of the cube and the phenomenon value in each cell. - ``data`` can be a dask array, a NumPy array, a NumPy array subclass (such as :class:`numpy.ma.MaskedArray`), or array_like (as described in :func:`numpy.asarray`). - See :attr:`Cube.data`. - Kwargs: - * standard_name The standard name for the Cube's data. * long_name @@ -920,7 +868,6 @@ def __init__( A list of CellMeasures with dimension mappings. * ancillary_variables_and_dims A list of AncillaryVariables with dimension mappings. - For example:: >>> from iris.coords import DimCoord >>> from iris.cube import Cube @@ -933,7 +880,6 @@ def __init__( >>> cube = Cube(np.zeros((4, 8), np.float32), ... dim_coords_and_dims=[(latitude, 0), ... (longitude, 1)]) - """ # Temporary error while we transition the API. if isinstance(data, str): @@ -1014,7 +960,6 @@ def _names(self): of a :class:`iris.cube.Cube`. This includes the standard name, long name, NetCDF variable name, and the STASH from the attributes dictionary. - """ return self._metadata_manager._names @@ -1022,7 +967,6 @@ def _dimensional_metadata(self, name_or_dimensional_metadata): """ Return a single _DimensionalMetadata instance that matches the given name_or_dimensional_metadata. If one is not found, raise an error. - """ found_item = None for cube_method in [ @@ -1045,13 +989,10 @@ def _dimensional_metadata(self, name_or_dimensional_metadata): def is_compatible(self, other, ignore=None): """ Return whether the cube is compatible with another. - Compatibility is determined by comparing :meth:`iris.cube.Cube.name()`, :attr:`iris.cube.Cube.units`, :attr:`iris.cube.Cube.cell_methods` and :attr:`iris.cube.Cube.attributes` that are present in both objects. - Args: - * other: An instance of :class:`iris.cube.Cube` or :class:`iris.cube.CubeMetadata`. @@ -1059,21 +1000,15 @@ def is_compatible(self, other, ignore=None): A single attribute key or iterable of attribute keys to ignore when comparing the cubes. Default is None. To ignore all attributes set this to other.attributes. - Returns: Boolean. - .. seealso:: - :meth:`iris.util.describe_diff()` - .. note:: - This function does not indicate whether the two cubes can be merged, instead it checks only the four items quoted above for equality. Determining whether two cubes will merge requires additional logic that is beyond the scope of this method. - """ compatible = ( self.name() == other.name() @@ -1097,18 +1032,16 @@ def is_compatible(self, other, ignore=None): def convert_units(self, unit): """ Change the cube's units, converting the values in the data array. - For example, if a cube's :attr:`~iris.cube.Cube.units` are kelvin then:: - cube.convert_units('celsius') - will change the cube's :attr:`~iris.cube.Cube.units` attribute to celsius and subtract 273.15 from each value in :attr:`~iris.cube.Cube.data`. - - This operation preserves lazy data. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # If the cube has units convert the data. if self.units.is_unknown(): @@ -1132,30 +1065,36 @@ def convert_units(self, unit): self.units = unit def add_cell_method(self, cell_method): - """Add a :class:`~iris.coords.CellMethod` to the Cube.""" + """ + Add a :class:`~iris.coords.CellMethod` to the Cube. + + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + See also :meth:`Cube.remove_coord()`. + """ self.cell_methods += (cell_method,) def add_aux_coord(self, coord, data_dims=None): """ Adds a CF auxiliary coordinate to the cube. - Args: - * coord The :class:`iris.coords.DimCoord` or :class:`iris.coords.AuxCoord` instance to add to the cube. - Kwargs: - * data_dims Integer or iterable of integers giving the data dimensions spanned by the coordinate. - Raises a ValueError if a coordinate with identical metadata already exists on the cube. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. See also :meth:`Cube.remove_coord()`. - """ if self.coords(coord): # TODO: just fail on duplicate object raise ValueError("Duplicate coordinates are not permitted.") @@ -1246,12 +1185,9 @@ def _add_unique_aux_coord(self, coord, data_dims): def add_aux_factory(self, aux_factory): """ Adds an auxiliary coordinate factory to the cube. - Args: - * aux_factory The :class:`iris.aux_factory.AuxCoordFactory` instance to add. - """ if not isinstance(aux_factory, iris.aux_factory.AuxCoordFactory): raise TypeError( @@ -1278,25 +1214,18 @@ def coordsonly(coords_and_dims): def add_cell_measure(self, cell_measure, data_dims=None): """ Adds a CF cell measure to the cube. - Args: - * cell_measure The :class:`iris.coords.CellMeasure` instance to add to the cube. - Kwargs: - * data_dims Integer or iterable of integers giving the data dimensions spanned by the coordinate. - Raises a ValueError if a cell_measure with identical metadata already exists on the cube. - See also :meth:`Cube.remove_cell_measure()`. - """ if self.cell_measures(cell_measure): raise ValueError("Duplicate cell_measures are not permitted.") @@ -1309,19 +1238,14 @@ def add_cell_measure(self, cell_measure, data_dims=None): def add_ancillary_variable(self, ancillary_variable, data_dims=None): """ Adds a CF ancillary variable to the cube. - Args: - * ancillary_variable The :class:`iris.coords.AncillaryVariable` instance to be added to the cube - Kwargs: - * data_dims Integer or iterable of integers giving the data dimensions spanned by the ancillary variable. - Raises a ValueError if an ancillary variable with identical metadata already exists on the cube. """ @@ -1342,20 +1266,19 @@ def add_ancillary_variable(self, ancillary_variable, data_dims=None): def add_dim_coord(self, dim_coord, data_dim): """ Add a CF coordinate to the cube. - Args: - * dim_coord The :class:`iris.coords.DimCoord` instance to add to the cube. * data_dim Integer giving the data dimension spanned by the coordinate. - Raises a ValueError if a coordinate with identical metadata already exists on the cube or if a coord already exists for the given dimension. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. See also :meth:`Cube.remove_coord()`. - """ if self.coords(dim_coord): raise ValueError( @@ -1406,7 +1329,14 @@ def _add_unique_dim_coord(self, dim_coord, data_dim): self._dim_coords_and_dims.append((dim_coord, int(data_dim))) def remove_aux_factory(self, aux_factory): - """Removes the given auxiliary coordinate factory from the cube.""" + """Removes the given auxiliary coordinate factory from the cube. + + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + See also :meth:`Cube.remove_coord()`. + """ self._aux_factories.remove(aux_factory) def _remove_coord(self, coord): @@ -1427,15 +1357,15 @@ def _remove_coord(self, coord): def remove_coord(self, coord): """ Removes a coordinate from the cube. - Args: - * coord (string or coord) The (name of the) coordinate to remove from the cube. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. See also :meth:`Cube.add_dim_coord()` and :meth:`Cube.add_aux_coord()`. - """ coord = self.coord(coord) self._remove_coord(coord) @@ -1446,30 +1376,21 @@ def remove_coord(self, coord): def remove_cell_measure(self, cell_measure): """ Removes a cell measure from the cube. - Args: - * cell_measure (string or cell_measure) The (name of the) cell measure to remove from the cube. As either - (a) a :attr:`standard_name`, :attr:`long_name`, or :attr:`var_name`. Defaults to value of `default` (which itself defaults to `unknown`) as defined in :class:`iris.common.CFVariableMixin`. - (b) a cell_measure instance with metadata equal to that of the desired cell_measures. - .. note:: - If the argument given does not represent a valid cell_measure on the cube, an :class:`iris.exceptions.CellMeasureNotFoundError` is raised. - .. seealso:: - :meth:`Cube.add_cell_measure()` - """ cell_measure = self.cell_measure(cell_measure) @@ -1482,12 +1403,9 @@ def remove_cell_measure(self, cell_measure): def remove_ancillary_variable(self, ancillary_variable): """ Removes an ancillary variable from the cube. - Args: - * ancillary_variable (string or AncillaryVariable) The (name of the) AncillaryVariable to remove from the cube. - """ ancillary_variable = self.ancillary_variable(ancillary_variable) @@ -1500,7 +1418,10 @@ def remove_ancillary_variable(self, ancillary_variable): def replace_coord(self, new_coord): """ Replace the coordinate whose metadata matches the given coordinate. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ old_coord = self.coord(new_coord) dims = self.coord_dims(old_coord) @@ -1518,17 +1439,17 @@ def coord_dims(self, coord): """ Returns a tuple of the data dimensions relevant to the given coordinate. - When searching for the given coordinate in the cube the comparison is made using coordinate metadata equality. Hence the given coordinate instance need not exist on the cube, and may contain different coordinate values. - Args: - * coord (string or coord) The (name of the) coord to look for. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ name_provided = False if isinstance(coord, str): @@ -1582,10 +1503,8 @@ def cell_measure_dims(self, cell_measure): """ Returns a tuple of the data dimensions relevant to the given CellMeasure. - * cell_measure (string or CellMeasure) The (name of the) cell measure to look for. - """ cell_measure = self.cell_measure(cell_measure) @@ -1606,10 +1525,8 @@ def ancillary_variable_dims(self, ancillary_variable): """ Returns a tuple of the data dimensions relevant to the given AncillaryVariable. - * ancillary_variable (string or AncillaryVariable) The (name of the) AncillaryVariable to look for. - """ ancillary_variable = self.ancillary_variable(ancillary_variable) @@ -1634,9 +1551,7 @@ def aux_factory( """ Returns the single coordinate factory that matches the criteria, or raises an error if not found. - Kwargs: - * name If not None, matches against factory.name(). * standard_name @@ -1648,13 +1563,16 @@ def aux_factory( * var_name The NetCDF variable name of the desired coordinate factory. If None, does not check for var_name. - .. note:: - If the arguments given do not result in precisely 1 coordinate factory being matched, an :class:`iris.exceptions.CoordinateNotFoundError` is raised. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + See also :meth:`Cube.remove_coord()`. """ factories = self.aux_factories @@ -1719,76 +1637,62 @@ def coords( """ Return a list of coordinates from the :class:`Cube` that match the provided criteria. - .. seealso:: - :meth:`Cube.coord` for matching exactly one coordinate. - Kwargs: - * name_or_coord: Either, - * a :attr:`~iris.common.mixin.CFVariableMixin.standard_name`, :attr:`~iris.common.mixin.CFVariableMixin.long_name`, or :attr:`~iris.common.mixin.CFVariableMixin.var_name` which is compared against the :meth:`~iris.common.mixin.CFVariableMixin.name`. - * a coordinate or metadata instance equal to that of the desired coordinate e.g., :class:`~iris.coords.DimCoord` or :class:`~iris.common.metadata.CoordMetadata`. - * standard_name: The CF standard name of the desired coordinate. If ``None``, does not check for ``standard name``. - * long_name: An unconstrained description of the coordinate. If ``None``, does not check for ``long_name``. - * var_name: The NetCDF variable name of the desired coordinate. If ``None``, does not check for ``var_name``. - * attributes: A dictionary of attributes desired on the coordinates. If ``None``, does not check for ``attributes``. - * axis: The desired coordinate axis, see :func:`iris.util.guess_coord_axis`. If ``None``, does not check for ``axis``. Accepts the values ``X``, ``Y``, ``Z`` and ``T`` (case-insensitive). - * contains_dimension: The desired coordinate contains the data dimension. If ``None``, does not check for the dimension. - * dimensions: The exact data dimensions of the desired coordinate. Coordinates with no data dimension can be found with an empty ``tuple`` or ``list`` i.e., ``()`` or ``[]``. If ``None``, does not check for dimensions. - * coord_system: Whether the desired coordinates have a coordinate system equal to the given coordinate system. If ``None``, no check is done. - * dim_coords: Set to ``True`` to only return coordinates that are the cube's dimension coordinates. Set to ``False`` to only return coordinates that are the cube's auxiliary, mesh and derived coordinates. If ``None``, returns all coordinates. - * mesh_coords: Set to ``True`` to return only coordinates which are :class:`~iris.experimental.ugrid.MeshCoord`\\ s. Set to ``False`` to return only non-mesh coordinates. If ``None``, returns all coordinates. - Returns: A list containing zero or more coordinates matching the provided criteria. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ coords_and_factories = [] @@ -1891,80 +1795,63 @@ def coord( """ Return a single coordinate from the :class:`Cube` that matches the provided criteria. - .. note:: - If the arguments given do not result in **precisely one** coordinate, then a :class:`~iris.exceptions.CoordinateNotFoundError` is raised. - .. seealso:: - :meth:`Cube.coords` for matching zero or more coordinates. - Kwargs: - * name_or_coord: Either, - * a :attr:`~iris.common.mixin.CFVariableMixin.standard_name`, :attr:`~iris.common.mixin.CFVariableMixin.long_name`, or :attr:`~iris.common.mixin.CFVariableMixin.var_name` which is compared against the :meth:`~iris.common.mixin.CFVariableMixin.name`. - * a coordinate or metadata instance equal to that of the desired coordinate e.g., :class:`~iris.coords.DimCoord` or :class:`~iris.common.metadata.CoordMetadata`. - * standard_name: The CF standard name of the desired coordinate. If ``None``, does not check for ``standard name``. - * long_name: An unconstrained description of the coordinate. If ``None``, does not check for ``long_name``. - * var_name: The NetCDF variable name of the desired coordinate. If ``None``, does not check for ``var_name``. - * attributes: A dictionary of attributes desired on the coordinates. If ``None``, does not check for ``attributes``. - * axis: The desired coordinate axis, see :func:`iris.util.guess_coord_axis`. If ``None``, does not check for ``axis``. Accepts the values ``X``, ``Y``, ``Z`` and ``T`` (case-insensitive). - * contains_dimension: The desired coordinate contains the data dimension. If ``None``, does not check for the dimension. - * dimensions: The exact data dimensions of the desired coordinate. Coordinates with no data dimension can be found with an empty ``tuple`` or ``list`` i.e., ``()`` or ``[]``. If ``None``, does not check for dimensions. - * coord_system: Whether the desired coordinates have a coordinate system equal to the given coordinate system. If ``None``, no check is done. - * dim_coords: Set to ``True`` to only return coordinates that are the cube's dimension coordinates. Set to ``False`` to only return coordinates that are the cube's auxiliary, mesh and derived coordinates. If ``None``, returns all coordinates. - * mesh_coords: Set to ``True`` to return only coordinates which are :class:`~iris.experimental.ugrid.MeshCoord`\\ s. Set to ``False`` to return only non-mesh coordinates. If ``None``, returns all coordinates. - Returns: The coordinate that matches the provided criteria. - + .. note:: + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ coords = self.coords( name_or_coord=name_or_coord, @@ -1990,12 +1877,6 @@ def coord( if name_or_coord is not None: if not isinstance(name_or_coord, str): _name = name_or_coord.name() - emsg = ( - "Expected to find exactly 1 coordinate matching the given " - f"{_name!r} coordinate's metadata, but found none." - ) - raise iris.exceptions.CoordinateNotFoundError(emsg) - bad_name = _name or standard_name or long_name or "" emsg = ( f"Expected to find exactly 1 {bad_name!r} coordinate, " @@ -2008,28 +1889,24 @@ def coord( def coord_system(self, spec=None): """ Find the coordinate system of the given type. - If no target coordinate system is provided then find any available coordinate system. - Kwargs: - * spec: The the name or type of a coordinate system subclass. E.g. :: - cube.coord_system("GeogCS") cube.coord_system(iris.coord_systems.GeogCS) - If spec is provided as a type it can be a superclass of any coordinate system found. - If spec is None, then find any available coordinate systems within the :class:`iris.cube.Cube`. - Returns: The :class:`iris.coord_systems.CoordSystem` or None. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ if isinstance(spec, str) or spec is None: spec_name = spec @@ -2072,14 +1949,11 @@ def mesh(self): associated with the cube, if the cube has any :class:`~iris.experimental.ugrid.MeshCoord`\\ s, or ``None`` if it has none. - Returns: - * mesh (:class:`iris.experimental.ugrid.mesh.Mesh` or None): The mesh of the cube :class:`~iris.experimental.ugrid.MeshCoord`\\s, or ``None``. - """ result = self._any_meshcoord() if result is not None: @@ -2092,15 +1966,12 @@ def location(self): Return the mesh "location" of the cube data, if the cube has any :class:`~iris.experimental.ugrid.MeshCoord`\\ s, or ``None`` if it has none. - Returns: - * location (str or None): The mesh location of the cube :class:`~iris.experimental.ugrid.MeshCoord`\\s (i.e. one of 'face' / 'edge' / 'node'), or ``None``. - """ result = self._any_meshcoord() if result is not None: @@ -2112,14 +1983,11 @@ def mesh_dim(self): Return the cube dimension of the mesh, if the cube has any :class:`~iris.experimental.ugrid.MeshCoord`\\ s, or ``None`` if it has none. - Returns: - * mesh_dim (int, or None): the cube dimension which the cube :class:`~iris.experimental.ugrid.MeshCoord`\\s map to, or ``None``. - """ result = self._any_meshcoord() if result is not None: @@ -2129,22 +1997,16 @@ def mesh_dim(self): def cell_measures(self, name_or_cell_measure=None): """ Return a list of cell measures in this cube fitting the given criteria. - Kwargs: - * name_or_cell_measure Either - (a) a :attr:`standard_name`, :attr:`long_name`, or :attr:`var_name`. Defaults to value of `default` (which itself defaults to `unknown`) as defined in :class:`iris.common.CFVariableMixin`. - (b) a cell_measure instance with metadata equal to that of the desired cell_measures. - See also :meth:`Cube.cell_measure()`. - """ name = None @@ -2168,18 +2030,19 @@ def cell_measure(self, name_or_cell_measure=None): """ Return a single cell_measure given the same arguments as :meth:`Cube.cell_measures`. - .. note:: - If the arguments given do not result in precisely 1 cell_measure being matched, an :class:`iris.exceptions.CellMeasureNotFoundError` is raised. - .. seealso:: - :meth:`Cube.cell_measures()` for full keyword documentation. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ cell_measures = self.cell_measures(name_or_cell_measure) @@ -2200,15 +2063,9 @@ def cell_measure(self, name_or_cell_measure=None): bad_name = ( name_or_cell_measure and name_or_cell_measure.name() ) or "" - if name_or_cell_measure is not None: - emsg = ( - "Expected to find exactly 1 cell measure matching the given " - f"{bad_name!r} cell measure's metadata, but found none." - ) - raise iris.exceptions.CellMeasureNotFoundError(emsg) msg = ( - f"Expected to find exactly 1 {bad_name!r} cell measure, " - "but found none." + "Expected to find exactly 1 %s cell_measure, but found " + "none." % bad_name ) raise iris.exceptions.CellMeasureNotFoundError(msg) @@ -2218,23 +2075,22 @@ def ancillary_variables(self, name_or_ancillary_variable=None): """ Return a list of ancillary variable in this cube fitting the given criteria. - Kwargs: - * name_or_ancillary_variable Either - (a) a :attr:`standard_name`, :attr:`long_name`, or :attr:`var_name`. Defaults to value of `default` (which itself defaults to `unknown`) as defined in :class:`iris.common.CFVariableMixin`. - (b) a ancillary_variable instance with metadata equal to that of the desired ancillary_variables. - See also :meth:`Cube.ancillary_variable()`. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ name = None @@ -2258,18 +2114,18 @@ def ancillary_variable(self, name_or_ancillary_variable=None): """ Return a single ancillary_variable given the same arguments as :meth:`Cube.ancillary_variables`. - .. note:: - If the arguments given do not result in precisely 1 ancillary_variable being matched, an :class:`iris.exceptions.AncillaryVariableNotFoundError` is raised. - .. seealso:: - :meth:`Cube.ancillary_variables()` for full keyword documentation. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ ancillary_variables = self.ancillary_variables( name_or_ancillary_variable @@ -2293,16 +2149,9 @@ def ancillary_variable(self, name_or_ancillary_variable=None): name_or_ancillary_variable and name_or_ancillary_variable.name() ) or "" - if name_or_ancillary_variable is not None: - emsg = ( - "Expected to find exactly 1 ancillary_variable matching the " - f"given {bad_name!r} ancillary_variable's metadata, but found " - "none." - ) - raise iris.exceptions.AncillaryVariableNotFoundError(emsg) msg = ( - f"Expected to find exactly 1 {bad_name!r} ancillary_variable, " - "but found none." + "Expected to find exactly 1 {!s} ancillary_variable, but " + "found none.".format(bad_name) ) raise iris.exceptions.AncillaryVariableNotFoundError(msg) @@ -2313,7 +2162,6 @@ def cell_methods(self): """ Tuple of :class:`iris.coords.CellMethod` representing the processing done on the phenomenon. - """ return self._metadata_manager.cell_methods @@ -2340,18 +2188,25 @@ def core_data(self): """ Retrieve the data array of this :class:`~iris.cube.Cube` in its current state, which will either be real or lazy. - If this :class:`~iris.cube.Cube` has lazy data, accessing its data array via this method **will not** realise the data array. This means you can perform operations using this method that work equivalently on real or lazy data, and will maintain lazy data if present. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ return self._data_manager.core_data() @property def shape(self): - """The shape of the data of this cube.""" + """The shape of the data of this cube. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ return self._data_manager.shape @property @@ -2359,13 +2214,22 @@ def dtype(self): """ The data type of the values in the data array of this :class:`~iris.cube.Cube`. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ return self._data_manager.dtype @property def ndim(self): - """The number of dimensions in the data of this cube.""" + """ + The number of dimensions in the data of this cube. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. + """ return self._data_manager.ndim def lazy_data(self): @@ -2373,20 +2237,16 @@ def lazy_data(self): Return a "lazy array" representing the Cube data. A lazy array describes an array whose data values have not been loaded into memory from disk. - Accessing this method will never cause the Cube data to be loaded. Similarly, calling methods on, or indexing, the returned Array will not cause the Cube data to be loaded. - If the Cube data have already been loaded (for example by calling :meth:`~iris.cube.Cube.data`), the returned Array will be a view of the loaded cube data represented as a lazy array object. Note that this does _not_ make the Cube data lazy again; the Cube data remains loaded in memory. - Returns: A lazy array, representing the Cube data. - """ return self._data_manager.lazy_data() @@ -2395,15 +2255,14 @@ def data(self): """ The :class:`numpy.ndarray` representing the multi-dimensional data of the cube. - .. note:: - Cubes obtained from NetCDF, PP, and FieldsFile files will only populate this attribute on its first use. - To obtain the shape of the data without causing it to be loaded, use the Cube.shape attribute. - + .. note:: + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. Example:: >>> fname = iris.sample_data_path('air_temp.pp') >>> cube = iris.load_cube(fname, 'air_temperature') @@ -2421,7 +2280,6 @@ def data(self): ... >>> print(data.shape) (10, 20) - """ return self._data_manager.data @@ -2432,10 +2290,8 @@ def data(self, data): def has_lazy_data(self): """ Details whether this :class:`~iris.cube.Cube` has lazy data. - Returns: Boolean. - """ return self._data_manager.has_lazy_data() @@ -2443,16 +2299,16 @@ def has_lazy_data(self): def dim_coords(self): """ Return a tuple of all the dimension coordinates, ordered by dimension. - .. note:: - The length of the returned tuple is not necessarily the same as :attr:`Cube.ndim` as there may be dimensions on the cube without dimension coordinates. It is therefore unreliable to use the resulting tuple to identify the dimension coordinates for a given dimension - instead use the :meth:`Cube.coord` method with the ``dimensions`` and ``dim_coords`` keyword arguments. - + .. note:: + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ return tuple( ( @@ -2469,7 +2325,10 @@ def aux_coords(self): """ Return a tuple of all the auxiliary coordinates, ordered by dimension(s). - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ return tuple( ( @@ -2486,7 +2345,10 @@ def derived_coords(self): """ Return a tuple of all the coordinates generated by the coordinate factories. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ return tuple( factory.make_coord(self.coord_dims) @@ -2497,16 +2359,18 @@ def derived_coords(self): @property def aux_factories(self): - """Return a tuple of all the coordinate factories.""" + """Return a tuple of all the coordinate factories. + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`.""" return tuple(self._aux_factories) def summary(self, shorten=False, name_padding=35): """ String summary of the Cube with name+units, a list of dim coord names versus length and, optionally, a summary of all other components. - Kwargs: - * shorten (bool): If set, produce a one-line summary of minimal width, showing only the cube name, units and dimensions. @@ -2514,7 +2378,10 @@ def summary(self, shorten=False, name_padding=35): * name_padding (int): Control the *minimum* width of the cube name + units, i.e. the indent of the dimension map section. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ from iris._representation.cube_printout import CubePrinter @@ -2547,7 +2414,6 @@ def __getitem__(self, keys): method should be aligned to the data of the cube, and thus the indices requested must be applicable directly to the cube.data attribute. All metadata will be subsequently indexed appropriately. - """ # turn the keys into a full slice spec (all dims) full_slice = iris.util._build_full_slice_given_keys(keys, self.ndim) @@ -2664,7 +2530,10 @@ def subset(self, coord): Get a subset of the cube by providing the desired resultant coordinate. If the coordinate provided applies to the whole cube; the whole cube is returned. As such, the operation is not strict. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ if not isinstance(coord, iris.coords.Coord): raise ValueError("coord_to_extract must be a valid Coord.") @@ -2719,7 +2588,10 @@ def extract(self, constraint): """ Filter the cube by the given constraint using :meth:`iris.Constraint.extract` method. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # Cast the constraint into a proper constraint if it is not so already constraint = iris._constraints.as_constraint(constraint) @@ -2729,60 +2601,46 @@ def intersection(self, *args, **kwargs): """ Return the intersection of the cube with specified coordinate ranges. - Coordinate ranges can be specified as: - (a) positional arguments: instances of :class:`iris.coords.CoordExtent`, or equivalent tuples of 3-5 items: - * coord Either a :class:`iris.coords.Coord`, or coordinate name (as defined in :meth:`iris.cube.Cube.coords()`) - * minimum The minimum value of the range to select. - * maximum The maximum value of the range to select. - * min_inclusive If True, coordinate values equal to `minimum` will be included in the selection. Default is True. - * max_inclusive If True, coordinate values equal to `maximum` will be included in the selection. Default is True. - (b) keyword arguments, where the keyword name specifies the name of the coordinate, and the value defines the corresponding range of coordinate values as a tuple. The tuple must contain two, three, or four items, corresponding to `(minimum, maximum, min_inclusive, max_inclusive)` as defined above. - Kwargs: - * ignore_bounds: Intersect based on points only. Default False. - * threshold: Minimum proportion of a bounded cell that must overlap with the specified range. Default 0. - .. note:: - For ranges defined over "circular" coordinates (i.e. those where the `units` attribute has a modulus defined) the cube will be "rolled" to fit where necessary. When requesting a range that covers the entire modulus, a split cell will preferentially be placed at the ``minimum`` end. - + .. note:: + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. .. warning:: - Currently this routine only works with "circular" coordinates (as defined in the previous note.) - For example:: - >>> import iris >>> cube = iris.load_cube(iris.sample_data_path('air_temp.pp')) >>> print(cube.coord('longitude').points[::10]) @@ -2796,11 +2654,9 @@ def intersection(self, *args, **kwargs): >>> subset = cube.intersection(longitude=(-10, 10)) >>> print(subset.coord('longitude').points) [-7.50012207 -3.75012207 0. 3.75 7.5 ] - Returns: A new :class:`~iris.cube.Cube` giving the subset of the cube which intersects with the requested coordinate intervals. - """ result = self ignore_bounds = kwargs.pop("ignore_bounds", False) @@ -2943,11 +2799,9 @@ def _intersect_derive_subset(self, coord, points, bounds, inside_indices): def dim_coord_subset(): """ Derive the subset for dimension coordinates. - Ensure that we do not wrap if blocks are at the very edge. That is, if the very edge is wrapped and corresponds to base + period, stop this unnecessary wraparound. - """ # A contiguous block at the start and another at the end. # (NB. We can't have more than two blocks because we've already @@ -3146,30 +3000,24 @@ def slices_over(self, ref_to_slice): """ Return an iterator of all subcubes along a given coordinate or dimension index, or multiple of these. - Args: - * ref_to_slice (string, coord, dimension index or a list of these): Determines which dimensions will be iterated along (i.e. the dimensions that are not returned in the subcubes). A mix of input types can also be provided. - Returns: An iterator of subcubes. - For example, to get all subcubes along the time dimension:: - for sub_cube in cube.slices_over('time'): print(sub_cube) - .. seealso:: :meth:`iris.cube.Cube.slices`. - .. note:: - The order of dimension references to slice along does not affect the order of returned items in the iterator; instead the ordering is based on the fastest-changing dimension. - + .. note:: + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # Required to handle a mix between types. if _is_single_item(ref_to_slice): @@ -3202,33 +3050,27 @@ def slices(self, ref_to_slice, ordered=True): """ Return an iterator of all subcubes given the coordinates or dimension indices desired to be present in each subcube. - Args: - * ref_to_slice (string, coord, dimension index or a list of these): Determines which dimensions will be returned in the subcubes (i.e. the dimensions that are not iterated over). A mix of input types can also be provided. They must all be orthogonal (i.e. point to different dimensions). - Kwargs: - * ordered: if True, the order which the coords to slice or data_dims are given will be the order in which they represent the data in the resulting cube slices. If False, the order will follow that of the source cube. Default is True. - Returns: An iterator of subcubes. - For example, to get all 2d longitude/latitude subcubes from a multi-dimensional cube:: - for sub_cube in cube.slices(['longitude', 'latitude']): print(sub_cube) - + .. note:: + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. .. seealso:: :meth:`iris.cube.Cube.slices_over`. - """ if not isinstance(ordered, bool): raise TypeError("'ordered' argument to slices must be boolean.") @@ -3285,20 +3127,17 @@ def slices(self, ref_to_slice, ordered=True): def transpose(self, new_order=None): """ Re-order the data dimensions of the cube in-place. - new_order - list of ints, optional By default, reverse the dimensions, otherwise permute the axes according to the values given. - .. note:: If defined, new_order must span all of the data dimensions. - + .. note:: + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. Example usage:: - # put the second dimension first, followed by the third dimension, # and finally put the first dimension third:: - >>> cube.transpose([1, 2, 0]) - """ if new_order is None: new_order = np.arange(self.ndim)[::-1] @@ -3344,7 +3183,10 @@ def remap_cube_metadata(metadata_and_dims): def xml(self, checksum=False, order=True, byteorder=True): """ Returns a fully valid CubeML string representation of the Cube. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ doc = Document() @@ -3526,15 +3368,15 @@ def _order(array): def copy(self, data=None): """ Returns a deep copy of this cube. - Kwargs: - * data: Replace the data of the cube copy with provided data payload. - Returns: A copy instance of the :class:`Cube`. - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ memo = {} cube = self._deepcopy(memo, data=data) @@ -3702,45 +3544,33 @@ def collapsed(self, coords, aggregator, **kwargs): """ Collapse one or more dimensions over the cube given the coordinate/s and an aggregation. - Examples of aggregations that may be used include :data:`~iris.analysis.COUNT` and :data:`~iris.analysis.MAX`. - Weighted aggregations (:class:`iris.analysis.WeightedAggregator`) may also be supplied. These include :data:`~iris.analysis.MEAN` and sum :data:`~iris.analysis.SUM`. - Weighted aggregations support an optional *weights* keyword argument. If set, this should be supplied as an array of weights whose shape matches the cube. Values for latitude-longitude area weights may be calculated using :func:`iris.analysis.cartography.area_weights`. - Some Iris aggregators support "lazy" evaluation, meaning that cubes resulting from this method may represent data arrays which are not computed until the data is requested (e.g. via ``cube.data`` or ``iris.save``). If lazy evaluation exists for the given aggregator it will be used wherever possible when this cube's data is itself a deferred array. - Args: - * coords (string, coord or a list of strings/coords): Coordinate names/coordinates over which the cube should be collapsed. - * aggregator (:class:`iris.analysis.Aggregator`): Aggregator to be applied for collapse operation. - Kwargs: - * kwargs: Aggregation function keyword arguments. - Returns: Collapsed cube. - For example: - >>> import iris >>> import iris.analysis >>> path = iris.sample_data_path('ostia_monthly.nc') @@ -3763,34 +3593,27 @@ def collapsed(self, coords, aggregator, **kwargs): Attributes: Conventions 'CF-1.5' STASH m01s00i024 - - .. note:: - Some aggregations are not commutative and hence the order of processing is important i.e.:: - tmp = cube.collapsed('realization', iris.analysis.VARIANCE) result = tmp.collapsed('height', iris.analysis.VARIANCE) - is not necessarily the same result as:: - tmp = cube.collapsed('height', iris.analysis.VARIANCE) result2 = tmp.collapsed('realization', iris.analysis.VARIANCE) - Conversely operations which operate on more than one coordinate at the same time are commutative as they are combined internally into a single operation. Hence the order of the coordinates supplied in the list does not matter:: - cube.collapsed(['longitude', 'latitude'], iris.analysis.VARIANCE) - is the same (apart from the logically equivalent cell methods that may be created etc.) as:: - cube.collapsed(['latitude', 'longitude'], iris.analysis.VARIANCE) + .. note:: + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ # Convert any coordinate names to coordinates coords = self._as_list_of_coords(coords) @@ -3947,24 +3770,19 @@ def aggregated_by( ): """ Perform aggregation over the cube given one or more "group coordinates". - A "group coordinate" is a coordinate where repeating values represent a single group, such as a month coordinate on a daily time slice. Repeated values will form a group even if they are not consecutive. - The group coordinates must all be over the same cube dimension. Each common value group identified over all the group-by coordinates is collapsed using the provided aggregator. - Weighted aggregations (:class:`iris.analysis.WeightedAggregator`) may also be supplied. These include :data:`~iris.analysis.MEAN` and :data:`~iris.analysis.SUM`. - Weighted aggregations support an optional *weights* keyword argument. If set, this should be supplied as an array of weights whose shape matches the cube or as 1D array whose length matches the dimension over which is aggregated. - Parameters ---------- coords : (list of coord names or :class:`iris.coords.Coord` instances) @@ -3977,19 +3795,15 @@ def aggregated_by( any aggregated time coord(s), this causes the climatological flag to be set and the point for each cell to equal its first bound, thereby preserving the time of year. - Returns ------- :class:`iris.cube.Cube` - Other Parameters ---------------- kwargs: Aggregator and aggregation function keyword arguments. - Examples -------- - >>> import iris >>> import iris.analysis >>> import iris.coord_categorisation as cat @@ -4020,7 +3834,10 @@ def aggregated_by( Attributes: Conventions 'CF-1.5' STASH m01s00i024 - + Notes + ------ + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. """ groupby_coords = [] dimension_to_groupby = None @@ -4076,9 +3893,8 @@ def aggregated_by( # coordinate dimension. shared_coords = list( filter( - lambda coord_: coord_ not in groupby_coords - and dimension_to_groupby in self.coord_dims(coord_), - self.dim_coords + self.aux_coords, + lambda coord_: coord_ not in groupby_coords, + self.coords(contains_dimension=dimension_to_groupby), ) ) @@ -4110,11 +3926,6 @@ def aggregated_by( for coord in groupby_coords + shared_coords: aggregateby_cube.remove_coord(coord) - coord_mapping = {} - for coord in aggregateby_cube.coords(): - orig_id = id(self.coord(coord)) - coord_mapping[orig_id] = coord - # Determine the group-by cube data shape. data_shape = list(self.shape + aggregator.aggregate_shape(**kwargs)) data_shape[dimension_to_groupby] = len(groupby) @@ -4243,11 +4054,6 @@ def aggregated_by( aggregateby_cube.add_aux_coord( new_coord, self.coord_dims(lookup_coord) ) - coord_mapping[id(self.coord(lookup_coord))] = new_coord - - aggregateby_cube._aux_factories = [] - for factory in self.aux_factories: - aggregateby_cube.add_aux_factory(factory.updated(coord_mapping)) # Attach the aggregate-by data into the aggregate-by cube. if aggregateby_weights is None: @@ -4264,9 +4070,7 @@ def rolling_window(self, coord, aggregator, window, **kwargs): """ Perform rolling window aggregation on a cube given a coordinate, an aggregation method and a window size. - Args: - * coord (string/:class:`iris.coords.Coord`): The coordinate over which to perform the rolling window aggregation. @@ -4274,23 +4078,19 @@ def rolling_window(self, coord, aggregator, window, **kwargs): Aggregator to be applied to the data. * window (int): Size of window to use. - Kwargs: - * kwargs: Aggregator and aggregation function keyword arguments. The weights argument to the aggregator, if any, should be a 1d array with the same length as the chosen window. - Returns: :class:`iris.cube.Cube`. - .. note:: - This operation does not yet have support for lazy evaluation. - + .. note:: + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. For example: - >>> import iris, iris.analysis >>> fname = iris.sample_data_path('GloSea4', 'ensemble_010.pp') >>> air_press = iris.load_cube(fname, 'surface_temperature') @@ -4317,8 +4117,6 @@ def rolling_window(self, coord, aggregator, window, **kwargs): source \ 'Data from Met Office Unified Model' um_version '7.6' - - >>> print(air_press.rolling_window('time', iris.analysis.MEAN, 3)) surface_temperature / (K) \ (time: 4; latitude: 145; longitude: 192) @@ -4343,10 +4141,8 @@ def rolling_window(self, coord, aggregator, window, **kwargs): source \ 'Data from Met Office Unified Model' um_version '7.6' - Notice that the forecast_period dimension now represents the 4 possible windows of size 3 from the original cube. - """ coord = self._as_list_of_coords(coord)[0] @@ -4464,9 +4260,7 @@ def interpolate(self, sample_points, scheme, collapse_scalar=True): """ Interpolate from this :class:`~iris.cube.Cube` to the given sample points using the given interpolation scheme. - Args: - * sample_points: A sequence of (coordinate, points) pairs over which to interpolate. The values for coordinates that correspond to @@ -4478,24 +4272,18 @@ def interpolate(self, sample_points, scheme, collapse_scalar=True): An instance of the type of interpolation to use to interpolate from this :class:`~iris.cube.Cube` to the given sample points. The interpolation schemes currently available in Iris are: - * :class:`iris.analysis.Linear`, and * :class:`iris.analysis.Nearest`. - Kwargs: - * collapse_scalar: Whether to collapse the dimension of scalar sample points in the resulting cube. Default is True. - Returns: A cube interpolated at the given sample points. If `collapse_scalar` is True then the dimensionality of the cube will be the number of original cube dimensions minus the number of scalar coordinates. - For example: - >>> import datetime >>> import iris >>> path = iris.sample_data_path('uk_hires.pp') @@ -4541,7 +4329,6 @@ def interpolate(self, sample_points, scheme, collapse_scalar=True): [349618.5] >>> print(result == result2) True - """ coords, points = zip(*sample_points) interp = scheme.interpolator(self, coords) @@ -4551,37 +4338,28 @@ def regrid(self, grid, scheme): r""" Regrid this :class:`~iris.cube.Cube` on to the given target `grid` using the given regridding `scheme`. - Args: - * grid: A :class:`~iris.cube.Cube` that defines the target grid. * scheme: An instance of the type of regridding to use to regrid this cube onto the target grid. The regridding schemes in Iris currently include: - * :class:`iris.analysis.Linear`\*, * :class:`iris.analysis.Nearest`\*, * :class:`iris.analysis.AreaWeighted`\*, * :class:`iris.analysis.UnstructuredNearest`, * :class:`iris.analysis.PointInCell`, - \* Supports lazy regridding. - Returns: A cube defined with the horizontal dimensions of the target grid and the other dimensions from this cube. The data values of this cube will be converted to values on the new grid according to the given regridding scheme. - The returned cube will have lazy data if the original cube has lazy data and the regridding scheme supports lazy regridding. - .. note:: - Both the source and target cubes must have a CoordSystem, otherwise this function is not applicable. - """ regridder = scheme.regridder(self, grid) return regridder(self) @@ -4590,12 +4368,10 @@ def regrid(self, grid, scheme): class ClassDict(MutableMapping): """ A mapping that stores objects keyed on their superclasses and their names. - The mapping has a root class, all stored objects must be a subclass of the root class. The superclasses used for an object include the class of the object, but do not include the root class. Only one object is allowed for any key. - """ def __init__(self, superclass): @@ -4669,7 +4445,6 @@ def sorted_axes(axes): """ Returns the axis names sorted alphabetically, with the exception that 't', 'z', 'y', and, 'x' are sorted to the end. - """ return sorted( axes, @@ -4717,4 +4492,4 @@ def __next__(self): return cube - next = __next__ + next = __next__ \ No newline at end of file diff --git a/lib/iris/pandas.py b/lib/iris/pandas.py index b00eb3f117..1cb85d6ed8 100644 --- a/lib/iris/pandas.py +++ b/lib/iris/pandas.py @@ -160,6 +160,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 " @@ -241,6 +243,8 @@ def as_cubes( Dask ``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 @@ -537,6 +541,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. + """ data = cube.data if ma.isMaskedArray(data): @@ -583,6 +591,10 @@ def as_data_frame(cube, copy=True): for example when creating from an int32 array. Iris will detect this and raise an exception if copy=False. + Notes + ------ + Since this function converts to/from a Pandas object, laziness will not be preserved. + """ data = cube.data if ma.isMaskedArray(data): diff --git a/lib/iris/plot.py b/lib/iris/plot.py index 8cd849b716..ddf93c69ce 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] @@ -1334,6 +1354,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 +1401,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 +1440,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 +1470,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 +1566,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 +1621,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 +1672,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 +1709,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)): @@ -1862,6 +1922,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 18ed2554a3..000e2fd105 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -175,6 +175,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") @@ -202,6 +207,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") @@ -230,6 +239,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 @@ -245,6 +259,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") @@ -259,6 +277,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") @@ -273,6 +296,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") @@ -289,6 +317,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) @@ -304,6 +337,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) diff --git a/lib/iris/util.py b/lib/iris/util.py index 3d82ea68c5..87ae4cbb5a 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): @@ -510,6 +539,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 +622,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 +679,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 = [] @@ -1056,7 +1100,7 @@ def clip_string(the_str, clip_length=70, rider="..."): return first_part + remainder[:termination_point] + rider - +# needs doing def format_array(arr): """ Returns the given array as a string, using the python builtin str @@ -1096,7 +1140,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. @@ -1240,6 +1284,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 = [ @@ -1309,7 +1358,13 @@ 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. + + ------ + 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: @@ -1320,7 +1375,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: @@ -1371,6 +1434,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) @@ -1400,6 +1469,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 = {} @@ -1540,6 +1614,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 @@ -1666,6 +1746,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 @@ -1757,6 +1843,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", @@ -1897,6 +1989,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. @@ -1943,6 +2039,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. @@ -1986,6 +2087,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() @@ -2002,7 +2109,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() From cee5323ab0069c9da5515da0056089d174d4ad9c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 08:31:09 +0000 Subject: [PATCH 08/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- lib/iris/cube.py | 2 +- lib/iris/util.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index 0ff09e353a..d042962357 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -4502,4 +4502,4 @@ def __next__(self): return cube - next = __next__ \ No newline at end of file + next = __next__ diff --git a/lib/iris/util.py b/lib/iris/util.py index 87ae4cbb5a..75c6778dd3 100644 --- a/lib/iris/util.py +++ b/lib/iris/util.py @@ -1100,6 +1100,7 @@ def clip_string(the_str, clip_length=70, rider="..."): return first_part + remainder[:termination_point] + rider + # needs doing def format_array(arr): """ @@ -1140,7 +1141,7 @@ def format_array(arr): return result -def new_axis(src_cube, scalar_coord=None, expand_extras=()): #maybe not lazy +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. From 2f1970f7df8515b9f9c9d70e25d6650bea0d2cbd Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Wed, 18 Jan 2023 08:38:41 +0000 Subject: [PATCH 09/11] updated lastest what'snew --- docs/src/whatsnew/latest.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index ca31fc7a1d..ffbedb0fcd 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -82,8 +82,8 @@ This document explains the changes made to Iris for this release and removed an ECMWF link in the ``v1.0`` What's New that was failing the linkcheck CI. (:pull:`5109`) -#. `@Esadek-MO`_ added notes at the bottom of functions to - to clarify if the function preserves laziness or not. (:pull:`5066`) +#. `@Esadek-MO`_ added notes to function docstings to + to clarify if the function preserves laziness or not. (:pull:`5137`) 💼 Internal =========== From 10488940b34902228b6a35596b25f433ec61a7be Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Sun, 2 Apr 2023 17:54:45 +0100 Subject: [PATCH 10/11] I almost hope this wasn't the fix, I'm such a moron --- lib/iris/util.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/iris/util.py b/lib/iris/util.py index 75c6778dd3..b29fc784e8 100644 --- a/lib/iris/util.py +++ b/lib/iris/util.py @@ -1362,6 +1362,7 @@ def is_regular(coord): """ 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`. From bb3a431e92dc5d6c5f38789016b561eb78f38d72 Mon Sep 17 00:00:00 2001 From: Elias Sadek Date: Wed, 5 Apr 2023 16:18:21 +0100 Subject: [PATCH 11/11] adressed review changes --- lib/iris/plot.py | 31 +++++++++++++++++++++++++++++-- lib/iris/quickplot.py | 9 +++++++++ lib/iris/util.py | 37 ++++++++++++++++++++++++++++++++----- 3 files changed, 70 insertions(+), 7 deletions(-) diff --git a/lib/iris/plot.py b/lib/iris/plot.py index d0c10c84d8..47e345b83c 100644 --- a/lib/iris/plot.py +++ b/lib/iris/plot.py @@ -1275,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( @@ -1308,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} @@ -1749,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)): @@ -1781,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 @@ -1827,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() diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index 2b79b889f6..9209d4b3b7 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -355,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) @@ -368,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 ac6b03edd6..7900b734a8 100644 --- a/lib/iris/util.py +++ b/lib/iris/util.py @@ -436,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, " @@ -485,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 @@ -1079,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: @@ -1100,7 +1114,6 @@ def clip_string(the_str, clip_length=70, rider="..."): return first_part + remainder[:termination_point] + rider -# needs doing def format_array(arr): """ Returns the given array as a string, using the python builtin str @@ -1110,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 @@ -1173,6 +1191,11 @@ def new_axis(src_cube, scalar_coord=None, expand_extras=()): # maybe not lazy >>> 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): @@ -1421,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) @@ -1850,10 +1877,10 @@ 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`. + Notes + ------ + This function does not maintain laziness when called; it realises data. + See more at :doc:`/userguide/real_and_lazy_data`. """