From 41f110776ae06c4875b77fef7815b83938056611 Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Tue, 2 Jan 2024 09:32:24 +0000 Subject: [PATCH 01/26] Various ruff rule compliance (W, CPY, ISC, AIR) (#5667) * fix pycodestyle W * fix for ruff: flake8-copyright (CPY) * ruff, no fix needed: flake8-implicit-str-concat (ISC) * ruff, no fix needed: Airflow (AIR) --- .ruff.toml | 13 ------------- benchmarks/bm_runner.py | 4 ++-- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index 9451023469..e396c2d025 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -11,7 +11,6 @@ lint.ignore = [ # pycodestyle (E, W) # https://docs.astral.sh/ruff/rules/#pycodestyle-e-w "E", - "W", # mccabe (C90) # https://docs.astral.sh/ruff/rules/#mccabe-c90 @@ -71,10 +70,6 @@ lint.ignore = [ # https://docs.astral.sh/ruff/rules/#flake8-builtins-a "A", - # flake8-copyright (CPY) - # https://docs.astral.sh/ruff/rules/#flake8-copyright-cpy - "CPY", - # flake8-comprehensions (C4) # https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4 "C4", @@ -91,10 +86,6 @@ lint.ignore = [ # https://docs.astral.sh/ruff/rules/#flake8-future-annotations-fa "FA", - # flake8-implicit-str-concat (ISC) - # https://docs.astral.sh/ruff/rules/#flake8-implicit-str-concat-isc - "ISC", - # flake8-logging-format (G) # https://docs.astral.sh/ruff/rules/#flake8-logging-format-g "G", @@ -187,10 +178,6 @@ lint.ignore = [ # https://docs.astral.sh/ruff/rules/#flynt-fly "FLY", - # Airflow (AIR) - # https://docs.astral.sh/ruff/rules/#airflow-air - "AIR", - # Perflint (PERF) # https://docs.astral.sh/ruff/rules/#perflint-perf "PERF", diff --git a/benchmarks/bm_runner.py b/benchmarks/bm_runner.py index 8b45031fca..0195d259fe 100644 --- a/benchmarks/bm_runner.py +++ b/benchmarks/bm_runner.py @@ -257,8 +257,8 @@ def _gh_create_reports(commit_sha: str, results_full: str, results_shifts: str) * commit {commit_sha} ({pr_tag}).

- Please review the report below and - take corrective/congratulatory action as appropriate + Please review the report below and + take corrective/congratulatory action as appropriate :slightly_smiling_face:

""" From e2e94547d00c7067d4997983d08ceaeec25250ae Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Tue, 2 Jan 2024 22:26:42 +0000 Subject: [PATCH 02/26] ruff compliance for D405 and D407 (#5666) * ruff compliance D405. * ruff complliance with D407. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix typos * remove comment * minor tweaks * undo changes * fix typo in comment * remove comments * string update * review comments (None use) * Update lib/iris/analysis/stats.py Co-authored-by: Patrick Peglar * reivew fix. * Update lib/iris/analysis/stats.py Co-authored-by: Patrick Peglar * Update lib/iris/analysis/stats.py Co-authored-by: Patrick Peglar * Update lib/iris/analysis/cartography.py Co-authored-by: Patrick Peglar * Update lib/iris/analysis/stats.py Co-authored-by: Patrick Peglar * Update lib/iris/_concatenate.py Co-authored-by: Patrick Peglar * Update lib/iris/_concatenate.py Co-authored-by: Patrick Peglar * Update lib/iris/_concatenate.py Co-authored-by: Patrick Peglar * review actions --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Patrick Peglar --- .ruff.toml | 4 +- .../documenting/docstrings_attribute.py | 18 +- .../documenting/docstrings_sample_routine.py | 19 +- lib/iris/_concatenate.py | 325 ++++--- lib/iris/_data_manager.py | 91 +- lib/iris/_lazy_data.py | 141 ++-- lib/iris/_merge.py | 452 +++++----- lib/iris/_representation/cube_printout.py | 30 +- lib/iris/analysis/_area_weighted.py | 37 +- lib/iris/analysis/_interpolation.py | 100 +-- lib/iris/analysis/_regrid.py | 179 ++-- lib/iris/analysis/cartography.py | 305 ++++--- lib/iris/analysis/maths.py | 309 ++++--- lib/iris/analysis/stats.py | 20 +- lib/iris/analysis/trajectory.py | 102 ++- lib/iris/common/lenient.py | 112 +-- lib/iris/common/metadata.py | 308 ++++--- lib/iris/common/resolve.py | 371 ++++---- lib/iris/coord_categorisation.py | 90 +- lib/iris/coords.py | 397 ++++----- lib/iris/cube.py | 791 +++++++++--------- lib/iris/experimental/regrid.py | 131 +-- lib/iris/experimental/regrid_conservative.py | 27 +- lib/iris/experimental/ugrid/mesh.py | 396 ++++----- lib/iris/experimental/ugrid/metadata.py | 99 ++- lib/iris/fileformats/_ff.py | 124 +-- lib/iris/fileformats/cf.py | 119 +-- lib/iris/fileformats/dot.py | 2 +- lib/iris/fileformats/name.py | 16 +- lib/iris/fileformats/name_loaders.py | 134 +-- lib/iris/fileformats/nimrod.py | 19 +- lib/iris/fileformats/pp_load_rules.py | 152 ++-- lib/iris/fileformats/pp_save_rules.py | 124 ++- lib/iris/fileformats/rules.py | 26 +- lib/iris/fileformats/um/_fast_load.py | 28 +- .../um/_fast_load_structured_fields.py | 48 +- lib/iris/fileformats/um/_ff_replacement.py | 48 +- .../um/_optimal_array_structuring.py | 58 +- lib/iris/iterate.py | 23 +- lib/iris/palette.py | 59 +- lib/iris/tests/__init__.py | 97 +-- .../integration/test_netcdf__loadsaveattrs.py | 7 +- lib/iris/tests/stock/mesh.py | 48 +- lib/iris/tests/test_concatenate.py | 88 +- lib/iris/tests/test_cube_to_pp.py | 6 +- .../netcdf/saver/test_Saver__ugrid.py | 72 +- lib/iris/util.py | 366 ++++---- 47 files changed, 3290 insertions(+), 3228 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index e396c2d025..eca1660fbf 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -30,7 +30,7 @@ lint.ignore = [ "D102", # Missing docstring in public method "D104", # Missing docstring in public package "D106", # Missing docstring in public nested class - # (D-3) Temporary, before an initial review, either fix ocurrenvces or move to (2). + # (D-3) Temporary, before an initial review, either fix ocurrences or move to (2). "D100", # Missing docstring in public module "D103", # Missing docstring in public function "D200", # One-line docstring should fit on one line @@ -38,9 +38,7 @@ lint.ignore = [ "D205", # 1 blank line required between summary line and description "D401", # First line of docstring should be in imperative mood: ... "D404", # First word of the docstring should not be "This" - "D405", # Section name should be properly capitalized "D406", # Section name should end with a newline - "D407", # Missing dashed underline after section # pyupgrade (UP) # https://docs.astral.sh/ruff/rules/#pyupgrade-up diff --git a/docs/src/developers_guide/documenting/docstrings_attribute.py b/docs/src/developers_guide/documenting/docstrings_attribute.py index 9485ca5af7..3044145b20 100644 --- a/docs/src/developers_guide/documenting/docstrings_attribute.py +++ b/docs/src/developers_guide/documenting/docstrings_attribute.py @@ -6,15 +6,16 @@ def __init__(self, arg1, arg2): Description section text. - Args: - - * arg1 (int): + Parameters + ---------- + arg1 : int First argument description. - * arg2 (float): + arg2 : float Second argument description. - Returns: - Boolean. + Returns + ------- + bool """ self.a = arg1 @@ -26,8 +27,9 @@ def __init__(self, arg1, arg2): def square(self): """*(read-only)* Purpose section description. - Returns: - int. + Returns + ------- + int """ return self.a * self.a diff --git a/docs/src/developers_guide/documenting/docstrings_sample_routine.py b/docs/src/developers_guide/documenting/docstrings_sample_routine.py index 65a312c027..d565e6a8df 100644 --- a/docs/src/developers_guide/documenting/docstrings_sample_routine.py +++ b/docs/src/developers_guide/documenting/docstrings_sample_routine.py @@ -3,22 +3,21 @@ def sample_routine(arg1, arg2, kwarg1="foo", kwarg2=None): Description section longer text goes here. - Args: - - * arg1 (numpy.ndarray): + Parameters + ---------- + arg1 : numpy.ndarray First argument description. - * arg2 (numpy.ndarray): + arg2 : numpy.ndarray Second argument description. - - Kwargs: - - * kwarg1 (string): + kwarg1: str, optional The first keyword argument. This argument description can be multi-lined. - * kwarg2 (Boolean or None): + kwarg2 : bool, optional The second keyword argument. - Returns: + Returns + ------- + numpy.ndarray numpy.ndarray of arg1 * arg2 """ diff --git a/lib/iris/_concatenate.py b/lib/iris/_concatenate.py index 049222953f..97c2840958 100644 --- a/lib/iris/_concatenate.py +++ b/lib/iris/_concatenate.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Automatic concatenation of multiple cubes over one or more existing dimensions. - -""" +"""Automatic concatenation of multiple cubes over one or more existing dimensions.""" from collections import defaultdict, namedtuple import warnings @@ -39,13 +37,10 @@ class _CoordAndDims(namedtuple("CoordAndDims", ["coord", "dims"])): """Container for a coordinate and the associated data dimension(s) spanned over a :class:`iris.cube.Cube`. - Args: - - * coord: - A :class:`iris.coords.DimCoord` or :class:`iris.coords.AuxCoord` - coordinate instance. - - * dims: + Parameters + ---------- + coord : :class:`iris.coords.DimCoord` or :class:`iris.coords.AuxCoord` + dims : tuple A tuple of the data dimension(s) spanned by the coordinate. """ @@ -62,22 +57,18 @@ class _CoordMetaData( """Container for the metadata that defines a dimension or auxiliary coordinate. - Args: - - * defn: + Parameters + ---------- + defn : :class:`iris.common.CoordMetadata` The :class:`iris.common.CoordMetadata` metadata that represents a coordinate. - - * dims: + dims : The dimension(s) associated with the coordinate. - - * points_dtype: + points_dtype : :class:`np.dtype` The points data :class:`np.dtype` of an associated coordinate. - - * bounds_dtype: + bounds_dtype : :class:`np.dtype` The bounds data :class:`np.dtype` of an associated coordinate. - - * kwargs: + **kwargs : A dictionary of key/value pairs required to define a coordinate. """ @@ -85,16 +76,15 @@ class _CoordMetaData( def __new__(mcs, coord, dims): """Create a new :class:`_CoordMetaData` instance. - Args: - - * coord: - The :class:`iris.coord.DimCoord` or :class:`iris.coord.AuxCoord`. - - * dims: + Parameters + ---------- + coord : :class:`iris.coord.DimCoord` or :class:`iris.coord.AuxCoord` + dims : The dimension(s) associated with the coordinate. - Returns: - The new class instance. + Returns + ------- + The new class instance. """ defn = coord.metadata @@ -163,17 +153,12 @@ class _DerivedCoordAndDims( """Container for a derived coordinate, the associated AuxCoordFactory, and the associated data dimension(s) spanned over a :class:`iris.cube.Cube`. - Args: - - * coord: - A :class:`iris.coords.DimCoord` or :class:`iris.coords.AuxCoord` - coordinate instance. - - * dims: + Parameters + ---------- + coord : :class:`iris.coord.DimCoord` or :class:`iris.coord.AuxCoord` + dims: tuple A tuple of the data dimension(s) spanned by the coordinate. - - * aux_factory: - A :class:`iris.aux_factory.AuxCoordFactory` instance. + aux_factory : :class:`iris.aux_factory.AuxCoordFactory` """ @@ -193,13 +178,12 @@ class _OtherMetaData(namedtuple("OtherMetaData", ["defn", "dims"])): """Container for the metadata that defines a cell measure or ancillary variable. - Args: - - * defn: + Parameters + ---------- + defn : :class:`iris.coords._DMDefn` or :class:`iris.coords._CellMeasureDefn` The :class:`iris.coords._DMDefn` or :class:`iris.coords._CellMeasureDefn` metadata that represents a coordinate. - - * dims: + dims : The dimension(s) associated with the coordinate. """ @@ -207,17 +191,15 @@ class _OtherMetaData(namedtuple("OtherMetaData", ["defn", "dims"])): def __new__(cls, ancil, dims): """Create a new :class:`_OtherMetaData` instance. - Args: - - * ancil: - The :class:`iris.coord.CellMeasure` or - :class:`iris.coord.AncillaryVariable`. - - * dims: + Parameters + ---------- + ancil : :class:`iris.coord.CellMeasure` or :class:`iris.coord.AncillaryVariable`. + dims : The dimension(s) associated with ancil. - Returns: - The new class instance. + Returns + ------- + The new class instance. """ defn = ancil.metadata @@ -250,12 +232,11 @@ class _SkeletonCube(namedtuple("SkeletonCube", ["signature", "data"])): """Basis of a source-cube, containing the associated coordinate metadata, coordinates and cube data payload. - Args: - - * signature: + Parameters + ---------- + signature : :class:`_CoordSignature` The :class:`_CoordSignature` of an associated source-cube. - - * data: + data : The data payload of an associated :class:`iris.cube.Cube` source-cube. """ @@ -266,12 +247,11 @@ class _SkeletonCube(namedtuple("SkeletonCube", ["signature", "data"])): class _Extent(namedtuple("Extent", ["min", "max"])): """Container representing the limits of a one-dimensional extent/range. - Args: - - * min: + Parameters + ---------- + min : The minimum value of the extent. - - * max: + max : The maximum value of the extent. """ @@ -283,12 +263,12 @@ class _CoordExtent(namedtuple("CoordExtent", ["points", "bounds"])): """Container representing the points and bounds extent of a one dimensional coordinate. - Args: - - * points: + Parameters + ---------- + points : :class:`_Extent` The :class:`_Extent` of the coordinate point values. - * bounds: + bounds : A list containing the :class:`_Extent` of the coordinate lower bound and the upper bound. Defaults to None if no associated bounds exist for the coordinate. @@ -308,34 +288,27 @@ def concatenate( ): """Concatenate the provided cubes over common existing dimensions. - Args: - - * cubes: + Parameters + ---------- + cubes : iterable of :class:`iris.cube.Cube` An iterable containing one or more :class:`iris.cube.Cube` instances to be concatenated together. - - Kwargs: - - * error_on_mismatch: + error_on_mismatch: bool, default=False If True, raise an informative :class:`~iris.exceptions.ContatenateError` if registration fails. - - * check_aux_coords + check_aux_coords : bool, default=True Checks if the points and bounds of 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 + check_cell_measures : bool, default=True Checks if the data of 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 + check_ancils : bool, default=True Checks if the data of 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. - - * check_derived_coords + check_derived_coords : bool, default=True Checks if the points and bounds of derived coordinates of the cubes match. This check is not applied to derived coordinates that span the dimension the concatenation is occurring along. Note that differences @@ -344,9 +317,10 @@ def concatenate( derive the coordinates can be ignored with `check_aux_coords`. Defaults to True. - Returns: - A :class:`iris.cube.CubeList` of concatenated :class:`iris.cube.Cube` - instances. + Returns + ------- + :class:`iris.cube.CubeList` + A :class:`iris.cube.CubeList` of concatenated :class:`iris.cube.Cube` instances. """ proto_cubes_by_name = defaultdict(list) @@ -409,9 +383,9 @@ def __init__(self, cube): """Represents the cube metadata and associated coordinate metadata that allows suitable cubes for concatenation to be identified. - Args: - - * cube: + Parameters + ---------- + cube : :class:`iris.cube.Cube` The :class:`iris.cube.Cube` source-cube. """ @@ -501,20 +475,20 @@ def _coordinate_differences(self, other, attr, reason="metadata"): """Determine the names of the coordinates that differ between `self` and `other` for a coordinate attribute on a _CubeSignature. - Args: - - * other (_CubeSignature): + Parameters + ---------- + other : _CubeSignature The _CubeSignature to compare against. - - * attr (string): + attr : str The _CubeSignature attribute within which differences exist between `self` and `other`. - - * reason (string): + reason : str The reason to give for mismatch (function is normally, but not always, testing metadata) - Returns: + Returns + ------- + tuple Tuple of a descriptive error message and the names of attributes that differ between `self` and `other`. @@ -550,24 +524,25 @@ def match(self, other, error_on_mismatch): This is the first step to determine if two "cubes" (either a real Cube or a ProtoCube) can be concatenated, by considering: - - data dimensions - - dimensions metadata - - aux coords metadata - - scalar coords - - attributes - - dtype - Args: + * data dimensions + * aux coords metadata + * scalar coords + * attributes + * dtype - * other (_CubeSignature): + Parameters + ---------- + other : _CubeSignature The _CubeSignature to compare against. - - * error_on_mismatch (bool): + error_on_mismatch : bool If True, raise a :class:`~iris.exceptions.MergeException` with a detailed explanation if the two do not match. - Returns: - Boolean. True if and only if this _CubeSignature matches the other. + Returns + ------- + bool + True if and only if this _CubeSignature matches the other. """ msg_template = "{}{} differ: {} != {}" @@ -634,9 +609,9 @@ def __init__(self, cube_signature): non-overlapping :class:`iris.cube.Cube` source-cubes for concatenation over a common single dimension. - Args: - - * cube_signature: + Parameters + ---------- + cube_signature : :class:`_CubeSignature` The :class:`_CubeSignature` that defines the source-cube. """ @@ -658,7 +633,9 @@ def __init__(self, cube_signature): def _cmp(coord, other): """Compare the coordinates for concatenation compatibility. - Returns: + Returns + ------- + bool tuple A boolean tuple pair of whether the coordinates are compatible, and whether they represent a candidate axis of concatenation. @@ -686,14 +663,15 @@ def candidate_axis(self, other): If a candidate axis is found, then the coordinate signatures are compatible. - Args: - - * other: - The :class:`_CoordSignature` + Parameters + ---------- + other : :class:`_CoordSignature` - Returns: - None if no single candidate axis exists, otherwise - the candidate axis of concatenation. + Returns + ------- + result : + None if no single candidate axis exists, otherwise the candidate + axis of concatenation. """ result = False @@ -754,9 +732,9 @@ def __init__(self, cube): """Create a new _ProtoCube from the given cube and record the cube as a source-cube. - Args: - - * cube: + Parameters + ---------- + cube : Source :class:`iris.cube.Cube` of the :class:`_ProtoCube`. """ @@ -788,7 +766,9 @@ def concatenate(self): """Concatenates all the source-cubes registered with the :class:`_ProtoCube` over the nominated common dimension. - Returns: + Returns + ------- + :class:`iris.cube.Cube` The concatenated :class:`iris.cube.Cube`. """ @@ -860,41 +840,35 @@ def register( check_ancils=False, check_derived_coords=False, ): - """Determine whether the given source-cube is suitable for concatenation - with this :class:`_ProtoCube`. + """Determine if the given source-cube is suitable for concatenation. - Args: + Determine if the given source-cube is suitable for concatenation + with this :class:`_ProtoCube`. - * cube: + Parameters + ---------- + cube : :class:`iris.cube.Cube` The :class:`iris.cube.Cube` source-cube candidate for concatenation. - - Kwargs: - - * axis: + axis : optional Seed the dimension of concatenation for the :class:`_ProtoCube` rather than rely on negotiation with source-cubes. - - * error_on_mismatch: + error_on_mismatch : bool, optional If True, raise an informative error if registration fails. - - * check_aux_coords + check_aux_coords : bool, optional Checks if the points and bounds of 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 False. - - * check_cell_measures + check_cell_measures : bool, optional Checks if the data of 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 False. - - * check_ancils + check_ancils : bool, optional Checks if the data of 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 False. - - * check_derived_coords + check_derived_coords : bool, optional Checks if the points and bounds of derived coordinates of the cubes match. This check is not applied to derived coordinates that span the dimension the concatenation is occurring along. Note that @@ -903,8 +877,9 @@ def register( coordinates used to derive the coordinates can be ignored with `check_aux_coords`. Defaults to False. - Returns: - Boolean. + Returns + ------- + bool """ # Verify and assert the nominated axis. @@ -1021,13 +996,13 @@ def _add_skeleton(self, coord_signature, data): """Create and add the source-cube skeleton to the :class:`_ProtoCube`. - Args: - - * coord_signature: + Parameters + ---------- + coord_signature : :`_CoordSignature` The :class:`_CoordSignature` of the associated given source-cube. - * data: + data : :class:`iris.cube.Cube` The data payload of an associated :class:`iris.cube.Cube` source-cube. @@ -1039,8 +1014,9 @@ def _build_aux_coordinates(self): """Generate the auxiliary coordinates with associated dimension(s) mapping for the new concatenated cube. - Returns: - A list of auxiliary coordinates and dimension(s) tuple pairs. + Returns + ------- + A list of auxiliary coordinates and dimension(s) tuple pairs. """ # Setup convenience hooks. @@ -1095,8 +1071,9 @@ def _build_aux_coordinates(self): def _build_scalar_coordinates(self): """Generate the scalar coordinates for the new concatenated cube. - Returns: - A list of scalar coordinates. + Returns + ------- + A list of scalar coordinates. """ scalar_coords = [] @@ -1109,8 +1086,9 @@ def _build_cell_measures(self): """Generate the cell measures with associated dimension(s) mapping for the new concatenated cube. - Returns: - A list of cell measures and dimension(s) tuple pairs. + Returns + ------- + A list of cell measures and dimension(s) tuple pairs. """ # Setup convenience hooks. @@ -1146,8 +1124,9 @@ def _build_ancillary_variables(self): """Generate the ancillary variables with associated dimension(s) mapping for the new concatenated cube. - Returns: - A list of ancillary variables and dimension(s) tuple pairs. + Returns + ------- + A list of ancillary variables and dimension(s) tuple pairs. """ # Setup convenience hooks. @@ -1184,21 +1163,20 @@ def _build_aux_factories( ): """Generate the aux factories for the new concatenated cube. - Args: - - * dim_coords_and_dims: + Parameters + ---------- + dim_coords_and_dims : A list of dimension coordinate and dimension tuple pairs from the concatenated cube. - - * aux_coords_and_dims: + aux_coords_and_dims : A list of auxiliary coordinates and dimension(s) tuple pairs from the concatenated cube. - - * scalar_coords: + scalar_coords : A list of scalar coordinates from the concatenated cube. - Returns: - A list of :class:`iris.aux_factory.AuxCoordFactory`. + Returns + ------- + list of :class:`iris.aux_factory.AuxCoordFactory` """ # Setup convenience hooks. @@ -1253,8 +1231,9 @@ def _build_aux_factories( def _build_data(self): """Generate the data payload for the new concatenated cube. - Returns: - The concatenated :class:`iris.cube.Cube` data payload. + Returns + ------- + The concatenated :class:`iris.cube.Cube` data payload. """ skeletons = self._skeletons @@ -1318,16 +1297,16 @@ def _sequence(self, extent, axis): this :class:`_ProtoCube` into non-overlapping segments for the given axis. - Args: - - * extent: + Parameters + ---------- + extent : :class:`_CoordExtent` The :class:`_CoordExtent` of the candidate source-cube. - - * axis: + axis : The candidate axis of concatenation. - Returns: - Boolean. + Returns + ------- + bool """ result = True diff --git a/lib/iris/_data_manager.py b/lib/iris/_data_manager.py index 601066630c..785440d094 100644 --- a/lib/iris/_data_manager.py +++ b/lib/iris/_data_manager.py @@ -20,9 +20,9 @@ class DataManager: def __init__(self, data): """Create a data manager for the specified data. - Args: - - * data: + Parameters + ---------- + data : The :class:`~numpy.ndarray` or :class:`~numpy.ma.core.MaskedArray` real data, or :class:`~dask.array.core.Array` lazy data to be managed. @@ -54,10 +54,10 @@ def __deepcopy__(self, memo): """Allow :class:`~iris._data_manager.DataManager` instance deepcopy support. - Args: - - * memo: - :class:`copy` memo dictionary. + Parameters + ---------- + memo : :func:`copy` + :func:`copy` memo dictionary. """ return self._deepcopy(memo) @@ -71,14 +71,15 @@ def __eq__(self, other): the realised_dtype, the dtype of the payload, the fill-value and the payload content. - Args: - - * other: + Parameters + ---------- + other : :class:`~iris._data_manager.DataManager` The :class:`~iris._data_manager.DataManager` instance to compare with. - Returns: - Boolean. + Returns + ------- + bool """ from iris.util import array_equal @@ -99,14 +100,15 @@ def __ne__(self, other): Note that, this is explicitly not a lazy operation and will load any lazy payload to determine the inequality result. - Args: - - * other: + Parameters + ---------- + other : :class:`~iris._data_manager.DataManager` The :class:`~iris._data_manager.DataManager` instance to compare with. - Returns: - Boolean. + Returns + ------- + bool """ result = self.__eq__(other) @@ -136,19 +138,17 @@ def _deepcopy(self, memo, data=None): """Perform a deepcopy of the :class:`~iris._data_manager.DataManager` instance. - Args: - - * memo: - :class:`copy` memo dictionary. - - Kwargs: - - * data: + Parameters + ---------- + memo : :func:`copy` + :func:`copy` memo dictionary. + data : optional Replacement data to substitute the currently managed data with. - Returns: - :class:`~iris._data_manager.DataManager` instance. + Returns + ------- + :class:`~iris._data_manager.DataManager` instance. """ try: @@ -176,8 +176,9 @@ def _deepcopy(self, memo, data=None): def data(self): """Returns the real data. Any lazy data being managed will be realised. - Returns: - :class:`~numpy.ndarray` or :class:`numpy.ma.core.MaskedArray`. + Returns + ------- + :class:`~numpy.ndarray` or :class:`numpy.ma.core.MaskedArray`. """ if self.has_lazy_data(): @@ -211,9 +212,9 @@ def data(self, data): Note that, the only shape promotion permitted is for 0-dimensional scalar data to be replaced with a single item 1-dimensional data. - Args: - - * data: + Parameters + ---------- + data : The :class:`~numpy.ndarray` or :class:`~numpy.ma.core.MaskedArray` real data, or :class:`~dask.array.core.Array` lazy data to be managed. @@ -272,13 +273,14 @@ def copy(self, data=None): """Returns a deep copy of this :class:`~iris._data_manager.DataManager` instance. - Kwargs: - - * data: + Parameters + ---------- + data : Replace the data of the copy with this data. - Returns: - A copy :class:`~iris._data_manager.DataManager` instance. + Returns + ------- + A copy :class:`~iris._data_manager.DataManager` instance. """ memo = {} @@ -289,8 +291,9 @@ def core_data(self): or :class:`numpy.ma.core.MaskedArray`. Otherwise, return the lazy :class:`~dask.array.core.Array`. - Returns: - The real or lazy data. + Returns + ------- + The real or lazy data. """ if self.has_lazy_data(): @@ -303,8 +306,9 @@ def core_data(self): def has_lazy_data(self): """Determine whether lazy data is being managed. - Returns: - Boolean. + Returns + ------- + bool """ return self._lazy_array is not None @@ -315,8 +319,9 @@ def lazy_data(self): If only real data is being managed, then return a lazy representation of that real data. - Returns: - :class:`~dask.array.core.Array` + Returns + ------- + :class:`~dask.array.core.Array` .. note:: This method will never realise any lazy data. diff --git a/lib/iris/_lazy_data.py b/lib/iris/_lazy_data.py index 5cfa08a7de..81af368203 100644 --- a/lib/iris/_lazy_data.py +++ b/lib/iris/_lazy_data.py @@ -62,40 +62,42 @@ def _optimum_chunksize_internals( size, while prioritising the splitting of the earlier (outer) dimensions and keeping intact the later (inner) ones. - Args: - - * chunks (tuple of int): + Parameters + ---------- + chunks : tuple of int Pre-existing chunk shape of the target data. - * shape (tuple of int): + shape : tuple of int The full array shape of the target data. - * limit (int): + limit : int The 'ideal' target chunk size, in bytes. Default from :mod:`dask.config`. - * dtype (np.dtype): + dtype : np.dtype Numpy dtype of target data. - * dims_fixed (list of bool): + dims_fixed : list of bool If set, a list of values equal in length to 'chunks' or 'shape'. 'True' values indicate a dimension that can not be changed, i.e. that element of the result must equal the corresponding value in 'chunks' or data.shape. - Returns: - * chunk (tuple of int): + Returns + ------- + tuple of int The proposed shape of one full chunk. - .. note:: - The purpose of this is very similar to - :func:`dask.array.core.normalize_chunks`, when called as - `(chunks='auto', shape, dtype=dtype, previous_chunks=chunks, ...)`. - Except, the operation here is optimised specifically for a 'c-like' - dimension order, i.e. outer dimensions first, as for netcdf variables. - So if, in future, this policy can be implemented in dask, then we would - prefer to replace this function with a call to that one. - Accordingly, the arguments roughly match 'normalize_chunks', except - that we don't support the alternative argument forms of that routine. - The return value, however, is a single 'full chunk', rather than a - complete chunking scheme : so an equivalent code usage could be - "chunks = [c[0] for c in normalise_chunks('auto', ...)]". + Notes + ----- + The purpose of this is very similar to + :func:`dask.array.core.normalize_chunks`, when called as + `(chunks='auto', shape, dtype=dtype, previous_chunks=chunks, ...)`. + Except, the operation here is optimised specifically for a 'c-like' + dimension order, i.e. outer dimensions first, as for netcdf variables. + So if, in future, this policy can be implemented in dask, then we would + prefer to replace this function with a call to that one. + Accordingly, the arguments roughly match 'normalize_chunks', except + that we don't support the alternative argument forms of that routine. + The return value, however, is a single 'full chunk', rather than a + complete chunking scheme : so an equivalent code usage could be + "chunks = [c[0] for c in normalise_chunks('auto', ...)]". """ @@ -220,40 +222,37 @@ def as_lazy_data( ): """Convert the input array `data` to a :class:`dask.array.Array`. - Args: - - * data (array-like): + Parameters + ---------- + data : array-like An indexable object with 'shape', 'dtype' and 'ndim' properties. This will be converted to a :class:`dask.array.Array`. - - Kwargs: - - * chunks (list of int): + chunks : list of int, optional If present, a source chunk shape, e.g. for a chunked netcdf variable. - - * asarray (bool): + asarray : bool, optional If True, then chunks will be converted to instances of `ndarray`. Set to False (default) to pass passed chunks through unchanged. - - * dims_fixed (list of bool): + dims_fixed : list of bool, optional If set, a list of values equal in length to 'chunks' or data.ndim. 'True' values indicate a dimension which can not be changed, i.e. the result for that index must equal the value in 'chunks' or data.shape. - - * dask_chunking (bool): + dask_chunking : bool, optional If True, Iris chunking optimisation will be bypassed, and dask's default chunking will be used instead. Including a value for chunks while dask_chunking is set to True will result in a failure. - Returns: + Returns + ------- + :class:`dask.array.Array` The input array converted to a :class:`dask.array.Array`. - .. note:: - The result chunk size is a multiple of 'chunks', if given, up to the - dask default chunksize, i.e. `dask.config.get('array.chunk-size'), - or the full data shape if that is smaller. - If 'chunks' is not given, the result has chunks of the full data shape, - but reduced by a factor if that exceeds the dask default chunksize. + Notes + ----- + The result chunk size is a multiple of 'chunks', if given, up to the + dask default chunksize, i.e. `dask.config.get('array.chunk-size'), + or the full data shape if that is smaller. + If 'chunks' is not given, the result has chunks of the full data shape, + but reduced by a factor if that exceeds the dask default chunksize. """ if dask_chunking: @@ -331,13 +330,14 @@ def as_concrete_data(data): If the input data is lazy, return the realised result. - Args: - - * data: + Parameters + ---------- + data : A dask array, NumPy `ndarray` or masked array - Returns: - A NumPy `ndarray` or masked array. + Returns + ------- + NumPy `ndarray` or masked array. """ if is_lazy_data(data): @@ -352,13 +352,14 @@ def multidim_lazy_stack(stack): This is needed because :meth:`dask.array.Array.stack` only accepts a 1-dimensional list. - Args: - - * stack: + Parameters + ---------- + stack : An ndarray of :class:`dask.array.Array`. - Returns: - The input array converted to a lazy :class:`dask.array.Array`. + Returns + ------- + The input array converted to a lazy :class:`dask.array.Array`. """ if stack.ndim == 0: @@ -380,12 +381,14 @@ def co_realise_cubes(*cubes): However, lazy calculations and data fetches can be shared between the computations, improving performance. - Args: - - * cubes (list of :class:`~iris.cube.Cube`): + Parameters + ---------- + cubes : list of :class:`~iris.cube.Cube` Arguments, each of which is a cube to be realised. - For example:: + Examples + -------- + :: # Form stats. a_std = cube_a.collapsed(['x', 'y'], iris.analysis.STD_DEV) @@ -398,9 +401,9 @@ def co_realise_cubes(*cubes): co_realise_cubes(a_std, b_std, ab_mean_diff, std_err) - .. Note:: + .. note:: - Cubes with non-lazy data may also be passed, with no ill effect. + Cubes with non-lazy data may also be passed, with no ill effect. """ results = _co_realise_lazy_arrays([cube.core_data() for cube in cubes]) @@ -414,13 +417,15 @@ def lazy_elementwise(lazy_array, elementwise_op): Elementwise means that it performs a independent calculation at each point of the input, producing a result array of the same shape. - Args: - - * lazy_array: + Parameters + ---------- + lazy_array : The lazy array object to operate on. - * elementwise_op: + elementwise_op : The elementwise operation, a function operating on numpy arrays. + Notes + ----- .. note: A single-point "dummy" call is made to the operation function, to @@ -445,15 +450,15 @@ def map_complete_blocks(src, func, dims, out_sizes): Complete means that the data is not chunked along the chosen dimensions. - Args: - - * src (:class:`~iris.cube.Cube` or array-like): + Parameters + ---------- + src : :class:`~iris.cube.Cube` or array-like Source cube that function is applied to. - * func: + func : Function to apply. - * dims (tuple of int): + dims : tuple of int Dimensions that cannot be chunked. - * out_sizes (tuple of int): + out_sizes : tuple of int Output size of dimensions that cannot be chunked. """ diff --git a/lib/iris/_merge.py b/lib/iris/_merge.py index 19848ff244..3bed7ef5ee 100644 --- a/lib/iris/_merge.py +++ b/lib/iris/_merge.py @@ -36,21 +36,18 @@ class _Template(namedtuple("Template", ["dims", "points", "bounds", "kwargs"])): """Common framework from which to build a dimension or auxiliary coordinate. - Args: - - * dims: + Parameters + ---------- + dims : Tuple of the associated :class:`iris.cube.Cube` data dimension/s spanned by this coordinate template. - - * points: + points : A :mod:`numpy` array representing the coordinate point data. No points data is represented by None. - - * bounds: + bounds : A :mod:`numpy` array representing the coordinate bounds data. No bounds data is represented by None. - - * kwargs: + kwargs : A dictionary of key/value pairs required to create a coordinate. """ @@ -63,17 +60,15 @@ class _CoordMetaData( ): """Bespoke metadata required to build a dimension or auxiliary coordinate. - Args: - - * points_dtype: + Parameters + ---------- + points_dtype : The points data :class:`numpy.dtype` of an associated coordinate. None otherwise. - - * bounds_dtype: + bounds_dtype : The bounds data :class:`numpy.dtype` of an associated coordinate. None otherwise. - - * kwargs: + kwargs: A dictionary of key/value pairs required to create a coordinate. """ @@ -85,13 +80,12 @@ class _CoordAndDims(namedtuple("CoordAndDims", ["coord", "dims"])): """Container for a coordinate and the associated data dimension/s spanned over a :class:`iris.cube.Cube`. - Args: - - * coord: + Parameters + ---------- + coord : A :class:`iris.coords.DimCoord` or :class:`iris.coords.AuxCoord` coordinate instance. - - * dims: + dims : A tuple of the data dimension/s spanned by the coordinate. """ @@ -108,18 +102,16 @@ class _ScalarCoordPayload( All scalar coordinate related data is sorted into ascending order of the associated coordinate definition. - Args: - - * defns: + Parameters + ---------- + defns : A list of scalar coordinate metadata :class:`iris.common.CoordMetadata` belonging to a :class:`iris.cube.Cube`. - - * values: + values : A list of scalar coordinate values belonging to a :class:`iris.cube.Cube`. Each scalar coordinate value is typically an :class:`iris.coords.Cell`. - - * metadata: + metadata : A list of :class:`_CoordMetaData` instances belonging to a :class:`iris.cube.Cube`. @@ -134,15 +126,14 @@ class _VectorCoordPayload( """Container for all vector coordinate data and metadata represented within a :class:`iris.cube.Cube`. - Args: - - * dim_coords_and_dims: + Parameters + ---------- + dim_coords_and_dims : A list of :class:`_CoordAndDim` instances containing non-scalar (i.e. multi-valued) :class:`iris.coords.DimCoord` instances and the associated data dimension spanned by them for a :class:`iris.cube.Cube`. - - * aux_coords_and_dims: + aux_coords_and_dims : A list of :class:`_CoordAndDim` instances containing non-scalar (i.e. multi-valued) :class:`iris.coords.DimCoord` and/or :class:`iris.coords.AuxCoord` instances and the associated data @@ -161,15 +152,13 @@ class _CoordPayload(namedtuple("CoordPayload", ["scalar", "vector", "factory_def All scalar coordinate and factory related data is sorted into ascending order of the associated coordinate definition. - Args: - - * scalar: + Parameters + ---------- + scalar: A :class:`_ScalarCoordPayload` instance. - - * vector: + vector: A :class:`_VectorCoordPayload` instance. - - * factory_defns: + factory_defns: A list of :class:`_FactoryDefn` instances. """ @@ -215,17 +204,18 @@ def match_signature(self, signature, error_on_mismatch): """Return whether this _CoordPayload matches the corresponding aspects of a _CoordSignature. - Args: - - * signature (_CoordSignature): + Parameters + ---------- + signature : _CoordSignature The _CoordSignature to compare against. - - * error_on_mismatch (bool): + error_on_mismatch : bool If True, raise an Exception with detailed explanation. - Returns: - Boolean. True if and only if this _CoordPayload matches - the corresponding aspects `other`. + Returns + ------- + bool + True if and only if this _CoordPayload matches + the corresponding aspects `other`. """ @@ -288,24 +278,21 @@ class _CoordSignature( based on its scalar and vector coordinate data and metadata, and auxiliary coordinate factories. - Args: - - * scalar_defns: + Parameters + ---------- + scalar_defns : A list of scalar coordinate definitions sorted into ascending order. - - * vector_dim_coords_and_dims: + vector_dim_coords_and_dims : A list of :class:`_CoordAndDim` instances containing non-scalar (i.e. multi-valued) :class:`iris.coords.DimCoord` instances and the associated data dimension spanned by them for a :class:`iris.cube.Cube`. - - * vector_aux_coords_and_dims: + vector_aux_coords_and_dims : A list of :class:`_CoordAndDim` instances containing non-scalar (i.e. multi-valued) :class:`iris.coords.DimCoord` and/or :class:`iris.coords.AuxCoord` instances and the associated data dimension/s spanned by them for a :class:`iris.cube.Cube`. - - * factory_defns: + factory_defns : A list of :class:`_FactoryDefn` instances. """ @@ -328,21 +315,17 @@ class _CubeSignature( """Criterion for identifying a specific type of :class:`iris.cube.Cube` based on its metadata. - Args: - - * defn: + Parameters + ---------- + defn : A cube definition tuple. - - * data_shape: + data_shape : The data payload shape of a :class:`iris.cube.Cube`. - - * data_type: + data_type : The data payload :class:`numpy.dtype` of a :class:`iris.cube.Cube`. - - * cell_measures_and_dims: + cell_measures_and_dims : A list of cell_measures and dims for the cube. - - * ancillary_variables_and_dims: + ancillary_variables_and_dims : A list of ancillary variables and dims for the cube. """ @@ -410,23 +393,25 @@ def match(self, other, error_on_mismatch): This is the first step to determine if two "cubes" (either a real Cube or a ProtoCube) can be merged, by considering: - - standard_name, long_name, var_name - - units - - attributes - - cell_methods - - shape, dtype - Args: + * standard_name, long_name, var_name + * units + * attributes + * cell_methods + * shape, dtype - * other (_CubeSignature): + Parameters + ---------- + other : _CubeSignature The _CubeSignature to compare against. - - * error_on_mismatch (bool): + error_on_mismatch : bool If True, raise a :class:`~iris.exceptions.MergeException` with a detailed explanation if the two do not match. - Returns: - Boolean. True if and only if this _CubeSignature matches `other`. + Returns + ------- + bool + True if and only if this _CubeSignature matches `other`. """ msgs = self._defn_msgs(other.defn) @@ -454,15 +439,14 @@ class _Skeleton(namedtuple("Skeleton", ["scalar_values", "data"])): """Basis of a source-cube, containing the associated scalar coordinate values and data payload of a :class:`iris.cube.Cube`. - Args: - - * scalar_values: + Parameters + ---------- + scalar_values : A list of scalar coordinate values belonging to a :class:`iris.cube.Cube` sorted into ascending order of the associated coordinate definition. Each scalar coordinate value is typically an :class:`iris.coords.Cell`. - - * data: + data : The data payload of a :class:`iris.cube.Cube`. """ @@ -473,12 +457,11 @@ class _Skeleton(namedtuple("Skeleton", ["scalar_values", "data"])): class _FactoryDefn(namedtuple("_FactoryDefn", ["class_", "dependency_defns"])): """The information required to identify and rebuild a single AuxCoordFactory. - Args: - - * class_: + Parameters + ---------- + class_ : The class of the AuxCoordFactory. - - * dependency_defns: + dependency_defns : A list of pairs, where each pair contains a dependency key and its corresponding coordinate definition. Sorted on dependency key. @@ -492,12 +475,11 @@ class _Relation(namedtuple("Relation", ["separable", "inseparable"])): :class:`ProtoCube` into separable 'independent' dimensions, and inseparable dependent dimensions. - Args: - - * separable: + Parameters + ---------- + separable : A set of independent candidate dimension names. - - * inseparable: + inseparable : A set of dependent candidate dimension names. """ @@ -512,13 +494,14 @@ def _is_combination(name): """Determine whether the candidate dimension is an 'invented' combination of candidate dimensions. - Args: - - * name: + Parameters + ---------- + name : The candidate dimension. - Returns: - Boolean. + Returns + ------- + bool """ return _COMBINATION_JOIN in str(name) @@ -557,14 +540,15 @@ def build_indexes(positions): 200: 'a': set([1]) 'b': set([10]) 300: 'a': set([2]) 'b': set([20]) - Args: - - * positions: + Parameters + ---------- + positions : A list containing a dictionary of candidate dimension key to scalar value pairs for each source-cube. - Returns: - The cross-reference dictionary for each candidate dimension. + Returns + ------- + The cross-reference dictionary for each candidate dimension. """ names = positions[0].keys() @@ -595,20 +579,19 @@ def _separable_pair(name, index): A candidate dimension X and Y are separable if each scalar value of X maps to the same set of scalar values of Y. - Args: - - * name1: + Parameters + ---------- + name1 : The first candidate dimension to be compared. - - * name2: + name2 : The second candidate dimension to be compared. - - * index: + index : The cross-reference dictionary for the first candidate dimension. - Returns: - Boolean. + Returns + ------- + bool """ items = iter(index.values()) @@ -624,16 +607,17 @@ def _separable(name, indexes): A candidate dimension X and Y are separable if each scalar value of X maps to the same set of scalar values of Y. - Args: - - * name: + Parameters + ---------- + name : The candidate dimension that requires its separable and inseparable relationship to be determined. - - * indexes: + indexes : The cross-reference dictionary for each candidate dimension. - Returns: + Returns + ------- + tupl A tuple containing the set of separable and inseparable candidate dimensions. @@ -676,13 +660,14 @@ def derive_relation_matrix(indexes): 'c': Relation(separable=set([]), inseparable=set(['a', 'b'])) 'b': Relation(separable=set([]), inseparable=set(['a', 'c'])) - Args: - - * indexes: + Parameters + ---------- + indexes : The cross-reference dictionary for each candidate dimension. - Returns: - The relation dictionary for each candidate dimension. + Returns + ------- + The relation dictionary for each candidate dimension. """ # TODO: This takes twice as long as it could do because it doesn't @@ -698,13 +683,14 @@ def derive_groups(relation_matrix): If candidate dimension A is inseparable for B and C, and B is inseparable from D, and E is inseparable from F. Then the groups are ABCD and EF. - Args: - - * relation_matrix: + Parameters + ---------- + relation_matrix : The relation dictionary for each candidate dimension. - Returns: - A list of all related (chained) inseparable candidate dimensions. + Returns + ------- + A list of all related (chained) inseparable candidate dimensions. """ names = set(relation_matrix) @@ -730,17 +716,16 @@ def derive_groups(relation_matrix): def _derive_separable_group(relation_matrix, group): """Determine which candidate dimensions in the group are separable. - Args: - - * relation_matrix: + Parameters + ---------- + relation_matrix : The relation dictionary for each candidate dimension. - - * group: + group : A set of related (chained) inseparable candidate dimensions. - Returns: - The set of candidate dimensions within the group that are - separable. + Returns + ------- + The set of candidate dimensions within the group that are separable. """ result = set() @@ -757,29 +742,25 @@ def _is_dependent(dependent, independent, positions, function_mapping=None): between the independent candidate dimension/s and the dependent candidate dimension. - Args: - - * dependent: + Parameters + ---------- + dependent : A candidate dimension that requires to be functionally dependent on all the independent candidate dimensions. - - * independent: + independent : A list of candidate dimension/s that require to act as the independent variables in a functional relationship. - - * positions: + positions : A list containing a dictionary of candidate dimension key to scalar value pairs for each source-cube. - - Kwargs: - - * function_mapping: + function_mapping : optional, default=None A dictionary that enumerates a valid functional relationship between the dependent candidate dimension and the independent candidate dimension/s. - Returns: - Boolean. + Returns + ------- + bool """ valid = True @@ -809,16 +790,16 @@ def _derive_consistent_groups(relation_matrix, separable_group): B and C. Then the candidate dimension group ABC is a separable consistent group if B is separable from A and C, and C is separable from A and B. - Args: - - * relation_matrix: + Parameters + ---------- + relation_matrix : The relation dictionary for each candidate dimension. - - * separable_group: + separable_group : The set of candidate dimensions that are separable. - Returns: - A list of candidate dimension groups that are consistently separable. + Returns + ------- + A list of candidate dimension groups that are consistently separable. """ result = [] @@ -861,28 +842,25 @@ def _build_separable_group( and D, and "C: None" means that this candidate dimension is independent. - Args: - - * space: + Parameters + ---------- + space : A dictionary defining for each candidate dimension its dependency on any other candidate dimensions within the space. - - * group: + group : A set of related (chained) inseparable candidate dimensions. - - * separable_consistent_groups: + separable_consistent_groups: A list of candidate dimension groups that are consistently separable. - - * positions: + positions : A list containing a dictionary of candidate dimension key to scalar value pairs for each source-cube. - - * function_matrix: + function_matrix : The function mapping dictionary for each candidate dimension that participates in a functional relationship. - Returns: - Boolean. + Returns + ------- + bool """ valid = False @@ -929,25 +907,23 @@ def _build_inseparable_group(space, group, positions, function_matrix): and all others in the group, as the group is considered inseparable in this context. - Args: - - * space: + Parameters + ---------- + space : A dictionary defining for each candidate dimension its dependency on any other candidate dimensions within the space. - - * group: + group : A set of related (chained) inseparable candidate dimensions. - - * positions: + positions : A list containing a dictionary of candidate dimension key to scalar value pairs for each source-cube. - - * function_matrix: + function_matrix : The function mapping dictionary for each candidate dimension that participates in a functional relationship. - Returns: - Boolean. + Returns + ------- + bool """ scalar = False @@ -989,25 +965,23 @@ def _build_combination_group(space, group, positions, function_matrix): coordinate associated with it. Rather, it is simply an enumeration of the group members for each of the positions (source-cubes). - Args: - - * space: + Parameters + ---------- + space : A dictionary defining for each candidate dimension its dependency on any other candidate dimensions within the space. - - * group: + group : A set of related (chained) inseparable candidate dimensions. - - * positions: + positions : A list containing a dictionary of candidate dimension key to scalar value pairs for each source-cube. - - * function_matrix: + function_matrix : The function mapping dictionary for each candidate dimension that participates in a functional relationship. - Returns: - None. + Returns + ------- + None """ combination = _COMBINATION_JOIN.join(sorted(map(str, group))) @@ -1037,25 +1011,22 @@ def _build_combination_group(space, group, positions, function_matrix): def derive_space(groups, relation_matrix, positions, function_matrix=None): """Determine the relationship between all the candidate dimensions. - Args: - * groups: - A list of all related (chained) inseparable candidate dimensions. - - * relation_matrix: - The relation dictionary for each candidate dimension. - - * positions: - A list containing a dictionary of candidate dimension key to - scalar value pairs for each source-cube. - - Kwargs: - * function_matrix: + Parameters + ---------- + groups : + A list of all related (chained) inseparable candidate dimensions. + relation_matrix: + The relation dictionary for each candidate dimension. + positions : + A list containing a dictionary of candidate dimension key to + scalar value pairs for each source-cube. + function_matrix : optional, default=None The function mapping dictionary for each candidate dimension that participates in a functional relationship. - Returns: - A space dictionary describing the relationship between each - candidate dimension. + Returns + ------- + A space dictionary describing the relationship between each candidate dimension. """ space = {} @@ -1184,14 +1155,15 @@ def merge(self, unique=True): """Returns the list of cubes resulting from merging the registered source-cubes. - Kwargs: - - * unique: + Parameters + ---------- + unique : If True, raises `iris.exceptions.DuplicateDataError` if duplicate cubes are detected. - Returns: - A :class:`iris.cube.CubeList` of merged cubes. + Returns + ------- + A :class:`iris.cube.CubeList` of merged cubes. """ positions = [ @@ -1286,20 +1258,19 @@ def register(self, cube, error_on_mismatch=False): cube and the signature of its scalar coordinates and vector coordinates being identical to that of the ProtoCube. - Args: - - * cube: + Parameters + ---------- + cube : Candidate :class:`iris.cube.Cube` to be associated with this :class:`ProtoCube`. - - Kwargs: - - * error_on_mismatch: + error_on_mismatch :bool, optional, default=False If True, raise an informative :class:`~iris.exceptions.MergeError` if registration fails. - Returns: - True iff the :class:`iris.cube.Cube` is compatible with + Returns + ------- + bool + True if the :class:`iris.cube.Cube` is compatible with this :class:`ProtoCube`. """ @@ -1326,13 +1297,14 @@ def _guess_axis(self, name): Based on the associated scalar coordinate definition rather than the scalar coordinate itself. - Args: - - * name: + Parameters + ---------- + name : The candidate dimension. - Returns: - 'T', 'Z', 'Y', 'X', or None. + Returns + ------- + axis : {'T', 'Z', 'Y', 'X'} or None. """ axis = None @@ -1348,20 +1320,17 @@ def _define_space(self, space, positions, indexes, function_matrix): terms of its dimensionality, shape, coordinates and associated coordinate to space dimension mappings. - Args: - - * space: + Parameters + ---------- + space : A dictionary defining for each candidate dimension its dependency on any other candidate dimensions within the space. - - * positions: + positions : A list containing a dictionary of candidate dimension key to scalar value pairs for each source-cube. - - * indexes: + indexes : A cross-reference dictionary for each candidate dimension. - - * function_matrix: + function_matrix : The function mapping dictionary for each candidate dimension that participates in a functional relationship. @@ -1655,13 +1624,14 @@ def _build_coordinates(self): def _build_signature(self, cube): """Generate the signature that defines this cube. - Args: - - * cube: + Parameters + ---------- + cube : The source cube to create the cube signature from. - Returns: - The cube signature. + Returns + ------- + The cube signature. """ diff --git a/lib/iris/_representation/cube_printout.py b/lib/iris/_representation/cube_printout.py index 81f60e595d..b1e5238eb0 100644 --- a/lib/iris/_representation/cube_printout.py +++ b/lib/iris/_representation/cube_printout.py @@ -52,12 +52,13 @@ def __init__(self, cols, aligns, i_col_unlimited=None): def add_row(self, cols, aligns, i_col_unlimited=None): """Create a new row at the bottom. - Args: - * cols (list of string): + Parameters + ---------- + cols : list of str Per-column content. Length must match the other rows (if any). - * aligns (list of {'left', 'right'}): + aligns : list of {'left', 'right'} Per-column alignments. Length must match 'cols'. - * i_col_unlimited (int or None): + i_col_unlimited : int or None, optional Column beyond which content does not affect the column widths. ( meaning contents will print without limit ). @@ -133,12 +134,13 @@ class CubePrinter: def __init__(self, cube_or_summary): """An object that provides a printout of a cube. - Args: - - * cube_or_summary (Cube or CubeSummary): + Parameters + ---------- + cube_or_summary : Cube or CubeSummary If a cube, first create a CubeSummary from it. - + Notes + ----- .. note:: The CubePrinter is based on a digest of a CubeSummary, but does not reference or store it. @@ -320,15 +322,17 @@ def _multiline_summary(self, name_padding): def to_string(self, oneline=False, name_padding=35): """Produce a printable summary. - Args: - * oneline (bool): + Parameters + ---------- + oneline : bool, optional, default=False If set, produce a one-line summary. Default is False = produce full (multiline) summary. - * name_padding (int): + name_padding int, optional, default=35 The minimum width for the "name" (#0) column. - Returns: - result (string) + Returns + ------- + str """ if oneline: diff --git a/lib/iris/analysis/_area_weighted.py b/lib/iris/analysis/_area_weighted.py index f882860d25..007050008b 100644 --- a/lib/iris/analysis/_area_weighted.py +++ b/lib/iris/analysis/_area_weighted.py @@ -24,16 +24,13 @@ def __init__(self, src_grid_cube, target_grid_cube, mdtol=1): """Create an area-weighted regridder for conversions between the source and target grids. - Args: - - * src_grid_cube: + Parameters + ---------- + src_grid_cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` providing the source grid. - * target_grid_cube: + target_grid_cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` providing the target grid. - - Kwargs: - - * mdtol (float): + mdtol : float, optional Tolerance of missing data. The value returned in each element of the returned array will be masked if the fraction of masked data exceeds mdtol. mdtol=0 means no missing data is tolerated while @@ -41,6 +38,8 @@ def __init__(self, src_grid_cube, target_grid_cube, mdtol=1): if all the contributing elements of data are masked. Defaults to 1. + Notes + ----- .. Note:: Both source and target cubes must have an XY grid defined by @@ -85,17 +84,21 @@ def __call__(self, cube): If the source cube has lazy data, the returned cube will also have lazy data. - Args: - - * cube: + Parameters + ---------- + cube : :class:`~iris.cube.Cube` A :class:`~iris.cube.Cube` to be regridded. - Returns: + Returns + ------- + :class:`~iris.cube.Cube` A cube defined with the horizontal dimensions of the target and the other dimensions from this cube. The data values of this cube will be converted to values on the new grid using area-weighted regridding. + Notes + ----- .. note:: If the source cube has lazy data, @@ -146,12 +149,14 @@ def _get_xy_coords(cube): have equal coordinate systems and that they do not occupy the same dimension on the cube. - Args: - - * cube: + Parameters + ---------- + cube : :class:`iris.cube.Cube` An instance of :class:`iris.cube.Cube`. - Returns: + Returns + ------- + tuple A tuple containing the cube's x and y coordinates. """ diff --git a/lib/iris/analysis/_interpolation.py b/lib/iris/analysis/_interpolation.py index b6e443c95c..15f5ba7893 100644 --- a/lib/iris/analysis/_interpolation.py +++ b/lib/iris/analysis/_interpolation.py @@ -94,12 +94,14 @@ def get_xy_dim_coords(cube): if the identified x and y coordinates do not have coordinate systems that are equal. - Args: - - * cube: + Parameters + ---------- + cube : :class:`iris.cube.Cube` An instance of :class:`iris.cube.Cube`. - Returns: + Returns + ------- + tuple A tuple containing the cube's x and y dimension coordinates. """ @@ -114,18 +116,17 @@ def get_xy_coords(cube, dim_coords=False): if the identified x and y coordinates do not have coordinate systems that are equal. - Args: - - * cube: + Parameters + ---------- + cube : :class:`iris.cube.Cube` An instance of :class:`iris.cube.Cube`. - - Kwargs: - - * dim_coords: + dim_coords : bool, optional, default=False Set this to True to only return dimension coordinates. Defaults to False. - Returns: + Returns + ------- + tuple A tuple containing the cube's x and y dimension coordinates. """ @@ -171,30 +172,30 @@ class RectilinearInterpolator: def __init__(self, src_cube, coords, method, extrapolation_mode): """Perform interpolation over one or more orthogonal coordinates. - Args: - - * src_cube: + Parameters + ---------- + src_cube : :class:`iris.cube.Cube` The :class:`iris.cube.Cube` which is to be interpolated. - * coords: + coords : The names or coordinate instances which are to be interpolated over - * method: + method : Either 'linear' or 'nearest'. - * extrapolation_mode: + extrapolation_mode : str Must be one of the following strings: - * 'extrapolate' - The extrapolation points will be calculated - according to the method. The 'linear' method extends the - gradient of the closest two points. The 'nearest' method - uses the value of the closest point. - * 'nan' - The extrapolation points will be be set to NaN. - * 'error' - A ValueError exception will be raised, notifying an - attempt to extrapolate. - * 'mask' - The extrapolation points will always be masked, even - if the source data is not a MaskedArray. - * 'nanmask' - If the source data is a MaskedArray the - extrapolation points will be masked. Otherwise they will be - set to NaN. + * 'extrapolate' - The extrapolation points will be calculated + according to the method. The 'linear' method extends the + gradient of the closest two points. The 'nearest' method + uses the value of the closest point. + * 'nan' - The extrapolation points will be be set to NaN. + * 'error' - A ValueError exception will be raised, notifying an + attempt to extrapolate. + * 'mask' - The extrapolation points will always be masked, even + if the source data is not a MaskedArray. + * 'nanmask' - If the source data is a MaskedArray the + extrapolation points will be masked. Otherwise they will be + set to NaN. """ # Trigger any deferred loading of the source cube's data and snapshot @@ -284,10 +285,11 @@ def _interpolate(self, data, interp_points): it to perform interpolation over the data at the given coordinate point values. - * data (ndarray): + Parameters + ---------- + data : ndarray A data array, to be interpolated in its first 'N' dimensions. - - * interp_points (ndarray): + interp_points : ndarray An array of interpolation coordinate values. Its shape is (..., N) where N is the number of interpolation dimensions. @@ -468,26 +470,25 @@ def _points(self, sample_points, data, data_dims=None): """Interpolate the given data values at the specified list of orthogonal (coord, points) pairs. - Args: - - * sample_points: + Parameters + ---------- + sample_points : A list of N iterables, where N is the number of coordinates passed to the constructor. [sample_values_for_coord_0, sample_values_for_coord_1, ...] - * data: + data : The data to interpolate - not necessarily the data from the cube that was used to construct this interpolator. If the data has fewer dimensions, then data_dims must be defined. - - Kwargs: - - * data_dims: + data_dims : optional, default=None The dimensions of the given data array in terms of the original cube passed through to this interpolator's constructor. If None, the data dimensions must map one-to-one onto the increasing dimension order of the cube. - Returns: + Returns + ------- + :class:`~numpy.ndarray` or :class:`~numpy.ma.MaskedArray` An :class:`~numpy.ndarray` or :class:`~numpy.ma.MaskedArray` instance of the interpolated data. @@ -565,20 +566,19 @@ def _points(self, sample_points, data, data_dims=None): def __call__(self, sample_points, collapse_scalar=True): """Construct a cube from the specified orthogonal interpolation points. - Args: - - * sample_points: + Parameters + ---------- + sample_points : A list of N iterables, where N is the number of coordinates passed to the constructor. [sample_values_for_coord_0, sample_values_for_coord_1, ...] - - Kwargs: - - * collapse_scalar: + collapse_scalar : bool, optional Whether to collapse the dimension of the scalar sample points in the resulting cube. Default is True. - Returns: + Returns + ------- + :class:`iris.cube.Cube` A cube interpolated at the given sample points. The dimensionality of the cube will be the number of original cube dimensions minus the number of scalar coordinates, if collapse_scalar is True. diff --git a/lib/iris/analysis/_regrid.py b/lib/iris/analysis/_regrid.py index b2ce99ee7a..3beada7131 100644 --- a/lib/iris/analysis/_regrid.py +++ b/lib/iris/analysis/_regrid.py @@ -28,15 +28,16 @@ def _transform_xy_arrays(crs_from, x, y, crs_to): NOTE: copied private function from iris.analysis.cartography. - Args: - - * crs_from, crs_to (:class:`cartopy.crs.Projection`): + Parameters + ---------- + crs_from, crs_to : :class:`cartopy.crs.Projection` The coordinate reference systems. - * x, y (arrays): + x, y : arrays point locations defined in 'crs_from'. - Returns: - x, y : Arrays of locations defined in 'crs_to'. + Returns + ------- + x, y : Arrays of locations defined in 'crs_to'. """ pts = crs_to.transform_points(crs_from, x, y) @@ -377,16 +378,13 @@ def __init__(self, src_grid_cube, target_grid_cube, weights=None): """Create a regridder for conversions between the source and target grids. - Args: - - * src_grid_cube: + Parameters + ---------- + src_grid_cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` providing the source grid. - * tgt_grid_cube: + tgt_grid_cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` providing the target grid. - - Optional Args: - - * weights: + weights : optional, default=None A :class:`numpy.ndarray` instance that defines the weights for the grid cells of the source grid. Must have the same shape as the data of the source grid. @@ -412,16 +410,16 @@ def _get_horizontal_coord(cube, axis): """Gets the horizontal coordinate on the supplied cube along the specified axis. - Args: - - * cube: + Parameters + ---------- + cube : :class:`iris.cube.Cube` An instance of :class:`iris.cube.Cube`. - * axis: + axis : Locate coordinates on `cube` along this axis. - Returns: - The horizontal coordinate on the specified axis of the supplied - cube. + Returns + ------- + The horizontal coordinate on the specified axis of the supplied cube. """ coords = cube.coords(axis=axis, dim_coords=False) @@ -443,12 +441,14 @@ def __call__(self, src): If the source cube has lazy data, it will be realized before regridding and the returned cube will also have realized data. - Args: - - * src: + Parameters + ---------- + src : :class:`~iris.cube.Cube` A :class:`~iris.cube.Cube` to be regridded. - Returns: + Returns + ------- + :class:`~iris.cube.Cube` A cube defined with the horizontal dimensions of the target and the other dimensions from this cube. The data values of this cube will be converted to values on the new grid using @@ -494,28 +494,28 @@ def __init__(self, src_grid_cube, tgt_grid_cube, method, extrapolation_mode): """Create a regridder for conversions between the source and target grids. - Args: - - * src_grid_cube: + Parameters + ---------- + src_grid_cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` providing the source grid. - * tgt_grid_cube: + tgt_grid_cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` providing the target grid. - * method: + method : Either 'linear' or 'nearest'. - * extrapolation_mode: + extrapolation_mode : str Must be one of the following strings: - * 'extrapolate' - The extrapolation points will be - calculated by extending the gradient of the closest two - points. - * 'nan' - The extrapolation points will be be set to NaN. - * 'error' - An exception will be raised, notifying an - attempt to extrapolate. - * 'mask' - The extrapolation points will always be masked, even - if the source data is not a MaskedArray. - * 'nanmask' - If the source data is a MaskedArray the - extrapolation points will be masked. Otherwise they will be - set to NaN. + * 'extrapolate' - The extrapolation points will be + calculated by extending the gradient of the closest two + points. + * 'nan' - The extrapolation points will be be set to NaN. + * 'error' - An exception will be raised, notifying an + attempt to extrapolate. + * 'mask' - The extrapolation points will always be masked, even + if the source data is not a MaskedArray. + * 'nanmask' - If the source data is a MaskedArray the + extrapolation points will be masked. Otherwise they will be + set to NaN. """ from iris.cube import Cube @@ -559,17 +559,19 @@ def _sample_grid(src_coord_system, grid_x_coord, grid_y_coord): The `grid_x_coord` and `grid_y_coord` must share a common coordinate system. - Args: - - * src_coord_system: + Parameters + ---------- + src_coord_system : :class:`iris.coord_system.CoordSystem` The :class:`iris.coord_system.CoordSystem` for the grid of the source Cube. - * grid_x_coord: + grid_x_coord : :class:`iris.coords.DimCoord` The :class:`iris.coords.DimCoord` for the X coordinate. - * grid_y_coord: + grid_y_coord : :class:`iris.coords.DimCoord` The :class:`iris.coords.DimCoord` for the Y coordinate. - Returns: + Returns + ------- + tuple A tuple of the X and Y coordinate values as 2-dimensional arrays. @@ -602,54 +604,55 @@ def _regrid( """Regrid the given data from the src grid to the sample grid. The result will be a MaskedArray if either/both of: - - the source array is a MaskedArray, - - the extrapolation_mode is 'mask' and the result requires - extrapolation. + + * the source array is a MaskedArray, + * the extrapolation_mode is 'mask' and the result requires + extrapolation. If the result is a MaskedArray the mask for each element will be set if either/both of: - - there is a non-zero contribution from masked items in the input data - - the element requires extrapolation and the extrapolation_mode - dictates a masked value. - Args: + * there is a non-zero contribution from masked items in the input data + * the element requires extrapolation and the extrapolation_mode + dictates a masked value. - * src_data: + Parameters + ---------- + src_data : An N-dimensional NumPy array or MaskedArray. - * x_dim: + x_dim : The X dimension within `src_data`. - * y_dim: + y_dim : The Y dimension within `src_data`. - * src_x_coord: + src_x_coord : :class:`iris.coords.DimCoord` The X :class:`iris.coords.DimCoord`. - * src_y_coord: + src_y_coord : :class:`iris.coords.DimCoord` The Y :class:`iris.coords.DimCoord`. - * sample_grid_x: + sample_grid_x : A 2-dimensional array of sample X values. - * sample_grid_y: + sample_grid_y : A 2-dimensional array of sample Y values. - - Kwargs: - - * method: + method: str, optional Either 'linear' or 'nearest'. The default method is 'linear'. - * extrapolation_mode: + extrapolation_mode : str, optional Must be one of the following strings: - * 'linear' - The extrapolation points will be calculated by - extending the gradient of the closest two points. - * 'nan' - The extrapolation points will be be set to NaN. - * 'error' - A ValueError exception will be raised, notifying an - attempt to extrapolate. - * 'mask' - The extrapolation points will always be masked, even - if the source data is not a MaskedArray. - * 'nanmask' - If the source data is a MaskedArray the - extrapolation points will be masked. Otherwise they will be - set to NaN. + * 'linear' - The extrapolation points will be calculated by + extending the gradient of the closest two points. + * 'nan' - The extrapolation points will be be set to NaN. + * 'error' - A ValueError exception will be raised, notifying an + attempt to extrapolate. + * 'mask' - The extrapolation points will always be masked, even + if the source data is not a MaskedArray. + * 'nanmask' - If the source data is a MaskedArray the + extrapolation points will be masked. Otherwise they will be + set to NaN. The default mode of extrapolation is 'nanmask'. - Returns: + Returns + ------- + NumPu array The regridded data as an N-dimensional NumPy array. The lengths of the X and Y dimensions will now match those of the sample grid. @@ -854,17 +857,21 @@ def __call__(self, src): If the source cube has lazy data, the returned cube will also have lazy data. - Args: - - * src: + Parameters + ---------- + src : :class:`~iris.cube.Cube` A :class:`~iris.cube.Cube` to be regridded. - Returns: + Returns + ------- + :class:`~iris.cube.Cube` A cube defined with the horizontal dimensions of the target and the other dimensions from this cube. The data values of this cube will be converted to values on the new grid using either nearest-neighbour or linear interpolation. + Notes + ----- .. note:: If the source cube has lazy data, @@ -962,13 +969,15 @@ def regrid_callback(*args, **kwargs): def _create_cube(data, src, src_dims, tgt_coords, num_tgt_dims, regrid_callback): r"""Return a new cube for the result of regridding. + Returned cube represents the result of regridding the source cube onto the horizontal coordinates (e.g. latitude) of the target cube. All the metadata and coordinates of the result cube are copied from the source cube, with two exceptions: - - Horizontal coordinates are copied from the target cube. - - Auxiliary coordinates which span the grid dimensions are - ignored. + + * Horizontal coordinates are copied from the target cube. + * Auxiliary coordinates which span the grid dimensions are + ignored. Parameters ---------- diff --git a/lib/iris/analysis/cartography.py b/lib/iris/analysis/cartography.py index c0613028e3..01c71b177a 100644 --- a/lib/iris/analysis/cartography.py +++ b/lib/iris/analysis/cartography.py @@ -55,12 +55,21 @@ def wrap_lons(lons, base, period): """Wrap longitude values into the range between base and base+period. + Parameters + ---------- + lons : + base : + period : + + Examples + -------- .. testsetup:: import numpy as np from iris.analysis.cartography import wrap_lons - For example: + :: + >>> print(wrap_lons(np.array([185, 30, -200, 75]), -180, 360)) [-175. 30. 160. 75.] @@ -85,28 +94,30 @@ def unrotate_pole(rotated_lons, rotated_lats, pole_lon, pole_lat): rectilinear grid, the arrays of rotated-pole longitudes and latitudes must be of the same shape as each other. - Example:: - - lons, lats = unrotate_pole(rotated_lons, rotated_lats, \ - pole_lon, pole_lat) - .. note:: Uses proj.4 to perform the conversion. - Args: + Parameters + ---------- + rotated_lons : + An array of rotated-pole longitude values. + rotated_lats : + An array of rotated-pole latitude values. + pole_lon : + The longitude of the rotated pole that describes the arrays of + rotated-pole longitudes and latitudes. + pole_lat : + The latitude of the rotated pole that describes the arrays of + rotated-pole longitudes and latitudes. + + Returns + ------- + An array of unrotated longitudes and an array of unrotated latitudes. - * rotated_lons: - An array of rotated-pole longitude values. - * rotated_lats: - An array of rotated-pole latitude values. - * pole_lon: - The longitude of the rotated pole that describes the arrays of - rotated-pole longitudes and latitudes. - * pole_lat: - The latitude of the rotated pole that describes the arrays of - rotated-pole longitudes and latitudes. + Examples + -------- + :: - Returns: - An array of unrotated longitudes and an array of unrotated latitudes. + lons, lats = unrotate_pole(rotated_lons, rotated_lats, pole_lon, pole_lat) """ src_proj = ccrs.RotatedGeodetic(pole_longitude=pole_lon, pole_latitude=pole_lat) @@ -128,29 +139,30 @@ def rotate_pole(lons, lats, pole_lon, pole_lat): the arrays of rotated-pole longitudes and latitudes must be of the same shape as each other. - Example:: - - rotated_lons, rotated_lats = rotate_pole(lons, lats,\ - pole_lon, pole_lat) - .. note:: Uses proj.4 to perform the conversion. - Args: + Parameters + ---------- + lons : + An array of longitude values. + lats : + An array of latitude values. + pole_lon : + The longitude of the rotated pole that the arrays of longitudes and + latitudes are to be rotated onto. + pole_lat : + The latitude of the rotated pole that the arrays of longitudes and + latitudes are to be rotated onto. + + Returns + ------- + An array of rotated-pole longitudes and an array of rotated-pole latitudes. - * lons: - An array of longitude values. - * lats: - An array of latitude values. - * pole_lon: - The longitude of the rotated pole that the arrays of longitudes and - latitudes are to be rotated onto. - * pole_lat: - The latitude of the rotated pole that the arrays of longitudes and - latitudes are to be rotated onto. + Examples + -------- + :: - Returns: - An array of rotated-pole longitudes and an array of rotated-pole - latitudes. + rotated_lons, rotated_lats = rotate_pole(lons, lats, pole_lon, pole_lat) """ src_proj = ccrs.Geodetic() @@ -185,15 +197,14 @@ def search_for_coord(coord_iterable, coord_name): def _xy_range(cube, mode=None): """Return the x & y range of this Cube. - Args: - - * cube - The cube for which to calculate xy extents. - - Kwargs: - - * mode - If the coordinate has bounds, set this to specify the - min/max calculation. - Set to iris.coords.POINT_MODE or iris.coords.BOUND_MODE. + Parameters + ---------- + cube : + The cube for which to calculate xy extents. + mode : optional, default=None + If the coordinate has bounds, set this to specify the + min/max calculation. + Set to iris.coords.POINT_MODE or iris.coords.BOUND_MODE. """ # Helpful error if we have an inappropriate CoordSystem @@ -249,11 +260,14 @@ def _xy_range(cube, mode=None): def get_xy_grids(cube): """Return 2D X and Y points for a given cube. - Args: + Parameters + ---------- + cube : + The cube for which to generate 2D X and Y points. - * cube - The cube for which to generate 2D X and Y points. - - Example:: + Examples + -------- + :: x, y = get_xy_grids(cube) @@ -261,6 +275,7 @@ def get_xy_grids(cube): ----- 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") @@ -284,7 +299,13 @@ def get_xy_contiguous_bounded_grids(cube): Returns array of shape (n+1, m+1). - Example:: + Parameters + ---------- + cube : :class:`iris.cube.Cube` + + Examples + -------- + :: xs, ys = get_xy_contiguous_bounded_grids(cube) @@ -306,16 +327,11 @@ def get_xy_contiguous_bounded_grids(cube): def _quadrant_area(radian_lat_bounds, radian_lon_bounds, radius_of_earth): """Calculate spherical segment areas. - - radian_lat_bounds -- [n,2] array of latitude bounds (radians) - - radian_lon_bounds -- [n,2] array of longitude bounds (radians) - - radius_of_earth -- radius of the earth - (currently assumed spherical) - Area weights are calculated for each lat/lon cell as: - .. math:: + .. math:: - r^2 (lon_1 - lon_0) ( sin(lat_1) - sin(lat_0)) + r^2 (lon_1 - lon_0) ( sin(lat_1) - sin(lat_0)) The resulting array will have a shape of *(radian_lat_bounds.shape[0], radian_lon_bounds.shape[0])* @@ -323,6 +339,15 @@ def _quadrant_area(radian_lat_bounds, radian_lon_bounds, radius_of_earth): The calculations are done at 64 bit precision and the returned array will be of type numpy.float64. + Parameters + ---------- + radian_lat_bounds : + [n,2] array of latitude bounds (radians) + radian_lon_bounds : + [n,2] array of longitude bounds (radians) + radius_of_earth : + radius of the earth (currently assumed spherical) + """ # ensure pairs of bounds if ( @@ -352,29 +377,30 @@ def area_weights(cube, normalize=False): This is a 2D lat/lon area weights array, repeated over the non lat/lon dimensions. - Args: - - * cube (:class:`iris.cube.Cube`): - The cube to calculate area weights for. - - Kwargs: - - * normalize (False/True): - If False, weights are grid cell areas. If True, weights are grid - cell areas divided by the total grid area. - The cube must have coordinates 'latitude' and 'longitude' with bounds. Area weights are calculated for each lat/lon cell as: - .. math:: + .. math:: - r^2 (lon_1 - lon_0) (\sin(lat_1) - \sin(lat_0)) + r^2 (lon_1 - lon_0) (\sin(lat_1) - \sin(lat_0)) Currently, only supports a spherical datum. Uses earth radius from the cube, if present and spherical. Defaults to iris.analysis.cartography.DEFAULT_SPHERICAL_EARTH_RADIUS. + Parameters + ---------- + cube : :class:`iris.cube.Cube` + The cube to calculate area weights for. + normalize : bool, optional, default=False + If False, weights are grid cell areas. If True, weights are grid + cell areas divided by the total grid area. + + Returns + ------- + broad_weights : + """ # Get the radius of the earth cs = cube.coord_system("CoordSystem") @@ -478,9 +504,13 @@ def cosine_latitude_weights(cube): Weights are calculated for each latitude as: - .. math:: + .. math:: - w_l = \cos \phi_l + w_l = \cos \phi_l + + Parameters + ---------- + cube : :class:`iris.cube.Cube` Examples -------- @@ -561,25 +591,29 @@ def project(cube, target_proj, nx=None, ny=None): prevent one from directly visualising the data, e.g. when the longitude and latitude are two dimensional and do not make up a regular grid. - Args: - * cube - An instance of :class:`iris.cube.Cube`. - * target_proj - An instance of the Cartopy Projection class, or an instance of - :class:`iris.coord_systems.CoordSystem` from which a projection - will be obtained. - Kwargs: - * nx - Desired number of sample points in the x direction for a domain - covering the globe. - * ny - Desired number of sample points in the y direction for a domain - covering the globe. - - Returns: + Parameters + ---------- + cube : :class:`iris.cube.Cube` + An instance of :class:`iris.cube.Cube`. + target_proj : :class:`iris.coord_systems.CoordSystem` + An instance of the Cartopy Projection class, or an instance of + :class:`iris.coord_systems.CoordSystem` from which a projection + will be obtained. + nx : optional, default=None + Desired number of sample points in the x direction for a domain + covering the globe. + ny : optional, default=None + Desired number of sample points in the y direction for a domain + covering the globe. + + Returns + ------- + :class:`iris.cube.Cube` An instance of :class:`iris.cube.Cube` and a list describing the extent of the projection. + Notes + ----- .. note:: If there are both dim and aux latitude-longitude coordinates, only @@ -852,15 +886,17 @@ def _transform_xy(crs_from, x, y, crs_to): """Shorthand function to transform 2d points between coordinate reference systems. - Args: - - * crs_from, crs_to (:class:`cartopy.crs.Projection`): + Parameters + ---------- + crs_from, crs_to : :class:`cartopy.crs.Projection` The coordinate reference systems. - * x, y (arrays): + x, y : array point locations defined in 'crs_from'. - Returns: - x, y : Arrays of locations defined in 'crs_to'. + Returns + ------- + x, y + Arrays of locations defined in 'crs_to'. """ pts = crs_to.transform_points(crs_from, x, y) @@ -872,14 +908,16 @@ def _inter_crs_differentials(crs1, x, y, crs2): Returns dx2/dx1, dy2/dx1, dx2/dy1 and dy2/dy1, at given locations. - Args: - - * crs1, crs2 (`cartopy.crs.Projection`): + Parameters + ---------- + crs1, crs2 : :class:`cartopy.crs.Projection` The coordinate systems, "from" and "to". - * x, y (array): + x, y : array Point locations defined in 'crs1'. - Returns: + Returns + ------- + arrays (dx2/dx1, dy2/dx1, dx2/dy1, dy2/dy1) at given locations. Each element of this tuple will be the same shape as the 'x' and 'y' arrays and will be the partial differentials between the two systems. @@ -918,19 +956,22 @@ def _inter_crs_differentials(crs1, x, y, crs2): def _crs_distance_differentials(crs, x, y): - """Calculate d(distance) / d(x) and ... / d(y) for a coordinate - reference system at specified locations. + """Calculate d(distance) / d(x) and ... / d(y). - Args: + Calculate d(distance) / d(x) and ... / d(y) for a coordinate + reference system at specified locations. - * crs (:class:`cartopy.crs.Projection`): + Parameters + ---------- + crs : :class:`cartopy.crs.Projection` The coordinate reference system. - * x, y (array): + x, y : array Locations at which to calculate the differentials, defined in 'crs' coordinate reference system. - Returns: - (abs(ds/dx), abs(ds/dy)). + Returns + ------- + (abs(ds/dx), abs(ds/dy)) Numerically approximated partial differentials, i.e. scaling factors between changes in distance and changes in coordinate values. @@ -953,18 +994,20 @@ def _transform_distance_vectors(u_dist, v_dist, ds, dx2, dy2): """Transform distance vectors from one coordinate reference system to another, preserving magnitude and physical direction. - Args: - - * u_dist, v_dist (array): + Parameters + ---------- + u_dist, v_dist : array Components of each vector along the x and y directions of the source crs at each location. - * ds (`DistanceDifferential`): + ds : `DistanceDifferential` Distance differentials for the source and the target crs at specified locations. - * dx2, dy2 (`PartialDifferential`): + dx2, dy2 : `PartialDifferential` Partial differentials from the source to the target crs. - Returns: + Returns + ------- + tuple (ut_dist, vt_dist): Tuple of arrays containing the vector components along the x and y directions of the target crs at each location. @@ -986,20 +1029,22 @@ def _transform_distance_vectors_tolerance_mask(src_crs, x, y, tgt_crs, ds, dx2, where the magnitude of vectors are not preserved due to numerical errors introduced by the transformation between coordinate systems. - Args: - * src_crs (`cartopy.crs.Projection`): + Parameters + ---------- + src_crs : `cartopy.crs.Projection` The source coordinate reference systems. - * x, y (array): + x, y : array Locations of each vector defined in 'src_crs'. - * tgt_crs (`cartopy.crs.Projection`): + tgt_crs : `cartopy.crs.Projection` The target coordinate reference systems. - * ds (`DistanceDifferential`): + ds : `DistanceDifferential` Distance differentials for src_crs and tgt_crs at specified locations - * dx2, dy2 (`PartialDifferential`): + dx2, dy2 : `PartialDifferential` Partial differentials from src_crs to tgt_crs. - Returns: - 2d boolean array that is the same shape as x and y. + Returns + ------- + 2d boolean array that is the same shape as x and y. """ if x.shape != y.shape: @@ -1040,23 +1085,27 @@ def rotate_winds(u_cube, v_cube, target_cs): also have two 2-dimensional auxiliary coordinates containing the X and Y locations in the target coordinate system. - Args: - - * u_cube + Parameters + ---------- + u_cube : An instance of :class:`iris.cube.Cube` that contains the x-component of the vector. - * v_cube + v_cube : An instance of :class:`iris.cube.Cube` that contains the y-component of the vector. - * target_cs + target_cs : An instance of :class:`iris.coord_systems.CoordSystem` that specifies the new grid directions. - Returns: + Returns + ------- + (u', v') tuple of :class:`iris.cube.Cube` A (u', v') tuple of :class:`iris.cube.Cube` instances that are the u and v components in the requested target coordinate system. The units are the same as the inputs. + Notes + ----- .. note:: The U and V values relate to distance, with units such as 'm s-1'. diff --git a/lib/iris/analysis/maths.py b/lib/iris/analysis/maths.py index 3d1df8d66f..0d865952ce 100644 --- a/lib/iris/analysis/maths.py +++ b/lib/iris/analysis/maths.py @@ -35,23 +35,20 @@ def _output_dtype(op, first_dtype, second_dtype=None, in_place=False): """Get the numpy dtype corresponding to the result of applying a unary or binary operation to arguments of specified dtype. - Args: - - * op: + Parameters + ---------- + op : A unary or binary operator which can be applied to array-like objects. - * first_dtype: + first_dtype : The dtype of the first or only argument to the operator. - - Kwargs: - - * second_dtype: + second_dtype : optional, default=None The dtype of the second argument to the operator. - - * in_place: + in_place : bool, optional, default=False Whether the operation is to be performed in place. - Returns: - An instance of :class:`numpy.dtype` + Returns + ------- + :class:`numpy.dtype` .. note:: @@ -74,17 +71,17 @@ def _output_dtype(op, first_dtype, second_dtype=None, in_place=False): def _get_dtype(operand): - """Get the numpy dtype corresponding to the numeric data in the object - provided. + """Get the numpy dtype corresponding to the numeric data in the object provided. - Args: - - * operand: + Parameters + ---------- + operand : An instance of :class:`iris.cube.Cube` or :class:`iris.coords.Coord`, or a number or :class:`numpy.ndarray`. - Returns: - An instance of :class:`numpy.dtype` + Returns + ------- + :class:`numpy.dtype` """ return np.min_scalar_type(operand) if np.isscalar(operand) else operand.dtype @@ -93,18 +90,16 @@ def _get_dtype(operand): def abs(cube, in_place=False): """Calculate the absolute values of the data in the Cube provided. - Args: - - * cube: + Parameters + ---------- + cube : An instance of :class:`iris.cube.Cube`. - - Kwargs: - - * in_place: + in_place : bool, optional, default=False Whether to create a new Cube, or alter the given "cube". - Returns: - An instance of :class:`iris.cube.Cube`. + Returns + ------- + :class:`iris.cube.Cube`. Notes ----- @@ -124,17 +119,21 @@ def intersection_of_cubes(cube, other_cube): .. note:: The intersection of cubes function will ignore all single valued coordinates in checking the intersection. - Args: - - * cube: + Parameters + ---------- + cube : An instance of :class:`iris.cube.Cube`. - * other_cube: + other_cube : An instance of :class:`iris.cube.Cube`. - Returns: + Returns + ------- + A paired tuple of :class:`iris.cube.Cube` A pair of :class:`iris.cube.Cube` instances in a tuple corresponding to the original cubes restricted to their intersection. + Notes + ----- .. deprecated:: 3.2.0 Instead use :meth:`iris.cube.CubeList.extract_overlapping`. For example, @@ -228,7 +227,7 @@ def add(cube, other, dim=None, in_place=False): If `other` is a coord which does not exist on the cube, specify the dimension to which it should be mapped. - in_place : bool, default=False + in_place : bool, optional, default=False If `True`, alters the input cube. Otherwise a new cube is created. Returns @@ -281,7 +280,7 @@ def subtract(cube, other, dim=None, in_place=False): If `other` is a coord which does not exist on the cube, specify the dimension to which it should be mapped. - in_place : bool, default=False + in_place : bool, optional, default=False If `True`, alters the input cube. Otherwise a new cube is created. Returns @@ -323,19 +322,25 @@ def _add_subtract_common( """Function which shares common code between addition and subtraction of cubes. - operation_function - function which does the operation - (e.g. numpy.subtract) - operation_name - the public name of the operation (e.g. 'divide') - cube - the cube whose data is used as the first argument - to `operation_function` - other - the cube, coord, ndarray, dask array or number whose - data is used as the second argument - new_dtype - the expected dtype of the output. Used in the - case of scalar masked arrays - dim - dimension along which to apply `other` if it's a - coordinate that is not found in `cube` - in_place - whether or not to apply the operation in place to - `cube` and `cube.data` + Parameters + ---------- + operation_function : + function which does the operation (e.g. numpy.subtract) + operation_name : + The public name of the operation (e.g. 'divide') + cube : + The cube whose data is used as the first argument to `operation_function` + other : + The cube, coord, ndarray, dask array or number whose + data is used as the second argument + new_dtype : + The expected dtype of the output. Used in the case of scalar + masked arrays + dim : optional, default=None + Dimension along which to apply `other` if it's a coordinate that is not + found in `cube` + in_place : bool, optional, default=False + Whether or not to apply the operation in place to `cube` and `cube.data` """ _assert_is_cube(cube) @@ -384,7 +389,7 @@ def multiply(cube, other, dim=None, in_place=False): If `other` is a coord which does not exist on the cube, specify the dimension to which it should be mapped. - in_place : bool, default=False + in_place : bool, optional, default=False If `True`, alters the input cube. Otherwise a new cube is created. Returns @@ -468,7 +473,7 @@ def divide(cube, other, dim=None, in_place=False): If `other` is a coord which does not exist on the cube, specify the dimension to which it should be mapped. - in_place : bool, default=False + in_place : bool, optional, default=False If `True`, alters the input cube. Otherwise a new cube is created. Returns @@ -520,11 +525,11 @@ def divide(cube, other, dim=None, in_place=False): def exponentiate(cube, exponent, in_place=False): """Returns the result of the given cube to the power of a scalar. - Args: - - * cube: + Parameters + ---------- + cube : An instance of :class:`iris.cube.Cube`. - * exponent: + exponent : The integer or floating point exponent. .. note:: When applied to the cube's unit, the exponent must @@ -532,14 +537,12 @@ def exponentiate(cube, exponent, in_place=False): powers of the basic units. e.g. Unit('meter^-2 kilogram second^-1') - - Kwargs: - - * in_place: + in_place : bool, optional, default=False Whether to create a new Cube, or alter the given "cube". - Returns: - An instance of :class:`iris.cube.Cube`. + Returns + ------- + :class:`iris.cube.Cube`. Notes ----- @@ -575,25 +578,21 @@ def power(data, out=None): def exp(cube, in_place=False): """Calculate the exponential (exp(x)) of the cube. - Args: - - * cube: + Parameters + ---------- + cube : An instance of :class:`iris.cube.Cube`. - - .. note:: - - Taking an exponential will return a cube with dimensionless units. - - Kwargs: - - * in_place: + in_place : bool, optional, default=False Whether to create a new Cube, or alter the given "cube". - Returns: - An instance of :class:`iris.cube.Cube`. + Returns + ------- + :class:`iris.cube.Cube`. Notes ----- + Taking an exponential will return a cube with dimensionless units. + This function maintains laziness when called; it does not realise data. See more at :doc:`/userguide/real_and_lazy_data`. @@ -609,18 +608,16 @@ def exp(cube, in_place=False): def log(cube, in_place=False): """Calculate the natural logarithm (base-e logarithm) of the cube. - Args: - - * cube: + Parameters + ---------- + cube : An instance of :class:`iris.cube.Cube`. - - Kwargs: - - * in_place: + in_place : bool, optional, default=False Whether to create a new Cube, or alter the given "cube". - Returns: - An instance of :class:`iris.cube.Cube`. + Returns + ------- + :class:`iris.cube.Cube` Notes ----- @@ -643,18 +640,16 @@ def log(cube, in_place=False): def log2(cube, in_place=False): """Calculate the base-2 logarithm of the cube. - Args: - - * cube: + Parameters + ---------- + cube : An instance of :class:`iris.cube.Cube`. - - Kwargs:lib/iris/tests/unit/analysis/maths/test_subtract.py - - * in_place: + in_place : bool, optional, default=False Whether to create a new Cube, or alter the given "cube". - Returns: - An instance of :class:`iris.cube.Cube`. + Returns + ------- + :class:`iris.cube.Cube` Notes ----- @@ -673,18 +668,16 @@ def log2(cube, in_place=False): def log10(cube, in_place=False): """Calculate the base-10 logarithm of the cube. - Args: - - * cube: + Parameters + ---------- + cube : An instance of :class:`iris.cube.Cube`. - - Kwargs: - - * in_place: + in_place : bool, optional, default=False Whether to create a new Cube, or alter the given "cube". - Returns: - An instance of :class:`iris.cube.Cube`. + Returns + ------- + :class:`iris.cube.Cube`. Notes ----- @@ -711,34 +704,33 @@ def apply_ufunc(ufunc, cube, other=None, new_unit=None, new_name=None, in_place= It is usually preferable to use these functions rather than :func:`iris.analysis.maths.apply_ufunc` where possible. - Args: - - * ufunc: + Parameters + ---------- + ufunc : An instance of :func:`numpy.ufunc` e.g. :func:`numpy.sin`, :func:`numpy.mod`. - - * cube: + cube : An instance of :class:`iris.cube.Cube`. Kwargs: - * other: + other ::class:`iris.cube.Cube`, optional, default=False An instance of :class:`iris.cube.Cube` to be given as the second argument to :func:`numpy.ufunc`. - - * new_unit: + new_unit : optional, default=False Unit for the resulting Cube. - - * new_name: + new_name : optional, default=False Name for the resulting Cube. - - * in_place: + in_place : bool, optional, default=False Whether to create a new Cube, or alter the given "cube". - Returns: - An instance of :class:`iris.cube.Cube`. + Returns + ------- + :class:`iris.cube.Cube`. - Example:: + Examples + -------- + :: cube = apply_ufunc(numpy.sin, cube, in_place=True) @@ -821,22 +813,29 @@ def _binary_op_common( ): """Function which shares common code between binary operations. - operation_function - function which does the operation - (e.g. numpy.divide) - operation_name - the public name of the operation (e.g. 'divide') - cube - the cube whose data is used as the first argument - to `operation_function` - other - the cube, coord, ndarray, dask array or number whose - data is used as the second argument - new_dtype - the expected dtype of the output. Used in the - case of scalar masked arrays - new_unit - unit for the resulting quantity - dim - dimension along which to apply `other` if it's a - coordinate that is not found in `cube` - in_place - whether or not to apply the operation in place to - `cube` and `cube.data` - sanitise_metadata - whether or not to remove metadata using - _sanitise_metadata function + Parameters + ---------- + operation_function : + Function which does the operation (e.g. numpy.divide) + operation_name : + The public name of the operation (e.g. 'divide') + cube : + The cube whose data is used as the first argument to `operation_function` + other : + The cube, coord, ndarray, dask array or number whose data is used + as the second argument + new_dtype : + The expected dtype of the output. Used in the case of scalar masked arrays + new_unit : optional, default=None + Unit for the resulting quantity + dim : optional, default=None + Dimension along which to apply `other` if it's a coordinate that is + not found in `cube` + in_place : bool, optional, default=False + whether or not to apply the operation in place to `cube` and `cube.data` + sanitise_metadata : bool, optional, default=True + Whether or not to remove metadata using _sanitise_metadata function + """ from iris.cube import Cube @@ -1041,25 +1040,24 @@ class IFunc: def __init__(self, data_func, units_func): """Create an ifunc from a data function and units function. - Args: - - * data_func: - + Parameters + ---------- + data_func : Function to be applied to one or two data arrays, which are given as positional arguments. Should return another data array, with the same shape as the first array. - May also have keyword arguments. - - * units_func: - + units_func : Function to calculate the units of the resulting cube. Should take the cube/s as input and return an instance of :class:`cf_units.Unit`. - Returns: - An ifunc. + Returns + ------- + ifunc + Examples + -------- **Example usage 1** Using an existing numpy ufunc, such as numpy.sin for the data function and a simple lambda function for the units function:: @@ -1090,6 +1088,7 @@ def ws_units_func(u_cube, v_cube): cs_ifunc = iris.analysis.maths.IFunc(numpy.cumsum, lambda a: a.units) cs_cube = cs_ifunc(cube, axis=1) + """ self._data_func_name = getattr( @@ -1164,33 +1163,27 @@ def __call__( ): """Applies the ifunc to the cube(s). - Args: - - * cube + Parameters + ---------- + cube : An instance of :class:`iris.cube.Cube`, whose data is used as the first argument to the data function. - - Kwargs: - - * other + * other : optional, default=None A cube, coord, ndarray, dask array or number whose data is used as the second argument to the data function. - - * new_name: + * new_name : optional, default=None Name for the resulting Cube. - - * in_place: + * in_place : bool, optional, default=False Whether to create a new Cube, or alter the given "cube". - - * dim: + * dim : optional, default=None Dimension along which to apply `other` if it's a coordinate that is not found in `cube` - - * kwargs_data_func: + ** kwargs_data_func : Keyword arguments that get passed on to the data_func. - Returns: - An instance of :class:`iris.cube.Cube`. + Returns + ------- + :class:`iris.cube.Cube` """ _assert_is_cube(cube) diff --git a/lib/iris/analysis/stats.py b/lib/iris/analysis/stats.py index e3a01f6933..2f5b125e06 100644 --- a/lib/iris/analysis/stats.py +++ b/lib/iris/analysis/stats.py @@ -24,34 +24,36 @@ def pearsonr( """Calculate the Pearson's r correlation coefficient over specified dimensions. - Args: - - * cube_a, cube_b (cubes): + Parameters + ---------- + cube_a, cube_b : cubes Cubes between which the correlation will be calculated. The cubes should either be the same shape and have the same dimension coordinates or one cube should be broadcastable to the other. - * corr_coords (str or list of str): + corr_coords : str or list of str The cube coordinate name(s) over which to calculate correlations. If no names are provided then correlation will be calculated over all common cube dimensions. - * weights (numpy.ndarray, optional): + weights : :class:`numpy.ndarray`, optional Weights array of same shape as (the smaller of) cube_a and cube_b. Note that latitude/longitude area weights can be calculated using :func:`iris.analysis.cartography.area_weights`. - * mdtol (float, optional): + mdtol : float, default=1.0 Tolerance of missing data. The missing data fraction is calculated based on the number of grid cells masked in both cube_a and cube_b. If this fraction exceed mdtol, the returned value in the corresponding cell is masked. mdtol=0 means no missing data is tolerated while mdtol=1 means the resulting element will be masked if and only if all contributing elements are masked in cube_a or cube_b. Defaults to 1. - * common_mask (bool): + common_mask : bool, default=False If True, applies a common mask to cube_a and cube_b so only cells which are unmasked in both cubes contribute to the calculation. If False, the variance for each cube is calculated from all available cells. Defaults to False. - Returns: + Returns + ------- + :class:`~iris.cube.Cube` A cube of the correlation between the two input cubes along the specified dimensions, at each point in the remaining dimensions of the cubes. @@ -61,6 +63,8 @@ def pearsonr( time/altitude cube describing the latitude/longitude (i.e. pattern) correlation at each time/altitude point. + Notes + ----- Reference: https://en.wikipedia.org/wiki/Pearson_correlation_coefficient diff --git a/lib/iris/analysis/trajectory.py b/lib/iris/analysis/trajectory.py index ed5b911b0c..c46fa2ebea 100644 --- a/lib/iris/analysis/trajectory.py +++ b/lib/iris/analysis/trajectory.py @@ -42,7 +42,16 @@ class Trajectory: def __init__(self, waypoints, sample_count=10): """Defines a trajectory using a sequence of waypoints. - For example:: + Parameters + ---------- + waypoints : + A sequence of dictionaries, mapping coordinate names to values. + sample_count : int, optional, default=10 + The number of sample positions to use along the trajectory. + + Examples + -------- + :: waypoints = [{'latitude': 45, 'longitude': -60}, {'latitude': 45, 'longitude': 0}] @@ -51,16 +60,6 @@ def __init__(self, waypoints, sample_count=10): .. note:: All the waypoint dictionaries must contain the same coordinate names. - Args: - - * waypoints - A sequence of dictionaries, mapping coordinate names to values. - - Kwargs: - - * sample_count - The number of sample positions to use along the trajectory. - """ self.waypoints = waypoints self.sample_count = sample_count @@ -75,7 +74,7 @@ def __init__(self, waypoints, sample_count=10): self.length = sum([seg.length for seg in segments]) # generate our sampled points - #: The trajectory points, as dictionaries of {coord_name: value}. + # The trajectory points, as dictionaries of {coord_name: value}. self.sampled_points = [] sample_step = self.length / (self.sample_count - 1) @@ -119,7 +118,9 @@ def _get_interp_points(self): """Translate `self.sampled_points` to the format expected by the interpolator. - Returns: + Returns + ------- + `self.sampled points` `self.sampled points` in the format required by `:func:`~iris.analysis.trajectory.interpolate`. @@ -134,8 +135,9 @@ def _src_cube_anon_dims(self, cube): """A helper method to locate the index of anonymous dimensions on the interpolation target, ``cube``. - Returns: - The index of any anonymous dimensions in ``cube``. + Returns + ------- + The index of any anonymous dimensions in ``cube``. """ named_dims = [cube.coord_dims(c)[0] for c in cube.dim_coords] @@ -150,14 +152,11 @@ def interpolate(self, cube, method=None): supplied in the same coord_system as in `cube`, where appropriate (i.e. for horizontal coordinate points). - Args: - - * cube + Parameters + ---------- + cube : The source Cube to interpolate. - - Kwargs: - - * method: + method : The interpolation method to use; "linear" (default) or "nearest". Only nearest is available when specifying multi-dimensional coordinates. @@ -186,23 +185,20 @@ def interpolate(self, cube, method=None): def interpolate(cube, sample_points, method=None): """Extract a sub-cube at the given n-dimensional points. - Args: - - * cube + Parameters + ---------- + cube : The source Cube. - - * sample_points + sample_points : A sequence of coordinate (name) - values pairs. - - Kwargs: - - * method + method : optional, default=None Request "linear" interpolation (default) or "nearest" neighbour. Only nearest neighbour is available when specifying multi-dimensional coordinates. - - For example:: + Examples + -------- + :: sample_points = [('latitude', [45, 45, 45]), ('longitude', [-60, -50, -40])] @@ -487,17 +483,17 @@ def _cartesian_sample_points(sample_points, sample_point_coord_names): Generates coords suitable for nearest point calculations with `scipy.spatial.cKDTree`. - Args: - - * sample_points[coord][datum]: - list of sample_positions for each datum, formatted for fast use of - :func:`_ll_to_cart()`. - - * sample_point_coord_names[coord]: - list of n coord names + Parameters + ---------- + sample_points : + [coord][datum] list of sample_positions for each datum, formatted for + fast use of :func:`_ll_to_cart()`. + sample_point_coord_names : + [coord] list of n coord names - Returns: - list of [x,y,z,t,etc] positions, formatted for kdtree. + Returns + ------- + list of [x,y,z,t,etc] positions, formatted for kdtree. """ # Find lat and lon coord indices @@ -717,29 +713,31 @@ def __init__(self, src_cube, target_grid_cube): This can then be applied to any source data with the same structure as the original 'src_cube'. - Args: - - * src_cube: + Parameters + ---------- + src_cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` defining the source grid. The X and Y coordinates can have any shape, but must be mapped over the same cube dimensions. - - * target_grid_cube: + target_grid_cube : :class:`~iris.cube.Cube` A :class:`~iris.cube.Cube`, whose X and Y coordinates specify a desired target grid. The X and Y coordinates must be one-dimensional dimension coordinates, mapped to different dimensions. All other cube components are ignored. - Returns: - regridder : (object) + Returns + ------- + regridder (object) + A callable object with the interface:: - A callable object with the interface: - `result_cube = regridder(data)` + result_cube = regridder(data) where `data` is a cube with the same grid as the original `src_cube`, that is to be regridded to the `target_grid_cube`. + Notes + ----- .. Note:: For latitude-longitude coordinates, the nearest-neighbour distances diff --git a/lib/iris/common/lenient.py b/lib/iris/common/lenient.py index 614060b9bf..821559c44b 100644 --- a/lib/iris/common/lenient.py +++ b/lib/iris/common/lenient.py @@ -53,22 +53,20 @@ def func() def func(): pass - Args: - - * dargs (tuple of callable): + Parameters + ---------- + dargs : tuple of callable A tuple containing the callable lenient client function/method to be wrapped by the decorator. This is automatically populated by Python through the decorator interface. No argument requires to be manually provided. - - Kwargs: - - * services (callable or str or iterable of callable/str) + services : callable or str or iterable of callable/str, optional, default=None Zero or more function/methods, or equivalent fully qualified string names, of lenient service function/methods. - Returns: - Closure wrapped function/method. + Returns + ------- + Closure wrapped function/method. """ ndargs = len(dargs) @@ -144,16 +142,17 @@ def func(): def func(): pass - Args: - - * dargs (tuple of callable): + Parameters + ---------- + dargs : tuple of callable A tuple containing the callable lenient service function/method to be wrapped by the decorator. This is automatically populated by Python through the decorator interface. No argument requires to be manually provided. - Returns: - Closure wrapped function/method. + Returns + ------- + Closure wrapped function/method. """ ndargs = len(dargs) @@ -195,12 +194,14 @@ def lenient_service_outer(func): def _qualname(func): """Return the fully qualified function/method string name. - Args: - - * func (callable): + Parameters + ---------- + func : callable Callable function/method. Non-callable arguments are simply passed through. + Notes + ----- .. note:: Inherited methods will be qualified with the base class that defines the method. @@ -218,14 +219,16 @@ class Lenient(threading.local): def __init__(self, **kwargs): """A container for managing the run-time lenient features and options. - Kwargs: - - * kwargs (dict) + Parameters + ---------- + **kwargs : dict Mapping of lenient key/value options to enable/disable. Note that, only the lenient "maths" options is available, which controls lenient/strict cube arithmetic. - For example:: + Examples + -------- + :: Lenient(maths=False) @@ -287,7 +290,9 @@ def context(self, **kwargs): applied. On exit from the context manager, the previous lenient option state is restored. + For example:: + with iris.common.Lenient.context(maths=False): pass @@ -320,20 +325,19 @@ def __init__(self, *args, **kwargs): """A container for managing the run-time lenient services and client options for pre-defined functions/methods. - Args: - - * args (callable or str or iterable of callable/str) + Parameters + ---------- + *args : callable or str or iterable of callable/str A function/method or fully qualified string name of the function/method acting as a lenient service. - - Kwargs: - - * kwargs (dict of callable/str or iterable of callable/str) + **kwargs : dict of callable/str or iterable of callable/str, optional Mapping of lenient client function/method, or fully qualified string name of the function/method, to one or more lenient service function/methods or fully qualified string name of function/methods. - For example:: + Examples + -------- + :: _Lenient(service1, service2, client1=service1, client2=(service1, service2)) @@ -355,13 +359,14 @@ def __call__(self, func): """Determine whether it is valid for the function/method to provide a lenient service at runtime to the actively executing lenient client. - Args: - - * func (callable or str): + Parameters + ---------- + func : callable or str A function/method or fully qualified string name of the function/method. - Returns: - Boolean. + Returns + ------- + bool """ result = False @@ -438,6 +443,7 @@ def context(self, *args, **kwargs): state is restored. For example:: + with iris._LENIENT.context(example_lenient_flag=False): # ... code that expects some non-lenient behaviour @@ -509,9 +515,9 @@ def enable(self, state): Setting the state to `False` disables all lenient services, and setting the state to `True` enables all lenient services. - Args: - - * state (bool): + Parameters + ---------- + state : bool Activate state for lenient services. """ @@ -525,19 +531,15 @@ def register_client(self, func, services, append=False): """Add the provided mapping of lenient client function/method to required lenient service function/methods. - Args: - - * func (callable or str): + Parameters + ---------- + func : callable or str A client function/method or fully qualified string name of the client function/method. - - * services (callable or str or iterable of callable/str): + services : callable or str or iterable of callable/str One or more service function/methods or fully qualified string names of the required service function/method. - - Kwargs: - - * append (bool): + append : bool, optional If True, append the lenient services to any pre-registered lenient services for the provided lenient client. Default is False. @@ -568,9 +570,9 @@ def register_service(self, func): """Add the provided function/method as providing a lenient service and activate it. - Args: - - * func (callable or str): + Parameters + ---------- + func : callable or str A service function/method or fully qualified string name of the service function/method. @@ -588,9 +590,9 @@ def register_service(self, func): def unregister_client(self, func): """Remove the provided function/method as a lenient client using lenient services. - Args: - - * func (callable or str): + Parameters + ---------- + func : callable or str A function/method of fully qualified string name of the function/method. """ @@ -614,9 +616,9 @@ def unregister_client(self, func): def unregister_service(self, func): """Remove the provided function/method as providing a lenient service. - Args: - - * func (callable or str): + Parameters + ---------- + func : callable or str A function/method or fully qualified string name of the function/method. """ diff --git a/lib/iris/common/metadata.py b/lib/iris/common/metadata.py index 691e427aa5..212691e046 100644 --- a/lib/iris/common/metadata.py +++ b/lib/iris/common/metadata.py @@ -59,12 +59,14 @@ def hexdigest(item): This provides a means to compare large and/or complex objects through simple string hexdigest comparison. - Args: - - * item (object): + Parameters + ---------- + item : object The item that requires to have its hexdigest calculated. - Returns: + Returns + ------- + str The string hexadecimal representation of the item's 64-bit hash. """ @@ -154,13 +156,14 @@ class BaseMetadata(metaclass=_NamedTupleMeta): def __eq__(self, other): """Determine whether the associated metadata members are equivalent. - Args: - - * other (metadata): + Parameters + ---------- + other : metadata A metadata instance of the same type. - Returns: - Boolean. + Returns + ------- + bool """ result = NotImplemented @@ -240,28 +243,23 @@ def __str__(self): def _api_common(self, other, func_service, func_operation, action, lenient=None): """Common entry-point for lenient metadata API methods. - Args: - - * other (metadata): + Parameters + ---------- + other : metadata A metadata instance of the same type. - - * func_service (callable): + func_service : callable The parent service method offering the API entry-point to the service. - - * func_operation (callable): + func_operation : callable The parent service method that provides the actual service. - - * action (str): + action : str The verb describing the service operation. - - Kwargs: - - * lenient (boolean): + lenient : bool, optional Enable/disable the lenient service operation. The default is to automatically detect whether this lenient service operation is enabled. - Returns: - The result of the service operation to the parent service caller. + Returns + ------- + The result of the service operation to the parent service caller. """ # Ensure that we have similar class instances. @@ -312,13 +310,14 @@ def func(field): def _combine_lenient(self, other): """Perform lenient combination of metadata members. - Args: - - * other (BaseMetadata): + Parameters + ---------- + other : BaseMetadata The other metadata participating in the lenient combination. - Returns: - A list of combined metadata member values. + Returns + ------- + A list of combined metadata member values. """ @@ -393,13 +392,14 @@ def _combine_strict_attributes(left, right): def _compare_lenient(self, other): """Perform lenient equality of metadata members. - Args: - - * other (BaseMetadata): + Parameters + ---------- + other : BaseMetadata The other metadata participating in the lenient comparison. - Returns: - Boolean. + Returns + ------- + bool """ result = False @@ -484,13 +484,14 @@ def func(field): def _difference_lenient(self, other): """Perform lenient difference of metadata members. - Args: - - * other (BaseMetadata): + Parameters + ---------- + other : BaseMetadata The other metadata participating in the lenient difference. - Returns: - A list of difference metadata member values. + Returns + ------- + A list of difference metadata member values. """ @@ -579,19 +580,17 @@ def combine(self, other, lenient=None): """Return a new metadata instance created by combining each of the associated metadata members. - Args: - - * other (metadata): + Parameters + ---------- + other : metadata A metadata instance of the same type. - - Kwargs: - - * lenient (boolean): + lenient : bool Enable/disable lenient combination. The default is to automatically detect whether this lenient operation is enabled. - Returns: - Metadata instance. + Returns + ------- + Metadata instance. """ result = self._api_common( @@ -608,19 +607,17 @@ def difference(self, other, lenient=None): is no difference between the members being compared. Otherwise, a tuple of the different values is returned. - Args: - - * other (metadata): + Parameters + ---------- + other : metadata A metadata instance of the same type. - - Kwargs: - - * lenient (boolean): + lenient : bool, optional Enable/disable lenient difference. The default is to automatically detect whether this lenient operation is enabled. - Returns: - Metadata instance of member differences or None. + Returns + ------- + Metadata instance of member differences or None. """ result = self._api_common( @@ -635,19 +632,17 @@ def difference(self, other, lenient=None): def equal(self, other, lenient=None): """Determine whether the associated metadata members are equivalent. - Args: - - * other (metadata): + Parameters + ---------- + other : metadata A metadata instance of the same type. - - Kwargs: - - * lenient (boolean): + lenient : bool, optional Enable/disable lenient equivalence. The default is to automatically detect whether this lenient operation is enabled. - Returns: - Boolean. + Returns + ------- + bool """ result = self._api_common( @@ -662,13 +657,14 @@ def from_metadata(cls, other): Non-common metadata members are set to ``None``. - Args: - - * other (metadata): + Parameters + ---------- + other : metadata A metadata instance of any type. - Returns: - New metadata instance. + Returns + ------- + New metadata instance. """ result = None @@ -690,19 +686,20 @@ def name(self, default=None, token=False): the NetCDF variable name, before falling-back to a default value, which itself defaults to the string 'unknown'. - Kwargs: - - * default: + Parameters + ---------- + default : optional The fall-back string representing the default name. Defaults to the string 'unknown'. - * token: + token : bool, optional If True, ensures that the name returned satisfies the criteria for the characters required by a valid NetCDF name. If it is not possible to return a valid name, then a ValueError exception is raised. Defaults to False. - Returns: - String. + Returns + ------- + str """ @@ -729,13 +726,14 @@ def token(cls, name): """Determine whether the provided name is a valid NetCDF name and thus safe to represent a single parsable token. - Args: - - * name: + Parameters + ---------- + name : str The string name to verify - Returns: - The provided name if valid, otherwise None. + Returns + ------- + The provided name if valid, otherwise None. """ if name is not None: @@ -786,14 +784,15 @@ def __eq__(self, other): def _combine_lenient(self, other): """Perform lenient combination of metadata members for cell measures. - Args: - - * other (CellMeasureMetadata): + Parameters + ---------- + other : CellMeasureMetadata The other cell measure metadata participating in the lenient combination. - Returns: - A list of combined metadata member values. + Returns + ------- + A list of combined metadata member values. """ # Perform "strict" combination for "measure". @@ -807,14 +806,15 @@ def _combine_lenient(self, other): def _compare_lenient(self, other): """Perform lenient equality of metadata members for cell measures. - Args: - - * other (CellMeasureMetadata): + Parameters + ---------- + other : CellMeasureMetadata The other cell measure metadata participating in the lenient comparison. - Returns: - Boolean. + Returns + ------- + bool """ # Perform "strict" comparison for "measure". @@ -828,14 +828,15 @@ def _compare_lenient(self, other): def _difference_lenient(self, other): """Perform lenient difference of metadata members for cell measures. - Args: - - * other (CellMeasureMetadata): + Parameters + ---------- + other : CellMeasureMetadata The other cell measure metadata participating in the lenient difference. - Returns: - A list of difference metadata member values. + Returns + ------- + A list of difference metadata member values. """ # Perform "strict" difference for "measure". @@ -908,14 +909,15 @@ def _sort_key(item): def _combine_lenient(self, other): """Perform lenient combination of metadata members for coordinates. - Args: - - * other (CoordMetadata): + Parameters + ---------- + other : CoordMetadata The other coordinate metadata participating in the lenient combination. - Returns: - A list of combined metadata member values. + Returns + ------- + A list of combined metadata member values. """ @@ -936,14 +938,15 @@ def func(field): def _compare_lenient(self, other): """Perform lenient equality of metadata members for coordinates. - Args: - - * other (CoordMetadata): + Parameters + ---------- + other : CoordMetadata The other coordinate metadata participating in the lenient comparison. - Returns: - Boolean. + Returns + ------- + bool """ # Perform "strict" comparison for "coord_system" and "climatological". @@ -962,14 +965,15 @@ def _compare_lenient(self, other): def _difference_lenient(self, other): """Perform lenient difference of metadata members for coordinates. - Args: - - * other (CoordMetadata): + Parameters + ---------- + other : CoordMetadata The other coordinate metadata participating in the lenient difference. - Returns: - A list of difference metadata member values. + Returns + ------- + A list of difference metadata member values. """ @@ -1057,13 +1061,14 @@ def _sort_key(item): def _combine_lenient(self, other): """Perform lenient combination of metadata members for cubes. - Args: - - * other (CubeMetadata): + Parameters + ---------- + other : CubeMetadata The other cube metadata participating in the lenient combination. - Returns: - A list of combined metadata member values. + Returns + ------- + A list of combined metadata member values. """ # Perform "strict" combination for "cell_methods". @@ -1077,13 +1082,14 @@ def _combine_lenient(self, other): def _compare_lenient(self, other): """Perform lenient equality of metadata members for cubes. - Args: - - * other (CubeMetadata): + Parameters + ---------- + other : CubeMetadata The other cube metadata participating in the lenient comparison. - Returns: - Boolean. + Returns + ------- + bool """ # Perform "strict" comparison for "cell_methods". @@ -1096,13 +1102,14 @@ def _compare_lenient(self, other): def _difference_lenient(self, other): """Perform lenient difference of metadata members for cubes. - Args: - - * other (CubeMetadata): + Parameters + ---------- + other : CubeMetadata The other cube metadata participating in the lenient difference. - Returns: - A list of difference metadata member values. + Returns + ------- + A list of difference metadata member values. """ # Perform "strict" difference for "cell_methods". @@ -1336,47 +1343,40 @@ def metadata_filter( Criteria can be either specific properties or other objects with metadata to be matched. - Args: - - * instances: + Parameters + ---------- + instances : One or more objects to be filtered. - - Kwargs: - - * item: + item : optional 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 objects e.g., :class:`~iris.coords.DimCoord` or :class:`CoordMetadata`. - - * standard_name: + standard_name : optional The CF standard name of the desired object. If ``None``, does not check for ``standard_name``. - - * long_name: + long_name : optional An unconstrained description of the object. If ``None``, does not check for ``long_name``. - - * var_name: + var_name : optional The NetCDF variable name of the desired object. If ``None``, does not check for ``var_name``. - - * attributes: + attributes : dict, optional A dictionary of attributes desired on the object. If ``None``, does not check for ``attributes``. - - * axis: + axis : optional The desired object's 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). - Returns: + Returns + ------- + list of the objects A list of the objects supplied in the ``instances`` argument, limited to only those that matched the given criteria. @@ -1559,20 +1559,18 @@ def metadata_manager_factory(cls, **kwargs): The factory instances returned by the factory are capable of managing their metadata state, which can be proxied by the owning container. - Args: - - * cls: + Parameters + ---------- + cls : A subclass of :class:`~iris.common.metadata.BaseMetadata`, defining the metadata to be managed. - - Kwargs: - - * kwargs: + **kwargs : Initial values for the manufactured metadata instance. Unspecified fields will default to a value of 'None'. - Returns: - A manager instance for the provided metadata ``cls``. + Returns + ------- + A manager instance for the provided metadata ``cls``. """ # Check whether kwargs have valid fields for the specified metadata. diff --git a/lib/iris/common/resolve.py b/lib/iris/common/resolve.py index 84ea6eed24..3885a94a14 100644 --- a/lib/iris/common/resolve.py +++ b/lib/iris/common/resolve.py @@ -205,7 +205,7 @@ class Resolve: >>> resolver = Resolve(cube1, cube2) >>> results = [resolver.cube(data) for data in payload] - """ # noqa: D214, D410, D411 + """ # noqa: D214, D407, D410, D411 def __init__(self, lhs=None, rhs=None): """Resolve the provided ``lhs`` :class:`~iris.cube.Cube` operand and @@ -236,8 +236,16 @@ def __init__(self, lhs=None, rhs=None): but this may not be possible when auto-transposition or extended broadcasting is involved during the operation. - For example: + Parameters + ---------- + lhs : :class:`~iris.cube.Cube` + The left-hand-side :class:`~iris.cube.Cube` operand. + rhs : :class:`~iris.cube.Cube` + The right-hand-side :class:`~iris.cube.Cube` operand. + + Examples + -------- .. doctest:: >>> cube1 @@ -249,14 +257,6 @@ def __init__(self, lhs=None, rhs=None): >>> result1 == result2 True - Kwargs: - - * lhs: - The left-hand-side :class:`~iris.cube.Cube` operand. - - * rhs: - The right-hand-side :class:`~iris.cube.Cube` operand. - """ #: The ``lhs`` operand to be resolved into the resultant :class:`~iris.cube.Cube`. self.lhs_cube = None # set in __call__ @@ -332,12 +332,11 @@ def __call__(self, lhs, rhs): :class:`~iris.cube.Cube`, which may be auto-transposed, can be determined. - Args: - - * lhs: + Parameters + ---------- + lhs : :class:`~iris.cube.Cube` The left-hand-side :class:`~iris.cube.Cube` operand. - - * rhs: + rhs : :class:`~iris.cube.Cube` The right-hand-side :class:`~iris.cube.Cube` operand. """ @@ -496,29 +495,26 @@ def _aux_coverage( The scalar coordinates local to the cube are also determined. - Args: - - * cube: + Parameters + ---------- + cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` to be analysed for coverage. - - * cube_items_aux: + cube_items_aux : The list of associated :class:`~iris.common.resolve._Item` metadata for each auxiliary coordinate owned by the cube. - - * cube_items_scalar: + cube_items_scalar : The list of associated :class:`~iris.common.resolve._Item` metadata for each scalar coordinate owned by the cube. - - * common_aux_metadata: + common_aux_metadata : The list of common auxiliary coordinate metadata shared by both the LHS and RHS cube operands being resolved. - - * common_scalar_metadata: + common_scalar_metadata : The list of common scalar coordinate metadata shared by both the LHS and RHS cube operands being resolved. - Returns: - :class:`~iris.common.resolve._AuxCoverage` + Returns + ------- + :class:`~iris.common.resolve._AuxCoverage` """ common_items_aux = [] @@ -565,20 +561,20 @@ def _aux_mapping(src_coverage, tgt_coverage): The ``src`` to ``tgt`` common auxiliary coordinate mapping is held by the :attr:`~iris.common.resolve.Resolve.mapping`. - Args: - - * src_coverage: + Parameters + ---------- + src_coverage : The :class:`~iris.common.resolve._DimCoverage` of the ``src`` :class:`~iris.cube.Cube` i.e., map from the common ``src`` dimensions. - - * tgt_coverage: + tgt_coverage : The :class:`~iris.common.resolve._DimCoverage` of the ``tgt`` :class:`~iris.cube.Cube` i.e., map to the common ``tgt`` dimensions. - Returns: - Dictionary of ``src`` to ``tgt`` dimension mapping. + Returns + ------- + dict of ``src`` to ``tgt`` dimension mapping. """ mapping = {} @@ -628,15 +624,16 @@ def _categorise_items(cube): coordinates and associated metadata into dimension, auxiliary and scalar categories. - Args: - - * cube: + Parameters + ---------- + cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` that will have its coordinates and metadata grouped into their associated dimension, auxiliary and scalar categories. - Returns: - :class:`~iris.common.resolve._CategoryItems` + Returns + ------- + :class:`~iris.common.resolve._CategoryItems` """ category = _CategoryItems(items_dim=[], items_aux=[], items_scalar=[]) @@ -675,35 +672,32 @@ def _create_prepared_item( containing the data and metadata required to construct and attach a coordinate to the resultant resolved cube. - Args: - - * coord: + Parameters + ---------- + coord : The coordinate with the ``points`` and ``bounds`` to be extracted. - - * dims (int or tuple): + dims : int or tuple The dimensions that the ``coord`` spans on the resulting resolved :class:`~iris.cube.Cube`. (Can also be a single dimension number). - - * src_metadata: + src_metadata : The coordinate metadata from the ``src`` :class:`~iris.cube.Cube`. - - * tgt_metadata: + tgt_metadata : The coordinate metadata from the ``tgt`` :class:`~iris.cube.Cube`. - - * points: + points : Override points array. When not given, use coord.points. - - * bounds: + bounds : Override bounds array. When not given, use coord.bounds. - - * container: + container : Override coord type (class constructor). When not given, use type(coord). - Returns: - The :class:`~iris.common.resolve._PreparedItem`. + Returns + ------- + :class:`~iris.common.resolve._PreparedItem`. + Notes + ----- .. note:: If container or type(coord) is DimCoord/AuxCoord (i.e. not @@ -802,21 +796,20 @@ def _dim_coverage(cube, cube_items_dim, common_dim_metadata): The cube dimensions not covered by any of the dimension coordinates is also determined; these are known as `free` dimensions. - Args: - - * cube: + Parameters + ---------- + cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` to be analysed for coverage. - - * cube_items_dim: + cube_items_dim : The list of associated :class:`~iris.common.resolve._Item` metadata for each dimension coordinate owned by the cube. - - * common_dim_metadata: + common_dim_metadata : The list of common dimension coordinate metadata shared by both the LHS and RHS cube operands being resolved. - Returns: - :class:`~iris.common.resolve._DimCoverage` + Returns + ------- + :class:`~iris.common.resolve._DimCoverage` """ ndim = cube.ndim @@ -854,20 +847,20 @@ def _dim_mapping(src_coverage, tgt_coverage): The ``src`` to ``tgt`` common dimension coordinate mapping is held by the :attr:`~iris.common.resolve.Resolve.mapping`. - Args: - - * src_coverage: + Parameters + ---------- + src_coverage : The :class:`~iris.common.resolve._DimCoverage` of the ``src`` :class:`~iris.cube.Cube` i.e., map from the common ``src`` dimensions. - - * tgt_coverage: + tgt_coverage : The :class:`~iris.common.resolve._DimCoverage` of the ``tgt`` :class:`~iris.cube.Cube` i.e., map to the common ``tgt`` dimensions. - Returns: - Dictionary of ``src`` to ``tgt`` dimension mapping. + Returns + ------- + dict of ``src`` to ``tgt`` dimension mapping. """ mapping = {} @@ -919,24 +912,23 @@ def _free_mapping( An exception will be raised if there are any ``src`` :class:`~iris.cube.Cube` dimensions not mapped to an associated ``tgt`` dimension. - Args: - - * src_dim_coverage: + Parameters + ---------- + src_dim_coverage : The :class:`~iris.common.resolve.._DimCoverage` of the ``src`` :class:`~iris.cube.Cube`. - - * tgt_dim_coverage: + tgt_dim_coverage : The :class:`~iris.common.resolve.._DimCoverage` of the ``tgt`` :class:`~iris.cube.Cube`. - - * src_aux_coverage: + src_aux_coverage : The :class:`~iris.common.resolve._AuxCoverage` of the ``src`` :class:`~iris.cube.Cube`. - - * tgt_aux_coverage: + tgt_aux_coverage : The :class:`~iris.common.resolve._AuxCoverage` of the ``tgt`` :class:`~iris.cube.Cube`. + Notes + ----- .. note:: All unmapped dimensions with an extend >1 are mapped before those @@ -1411,24 +1403,19 @@ def _prepare_common_aux_payload( For mixed ``src`` and ``tgt`` coordinate types with matching metadata, an :class:`~iris.coords.AuxCoord` will be nominated for construction. - Args: - - * src_common_items: + Parameters + ---------- + src_common_items : The list of :attr:`~iris.common.resolve._AuxCoverage.common_items_aux` metadata for the ``src`` :class:`~iris.cube.Cube`. - - * tgt_common_items: + tgt_common_items : The list of :attr:`~iris.common.resolve._AuxCoverage.common_items_aux` metadata for the ``tgt`` :class:`~iris.cube.Cube`. - - * prepared_items: + prepared_items : The list of :class:`~iris.common.resolve._PreparedItem` metadata that will be used to construct the auxiliary coordinates that will be attached to the resulting resolved :class:`~iris.cube.Cube`. - - Kwargs: - - * ignore_mismatch: + ignore_mismatch : optional When ``False``, an exception will be raised if a difference is detected between corresponding ``src`` and ``tgt`` coordinate ``points`` and/or ``bounds``. When ``True``, the coverage metadata is ignored i.e., a coordinate will not be constructed and @@ -1535,17 +1522,15 @@ def _prepare_common_dim_payload( each :class:`~iris.coords.DimCoord` to be constructed and attached to the resulting resolved :class:`~iris.cube.Cube`. - Args: - - * src_coverage: - The :class:`~iris.common.resolve._DimCoverage` metadata for the ``src`` :class:`~iris.cube.Cube`. - - * tgt_coverage: - The :class:`~iris.common.resolve._DimCoverage` metadata for the ``tgt`` :class:`~iris.cube.Cube`. - - Kwargs: - - * ignore_mismatch: + Parameters + ---------- + src_coverage : + The :class:`~iris.common.resolve._DimCoverage` metadata for the + ``src`` :class:`~iris.cube.Cube`. + tgt_coverage : + The :class:`~iris.common.resolve._DimCoverage` metadata for the + ``tgt`` :class:`~iris.cube.Cube`. + ignore_mismatch : optional When ``False``, an exception will be raised if a difference is detected between corresponding ``src`` and ``tgt`` :class:`~iris.coords.DimCoord` ``points`` and/or ``bounds``. When ``True``, the coverage metadata is ignored i.e., a :class:`~iris.coords.DimCoord` will not @@ -1599,29 +1584,26 @@ def _get_prepared_item( If a match is found, then a new `~iris.common.resolve._PreparedItem` is created and added to :attr:`~iris.common.resolve.Resolve.prepared_category` and returned. See ``from_local``. - Args: - - * metadata: + Parameters + ---------- + metadata : The target metadata of the prepared (or local) item to retrieve. - - * category_local: + category_local : The :class:`~iris.common.resolve._CategoryItems` containing the local metadata of either the ``src`` or ``tgt`` :class:`~iris.cube.Cube`. See ``from_local``. - - Kwargs: - - * from_src: + from_src : bool, optional Boolean stating whether the ``metadata`` is from the ``src`` (``True``) or ``tgt`` :class:`~iris.cube.Cube`. Defaults to ``True``. - - * from_local: + from_local: bool, optional Boolean controlling whether the ``metadata`` is used to search the ``category_local`` (``True``) or the :attr:`~iris.common.resolve.Resolve.prepared_category`. Defaults to ``False``. - Returns: + Returns + ------- + :class:`~iris.common.resolve._PreparedItem` The :class:`~iris.common.resolve._PreparedItem` matching the provided ``metadata``. """ @@ -1680,17 +1662,15 @@ def _prepare_factory_payload(self, cube, category_local, from_src=True): :attr:`~iris.common.resolve.Resolve.prepared_category` and therefore this is a legitimate reason to add the associated metadata of the local dependency to the ``prepared_category``. - Args: - - * cube: - The :class:`~iris.cube.Cube` that may contain an auxiliary factory to be prepared. - - * category_local: - The :class:`~iris.common.resolve._CategoryItems` of all metadata local to the provided ``cube``. - - Kwargs: - - * from_src: + Parameters + ---------- + cube : :class:`~iris.cube.Cube` + The :class:`~iris.cube.Cube` that may contain an auxiliary factory + to be prepared. + category_local : :class:`~iris.common.resolve._CategoryItems` + The :class:`~iris.common.resolve._CategoryItems` of all metadata + local to the provided ``cube``. + from_src : bool, optional, default=True Boolean stating whether the provided ``cube`` is either a ``src`` or ``tgt`` :class:`~iris.cube.Cube` - used to retrieve the appropriate metadata from a :class:`~iris.common.resolve._PreparedMetadata`. @@ -1755,19 +1735,22 @@ def _prepare_local_payload_aux(self, src_aux_coverage, tgt_aux_coverage): .. note:: - In general, lenient behaviour subscribes to the philosophy that it is easier to remove - metadata than it is to find then add metadata. To those ends, lenient behaviour supports - metadata richness by adding both local ``src`` and ``tgt`` auxiliary coordinates. - Alternatively, strict behaviour will only add a ``tgt`` local auxiliary coordinate that - spans dimensions not mapped to by the ``src`` e.g., extra ``tgt`` dimensions. - - Args: - - * src_aux_coverage: - The :class:`~iris.common.resolve.Resolve._AuxCoverage` for the ``src`` :class:`~iris.cube.Cube`. - - * tgt_aux_coverage: - The :class:~iris.common.resolve.Resolve._AuxCoverage` for the ``tgt`` :class:`~iris.cube.Cube`. + In general, lenient behaviour subscribes to the philosophy that + it is easier to remove metadata than it is to find then add + metadata. To those ends, lenient behaviour supports metadata + richness by adding both local ``src`` and ``tgt`` auxiliary + coordinates. Alternatively, strict behaviour will only add a + ``tgt`` local auxiliary coordinate that spans dimensions not + mapped to by the ``src`` e.g., extra ``tgt`` dimensions. + + Parameters + ---------- + src_aux_coverage : + The :class:`~iris.common.resolve.Resolve._AuxCoverage` for the + ``src`` :class:`~iris.cube.Cube`. + tgt_aux_coverage : + The :class:~iris.common.resolve.Resolve._AuxCoverage` for the + ``tgt`` :class:`~iris.cube.Cube`. """ # Determine whether there are tgt dimensions not mapped to by an @@ -1832,13 +1815,14 @@ def _prepare_local_payload_dim(self, src_dim_coverage, tgt_dim_coverage): is more liberal, whereas strict behaviour will only add a local ``tgt`` coordinate covering an unmapped "extra" ``tgt`` dimension/s. - Args: - - * src_dim_coverage: - The :class:`~iris.common.resolve.Resolve._DimCoverage` for the ``src`` :class:`~iris.cube.Cube`. - - * tgt_dim_coverage: - The :class:`~iris.common.resolve.Resolve._DimCoverage` for the ``tgt`` :class:`~iris.cube.Cube`. + Parameters + ---------- + src_dim_coverage : + The :class:`~iris.common.resolve.Resolve._DimCoverage` for the + ``src`` :class:`~iris.cube.Cube`. + tgt_dim_coverage : + The :class:`~iris.common.resolve.Resolve._DimCoverage` for the + ``tgt`` :class:`~iris.cube.Cube`. """ mapped_tgt_dims = self.mapping.values() @@ -1909,13 +1893,14 @@ def _prepare_local_payload_scalar(self, src_aux_coverage, tgt_aux_coverage): Alternatively, strict behaviour will only add a ``tgt`` local scalar coordinate when the ``src`` is a scalar :class:`~iris.cube.Cube` with no local scalar coordinates. - Args: - - * src_aux_coverage: - The :class:`~iris.common.resolve.Resolve._AuxCoverage` for the ``src`` :class:`~iris.cube.Cube`. - - * tgt_aux_coverage: - The :class:~iris.common.resolve.Resolve._AuxCoverage` for the ``tgt`` :class:`~iris.cube.Cube`. + Parameters + ---------- + src_aux_coverage : + The :class:`~iris.common.resolve.Resolve._AuxCoverage` for the + ``src`` :class:`~iris.cube.Cube`. + tgt_aux_coverage : + The :class:~iris.common.resolve.Resolve._AuxCoverage` for the + ``tgt`` :class:`~iris.cube.Cube`. """ # Add all local tgt scalar coordinates iff the src cube is a @@ -1954,19 +1939,20 @@ def _prepare_local_payload( and/or ``tgt`` :class:`~iris.cube.Cube` for each coordinate to be constructed and attached to the resulting resolved :class:`~iris.cube.Cube`. - Args: - - * src_dim_coverage: - The :class:`~iris.common.resolve.Resolve._DimCoverage` for the ``src`` :class:`~iris.cube.Cube`. - - * src_aux_coverage: - The :class:`~iris.common.resolve.Resolve._AuxCoverage` for the ``src`` :class:`~iris.cube.Cube`. - - * tgt_dim_coverage: - The :class:`~iris.common.resolve.Resolve._DimCoverage` for the ``tgt`` :class:`~iris.cube.Cube`. - - * tgt_aux_coverage: - The :class:~iris.common.resolve.Resolve._AuxCoverage` for the ``tgt`` :class:`~iris.cube.Cube`. + Parameters + ---------- + src_dim_coverage : + The :class:`~iris.common.resolve.Resolve._DimCoverage` for the + ``src`` :class:`~iris.cube.Cube`. + src_aux_coverage : + The :class:`~iris.common.resolve.Resolve._AuxCoverage` for the + ``src`` :class:`~iris.cube.Cube`. + tgt_dim_coverage : + The :class:`~iris.common.resolve.Resolve._DimCoverage` for the + ``tgt`` :class:`~iris.cube.Cube`. + tgt_aux_coverage : + The :class:~iris.common.resolve.Resolve._AuxCoverage` for the + ``tgt`` :class:`~iris.cube.Cube`. """ # Add local src/tgt dim coordinates. @@ -1994,31 +1980,26 @@ def _prepare_points_and_bounds( An exception will be raised if either the points or bounds are different, however appropriate lenient behaviour concessions are applied. - Args: - - * src_coord: + Parameters + ---------- + src_coord : The ``src`` :class:`~iris.cube.Cube` coordinate with metadata matching the ``tgt_coord``. - - * tgt_coord: + tgt_coord : The ``tgt`` :class`~iris.cube.Cube` coordinate with metadata matching the ``src_coord``. - - * src_dims: + src_dims : The dimension/s of the ``src_coord`` attached to the ``src`` :class:`~iris.cube.Cube`. - - * tgt_dims: + tgt_dims : The dimension/s of the ``tgt_coord`` attached to the ``tgt`` :class:`~iris.cube.Cube`. - - Kwargs: - - * ignore_mismatch: + ignore_mismatch : bool, optional For lenient behaviour only, don't raise an exception if there is a difference between the ``src`` and ``tgt`` coordinate points or bounds. Defaults to ``False``. - Returns: - Tuple of equivalent ``points`` and ``bounds``, otherwise ``None``. + Returns + ------- + Tuple of equivalent ``points`` and ``bounds``, otherwise ``None``. """ from iris.util import array_equal @@ -2262,16 +2243,13 @@ def cube(self, data, in_place=False): and ``rhs`` :class:`~iris.cube.Cube` operands, using the provided ``data``. - Args: - - * data: + Parameters + ---------- + data : The data payload for the resultant :class:`~iris.cube.Cube`, which **must match** the expected resolved :attr:`~iris.common.resolve.Resolve.shape`. - - Kwargs: - - * in_place: + in_place : optional If ``True``, the ``data`` is inserted into the ``tgt`` :class:`~iris.cube.Cube`. The existing metadata of the ``tgt`` :class:`~iris.cube.Cube` is replaced with the resolved metadata from @@ -2279,9 +2257,12 @@ def cube(self, data, in_place=False): a **new** :class:`~iris.cube.Cube` instance is returned. Default is ``False``. - Returns: - :class:`~iris.cube.Cube` + Returns + ------- + :class:`~iris.cube.Cube` + Notes + ----- .. note:: :class:`~iris.common.resolve.Resolve` will determine whether the @@ -2301,8 +2282,8 @@ def cube(self, data, in_place=False): match** the expected resolved :attr:`~iris.common.resolve.Resolve.shape`. - For example: - + Examples + -------- .. testsetup:: in-place import iris @@ -2493,7 +2474,7 @@ def mapped(self): >>> resolver.map_rhs_to_lhs False - """ # noqa: D214, D410, D411 + """ # noqa: D214, D407, D410, D411 result = None if self.mapping is not None: result = self._src_cube.ndim == len(self.mapping) @@ -2554,5 +2535,5 @@ def shape(self): >>> Resolve(cube2, cube1).shape (240, 37, 49) - """ # noqa: D214, D410, D411 + """ # noqa: D214, D407, D410, D411 return self._broadcast_shape diff --git a/lib/iris/coord_categorisation.py b/lib/iris/coord_categorisation.py index dbf27ea86e..a17dba6519 100644 --- a/lib/iris/coord_categorisation.py +++ b/lib/iris/coord_categorisation.py @@ -5,12 +5,13 @@ """Cube functions for coordinate categorisation. All the functions provided here add a new coordinate to a cube. - * The function :func:`add_categorised_coord` performs a generic - coordinate categorisation. - * The other functions all implement specific common cases - (e.g. :func:`add_day_of_month`). - Currently, these are all calendar functions, so they only apply to - "Time coordinates". + +* The function :func:`add_categorised_coord` performs a generic + coordinate categorisation. +* The other functions all implement specific common cases + (e.g. :func:`add_day_of_month`). + Currently, these are all calendar functions, so they only apply to + "Time coordinates". """ @@ -28,21 +29,18 @@ def add_categorised_coord(cube, name, from_coord, category_function, units="1"): Make a new :class:`iris.coords.AuxCoord` from mapped values, and add it to the cube. - Args: - - * cube (:class:`iris.cube.Cube`): - the cube containing 'from_coord'. The new coord will be added into it. - * name (string): + Parameters + ---------- + cube : :class:`iris.cube.Cube` + The cube containing 'from_coord'. The new coord will be added into it. + name : str name of the created coordinate - * from_coord (:class:`iris.coords.Coord` or string): + from_coord : :class:`iris.coords.Coord` or str coordinate in 'cube', or the name of one - * category_function (callable): + category_function : callable function(coordinate, value), returning a category value for a coordinate point-value - - Kwargs: - - * units: + units : str, optional, default="1" units of the category value, typically 'no_unit' or '1'. """ # Interpret coord, if given as a name @@ -90,15 +88,16 @@ def vectorised_fn(*args): def _pt_date(coord, time): """Return the datetime of a time-coordinate point. - Args: - - * coord (Coord): + Parameters + ---------- + coord : Coord coordinate (must be Time-type) - * time (float): + time : float value of a coordinate point - Returns: - cftime.datetime + Returns + ------- + cftime.datetime """ # NOTE: All of the currently defined categorisation functions are @@ -304,19 +303,16 @@ def add_season(cube, coord, name="season", seasons=("djf", "mam", "jja", "son")) """Add a categorical season-of-year coordinate, with user specified seasons. - Args: - - * cube (:class:`iris.cube.Cube`): + Parameters + ---------- + cube : :class:`iris.cube.Cube` The cube containing 'coord'. The new coord will be added into it. - * coord (:class:`iris.coords.Coord` or string): + coord : :class:`iris.coords.Coord` or str Coordinate in 'cube', or its name, representing time. - - Kwargs: - - * name (string): + name : str, optional Name of the created coordinate. Defaults to "season". - * seasons (:class:`list` of strings): + seasons : :class:`list` of str, optional List of seasons defined by month abbreviations. Each month must appear once and only once. Defaults to standard meteorological seasons ('djf', 'mam', 'jja', 'son'). @@ -343,19 +339,16 @@ def add_season_number( """Add a categorical season-of-year coordinate, values 0..N-1 where N is the number of user specified seasons. - Args: - - * cube (:class:`iris.cube.Cube`): + Parameters + ---------- + cube : :class:`iris.cube.Cube` The cube containing 'coord'. The new coord will be added into it. - * coord (:class:`iris.coords.Coord` or string): + coord : :class:`iris.coords.Coord` or str Coordinate in 'cube', or its name, representing time. - - Kwargs: - - * name (string): + name : str, optional Name of the created coordinate. Defaults to "season_number". - * seasons (:class:`list` of strings): + seasons : :class:`list` of str, optional List of seasons defined by month abbreviations. Each month must appear once and only once. Defaults to standard meteorological seasons ('djf', 'mam', 'jja', 'son'). @@ -429,19 +422,16 @@ def add_season_membership(cube, coord, season, name="season_membership"): The coordinate has the value True for every time that is within the given season, and the value False otherwise. - Args: - - * cube (:class:`iris.cube.Cube`): + Parameters + ---------- + cube : :class:`iris.cube.Cube` The cube containing 'coord'. The new coord will be added into it. - * coord (:class:`iris.coords.Coord` or string): + coord : :class:`iris.coords.Coord` or str Coordinate in 'cube', or its name, representing time. - * season (string): + season : str Season defined by month abbreviations. - - Kwargs: - - * name (string): + name : str, optional Name of the created coordinate. Defaults to "season_membership". """ diff --git a/lib/iris/coords.py b/lib/iris/coords.py index 9336f1f4c7..a1595530f9 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -71,23 +71,20 @@ def __init__( ): """Constructs a single dimensional metadata object. - Args: - - * values: + Parameters + ---------- + values : The values of the dimensional metadata. - - Kwargs: - - * standard_name: + standard_name : optional, default=None CF standard name of the dimensional metadata. - * long_name: + long_name : optional, default=None Descriptive name of the dimensional metadata. - * var_name: + var_name : optional, default=None The netCDF variable name for the dimensional metadata. - * units + units : optional, default=None The :class:`~cf_units.Unit` of the dimensional metadata's values. Can be a string, which will be converted to a Unit object. - * attributes + attributes : optional, default=None A dictionary containing other cf and user-defined attributes. """ @@ -164,9 +161,9 @@ def __getitem__(self, keys): def copy(self, values=None): """Returns a copy of this dimensional metadata object. - Kwargs: - - * values + Parameters + ---------- + values : optional An array of values for the new dimensional metadata object. This may be a different shape to the original values array being copied. @@ -287,7 +284,7 @@ def summary( linewidth : int or None, default = None Character-width controlling line splitting of array outputs. If unset, defaults to ``numpy.get_printoptions['linewidth']``\ . - edgeitems : int = 2 + edgeitems : int, default=2 Controls truncated array output. Overrides ``numpy.getprintoptions['edgeitems']``\ . precision : int or None, default = None @@ -303,7 +300,8 @@ def summary( result : str Output text, with embedded newlines when :attr:`shorten`\ =False. - + Notes + ----- .. note:: Arrays are formatted using :meth:`numpy.array2string`. Some aspects of the array formatting are controllable in the usual way, via @@ -809,13 +807,15 @@ def xml_element(self, doc): """Create the :class:`xml.dom.minidom.Element` that describes this :class:`_DimensionalMetadata`. - Args: - - * doc: + Parameters + ---------- + doc : The parent :class:`xml.dom.minidom.Document`. - Returns: - The :class:`xml.dom.minidom.Element` that will describe this + Returns + ------- + :class:`xml.dom.minidom.Element` + :class:`xml.dom.minidom.Element` that will describe this :class:`_DimensionalMetadata`. """ @@ -929,23 +929,20 @@ def __init__( ): """Constructs a single ancillary variable. - Args: - - * data: + Parameters + ---------- + data : The values of the ancillary variable. - - Kwargs: - - * standard_name: + standard_name : optional, default=None CF standard name of the ancillary variable. - * long_name: + long_name : optional, default=None Descriptive name of the ancillary variable. - * var_name: + var_name : optional, default=None The netCDF variable name for the ancillary variable. - * units + units : optional, default=None The :class:`~cf_units.Unit` of the ancillary variable's values. Can be a string, which will be converted to a Unit object. - * attributes + attributes : optional, default=None A dictionary containing other cf and user-defined attributes. """ @@ -980,8 +977,9 @@ def lazy_data(self): If the data have already been loaded for the ancillary variable, the returned Array will be a new lazy array wrapper. - Returns: - A lazy array, representing the ancillary variable data array. + Returns + ------- + A lazy array, representing the ancillary variable data array. """ return super()._lazy_values() @@ -1028,27 +1026,24 @@ def __init__( ): """Constructs a single cell measure. - Args: - - * data: + Parameters + ---------- + data : The values of the measure for each cell. Either a 'real' array (:class:`numpy.ndarray`) or a 'lazy' array (:class:`dask.array.Array`). - - Kwargs: - - * standard_name: + standard_name : optional, default=None CF standard name of the coordinate. - * long_name: + long_name : optional, default=None Descriptive name of the coordinate. - * var_name: + var_name : optional, default=None The netCDF variable name for the coordinate. - * units + units : optional, default=None The :class:`~cf_units.Unit` of the coordinate's values. Can be a string, which will be converted to a Unit object. - * attributes + attributes : optional, default=None A dictionary containing other CF and user-defined attributes. - * measure + measure : optional A string describing the type of measure. Supported values are 'area' and 'volume'. The default is 'area'. @@ -1094,12 +1089,14 @@ def xml_element(self, doc): """Create the :class:`xml.dom.minidom.Element` that describes this :class:`CellMeasure`. - Args: - - * doc: + Parameters + ---------- + doc : The parent :class:`xml.dom.minidom.Document`. - Returns: + Returns + ------- + :class:`xml.dom.minidom.Element` The :class:`xml.dom.minidom.Element` that describes this :class:`CellMeasure`. @@ -1139,25 +1136,19 @@ def __new__( """Create a CoordExtent for the specified coordinate and range of values. - Args: - - * name_or_coord + Parameters + ---------- + name_or_coord : Either a coordinate name or a coordinate, as defined in :meth:`iris.cube.Cube.coords()`. - - * minimum + minimum : The minimum value of the range to select. - - * maximum + maximum : The maximum value of the range to select. - - Kwargs: - - * min_inclusive + min_inclusive : optional If True, coordinate values equal to `minimum` will be included in the selection. Default is True. - - * max_inclusive + max_inclusive : optional If True, coordinate values equal to `maximum` will be included in the selection. Default is True. @@ -1193,12 +1184,14 @@ def _get_2d_coord_bound_grid(bounds): # 0-0-0-0-1 # 3-3-3-3-2 - Args: - * bounds: (array) + Parameters + ---------- + bounds : array Coordinate bounds array of shape (Y, X, 4) - Returns: - * grid: (array) + Returns + ------- + array Grid of shape (Y+1, X+1) """ @@ -1471,26 +1464,25 @@ def __init__( coord_system=None, climatological=False, ): - """Coordinate abstract base class. As of ``v3.0.0`` you **cannot** create an instance of :class:`Coord`. + """Coordinate abstract base class. - Args: + As of ``v3.0.0`` you **cannot** create an instance of :class:`Coord`. - * points: + Parameters + ---------- + points : The values (or value in the case of a scalar coordinate) for each cell of the coordinate. - - Kwargs: - - * standard_name: + standard_name : optional, default=None CF standard name of the coordinate. - * long_name: + long_name : optional, default=None Descriptive name of the coordinate. - * var_name: + var_name : optional, default=None The netCDF variable name for the coordinate. - * units + units : optional, default=None The :class:`~cf_units.Unit` of the coordinate's values. Can be a string, which will be converted to a Unit object. - * bounds + bounds : optional, default=None An array of values describing the bounds of each cell. Given n bounds for each cell, the shape of the bounds array should be points.shape + (n,). For example, a 1D coordinate with 100 points @@ -1498,13 +1490,13 @@ def __init__( (100, 2) Note if the data is a climatology, `climatological` should be set. - * attributes + attributes : optional, default=None A dictionary containing other CF and user-defined attributes. - * coord_system + coord_system : optional, default=None A :class:`~iris.coord_systems.CoordSystem` representing the coordinate system of the coordinate, e.g., a :class:`~iris.coord_systems.GeogCS` for a longitude coordinate. - * climatological (bool): + climatological : bool, optional, default=False When True: the coordinate is a NetCDF climatological time axis. When True: saving in NetCDF will give the coordinate variable a 'climatology' attribute and will create a boundary variable called @@ -1541,18 +1533,19 @@ def __init__( def copy(self, points=None, bounds=None): """Returns a copy of this coordinate. - Kwargs: - - * points: A points array for the new coordinate. - This may be a different shape to the points of the coordinate - being copied. - - * bounds: A bounds array for the new coordinate. - Given n bounds for each cell, the shape of the bounds array - should be points.shape + (n,). For example, a 1d coordinate - with 100 points and two bounds per cell would have a bounds - array of shape (100, 2). - + points : + A points array for the new coordinate. + This may be a different shape to the points of the coordinate + being copied. + bounds : + A bounds array for the new coordinate. + Given n bounds for each cell, the shape of the bounds array + should be points.shape + (n,). For example, a 1d coordinate + with 100 points and two bounds per cell would have a bounds + array of shape (100, 2). + + Notes + ----- .. note:: If the points argument is specified and bounds are not, the resulting coordinate will have no bounds. @@ -1709,8 +1702,9 @@ def lazy_points(self): If the data have already been loaded for the coord, the returned Array will be a new lazy array wrapper. - Returns: - A lazy array, representing the coord points array. + Returns + ------- + A lazy array, representing the coord points array. """ return super()._lazy_values() @@ -1725,7 +1719,9 @@ def lazy_bounds(self): If the data have already been loaded for the coord, the returned Array will be a new lazy array wrapper. - Returns: + Returns + ------- + lazy array A lazy array representing the coord bounds array or `None` if the coord does not have bounds. @@ -1860,18 +1856,18 @@ def _sanity_check_bounds(self): def _discontiguity_in_bounds(self, rtol=1e-5, atol=1e-8): """Checks that the bounds of the coordinate are contiguous. - Kwargs: - * rtol: (float) + rtol : float, optional Relative tolerance that is used when checking contiguity. Defaults to 1e-5. - * atol: (float) + atol : float, optional Absolute tolerance that is used when checking contiguity. Defaults to 1e-8. - Returns: - * contiguous: (boolean) + Returns + ------- + contiguous : bool True if there are no discontiguities. - * diffs: (array or tuple of arrays) + diffs : array or tuple of arrays A boolean array or tuple of boolean arrays which are true where there are discontiguities between neighbouring bounds. If self is a 2D coord of shape (Y, X), a pair of arrays is returned, where @@ -1959,15 +1955,16 @@ def is_contiguous(self, rtol=1e-05, atol=1e-08): it, and the upper left corner of each cell aligns with the lower left corner of the cell above it. - Args: - - * rtol: + Parameters + ---------- + rtol : optional The relative tolerance parameter (default is 1e-05). - * atol: + atol : optional The absolute tolerance parameter (default is 1e-08). - Returns: - Boolean. + Returns + ------- + bool """ if self.has_bounds(): @@ -2048,19 +2045,20 @@ def is_compatible(self, other, ignore=None): :attr:`iris.coords.Coord.coord_system` and :attr:`iris.coords.Coord.attributes` that are present in both objects. - Args: - - * other: + Parameters + ---------- + other : An instance of :class:`iris.coords.Coord`, :class:`iris.common.CoordMetadata` or :class:`iris.common.DimCoordMetadata`. - * ignore: + ignore : optional A single attribute key or iterable of attribute keys to ignore when comparing the coordinates. Default is None. To ignore all attributes, set this to other.attributes. - Returns: - Boolean. + Returns + ------- + bool """ compatible = False @@ -2216,15 +2214,18 @@ def serialize(x): def _guess_bounds(self, bound_position=0.5): """Return bounds for this coordinate based on its points. - Kwargs: - - * bound_position: + Parameters + ---------- + bound_position : optional, default=0.5 The desired position of the bounds relative to the position of the points. - Returns: - A numpy array of shape (len(self.points), 2). + Returns + ------- + A numpy array of shape (len(self.points), 2). + Notes + ----- .. note:: This method only works for coordinates with ``coord.ndim == 1``. @@ -2285,12 +2286,14 @@ def guess_bounds(self, bound_position=0.5): With irregular points, the first and last cells are given the same widths as the ones next to them. - Kwargs: - - * bound_position: + Parameters + ---------- + bound_position : optional, default=0.5 The desired position of the bounds relative to the position of the points. + Notes + ----- .. note:: An error is raised if the coordinate already has bounds, is not @@ -2311,9 +2314,9 @@ def intersect(self, other, return_indices=False): Both coordinates must be compatible as defined by :meth:`~iris.coords.Coord.is_compatible`. - Kwargs: - - * return_indices: + Parameters + ---------- + return_indices : optional, default=False If True, changes the return behaviour to return the intersection indices for the "self" coordinate. @@ -2449,12 +2452,14 @@ def xml_element(self, doc): """Create the :class:`xml.dom.minidom.Element` that describes this :class:`Coord`. - Args: - - * doc: + Parameters + ---------- + doc : The parent :class:`xml.dom.minidom.Document`. - Returns: + Returns + ------- + :class:`xml.dom.minidom.Element` The :class:`xml.dom.minidom.Element` that will describe this :class:`DimCoord`. @@ -2480,7 +2485,9 @@ def _xml_id_extra(self, unique_value): class DimCoord(Coord): - """A coordinate that is 1D, and numeric, with values that have a strict monotonic ordering. Missing values are not + """A coordinate that is 1D, and numeric. + + With values that have a strict monotonic ordering. Missing values are not permitted in a :class:`DimCoord`. """ @@ -2507,18 +2514,15 @@ def from_regular( The majority of the arguments are defined as for :class:`Coord`, but those which differ are defined below. - Args: - - * zeroth: + Parameters + ---------- + zeroth : The value *prior* to the first point value. - * step: + step : The numeric difference between successive point values. - * count: + count : The number of point values. - - Kwargs: - - * with_bounds: + with_bounds : optional If True, the resulting DimCoord will possess bound values which are equally spaced around the points. Otherwise no bounds values will be defined. Defaults to False. @@ -2566,25 +2570,22 @@ def __init__( Missing values are not permitted. - Args: - - * points: + Parameters + ---------- + points : 1D numpy array-like of values (or single value in the case of a scalar coordinate) for each cell of the coordinate. The values must be strictly monotonic and masked values are not allowed. - - Kwargs: - - * standard_name: + standard_name : optional, default=None CF standard name of the coordinate. - * long_name: + long_name : optional, default=None Descriptive name of the coordinate. - * var_name: + var_name : optional, default=None The netCDF variable name for the coordinate. - * units: + units : :class:`~cf_units.Unit`, optional, default=None The :class:`~cf_units.Unit` of the coordinate's values. Can be a string, which will be converted to a Unit object. - * bounds: + bounds : optional, default=None An array of values describing the bounds of each cell. Given n bounds and m cells, the shape of the bounds array should be (m, n). For each bound, the values must be strictly monotonic along @@ -2595,16 +2596,16 @@ def __init__( in the same direction. Masked values are not allowed. Note if the data is a climatology, `climatological` should be set. - * attributes: + attributes : optional, default=None A dictionary containing other CF and user-defined attributes. - * coord_system: + coord_system : :class:`~iris.coord_systems.CoordSystem`, optional, default=None A :class:`~iris.coord_systems.CoordSystem` representing the coordinate system of the coordinate, e.g., a :class:`~iris.coord_systems.GeogCS` for a longitude coordinate. - * circular (bool): + circular : bool, optional, default=False Whether the coordinate wraps by the :attr:`~iris.coords.DimCoord.units.modulus` i.e., the longitude coordinate wraps around the full great circle. - * climatological (bool): + climatological : bool, optional, default=False When True: the coordinate is a NetCDF climatological time axis. When True: saving in NetCDF will give the coordinate variable a 'climatology' attribute and will create a boundary variable called @@ -2698,12 +2699,15 @@ def collapsed(self, dims_to_collapse=None): return coord def _new_points_requirements(self, points): - """Confirm that a new set of coord points adheres to the requirements for + """Confirm that a new set of coord points adheres to the requirements. + + Confirm that a new set of coord points adheres to the requirements for :class:`~iris.coords.DimCoord` points, being: - * points are scalar or 1D, - * points are numeric, - * points are not masked, and - * points are monotonic. + + * points are scalar or 1D, + * points are numeric, + * points are not masked, and + * points are monotonic. """ if points.ndim not in (0, 1): @@ -2744,12 +2748,15 @@ def _values(self, points): points.flags.writeable = False def _new_bounds_requirements(self, bounds): - """Confirm that a new set of coord bounds adheres to the requirements for + """Confirm that a new set of coord bounds adheres to the requirements. + + Confirm that a new set of coord bounds adheres to the requirements for :class:`~iris.coords.DimCoord` bounds, being: - * bounds are compatible in shape with the points - * bounds are numeric, - * bounds are not masked, and - * bounds are monotonic in the first dimension. + + * bounds are compatible in shape with the points + * bounds are numeric, + * bounds are not masked, and + * bounds are monotonic in the first dimension. Also reverse the order of the second dimension if necessary to match the first dimension's direction. I.e. both should increase or both should @@ -2840,12 +2847,14 @@ def xml_element(self, doc): """Create the :class:`xml.dom.minidom.Element` that describes this :class:`DimCoord`. - Args: - - * doc: + Parameters + ---------- + doc : The parent :class:`xml.dom.minidom.Document`. - Returns: + Returns + ------- + :class:`xml.dom.minidom.Element` The :class:`xml.dom.minidom.Element` that describes this :class:`DimCoord`. @@ -2862,24 +2871,21 @@ class AuxCoord(Coord): def __init__(self, *args, **kwargs): """Create a coordinate with **mutable** points and bounds. - Args: - - * points: + Parameters + ---------- + points : The values (or value in the case of a scalar coordinate) for each cell of the coordinate. - - Kwargs: - - * standard_name: + standard_name : optional CF standard name of the coordinate. - * long_name: + long_name : optional Descriptive name of the coordinate. - * var_name: + var_name : optional The netCDF variable name for the coordinate. - * units + unit : :class:`~cf_units.Unit`, optional The :class:`~cf_units.Unit` of the coordinate's values. Can be a string, which will be converted to a Unit object. - * bounds + bounds : optional An array of values describing the bounds of each cell. Given n bounds for each cell, the shape of the bounds array should be points.shape + (n,). For example, a 1D coordinate with 100 points @@ -2887,13 +2893,13 @@ def __init__(self, *args, **kwargs): (100, 2) Note if the data is a climatology, `climatological` should be set. - * attributes + attributes : optional A dictionary containing other CF and user-defined attributes. - * coord_system + coord_system : :class:`~iris.coord_systems.CoordSystem`, optional A :class:`~iris.coord_systems.CoordSystem` representing the coordinate system of the coordinate, e.g., a :class:`~iris.coord_systems.GeogCS` for a longitude coordinate. - * climatological (bool): + climatological bool, optional When True: the coordinate is a NetCDF climatological time axis. When True: saving in NetCDF will give the coordinate variable a 'climatology' attribute and will create a boundary variable called @@ -2936,22 +2942,17 @@ class CellMethod(iris.util._OrderedHashable): def __init__(self, method, coords=None, intervals=None, comments=None): """Call Method initialise. - Args: - - * method: + Parameters + ---------- + method : The name of the operation. - - Kwargs: - - * coords: + coords : :class:`.Coord` instances, optional A single instance or sequence of :class:`.Coord` instances or coordinate names. - - * intervals: + intervals : optional A single string, or a sequence strings, describing the intervals within the cell method. - - * comments: + comments : optional A single string, or a sequence strings, containing any additional comments. @@ -3023,12 +3024,14 @@ def xml_element(self, doc): """Create the :class:`xml.dom.minidom.Element` that describes this :class:`CellMethod`. - Args: - - * doc: + Parameters + ---------- + doc : The parent :class:`xml.dom.minidom.Document`. - Returns: + Returns + ------- + :class:`xml.dom.minidom.Element` The :class:`xml.dom.minidom.Element` that describes this :class:`CellMethod`. diff --git a/lib/iris/cube.py b/lib/iris/cube.py index 1199831b7b..d414cc3e09 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -80,9 +80,9 @@ def merged(self, unique=False): """Returns a new :class:`_CubeFilter` by merging the list of cubes. - Kwargs: - - * unique: + Parameters + ---------- + unique : bool, optional, default=False If True, raises `iris.exceptions.DuplicateDataError` if duplicate cubes are detected. @@ -131,9 +131,9 @@ def merged(self, unique=False): """Returns a new :class:`_CubeFilterCollection` by merging all the cube lists of this collection. - Kwargs: - - * unique: + Parameters + ---------- + unique : bool, optional, default=False If True, raises `iris.exceptions.DuplicateDataError` if duplicate cubes are detected. @@ -227,10 +227,11 @@ def append(self, cube): def extend(self, other_cubes): """Extend cubelist by appending the cubes contained in other_cubes. - Args: - - * other_cubes: + Parameters + ---------- + other_cubes : A cubelist or other sequence of cubes. + """ super(CubeList, self).extend(CubeList(other_cubes)) @@ -268,9 +269,9 @@ def extract(self, constraints): **n** when filtered with **m** constraints can generate a maximum of **m * n** cubes. - Args: - - * constraints (:class:`~iris.Constraint` or iterable of constraints): + Parameters + ---------- + constraints : :class:`~iris.Constraint` or iterable of constraints A single constraint or an iterable. """ @@ -280,13 +281,14 @@ 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`): + Parameters + ---------- + constraint : :class:`~iris.Constraint` The constraint to extract with. - .. see also:: - :meth:`~iris.cube.CubeList.extract` + See Also + -------- + :meth:`~iris.cube.CubeList.extract` """ # Just validate this, so we can accept strings etc, but not multiples. @@ -300,13 +302,14 @@ def extract_cubes(self, constraints): Each constraint must produce exactly one cube, otherwise an error is raised. - Args: - - * constraints (iterable of, or single, :class:`~iris.Constraint`): + Parameters + ---------- + constraints : iter of, or single, :class:`~iris.Constraint` The constraints to extract with. - .. see also:: - :meth:`~iris.cube.CubeList.extract` + See Also + -------- + :meth:`~iris.cube.CubeList.extract` """ return self._extract_and_merge( @@ -355,9 +358,9 @@ def extract_overlapping(self, coord_names): where the coordinates overlap, for the coordinates in coord_names. - Args: - - * coord_names: + Parameters + ---------- + coord_names : str or list of str A string or list of strings of the names of the coordinates over which to perform the extraction. @@ -417,12 +420,14 @@ def merge(self, unique=True): """Returns the :class:`CubeList` resulting from merging this :class:`CubeList`. - Kwargs: - - * unique: + Parameters + ---------- + unique : bool, optional, default=True If True, raises `iris.exceptions.DuplicateDataError` if duplicate cubes are detected. + Examples + -------- This combines cubes with different values of an auxiliary scalar coordinate, by constructing a new dimension. @@ -436,7 +441,7 @@ def merge(self, unique=True): c2 = c1.copy() c2.coord('y_vals').points = [200] - For example:: + :: >>> print(c1) some_parameter / (unknown) (x_vals: 3) @@ -522,25 +527,22 @@ def concatenate_cube( `Cube`, a :class:`~iris.exceptions.ConcatenateError` will be raised describing the reason for the failure. - Kwargs: - - * check_aux_coords + Parameters + ---------- + check_aux_coords : bool, optional, default=True Checks if the points and bounds of 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 + check_cell_measures : bool, optional, default=True Checks if the data of 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 + check_ancils : bool, optional, default=True Checks if the data of 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. - - * check_derived_coords + check_derived_coords : bool, optional, default=True Checks if the points and bounds of derived coordinates of the cubes match. This check is not applied to derived coordinates that span the dimension the concatenation is occurring along. Note that @@ -549,6 +551,8 @@ def concatenate_cube( coordinates used to derive the coordinates can be ignored with `check_aux_coords`. Defaults to True. + Notes + ----- .. note:: Concatenation cannot occur along an anonymous dimension. @@ -596,25 +600,22 @@ def concatenate( ): """Concatenate the cubes over their common dimensions. - Kwargs: - - * check_aux_coords + Parameters + ---------- + check_aux_coords : bool, optional, default=True Checks if the points and bounds of 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 + check_cell_measures : bool, optional, default=True Checks if the data of 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 + check_ancils : bool, optional, default=True Checks if the data of 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. - - * check_derived_coords + check_derived_coords : bool, optional, default=True Checks if the points and bounds of derived coordinates of the cubes match. This check is not applied to derived coordinates that span the dimension the concatenation is occurring along. Note that @@ -623,10 +624,14 @@ def concatenate( coordinates used to derive the coordinates can be ignored with `check_aux_coords`. Defaults to True. - Returns: + Returns + ------- + :class:`iris.cube.CubeList` A new :class:`iris.cube.CubeList` of concatenated :class:`iris.cube.Cube` instances. + Notes + ----- This combines cubes with a common dimension coordinate, but occupying different regions of the coordinate value. The cubes are joined across that dimension. @@ -1132,12 +1137,13 @@ def _sort_xml_attrs(cls, doc): 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`. + Parameters + ---------- + doc : :class:`xml.dom.minidom.Document`. - Returns: + Returns + ------- + :class:`xml.dom.minidom.Document` The :class:`xml.dom.minidom.Document` with sorted element attributes. @@ -1196,9 +1202,9 @@ def __init__( Not typically used - normally cubes are obtained by loading data (e.g. :func:`iris.load`) or from manipulating existing cubes. - Args: - - * data + Parameters + ---------- + data : This object defines the shape of the cube and the phenomenon value in each cell. @@ -1208,39 +1214,39 @@ def __init__( array_like (as described in :func:`numpy.asarray`). See :attr:`Cube.data`. - - Kwargs: - - * standard_name + standard_name : optional, default=None The standard name for the Cube's data. - * long_name + long_name : optional, default=None An unconstrained description of the cube. - * var_name + var_name : optional, default=None The NetCDF variable name for the cube. - * units + units : optional, default=None The unit of the cube, e.g. ``"m s-1"`` or ``"kelvin"``. - * attributes + attributes : optional, default=None A dictionary of cube attributes - * cell_methods + cell_methods : optional, default=None A tuple of CellMethod objects, generally set by Iris, e.g. ``(CellMethod("mean", coords='latitude'), )``. - * dim_coords_and_dims + dim_coords_and_dims : optional, default=None A list of coordinates with scalar dimension mappings, e.g ``[(lat_coord, 0), (lon_coord, 1)]``. - * aux_coords_and_dims + aux_coords_and_dims : optional, default=None A list of coordinates with dimension mappings, e.g ``[(lat_coord, 0), (lon_coord, (0, 1))]``. See also :meth:`Cube.add_dim_coord()` and :meth:`Cube.add_aux_coord()`. - * aux_factories + aux_factories : optional, default=None A list of auxiliary coordinate factories. See :mod:`iris.aux_factory`. - * cell_measures_and_dims + cell_measures_and_dims : optional, default=None A list of CellMeasures with dimension mappings. - * ancillary_variables_and_dims + ancillary_variables_and_dims : optional, default=None A list of AncillaryVariables with dimension mappings. - For example:: + Examples + -------- + :: + >>> from iris.coords import DimCoord >>> from iris.cube import Cube >>> latitude = DimCoord(np.linspace(-90, 90, 4), @@ -1379,19 +1385,22 @@ def is_compatible(self, other, ignore=None): :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: + Parameters + ---------- + other : An instance of :class:`iris.cube.Cube` or :class:`iris.cube.CubeMetadata`. - * ignore: + ignore : optional, default=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. + Returns + ------- + bool + Notes + ----- .. seealso:: :meth:`iris.util.describe_diff()` @@ -1467,22 +1476,24 @@ def add_cell_method(self, cell_method): def add_aux_coord(self, coord, data_dims=None): """Adds a CF auxiliary coordinate to the cube. - Args: - - * coord + Parameters + ---------- + coord : The :class:`iris.coords.DimCoord` or :class:`iris.coords.AuxCoord` instance to add to the cube. - - Kwargs: - - * data_dims + data_dims : optional, default=None 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. + Raises + ------ + ValueError + Raises a ValueError if a coordinate with identical metadata already + exists on the cube. - See also :meth:`Cube.remove_coord()`. + See Also + -------- + :meth:`Cube.remove_coord()`. """ if self.coords(coord): # TODO: just fail on duplicate object @@ -1574,9 +1585,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 + Parameters + ---------- + aux_factory : The :class:`iris.aux_factory.AuxCoordFactory` instance to add. """ @@ -1606,22 +1617,23 @@ 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 + Parameters + ---------- + cell_measure : The :class:`iris.coords.CellMeasure` instance to add to the cube. - - Kwargs: - - * data_dims + data_dims : optional, default=None 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. + Raises + ------ + ValueError + Raises a ValueError if a cell_measure with identical metadata already + exists on the cube. - See also + See Also + -------- :meth:`Cube.remove_cell_measure()`. """ @@ -1638,20 +1650,20 @@ 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 + Parameters + ---------- + ancillary_variable : The :class:`iris.coords.AncillaryVariable` instance to be added to the cube - - Kwargs: - - * data_dims + data_dims : optional, default=None 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. + Raises + ------ + ValueError + Raises a ValueError if an ancillary variable with identical metadata + already exists on the cube. """ if self.ancillary_variables(ancillary_variable): @@ -1668,17 +1680,22 @@ 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 + Parameters + ---------- + dim_coord : :class:`iris.coords.DimCoord` The :class:`iris.coords.DimCoord` instance to add to the cube. - * data_dim + 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. + Raises + ------ + ValueError + Raises a ValueError if a coordinate with identical metadata already + exists on the cube or if a coord already exists for the + given dimension. + See Also + -------- See also :meth:`Cube.remove_coord()`. """ @@ -1752,13 +1769,15 @@ def _remove_coord(self, coord): def remove_coord(self, coord): """Removes a coordinate from the cube. - Args: - - * coord (string or coord) + Parameters + ---------- + coord : str or coord The (name of the) coordinate to remove from the cube. - See also :meth:`Cube.add_dim_coord()` - and :meth:`Cube.add_aux_coord()`. + See Also + -------- + :meth:`Cube.add_dim_coord()` + :meth:`Cube.add_aux_coord()` """ coord = self.coord(coord) @@ -1770,28 +1789,30 @@ 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) + Parameters + ---------- + cell_measure : str 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`. + * (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. + * (b) a cell_measure instance with metadata equal to that of + the desired cell_measures. + Notes + ----- .. 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()` + See Also + -------- + :meth:`Cube.add_cell_measure()` """ cell_measure = self.cell_measure(cell_measure) @@ -1805,9 +1826,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) + Parameters + ---------- + ancillary_variable : str or AncillaryVariable The (name of the) AncillaryVariable to remove from the cube. """ @@ -1842,9 +1863,9 @@ def coord_dims(self, coord): instance need not exist on the cube, and may contain different coordinate values. - Args: - - * coord (string or coord) + Parameters + ---------- + coord : str or coord The (name of the) coord to look for. """ @@ -1898,7 +1919,9 @@ def cell_measure_dims(self, cell_measure): """Returns a tuple of the data dimensions relevant to the given CellMeasure. - * cell_measure (string or CellMeasure) + Parameters + ---------- + cell_measure : str or CellMeasure The (name of the) cell measure to look for. """ @@ -1919,7 +1942,9 @@ def ancillary_variable_dims(self, ancillary_variable): """Returns a tuple of the data dimensions relevant to the given AncillaryVariable. - * ancillary_variable (string or AncillaryVariable) + Parameters + ---------- + ancillary_variable : str or AncillaryVariable The (name of the) AncillaryVariable to look for. """ @@ -1944,20 +1969,22 @@ def aux_factory(self, name=None, standard_name=None, long_name=None, var_name=No """Returns the single coordinate factory that matches the criteria, or raises an error if not found. - Kwargs: - - * name + Parameters + ---------- + name : optional, default=None If not None, matches against factory.name(). - * standard_name + standard_name : optional, default=None The CF standard name of the desired coordinate factory. If None, does not check for standard name. - * long_name + long_name : optional, default=None An unconstrained description of the coordinate factory. If None, does not check for long_name. - * var_name + var_name : optional, default=None The NetCDF variable name of the desired coordinate factory. If None, does not check for var_name. + Notes + ----- .. note:: If the arguments given do not result in precisely 1 coordinate @@ -2019,13 +2046,9 @@ def coords( r"""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: + Parameters + ---------- + name_or_coord : optional, default=None Either, * a :attr:`~iris.common.mixin.CFVariableMixin.standard_name`, @@ -2036,57 +2059,52 @@ def coords( * 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: + standard_name : optional, default=None The CF standard name of the desired coordinate. If ``None``, does not check for ``standard name``. - - * long_name: + long_name : optional, default=None An unconstrained description of the coordinate. If ``None``, does not check for ``long_name``. - - * var_name: + var_name : optional, default=None The NetCDF variable name of the desired coordinate. If ``None``, does not check for ``var_name``. - - * attributes: + attributes : optional, default=None A dictionary of attributes desired on the coordinates. If ``None``, does not check for ``attributes``. - - * axis: + axis : optional, default=None 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: + contains_dimension : optional, default=None The desired coordinate contains the data dimension. If ``None``, does not check for the dimension. - - * dimensions: + dimensions : optional, default=None 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: + coord_system : optional, default=None Whether the desired coordinates have a coordinate system equal to the given coordinate system. If ``None``, no check is done. - - * dim_coords: + dim_coords : optional, default=None 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: + mesh_coords : optional, default=None Set to ``True`` to return only coordinates which are - :class:`~iris.experimental.ugrid.MeshCoord`\\ s. + :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. + Returns + ------- + A list containing zero or more coordinates matching the provided criteria. + + See Also + -------- + :meth:`Cube.coord` for matching exactly one coordinate. + """ coords_and_factories = [] @@ -2185,18 +2203,9 @@ def coord( r"""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: + Parameters + ---------- + name_or_coord : optional, default=None Either, * a :attr:`~iris.common.mixin.CFVariableMixin.standard_name`, @@ -2207,57 +2216,58 @@ def coord( * 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: + standard_name : optional, default=None The CF standard name of the desired coordinate. If ``None``, does not check for ``standard name``. - - * long_name: + long_name : optional, default=None An unconstrained description of the coordinate. If ``None``, does not check for ``long_name``. - - * var_name: + var_name : optional, default=None The NetCDF variable name of the desired coordinate. If ``None``, does not check for ``var_name``. - - * attributes: + attributes : optional, default=None A dictionary of attributes desired on the coordinates. If ``None``, does not check for ``attributes``. - - * axis: + axis : optional, default=None 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: + contains_dimension : optional, default=None The desired coordinate contains the data dimension. If ``None``, does not check for the dimension. - - * dimensions: + dimensions : optional, default=None 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: + coord_system : optional, default=None Whether the desired coordinates have a coordinate system equal to the given coordinate system. If ``None``, no check is done. - - * dim_coords: + dim_coords : optional, default=None 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: + mesh_coords : optional, default=None Set to ``True`` to return only coordinates which are - :class:`~iris.experimental.ugrid.MeshCoord`\\ s. + :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. + Returns + ------- + The coordinate that matches the provided criteria. + Notes + ----- + .. note:: + + If the arguments given do not result in **precisely one** coordinate, + then a :class:`~iris.exceptions.CoordinateNotFoundError` is raised. + + See Also + -------- + :meth:`Cube.coords` for matching zero or more coordinates. """ coords = self.coords( name_or_coord=name_or_coord, @@ -2304,9 +2314,9 @@ def coord_system(self, spec=None): If no target coordinate system is provided then find any available coordinate system. - Kwargs: - - * spec: + Parameters + ---------- + spec : optional, default=None The the name or type of a coordinate system subclass. E.g. :: @@ -2319,8 +2329,9 @@ def coord_system(self, spec=None): 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. + Returns + ------- + :class:`iris.coord_systems.CoordSystem` or None. """ if isinstance(spec, str) or spec is None: @@ -2415,20 +2426,22 @@ 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 + Parameters + ---------- + name_or_cell_measure : optional, default=None 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`. + * (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. + * (b) a cell_measure instance with metadata equal to that of + the desired cell_measures. - See also :meth:`Cube.cell_measure()`. + See Also + -------- + :meth:`Cube.cell_measure()`. """ name = None @@ -2453,16 +2466,18 @@ def cell_measure(self, name_or_cell_measure=None): """Return a single cell_measure given the same arguments as :meth:`Cube.cell_measures`. + Notes + ----- .. 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. + See Also + -------- + :meth:`Cube.cell_measures()` + For full keyword documentation. """ cell_measures = self.cell_measures(name_or_cell_measure) @@ -2500,20 +2515,21 @@ 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 + Parameters + ---------- + name_or_ancillary_variable : optional, default=None 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`. + * (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. + * (b) a ancillary_variable instance with metadata equal to that of + the desired ancillary_variables. - See also + See Also + -------- :meth:`Cube.ancillary_variable()`. """ @@ -2539,16 +2555,18 @@ def ancillary_variable(self, name_or_ancillary_variable=None): """Return a single ancillary_variable given the same arguments as :meth:`Cube.ancillary_variables`. + Notes + ----- .. 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. + See Also + -------- + :meth:`Cube.ancillary_variables()` + For full keyword documentation. """ ancillary_variables = self.ancillary_variables(name_or_ancillary_variable) @@ -2657,8 +2675,9 @@ def lazy_data(self): does _not_ make the Cube data lazy again; the Cube data remains loaded in memory. - Returns: - A lazy array, representing the Cube data. + Returns + ------- + A lazy array, representing the Cube data. """ return self._data_manager.lazy_data() @@ -2668,6 +2687,8 @@ def data(self): """The :class:`numpy.ndarray` representing the multi-dimensional data of the cube. + Notes + ----- .. note:: Cubes obtained from NetCDF, PP, and FieldsFile files will only @@ -2704,8 +2725,9 @@ def data(self, data): def has_lazy_data(self): """Details whether this :class:`~iris.cube.Cube` has lazy data. - Returns: - Boolean. + Returns + ------- + bool """ return self._data_manager.has_lazy_data() @@ -2772,13 +2794,13 @@ 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): + Parameters + ---------- + shorten : bool If set, produce a one-line summary of minimal width, showing only the cube name, units and dimensions. When not set (default), produces a full multi-line summary string. - * name_padding (int): + name_padding : int Control the *minimum* width of the cube name + units, i.e. the indent of the dimension map section. @@ -2962,10 +2984,7 @@ def subset(self, coord): return result def extract(self, constraint): - """Filter the cube by the given constraint using - :meth:`iris.Constraint.extract` method. - - """ + """Filter cube by the given constraint using :meth:`iris.Constraint.extract`.""" # Cast the constraint into a proper constraint if it is not so already constraint = iris._constraints.as_constraint(constraint) return constraint.extract(self) @@ -2976,42 +2995,38 @@ def intersection(self, *args, **kwargs): 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. + * (a) positional arguments: instances of :class:`iris.coords.CoordExtent`, + or equivalent tuples of 3-5 items: - * min_inclusive - If True, coordinate values equal to `minimum` 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. - * 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: + Parameters + ---------- + 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. + ignore_bounds : optional Intersect based on points only. Default False. - - * threshold: + threshold : optional Minimum proportion of a bounded cell that must overlap with the specified range. Default 0. + Notes + ----- .. note:: For ranges defined over "circular" coordinates (i.e. those @@ -3020,10 +3035,10 @@ def intersection(self, *args, **kwargs): range that covers the entire modulus, a split cell will preferentially be placed at the ``minimum`` end. - .. warning:: - - Currently this routine only works with "circular" - coordinates (as defined in the previous note.) + Warnings + -------- + Currently this routine only works with "circular" + coordinates (as defined in the previous note.) For example:: @@ -3032,7 +3047,7 @@ def intersection(self, *args, **kwargs): >>> print(cube.coord('longitude').points[::10]) [ 0. 37.49999237 74.99998474 112.49996948 \ 149.99996948 - 187.49995422 224.99993896 262.49993896 299.99993896 \ + 187.49995422 224.99993896 262.49993896 299.99993896 \ 337.49990845] >>> subset = cube.intersection(longitude=(30, 50)) >>> print(subset.coord('longitude').points) @@ -3041,7 +3056,9 @@ def intersection(self, *args, **kwargs): >>> print(subset.coord('longitude').points) [-7.50012207 -3.75012207 0. 3.75 7.5 ] - Returns: + Returns + ------- + :class:`~iris.cube.Cube` A new :class:`~iris.cube.Cube` giving the subset of the cube which intersects with the requested coordinate intervals. @@ -3364,32 +3381,41 @@ def _as_list_of_coords(self, names_or_coords): return coords def slices_over(self, ref_to_slice): - """Return an iterator of all subcubes along a given coordinate or - dimension index, or multiple of these. + """Return an iterator of all subcubes. - Args: + Return an iterator of all subcubes along a given coordinate or + dimension index, or multiple of these. - * ref_to_slice (string, coord, dimension index or a list of these): + Parameters + ---------- + ref_to_slice: str, 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. + Returns + ------- + An iterator of subcubes. + Examples + -------- 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`. - + Notes + ----- .. 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. + See Also + -------- + :meth:`iris.cube.Cube.slices`. + """ # Required to handle a mix between types. if _is_single_item(ref_to_slice): @@ -3422,31 +3448,34 @@ 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): + Parameters + ---------- + ref_to_slice : str, 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 + ordered : bool, optional + 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. + Returns + ------- + An iterator of subcubes. + Examples + -------- 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) - .. seealso:: :meth:`iris.cube.Cube.slices_over`. + See Also + -------- + :meth:`iris.cube.Cube.slices_over`. """ if not isinstance(ordered, bool): @@ -3503,13 +3532,19 @@ 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. + Parameters + ---------- + new_order : list of ints, optional + By default, reverse the dimensions, otherwise permute the + axes according to the values given. + Notes + ----- .. note:: If defined, new_order must span all of the data dimensions. - Example usage:: + Examples + -------- + :: # put the second dimension first, followed by the third dimension, # and finally put the first dimension third:: @@ -3734,13 +3769,14 @@ def _order(array): def copy(self, data=None): """Returns a deep copy of this cube. - Kwargs: - - * data: + Parameters + ---------- + data : optional, default=None Replace the data of the cube copy with provided data payload. - Returns: - A copy instance of the :class:`Cube`. + Returns + ------- + A copy instance of the :class:`Cube`. """ memo = {} @@ -3927,25 +3963,22 @@ def collapsed(self, coords, aggregator, **kwargs): 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): + Parameters + ---------- + coords : str, coord or a list of strings/coords Coordinate names/coordinates over which the cube should be collapsed. - - * aggregator (:class:`iris.analysis.Aggregator`): + aggregator : :class:`iris.analysis.Aggregator` Aggregator to be applied for collapse operation. - - Kwargs: - - * kwargs: + **kwargs : Aggregation function keyword arguments. - Returns: - Collapsed cube. - - For example: + Returns + ------- + Collapsed cube. + Examples + -------- >>> import iris >>> import iris.analysis >>> path = iris.sample_data_path('ostia_monthly.nc') @@ -3969,7 +4002,8 @@ def collapsed(self, coords, aggregator, **kwargs): Conventions 'CF-1.5' STASH m01s00i024 - + Notes + ----- .. note:: Some aggregations are not commutative and hence the order of @@ -4176,15 +4210,12 @@ def aggregated_by(self, coords, aggregator, climatological=False, **kwargs): 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. + **kwargs : optional + Aggregator and aggregation function keyword arguments. Returns ------- - :class:`iris.cube.Cube` - - Other Parameters - ---------------- - kwargs: - Aggregator and aggregation function keyword arguments. + :class:`iris.cube.Cube` Examples -------- @@ -4432,19 +4463,16 @@ 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`): + Parameters + ---------- + coord : str or :class:`iris.coords.Coord` The coordinate over which to perform the rolling window aggregation. - * aggregator (:class:`iris.analysis.Aggregator`): + aggregator : :class:`iris.analysis.Aggregator` Aggregator to be applied to the data. - * window (int): + window : int Size of window to use. - - Kwargs: - - * kwargs: + **kwargs : optional Aggregator and aggregation function keyword arguments. The weights argument to the aggregator, if any, should be a 1d array, cube, or (names of) :meth:`~iris.cube.Cube.coords`, @@ -4452,15 +4480,18 @@ def rolling_window(self, coord, aggregator, window, **kwargs): :meth:`~iris.cube.Cube.ancillary_variables` with the same length as the chosen window. - Returns: - :class:`iris.cube.Cube`. + Returns + ------- + :class:`iris.cube.Cube`. + Notes + ----- .. note:: This operation does not yet have support for lazy evaluation. - For example: - + Examples + -------- >>> import iris, iris.analysis >>> fname = iris.sample_data_path('GloSea4', 'ensemble_010.pp') >>> air_press = iris.load_cube(fname, 'surface_temperature') @@ -4488,7 +4519,6 @@ def rolling_window(self, coord, aggregator, window, **kwargs): '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) @@ -4517,7 +4547,7 @@ def rolling_window(self, coord, aggregator, window, **kwargs): Notice that the forecast_period dimension now represents the 4 possible windows of size 3 from the original cube. - """ # noqa: D214, D410, D411 + """ # noqa: D214, D407, D410, D411 # Update weights kwargs (if necessary) to handle different types of # weights @@ -4639,37 +4669,36 @@ 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: + Parameters + ---------- + sample_points : A sequence of (coordinate, points) pairs over which to interpolate. The values for coordinates that correspond to dates or times may optionally be supplied as datetime.datetime or cftime.datetime instances. The N pairs supplied will be used to create an N-d grid of points that will then be sampled (rather than just N points). - * scheme: + scheme : 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: + * :class:`iris.analysis.Linear`, and + * :class:`iris.analysis.Nearest`. + collapse_scalar : bool, optional Whether to collapse the dimension of scalar sample points in the resulting cube. Default is True. - Returns: + Returns + ------- + cube 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: - + Examples + -------- >>> import datetime >>> import iris >>> path = iris.sample_data_path('uk_hires.pp') @@ -4725,23 +4754,25 @@ 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: + Parameters + ---------- + grid : A :class:`~iris.cube.Cube` that defines the target grid. - * scheme: + 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`, + * :class:`iris.analysis.Linear`\*, + * :class:`iris.analysis.Nearest`\*, + * :class:`iris.analysis.AreaWeighted`\*, + * :class:`iris.analysis.UnstructuredNearest`, + * :class:`iris.analysis.PointInCell`, \* Supports lazy regridding. - Returns: + Returns + ------- + :class:`~iris.cube` 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 @@ -4750,6 +4781,8 @@ def regrid(self, grid, scheme): The returned cube will have lazy data if the original cube has lazy data and the regridding scheme supports lazy regridding. + Notes + ----- .. note:: Both the source and target cubes must have a CoordSystem, otherwise diff --git a/lib/iris/experimental/regrid.py b/lib/iris/experimental/regrid.py index b0ebfc5679..aa37d76fe0 100644 --- a/lib/iris/experimental/regrid.py +++ b/lib/iris/experimental/regrid.py @@ -82,18 +82,15 @@ def regrid_area_weighted_rectilinear_src_and_grid(src_cube, grid_cube, mdtol=0): or entirely outside of the horizontal extent of the src_cube will be masked irrespective of the value of mdtol. - Args: - - * src_cube: + Parameters + ---------- + src_cube : :class:`iris.cube.Cube` An instance of :class:`iris.cube.Cube` that supplies the data, metadata and coordinates. - * grid_cube: + grid_cube : :class:`iris.cube.Cube` An instance of :class:`iris.cube.Cube` that supplies the desired horizontal grid definition. - - Kwargs: - - * mdtol: + mdtol : int, optional, default=0 Tolerance of missing data. The value returned in each element of the returned cube's data array will be masked if the fraction of masked data in the overlapping cells of the source cube exceeds mdtol. This @@ -102,8 +99,9 @@ def regrid_area_weighted_rectilinear_src_and_grid(src_cube, grid_cube, mdtol=0): will mean the resulting element will be masked if and only if all the overlapping cells of the source cube are masked. Defaults to 0. - Returns: - A new :class:`iris.cube.Cube` instance. + Returns + ------- + A new :class:`iris.cube.Cube` instance. """ wmsg = ( @@ -165,24 +163,25 @@ def regrid_weighted_curvilinear_to_rectilinear(src_cube, weights, grid_cube): .. warning:: - * All coordinates that span the :data:`src_cube` that don't define - the horizontal curvilinear grid will be ignored. + All coordinates that span the :data:`src_cube` that don't define + the horizontal curvilinear grid will be ignored. - Args: - - * src_cube: + Parameters + ---------- + src_cube : :class:`iris.cube.Cube` A :class:`iris.cube.Cube` instance that defines the source variable grid to be regridded. - * weights (array or None): + weights : array or None A :class:`numpy.ndarray` instance that defines the weights for the source variable grid cells. Must have the same shape as the X and Y coordinates. If weights is None, all-ones will be used. - * grid_cube: + grid_cube : :class:`iris.cube.Cube` A :class:`iris.cube.Cube` instance that defines the target rectilinear grid. - Returns: - A :class:`iris.cube.Cube` instance. + Returns + ------- + A :class:`iris.cube.Cube` instance. """ wmsg = ( @@ -241,15 +240,15 @@ def __init__(self, src_cube, tgt_grid_cube, method, projection=None): """Create a regridder for conversions between the source and target grids. - Args: - - * src_cube: + Parameters + ---------- + src_cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` providing the source points. - * tgt_grid_cube: + tgt_grid_cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` providing the target grid. - * method: + method : Either 'linear' or 'nearest'. - * projection: + projection : optional The projection in which the interpolation is performed. If None, a PlateCarree projection is used. Defaults to None. @@ -397,37 +396,39 @@ def _create_cube( All the metadata and coordinates of the result Cube are copied from the source Cube, with two exceptions: - - Grid dimension coordinates are copied from the grid Cube. - - Auxiliary coordinates which span the grid dimensions are - ignored, except where they provide a reference surface for an - :class:`iris.aux_factory.AuxCoordFactory`. - Args: + * Grid dimension coordinates are copied from the grid Cube. + * Auxiliary coordinates which span the grid dimensions are + ignored, except where they provide a reference surface for an + :class:`iris.aux_factory.AuxCoordFactory`. - * data: + Parameters + ---------- + data : The regridded data as an N-dimensional NumPy array. - * src: + src : :class:`~iris.cube.Cube` The source Cube. - * src_xy_dim: + src_xy_dim : The dimension the X and Y coord span within the source Cube. - * src_x_coord: + src_x_coord : The X coordinate (either :class:`iris.coords.AuxCoord` or :class:`iris.coords.DimCoord`). - * src_y_coord: + src_y_coord : The Y coordinate (either :class:`iris.coords.AuxCoord` or :class:`iris.coords.DimCoord`). - * grid_x_coord: + grid_x_coord : The :class:`iris.coords.DimCoord` for the new grid's X coordinate. - * grid_y_coord: + grid_y_coord : The :class:`iris.coords.DimCoord` for the new grid's Y coordinate. - * regrid_callback: + regrid_callback : The routine that will be used to calculate the interpolated values of any reference surfaces. - Returns: - The new, regridded Cube. + Returns + ------- + The new, regridded Cube. """ # Create a result cube with the appropriate metadata @@ -523,12 +524,14 @@ def __call__(self, src_cube): The given cube must be defined with the same grid as the source grid used to create this :class:`UnstructuredProjectedRegridder`. - Args: - - * src_cube: + Parameters + ---------- + src_cube : :class:`~iris.cube.Cube` A :class:`~iris.cube.Cube` to be regridded. - Returns: + Returns + ------- + :class:`~iris.cube.Cube` A cube defined with the horizontal dimensions of the target and the other dimensions from this cube. The data values of this cube will be converted to values on the new grid using @@ -620,9 +623,9 @@ def __init__(self, projection=None): Developers to discuss how to retain it (which could include reversing the deprecation). - Optional Args: - - * projection: `cartopy.crs instance` + Parameters + ---------- + projection : `cartopy.crs instance`, optional The projection that the scipy calculation is performed in. If None is given, a PlateCarree projection is used. Defaults to None. @@ -649,16 +652,18 @@ def regridder(self, src_cube, target_grid): Does not support lazy regridding. - Args: - - * src_cube: + Parameters + ---------- + src_cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` defining the unstructured source points. - * target_grid: + target_grid : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` defining the target grid. - Returns: - A callable with the interface: + Returns + ------- + callable + A callable with the interface:: `callable(cube)` @@ -701,9 +706,9 @@ def __init__(self, projection=None): contact the Iris Developers to discuss how to retain it (which could include reversing the deprecation). - Optional Args: - - * projection: `cartopy.crs instance` + Parameters + ---------- + projection : `cartopy.crs instance`, optional The projection that the scipy calculation is performed in. If None is given, a PlateCarree projection is used. Defaults to None. @@ -731,16 +736,18 @@ def regridder(self, src_cube, target_grid): Does not support lazy regridding. - Args: - - * src_cube: + Parameters + ---------- + src_cube : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` defining the unstructured source points. - * target_grid: + target_grid : :class:`~iris.cube.Cube` The :class:`~iris.cube.Cube` defining the target grid. - Returns: - A callable with the interface: + Returns + ------- + callable + A callable with the interface:: `callable(cube)` diff --git a/lib/iris/experimental/regrid_conservative.py b/lib/iris/experimental/regrid_conservative.py index 45ac0505ed..07b076b57e 100644 --- a/lib/iris/experimental/regrid_conservative.py +++ b/lib/iris/experimental/regrid_conservative.py @@ -60,17 +60,14 @@ def _make_esmpy_field(x_coord, y_coord, ref_name="field", data=None, mask=None): Add a grid mask if provided. Create and return a Field mapped on this Grid, setting data if provided. - Args: - - * x_coord, y_coord (:class:`iris.coords.Coord`): + Parameters + ---------- + x_coord, y_coord : :class:`iris.coords.Coord` One-dimensional coordinates of shape (nx,) and (ny,). Their contiguous bounds define an ESMF.Grid of shape (nx, ny). - - Kwargs: - - * data (:class:`numpy.ndarray`, shape (nx,ny)): + data : :class:`numpy.ndarray`, shape (nx,ny), optional Set the Field data content. - * mask (:class:`numpy.ndarray`, boolean, shape (nx,ny)): + mask : :class:`numpy.ndarray`, bool, shape (nx,ny), optional Add a mask item to the grid, assigning it 0/1 where mask=False/True. """ @@ -164,19 +161,23 @@ def regrid_conservative_via_esmpy(source_cube, grid_cube): Regrids the data of a source cube onto a new grid defined by a destination cube. - Args: - - * source_cube (:class:`iris.cube.Cube`): + Parameters + ---------- + source_cube : :class:`iris.cube.Cube` Source data. Must have two identifiable horizontal dimension coordinates. - * grid_cube (:class:`iris.cube.Cube`): + grid_cube : :class:`iris.cube.Cube` Define the target horizontal grid: Only the horizontal dimension coordinates are actually used. - Returns: + Returns + ------- + :class:`iris.cube.Cube` A new cube derived from source_cube, regridded onto the specified horizontal grid. + Notes + ----- Any additional coordinates which map onto the horizontal dimensions are removed, while all other metadata is retained. If there are coordinate factories with 2d horizontal reference surfaces, diff --git a/lib/iris/experimental/ugrid/mesh.py b/lib/iris/experimental/ugrid/mesh.py index 14bb313474..dfd0d74552 100644 --- a/lib/iris/experimental/ugrid/mesh.py +++ b/lib/iris/experimental/ugrid/mesh.py @@ -119,9 +119,9 @@ def __init__( ): """Constructs a single connectivity. - Args: - - * indices (:class:`numpy.ndarray` or :class:`numpy.ma.core.MaskedArray` or :class:`dask.array.Array`): + Parameters + ---------- + indices : :class:`numpy.ndarray` or :class:`numpy.ma.core.MaskedArray` or :class:`dask.array.Array` 2D array giving the topological connection relationship between :attr:`location` elements and :attr:`connected` elements. The :attr:`location_axis` dimension indexes over the @@ -135,34 +135,31 @@ def __init__( elements: use a :class:`numpy.ma.core.MaskedArray` and mask the :attr:`location` elements' unused index 'slots'. Use a :class:`dask.array.Array` to keep indices 'lazy'. - * cf_role (str): + cf_role : str Denotes the topological relationship that this connectivity describes. Made up of this array's :attr:`location`, and the :attr:`connected` element type that is indexed by the array. See :attr:`UGRID_CF_ROLES` for valid arguments. - - Kwargs: - - * standard_name (str): + standard_name : str, optional CF standard name of the connectivity. (NOTE: this is not expected by the UGRID conventions, but will be handled in Iris' standard way if provided). - * long_name (str): + long_name : str, optional Descriptive name of the connectivity. - * var_name (str): + var_name : str, optional The NetCDF variable name for the connectivity. - * units (cf_units.Unit): + units : cf_units.Unit, optional The :class:`~cf_units.Unit` of the connectivity's values. Can be a string, which will be converted to a Unit object. (NOTE: this is not expected by the UGRID conventions, but will be handled in Iris' standard way if provided). - * attributes (dict): + attributes : dict, optional A dictionary containing other cf and user-defined attributes. - * start_index (int): + start_index : int, optional Either ``0`` or ``1``. Default is ``0``. Denotes whether :attr:`indices` uses 0-based or 1-based indexing (allows support for Fortran and legacy NetCDF files). - * location_axis (int): + location_axis : int, optional Either ``0`` or ``1``. Default is ``0``. Denotes which axis of :attr:`indices` varies over the :attr:`location` elements (the alternate axis therefore varying over :attr:`connected` elements). @@ -294,19 +291,23 @@ def indices(self): return self._values def indices_by_location(self, indices=None): - """Return a view of the indices array with :attr:`location_axis` **always** as + """Return a view of the indices array. + + Return a view of the indices array with :attr:`location_axis` **always** as the first axis - transposed if necessary. Can optionally pass in an identically shaped array on which to perform this operation (e.g. the output from :meth:`core_indices` or :meth:`lazy_indices`). - Kwargs: - - * indices (array): + Parameters + ---------- + indices : array The array on which to operate. If ``None``, will operate on :attr:`indices`. Default is ``None``. - Returns: - A view of the indices array, transposed - if necessary - to put + Returns + ------- + result : + A view of the indices array Transposed - if necessary - to put :attr:`location_axis` first. """ @@ -438,7 +439,9 @@ def transpose(self): """Create a new :class:`Connectivity`, identical to this one but with the :attr:`indices` array transposed and the :attr:`location_axis` value flipped. - Returns: + Returns + ------- + :class:`Connectivity` A new :class:`Connectivity` that is the transposed equivalent of the original. @@ -466,8 +469,9 @@ def lazy_indices(self): If the :attr:`indices` have already been loaded for the connectivity, the returned Array will be a new lazy array wrapper. - Returns: - A lazy array, representing the connectivity indices array. + Returns + ------- + A lazy array, representing the connectivity indices array. """ return super()._lazy_values() @@ -476,8 +480,9 @@ def core_indices(self): """The indices array at the core of this connectivity, which may be a NumPy array or a Dask array. - Returns: - :class:`numpy.ndarray` or :class:`numpy.ma.core.MaskedArray` or :class:`dask.array.Array` + Returns + ------- + :class:`numpy.ndarray` or :class:`numpy.ma.core.MaskedArray` or :class:`dask.array.Array` """ return super()._core_values() @@ -486,8 +491,9 @@ def has_lazy_indices(self): """Return a boolean indicating whether the connectivity's :attr:`indices` array is a lazy Dask array or not. - Returns: - boolean + Returns + ------- + bool """ return super()._has_lazy_values() @@ -504,9 +510,11 @@ def lazy_location_lengths(self): The returned Array will be lazy regardless of whether the :attr:`indices` have already been loaded. - Returns: + Returns + ------- + lazy array A lazy array, representing the number of :attr:`connected` - elements associated with each :attr:`location` element. + elements associated with each :attr:`location` element. """ location_mask_counts = da.sum( @@ -520,9 +528,11 @@ def location_lengths(self): elements associated with each of the connectivity's :attr:`location` elements, accounting for masks if present. - Returns: + Returns + ------- + NumPy array A NumPy array, representing the number of :attr:`connected` - elements associated with each :attr:`location` element. + elements associated with each :attr:`location` element. """ return self.lazy_location_lengths().compute() @@ -668,14 +678,12 @@ def from_coords(cls, *coords): * ``None`` or ``(n, <2)``: Not supported - * ``(n, 2)``: :attr:`~Mesh.topology_dimension` = ``1``. :attr:`~Mesh.node_coords` and :attr:`~Mesh.edge_node_connectivity` constructed from :attr:`~iris.coords.Coord.bounds`. :attr:`~Mesh.edge_coords` constructed from :attr:`~iris.coords.Coord.points`. - * ``(n, >=3)``: :attr:`~Mesh.topology_dimension` = ``2``. :attr:`~Mesh.node_coords` and :attr:`~Mesh.face_node_connectivity` @@ -683,17 +691,20 @@ def from_coords(cls, *coords): :attr:`~Mesh.face_coords` constructed from :attr:`~iris.coords.Coord.points`. - Args: - - * \\*coords (Iterable of :class:`~iris.coords.Coord`): + Parameters + ---------- + *coords : Iterable of :class:`~iris.coords.Coord` Coordinates to pass into the :class:`Mesh`. All :attr:`~iris.coords.Coord.points` must have the same shapes; all :attr:`~iris.coords.Coord.bounds` must have the same shapes, and must not be ``None``. - Returns: - :class:`Mesh` + Returns + ------- + :class:`Mesh` + Notes + ----- .. note:: Any resulting duplicate nodes are not currently removed, due to the computational intensity. @@ -717,7 +728,9 @@ def from_coords(cls, *coords): with PARSE_UGRID_ON_LOAD.context(): cube_w_mesh = load_cube(file_path) - For example:: + Examples + -------- + :: # Reconstruct a cube-with-mesh after subsetting it. @@ -891,7 +904,7 @@ def summary(self, shorten=False): Parameters ---------- - shorten : bool, default = False + shorten : bool, default=False If True, produce a oneline string form of the form . If False, produce a multi-line detailed print output. @@ -1207,9 +1220,9 @@ def node_dimension(self, name): def add_connectivities(self, *connectivities): """Add one or more :class:`~iris.experimental.ugrid.mesh.Connectivity` instances to the :class:`Mesh`. - Args: - - * connectivities (iterable of object): + Parameters + ---------- + *connectivities : iterable of object A collection of one or more :class:`~iris.experimental.ugrid.mesh.Connectivity` instances to add to the :class:`Mesh`. @@ -1228,24 +1241,19 @@ def add_coords( ): """Add one or more :class:`~iris.coords.AuxCoord` coordinates to the :class:`Mesh`. - Kwargs: - - * node_x (object): + Parameters + ---------- + node_x (object) : optional, default=None The ``x-axis`` like ``node`` :class:`~iris.coords.AuxCoord`. - - * node_y (object): + node_y (object): optional, default=None The ``y-axis`` like ``node`` :class:`~iris.coords.AuxCoord`. - - * edge_x (object): + edge_x (object): optional, default=None The ``x-axis`` like ``edge`` :class:`~iris.coords.AuxCoord`. - - * edge_y (object): + edge_y (object): optional, default=None The ``y-axis`` like ``edge`` :class:`~iris.coords.AuxCoord`. - - * face_x (object): + face_x (object): optional, default=None The ``x-axis`` like ``face`` :class:`~iris.coords.AuxCoord`. - - * face_y (object): + face_y (object): optional, default=None The ``y-axis`` like ``face`` :class:`~iris.coords.AuxCoord`. """ @@ -1285,9 +1293,9 @@ def connectivities( :meth:`Mesh.connectivity` for matching exactly one connectivity. - Kwargs: - - * item (str or object): + Parameters + ---------- + item : str or object Either, * a :attr:`~iris.common.mixin.CFVariableMixin.standard_name`, @@ -1299,47 +1307,41 @@ def connectivities( the desired objects e.g., :class:`~iris.experimental.ugrid.mesh.Connectivity` or :class:`~iris.experimental.ugrid.metadata.ConnectivityMetadata`. - - * standard_name (str): + standard_name : str, optional, default=None The CF standard name of the desired :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``standard_name``. - - * long_name (str): + long_name : str, optional, default=None An unconstrained description of the :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``long_name``. - - * var_name (str): + var_name : str, optional, default=None The NetCDF variable name of the desired :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``var_name``. - - * attributes (dict): + attributes : dict, optional, default=None A dictionary of attributes desired on the :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``attributes``. - - * cf_role (str): + cf_role : str, optional, default=None The UGRID ``cf_role`` of the desired :class:`~iris.experimental.ugrid.mesh.Connectivity`. - - * contains_node (bool): + contains_node : bool, optional Contains the ``node`` element as part of the :attr:`~iris.experimental.ugrid.metadata.ConnectivityMetadata.cf_role` in the list of objects to be matched. - - * contains_edge (bool): + contains_edge : bool, optional Contains the ``edge`` element as part of the :attr:`~iris.experimental.ugrid.metadata.ConnectivityMetadata.cf_role` in the list of objects to be matched. - - * contains_face (bool): + contains_face : bool, optional Contains the ``face`` element as part of the :attr:`~iris.experimental.ugrid.metadata.ConnectivityMetadata.cf_role` in the list of objects to be matched. - Returns: + Returns + ------- + list of :class:`~iris.experimental.ugrid.mesh.Connectivity` A list of :class:`~iris.experimental.ugrid.mesh.Connectivity` instances from the :class:`Mesh` that matched the given criteria. @@ -1385,9 +1387,9 @@ def connectivity( :meth:`Mesh.connectivities` for matching zero or more connectivities. - Kwargs: - - * item (str or object): + Parameters + ---------- + item : str or object Either, * a :attr:`~iris.common.mixin.CFVariableMixin.standard_name`, @@ -1399,47 +1401,41 @@ def connectivity( the desired object e.g., :class:`~iris.experimental.ugrid.mesh.Connectivity` or :class:`~iris.experimental.ugrid.metadata.ConnectivityMetadata`. - - * standard_name (str): + standard_name : str, optional, default=None The CF standard name of the desired :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``standard_name``. - - * long_name (str): + long_name : str, optional, default=None An unconstrained description of the :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``long_name``. - - * var_name (str): + var_name : str, optional, default=None The NetCDF variable name of the desired :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``var_name``. - - * attributes (dict): + attributes : dict, optional, default=None A dictionary of attributes desired on the :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``attributes``. - - * cf_role (str): + cf_role : str, optional, default=None The UGRID ``cf_role`` of the desired :class:`~iris.experimental.ugrid.mesh.Connectivity`. - - * contains_node (bool): + contains_node : bool, optional Contains the ``node`` element as part of the :attr:`~iris.experimental.ugrid.metadata.ConnectivityMetadata.cf_role` in the list of objects to be matched. - - * contains_edge (bool): + contains_edge : bool, optional Contains the ``edge`` element as part of the :attr:`~iris.experimental.ugrid.metadata.ConnectivityMetadata.cf_role` in the list of objects to be matched. - - * contains_face (bool): + contains_face : bool, optional Contains the ``face`` element as part of the :attr:`~iris.experimental.ugrid.metadata.ConnectivityMetadata.cf_role` in the list of objects to be matched. - Returns: + Returns + ------- + :class:`~iris.experimental.ugrid.mesh.Connectivity` The :class:`~iris.experimental.ugrid.mesh.Connectivity` from the :class:`Mesh` that matched the given criteria. @@ -1485,9 +1481,9 @@ def coord( :meth:`Mesh.coords` for matching zero or more coordinates. - Kwargs: - - * item (str or object): + Parameters + ---------- + item : str or object, optional, default=None Either, * a :attr:`~iris.common.mixin.CFVariableMixin.standard_name`, @@ -1498,38 +1494,32 @@ def coord( * a coordinate or metadata instance equal to that of the desired coordinate e.g., :class:`~iris.coords.AuxCoord` or :class:`~iris.common.metadata.CoordMetadata`. - - * standard_name (str): + standard_name : str, optional, default=None The CF standard name of the desired coordinate. If ``None``, does not check for ``standard_name``. - - * long_name (str): + long_name : str, optional, default=None An unconstrained description of the coordinate. If ``None``, does not check for ``long_name``. - - * var_name (str): + var_name : str, optional, default=None The NetCDF variable name of the desired coordinate. If ``None``, does not check for ``var_name``. - - * attributes (dict): + attributes : dict, optional, default=None A dictionary of attributes desired on the coordinates. If ``None``, does not check for ``attributes``. - - * axis (str): + axis : str, optional, default=None 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). - - * include_node (bool): + include_node : bool, optional Include all ``node`` coordinates in the list of objects to be matched. - - * include_edge (bool): + include_edge : bool, optional Include all ``edge`` coordinates in the list of objects to be matched. - - * include_face (bool): + include_face : bool, optional Include all ``face`` coordinates in the list of objects to be matched. - Returns: + Returns + ------- + :class:`~iris.coords.AuxCoord` The :class:`~iris.coords.AuxCoord` coordinate from the :class:`Mesh` that matched the given criteria. @@ -1569,9 +1559,9 @@ def coords( :meth:`Mesh.coord` for matching exactly one coordinate. - Kwargs: - - * item (str or object): + Parameters + ---------- + item : str or object, optional, default=None Either, * a :attr:`~iris.common.mixin.CFVariableMixin.standard_name`, @@ -1582,38 +1572,32 @@ def coords( * a coordinate or metadata instance equal to that of the desired coordinates e.g., :class:`~iris.coords.AuxCoord` or :class:`~iris.common.metadata.CoordMetadata`. - - * standard_name (str): + standard_name : str, optional, default=None The CF standard name of the desired coordinate. If ``None``, does not check for ``standard_name``. - - * long_name (str): + long_name : str, optional, default=None An unconstrained description of the coordinate. If ``None``, does not check for ``long_name``. - - * var_name (str): + var_name : str, optional, default=None The NetCDF variable name of the desired coordinate. If ``None``, does not check for ``var_name``. - - * attributes (dict): + attributes : dict, optional, default=None A dictionary of attributes desired on the coordinates. If ``None``, does not check for ``attributes``. - - * axis (str): + axis : str, optional, default=None 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). - - * include_node (bool): + include_node : bool, optional Include all ``node`` coordinates in the list of objects to be matched. - - * include_edge (bool): + include_edge : bool, optional Include all ``edge`` coordinates in the list of objects to be matched. - - * include_face (bool): + include_face : bool, optional Include all ``face`` coordinates in the list of objects to be matched. - Returns: + Returns + ------- + list of :class:`~iris.coords.AuxCoord` A list of :class:`~iris.coords.AuxCoord` coordinates from the :class:`Mesh` that matched the given criteria. @@ -1649,9 +1633,9 @@ def remove_connectivities( Criteria can be either specific properties or other objects with metadata to be matched. - Kwargs: - - * item (str or object): + Parameters + ---------- + item : str or object, optional, default=None Either, * a :attr:`~iris.common.mixin.CFVariableMixin.standard_name`, @@ -1663,47 +1647,41 @@ def remove_connectivities( the desired objects e.g., :class:`~iris.experimental.ugrid.mesh.Connectivity` or :class:`~iris.experimental.ugrid.metadata.ConnectivityMetadata`. - - * standard_name (str): + standard_name : str, optional, default=None The CF standard name of the desired :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``standard_name``. - - * long_name (str): + long_name : str, optional, default=None An unconstrained description of the - :class:`~iris.experimental.ugrid.mesh.Connectivity. If ``None``, + :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``long_name``. - - * var_name (str): + var_name : str, optional, default=None The NetCDF variable name of the desired :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``var_name``. - - * attributes (dict): + attributes : dict, optional, default=None A dictionary of attributes desired on the :class:`~iris.experimental.ugrid.mesh.Connectivity`. If ``None``, does not check for ``attributes``. - - * cf_role (str): + cf_role : str, optional, default=None The UGRID ``cf_role`` of the desired :class:`~iris.experimental.ugrid.mesh.Connectivity`. - - * contains_node (bool): + contains_node : bool, optional Contains the ``node`` element as part of the :attr:`~iris.experimental.ugrid.metadata.ConnectivityMetadata.cf_role` in the list of objects to be matched for potential removal. - - * contains_edge (bool): + contains_edge : bool, optional Contains the ``edge`` element as part of the :attr:`~iris.experimental.ugrid.metadata.ConnectivityMetadata.cf_role` in the list of objects to be matched for potential removal. - - * contains_face (bool): + contains_face : bool, optional Contains the ``face`` element as part of the :attr:`~iris.experimental.ugrid.metadata.ConnectivityMetadata.cf_role` in the list of objects to be matched for potential removal. - Returns: + Returns + ------- + list of :class:`~iris.experimental.ugrid.mesh.Connectivity` A list of :class:`~iris.experimental.ugrid.mesh.Connectivity` instances removed from the :class:`Mesh` that matched the given criteria. @@ -1739,9 +1717,9 @@ def remove_coords( Criteria can be either specific properties or other objects with metadata to be matched. - Kwargs: - - * item (str or object): + Parameters + ---------- + item : str or object, optional, default=None Either, * a :attr:`~iris.common.mixin.CFVariableMixin.standard_name`, @@ -1752,41 +1730,35 @@ def remove_coords( * a coordinate or metadata instance equal to that of the desired coordinates e.g., :class:`~iris.coords.AuxCoord` or :class:`~iris.common.metadata.CoordMetadata`. - - * standard_name (str): + standard_name : str, optional, default=None The CF standard name of the desired coordinate. If ``None``, does not check for ``standard_name``. - - * long_name (str): + long_name : str, optional, default=None An unconstrained description of the coordinate. If ``None``, does not check for ``long_name``. - - * var_name (str): + var_name : str, optional, default=None The NetCDF variable name of the desired coordinate. If ``None``, does not check for ``var_name``. - - * attributes (dict): + attributes : dict, optional, default=None A dictionary of attributes desired on the coordinates. If ``None``, does not check for ``attributes``. - - * axis (str): + axis : str, optional, default=None 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). - - * include_node (bool): + include_node : bool, optional Include all ``node`` coordinates in the list of objects to be matched for potential removal. - - * include_edge (bool): + include_edge : bool, optional Include all ``edge`` coordinates in the list of objects to be matched for potential removal. - - * include_face (bool): + include_face : bool, optional Include all ``face`` coordinates in the list of objects to be matched for potential removal. - Returns: + Returns + ------- + list of :class:`~iris.coords.AuxCoord` A list of :class:`~iris.coords.AuxCoord` coordinates removed from the :class:`Mesh` that matched the given criteria. @@ -1812,12 +1784,14 @@ def xml_element(self, doc): """Create the :class:`xml.dom.minidom.Element` that describes this :class:`Mesh`. - Args: - - * doc (object): + Parameters + ---------- + doc : object The parent :class:`xml.dom.minidom.Document`. - Returns: + Returns + ------- + :class:`xml.dom.minidom.Element` The :class:`xml.dom.minidom.Element` that will describe this :class:`Mesh`, and the dictionary of attributes that require to be added to this element. @@ -1847,17 +1821,18 @@ def to_MeshCoord(self, location, axis): :meth:`to_MeshCoords` for generating a series of mesh coords. - Args: - - * location (str) + Parameters + ---------- + location : str The ``location`` argument for :class:`~iris.experimental.ugrid.mesh.MeshCoord` instantiation. - - * axis (str) + axis : str The ``axis`` argument for :class:`~iris.experimental.ugrid.mesh.MeshCoord` instantiation. - Returns: + Returns + ------- + :class:`~iris.experimental.ugrid.mesh.MeshCoord` A :class:`~iris.experimental.ugrid.mesh.MeshCoord` referencing the current :class:`Mesh`. @@ -1874,13 +1849,15 @@ def to_MeshCoords(self, location): :meth:`to_MeshCoord` for generating a single mesh coord. - Args: - - * location (str) + Parameters + ---------- + location : str The ``location`` argument for :class:`MeshCoord` instantiation. - Returns: - tuple of :class:`~iris.experimental.ugrid.mesh.MeshCoord`\\ s + Returns + ------- + tuple of :class:`~iris.experimental.ugrid.mesh.MeshCoord` + tuple of :class:`~iris.experimental.ugrid.mesh.MeshCoord` referencing the current :class:`Mesh`. One for each value in :attr:`AXES`, using the value for the ``axis`` argument. @@ -1893,17 +1870,15 @@ def dimension_names_reset(self, node=False, edge=False, face=False): """Reset the name used for the NetCDF variable representing the ``node``, ``edge`` and/or ``face`` dimension to ``None``. - Kwargs: - - * node (bool): + Parameters + ---------- + node : bool, optional, default=False Reset the name of the ``node`` dimension if ``True``. Default is ``False``. - - * edge (bool): + edge : bool, optional, default=False Reset the name of the ``edge`` dimension if ``True``. Default is ``False``. - - * face (bool): + face : bool, optional, default=False Reset the name of the ``face`` dimension if ``True``. Default is ``False``. @@ -1918,17 +1893,15 @@ def dimension_names(self, node=None, edge=None, face=None): associated ``node``, ``edge`` or ``face``. Instead use :meth:`Mesh.dimension_names_reset`. - Kwargs: - - * node (str): + Parameters + ---------- + node : str, optional, default=None The name to be used for the NetCDF variable representing the ``node`` dimension. - - * edge (str): + edge : str, optional, default=None The name to be used for the NetCDF variable representing the ``edge`` dimension. - - * face (str): + face : str, optional, default=None The name to be used for the NetCDF variable representing the ``face`` dimension. @@ -2827,9 +2800,9 @@ def __getitem__(self, keys): def copy(self, points=None, bounds=None): """Make a copy of the MeshCoord. - Kwargs: - - * points, bounds (array): + Parameters + ---------- + points, bounds : array) Provided solely for signature compatibility with other types of :class:`~iris.coords.Coord`. In this case, if either is not 'None', an error is raised. @@ -2939,8 +2912,9 @@ def _construct_access_arrays(self): """Build lazy points and bounds arrays, providing dynamic access via the Mesh, according to the location and axis. - Returns: - * points, bounds (array or None): + Returns + ------- + points, bounds : array or None lazy arrays which calculate the correct points and bounds from the Mesh data, based on the location and axis. The Mesh coordinates accessed are not identified on construction, diff --git a/lib/iris/experimental/ugrid/metadata.py b/lib/iris/experimental/ugrid/metadata.py index 153f71bfcb..8969ab72a1 100644 --- a/lib/iris/experimental/ugrid/metadata.py +++ b/lib/iris/experimental/ugrid/metadata.py @@ -37,14 +37,15 @@ def __eq__(self, other): def _combine_lenient(self, other): """Perform lenient combination of metadata members for connectivities. - Args: - - * other (ConnectivityMetadata): + Parameters + ---------- + other : ConnectivityMetadata The other connectivity metadata participating in the lenient combination. - Returns: - A list of combined metadata member values. + Returns + ------- + A list of combined metadata member values. """ @@ -65,14 +66,15 @@ def func(field): def _compare_lenient(self, other): """Perform lenient equality of metadata members for connectivities. - Args: - - * other (ConnectivityMetadata): + Parameters + ---------- + other : ConnectivityMetadata The other connectivity metadata participating in the lenient comparison. - Returns: - Boolean. + Returns + ------- + bool """ # Perform "strict" comparison for "cf_role", "start_index". @@ -93,14 +95,15 @@ def _compare_lenient(self, other): def _difference_lenient(self, other): """Perform lenient difference of metadata members for connectivities. - Args: - - * other (ConnectivityMetadata): + Parameters + ---------- + other : ConnectivityMetadata The other connectivity metadata participating in the lenient difference. - Returns: - A list of difference metadata member values. + Returns + ------- + A list of difference metadata member values. """ @@ -156,14 +159,15 @@ def __eq__(self, other): def _combine_lenient(self, other): """Perform lenient combination of metadata members for meshes. - Args: - - * other (MeshMetadata): + Parameters + ---------- + other : MeshMetadata The other mesh metadata participating in the lenient combination. - Returns: - A list of combined metadata member values. + Returns + ------- + A list of combined metadata member values. """ @@ -185,14 +189,15 @@ def func(field): def _compare_lenient(self, other): """Perform lenient equality of metadata members for meshes. - Args: - - * other (MeshMetadata): + Parameters + ---------- + other : MeshMetadata The other mesh metadata participating in the lenient comparison. - Returns: - Boolean. + Returns + ------- + bool """ # Perform "strict" comparison for "topology_dimension". @@ -208,14 +213,15 @@ def _compare_lenient(self, other): def _difference_lenient(self, other): """Perform lenient difference of metadata members for meshes. - Args: - - * other (MeshMetadata): + Parameters + ---------- + other : MeshMetadata The other mesh metadata participating in the lenient difference. - Returns: - A list of difference metadata member values. + Returns + ------- + A list of difference metadata member values. """ @@ -271,13 +277,14 @@ def __eq__(self, other): def _combine_lenient(self, other): """Perform lenient combination of metadata members for MeshCoord. - Args: - - * other (MeshCoordMetadata): + Parameters + ---------- + other : MeshCoordMetadata The other metadata participating in the lenient combination. - Returns: - A list of combined metadata member values. + Returns + ------- + A list of combined metadata member values. """ @@ -298,13 +305,14 @@ def func(field): def _compare_lenient(self, other): """Perform lenient equality of metadata members for MeshCoord. - Args: - - * other (MeshCoordMetadata): + Parameters + ---------- + other : MeshCoordMetadata The other metadata participating in the lenient comparison. - Returns: - Boolean. + Returns + ------- + bool """ # Perform "strict" comparison for the MeshCoord specific members @@ -321,14 +329,15 @@ def _compare_lenient(self, other): def _difference_lenient(self, other): """Perform lenient difference of metadata members for MeshCoord. - Args: - - * other (MeshCoordMetadata): + Parameters + ---------- + other : MeshCoordMetadata The other MeshCoord metadata participating in the lenient difference. - Returns: - A list of different metadata member values. + Returns + ------- + A list of different metadata member values. """ diff --git a/lib/iris/fileformats/_ff.py b/lib/iris/fileformats/_ff.py index 88bbfd45d5..336c4aa699 100644 --- a/lib/iris/fileformats/_ff.py +++ b/lib/iris/fileformats/_ff.py @@ -141,18 +141,15 @@ def __init__( ): """Create a Grid from the relevant sections of the FFHeader. - Args: - - * column_dependent_constants (numpy.ndarray): + Parameters + ---------- + column_dependent_constants : numpy.ndarray The `column_dependent_constants` from a FFHeader. - - * row_dependent_constants (numpy.ndarray): + row_dependent_constants : numpy.ndarray The `row_dependent_constants` from a FFHeader. - - * real_constants (numpy.ndarray): + real_constants : numpy.ndarray The `real_constants` from a FFHeader. - - * horiz_grid_type (integer): + horiz_grid_type : int `horiz_grid_type` from a FFHeader. """ @@ -186,12 +183,13 @@ def vectors(self, subgrid): """Return the X and Y coordinate vectors for the given sub-grid of this grid. - Args: - - * subgrid (integer): + Parameters + ---------- + subgrid : int A "grid type code" as described in UM documentation paper C4. - Returns: + Returns + ------- A 2-tuple of X-vector, Y-vector. """ @@ -225,12 +223,13 @@ def regular_x(self, subgrid): """Return the "zeroth" value and step for the X coordinate on the given sub-grid of this grid. - Args: - - * subgrid (integer): + Parameters + ---------- + subgrid : int A "grid type code" as described in UM documentation paper C4. - Returns: + Returns + ------- A 2-tuple of BZX, BDX. """ @@ -244,12 +243,13 @@ def regular_y(self, subgrid): """Return the "zeroth" value and step for the Y coordinate on the given sub-grid of this grid. - Args: - - * subgrid (integer): + Parameters + ---------- + subgrid : int A "grid type code" as described in UM documentation paper C4. - Returns: + Returns + ------- A 2-tuple of BZY, BDY. """ @@ -306,13 +306,14 @@ def __init__(self, filename, word_depth=DEFAULT_FF_WORD_DEPTH): FIXED_LENGTH_HEADER section of the FieldsFile, making the names defined in FF_HEADER available as attributes of a FFHeader instance. - Args: - - * filename (string): + Parameters + ---------- + filename : str Specify the name of the FieldsFile. - Returns: - FFHeader object. + Returns + ------- + FFHeader object. """ @@ -400,13 +401,14 @@ def shape(self, name): """Return the dimension shape of the FieldsFile FIXED_LENGTH_HEADER pointer attribute. - Args: - - * name (string): + Parameters + ---------- + name : str Specify the name of the FIXED_LENGTH_HEADER attribute. - Returns: - Dimension tuple. + Returns + ------- + Dimension tuple. """ @@ -443,21 +445,21 @@ def __init__(self, filename, read_data=False, word_depth=DEFAULT_FF_WORD_DEPTH): """Create a FieldsFile to Post Process instance that returns a generator of PPFields contained within the FieldsFile. - Args: - - * filename (string): + Parameters + ---------- + filename : str Specify the name of the FieldsFile. - - Kwargs: - - * read_data (boolean): + read_data : bool, optional Specify whether to read the associated PPField data within the FieldsFile. Default value is False. - Returns: - PPField generator. + Returns + ------- + PPField generator. - For example:: + Examples + -------- + :: >>> for field in ff.FF2PP(filename): ... print(field) @@ -809,15 +811,14 @@ def __iter__(self): def _parse_binary_stream(file_like, dtype=np.float64, count=-1): """Replacement :func:`numpy.fromfile` due to python3 performance issues. - Args: - - * file_like - Standard python file_like object. - - Kwargs: - - * dtype - Data type to be parsed out, used to work out bytes read in. - - * count - The number of values required to be generated from the parsing. + Parameters + ---------- + file_like : + Standard python file_like object. + dtype : no.float64, optional + Data type to be parsed out, used to work out bytes read in. + count : optional, default=-1 + The number of values required to be generated from the parsing. The default is -1, which will read the entire contexts of the file_like object and generate as many values as possible. @@ -842,15 +843,15 @@ def _parse_binary_stream(file_like, dtype=np.float64, count=-1): def load_cubes(filenames, callback, constraints=None): """Loads cubes from a list of fields files filenames. - Args: - - * filenames - list of fields files filenames to load - - Kwargs: - - * callback - a function which can be passed on to - :func:`iris.io.run_callback` + Parameters + ---------- + filenames : + List of fields files filenames to load + callback : + A function which can be passed on to :func:`iris.io.run_callback` + Notes + ----- .. note:: The resultant cubes may not be in the order that they are in the @@ -866,9 +867,10 @@ def load_cubes(filenames, callback, constraints=None): def load_cubes_32bit_ieee(filenames, callback, constraints=None): """Loads cubes from a list of 32bit ieee converted fieldsfiles filenames. - .. seealso:: - - :func:`load_cubes` for keyword details + See Also + -------- + :func:`load_cubes` + For keyword details """ return pp._load_cubes_variable_loader( diff --git a/lib/iris/fileformats/cf.py b/lib/iris/fileformats/cf.py index 737955b9a7..7bba1442da 100644 --- a/lib/iris/fileformats/cf.py +++ b/lib/iris/fileformats/cf.py @@ -5,7 +5,8 @@ """Provides the capability to load netCDF files and interpret them according to the 'NetCDF Climate and Forecast (CF) Metadata Conventions'. -References: +References +---------- [CF] NetCDF Climate and Forecast (CF) Metadata conventions. [NUG] NetCDF User's Guide, https://www.unidata.ucar.edu/software/netcdf/documentation/NUG/ @@ -112,22 +113,20 @@ def _identify_common(variables, ignore, target): def identify(self, variables, ignore=None, target=None, warn=True): """Identify all variables that match the criterion for this CF-netCDF variable class. - Args: - - * variables: + Parameters + ---------- + variables : Dictionary of netCDF4.Variable instance by variable name. - - Kwargs: - - * ignore: + ignore : optional, default=None List of variable names to ignore. - * target: + target : optional, default=None Name of a single variable to check. - * warn: + warn : optional, default=None Issue a warning if a missing variable is referenced. - Returns: - Dictionary of CFVariable instance by variable name. + Returns + ------- + Dictionary of CFVariable instance by variable name. """ pass @@ -139,13 +138,14 @@ def spans(self, cf_variable): Note that, by default scalar variables always span the dimensionality of the target variable. - Args: - - * cf_variable: + Parameters + ---------- + cf_variable : Compare dimensionality with the :class:`CFVariable`. - Returns: - Boolean. + Returns + ------- + bool """ result = set(self.dimensions).issubset(cf_variable.dimensions) @@ -215,15 +215,18 @@ def cf_attrs_reset(self): def add_formula_term(self, root, term): """Register the participation of this CF-netCDF variable in a CF-netCDF formula term. - Args: - - * root (string): - The name of CF-netCDF variable that defines the CF-netCDF formula_terms attribute. - * term (string): - The associated term name of this variable in the formula_terms definition. + Parameters + ---------- + root : str + The name of CF-netCDF variable that defines the CF-netCDF + formula_terms attribute. + term : str + The associated term name of this variable in the formula_terms + definition. - Returns: - None. + Returns + ------- + None """ self.cf_terms_by_root[root] = term @@ -231,8 +234,9 @@ def add_formula_term(self, root, term): def has_formula_terms(self): """Determine whether this CF-netCDF variable participates in a CF-netcdf formula term. - Returns: - Boolean. + Returns + ------- + bool """ return bool(self.cf_terms_by_root) @@ -375,13 +379,14 @@ def spans(self, cf_variable): Note that, by default scalar variables always span the dimensionality of the target variable. - Args: - - * cf_variable: + Parameters + ---------- + cf_variable : Compare dimensionality with the :class:`CFVariable`. - Returns: - Boolean. + Returns + ------- + bool """ # Scalar variables always span the target variable. @@ -446,13 +451,14 @@ def spans(self, cf_variable): Note that, by default scalar variables always span the dimensionality of the target variable. - Args: - - * cf_variable: + Parameters + ---------- + cf_variable : :class:`CFVariable` Compare dimensionality with the :class:`CFVariable`. - Returns: - Boolean. + Returns + ------- + bool """ # Scalar variables always span the target variable. @@ -678,13 +684,15 @@ def identify(cls, variables, ignore=None, target=None, warn=True): def cf_label_data(self, cf_data_var): """Return the associated CF-netCDF label variable strings. - Args: - - * cf_data_var (:class:`iris.fileformats.cf.CFDataVariable`): - The CF-netCDF data variable which the CF-netCDF label variable describes. + Parameters + ---------- + cf_data_var : :class:`iris.fileformats.cf.CFDataVariable` + The CF-netCDF data variable which the CF-netCDF label variable + describes. - Returns: - String labels. + Returns + ------- + str labels """ @@ -744,13 +752,15 @@ def cf_label_data(self, cf_data_var): def cf_label_dimensions(self, cf_data_var): """Return the name of the associated CF-netCDF label variable data dimensions. - Args: + Parameters + ---------- + cf_data_var : :class:`iris.fileformats.cf.CFDataVariable` + The CF-netCDF data variable which the CF-netCDF label variable + describes. - * cf_data_var (:class:`iris.fileformats.cf.CFDataVariable`): - The CF-netCDF data variable which the CF-netCDF label variable describes. - - Returns: - Tuple of label data dimension names. + Returns + ------- + Tuple of label data dimension names. """ @@ -775,13 +785,14 @@ def spans(self, cf_variable): Note that, by default scalar variables always span the dimensionality of the target variable. - Args: - - * cf_variable: + Parameters + ---------- + cf_variable : Compare dimensionality with the :class:`CFVariable`. - Returns: - Boolean. + Returns + ------- + bool """ # Scalar variables always span the target variable. diff --git a/lib/iris/fileformats/dot.py b/lib/iris/fileformats/dot.py index 3c24145073..83336a2249 100644 --- a/lib/iris/fileformats/dot.py +++ b/lib/iris/fileformats/dot.py @@ -343,7 +343,7 @@ def _dot_node(indent, id, name, attributes): The ID of the node. name : The visual name of the node. - attributes: + attributes : An iterable of (name, value) attribute pairs. """ # noqa: D410, D411 attributes = r"\n".join("%s: %s" % item for item in attributes) diff --git a/lib/iris/fileformats/name.py b/lib/iris/fileformats/name.py index 4742ec9001..3d01b07dee 100644 --- a/lib/iris/fileformats/name.py +++ b/lib/iris/fileformats/name.py @@ -46,18 +46,16 @@ def load_cubes(filenames, callback): """Return a generator of cubes given one or more filenames and an optional callback. - Args: - - * filenames (string/list): + Parameters + ---------- + filenames : str or list One or more NAME filenames to load. - - Kwargs: - - * callback (callable function): + callback : callable function, optional A function which can be passed on to :func:`iris.io.run_callback`. - Returns: - A generator of :class:`iris.cubes.Cube` instances. + Returns + ------- + A generator of :class:`iris.cubes.Cube` instances. """ from iris.io import run_callback diff --git a/lib/iris/fileformats/name_loaders.py b/lib/iris/fileformats/name_loaders.py index e6acb6aa66..3f4b2d13c6 100644 --- a/lib/iris/fileformats/name_loaders.py +++ b/lib/iris/fileformats/name_loaders.py @@ -45,16 +45,19 @@ def _split_name_and_units(name): def read_header(file_handle): - """Return a dictionary containing the header information extracted - from the the provided NAME file object. + """Return a dictionary containing the header information. - Args: + Return a dictionary containing the header information extracted + from the the provided NAME file object. - * file_handle (file-like object): + Parameters + ---------- + file_handle : file-like object A file-like object from which to read the header information. - Returns: - A dictionary containing the extracted header information. + Returns + ------- + A dictionary containing the extracted header information. """ header = {} @@ -221,13 +224,14 @@ def _parse_units(units): * Units where the characters used are non-standard (i.e. 'mc' for micro instead of 'u') - Args: - - * units (string): + Parameters + ---------- + units : str NAME units. - Returns: - An instance of :class:`cf_units.Unit`. + Returns + ------- + An instance of :class:`cf_units.Unit`. """ @@ -268,12 +272,14 @@ def _cf_height_from_name(z_coord, lower_bound=None, upper_bound=None): and flight level etc. This function returns an iris coordinate representing this field heading. - Args: - - * z_coord (list): + Parameters + ---------- + z_coord : list A field heading, specifically the z component. - Returns: + Returns + ------- + :class:`iris.coords.AuxCoord` An instance of :class:`iris.coords.AuxCoord` representing the interpretation of the supplied field heading. @@ -551,16 +557,18 @@ def _build_cell_methods(av_or_ints, coord): associated coordinate. If a given entry does not correspond to a cell method (e.g. "No time averaging"), a value of None is inserted. - Args: - - * av_or_ints (iterable of strings): + Parameters + ---------- + av_or_ints : iterable of str An iterable of strings containing the column heading entries to be parsed. - * coord (string or :class:`iris.coords.Coord`): + coord : str or :class:`iris.coords.Coord` The coordinate name (or :class:`iris.coords.Coord` instance) to which the column heading entries refer. - Returns: + Returns + ------- + list of :class:`iris.coords.CellMethod` or None. A list that is the same length as `av_or_ints` containing :class:`iris.coords.CellMethod` instances or values of None. @@ -586,13 +594,14 @@ def load_NAMEIII_field(filename): """Load a NAME III grid output file returning a generator of :class:`iris.cube.Cube` instances. - Args: - - * filename (string): + Parameters + ---------- + filename : str Name of file to load. - Returns: - A generator :class:`iris.cube.Cube` instances. + Returns + ------- + A generator :class:`iris.cube.Cube` instances. """ # Loading a file gives a generator of lines which can be progressed using @@ -677,16 +686,19 @@ def load_NAMEIII_field(filename): def load_NAMEII_field(filename): - """Load a NAME II grid output file returning a - generator of :class:`iris.cube.Cube` instances. + """Load a NAME II grid output file. - Args: + Load a NAME II grid output file returning a generator of + :class:`iris.cube.Cube` instances. - * filename (string): + Parameters + ---------- + filename : str Name of file to load. - Returns: - A generator :class:`iris.cube.Cube` instances. + Returns + ------- + A generator :class:`iris.cube.Cube` instances. """ with open(filename, "r") as file_handle: @@ -764,16 +776,19 @@ def load_NAMEII_field(filename): def load_NAMEIII_timeseries(filename): - """Load a NAME III time series file returning a - generator of :class:`iris.cube.Cube` instances. + """Load a NAME III time series file. - Args: + Load a NAME III time series file returning a generator of + :class:`iris.cube.Cube` instances. - * filename (string): + Parameters + ---------- + filename : str Name of file to load. - Returns: - A generator :class:`iris.cube.Cube` instances. + Returns + ------- + A generator :class:`iris.cube.Cube` instances. """ with open(filename, "r") as file_handle: @@ -852,16 +867,19 @@ def load_NAMEIII_timeseries(filename): def load_NAMEII_timeseries(filename): - """Load a NAME II Time Series file returning a - generator of :class:`iris.cube.Cube` instances. + """Load a NAME III time series file. - Args: + Load a NAME II Time Series file returning a generator of + :class:`iris.cube.Cube` instances. - * filename (string): + Parameters + ---------- + filename : str Name of file to load. - Returns: - A generator :class:`iris.cube.Cube` instances. + Returns + ------- + A generator :class:`iris.cube.Cube` instances. """ with open(filename, "r") as file_handle: @@ -922,16 +940,19 @@ def load_NAMEII_timeseries(filename): def load_NAMEIII_version2(filename): - """Load a NAME III version 2 file returning a - generator of :class:`iris.cube.Cube` instances. + """Load a NAME III version 2 file. - Args: + Load a NAME III version 2 file returning a generator of + :class:`iris.cube.Cube` instances. - * filename (string): + Parameters + ---------- + filename : str Name of file to load. - Returns: - A generator :class:`iris.cube.Cube` instances. + Returns + ------- + A generator :class:`iris.cube.Cube` instances. """ @@ -1141,16 +1162,19 @@ def load_NAMEIII_version2(filename): def load_NAMEIII_trajectory(filename): - """Load a NAME III trajectory file returning a - generator of :class:`iris.cube.Cube` instances. + """Load a NAME III trajectory file. - Args: + Load a NAME III trajectory file returning a generator of + :class:`iris.cube.Cube` instances. - * filename (string): + Parameters + ---------- + filename : str Name of file to load. - Returns: - A generator :class:`iris.cube.Cube` instances. + Returns + ------- + A generator :class:`iris.cube.Cube` instances. """ time_unit = cf_units.Unit("hours since epoch", calendar=cf_units.CALENDAR_STANDARD) diff --git a/lib/iris/fileformats/nimrod.py b/lib/iris/fileformats/nimrod.py index 3aea8b8b81..8cf109eed5 100644 --- a/lib/iris/fileformats/nimrod.py +++ b/lib/iris/fileformats/nimrod.py @@ -169,7 +169,8 @@ class NimrodField: Capable of converting itself into a :class:`~iris.cube.Cube` - References: + References + ---------- Met Office (2003): Met Office Rain Radar Data from the NIMROD System. NCAS British Atmospheric Data Centre, date of citation. https://catalogue.ceda.ac.uk/uuid/82adec1f896af6169112d09cc1174499 @@ -292,15 +293,15 @@ def _read_data(self, infile): def load_cubes(filenames, callback=None): """Loads cubes from a list of NIMROD filenames. - Args: - - * filenames - list of NIMROD filenames to load - - Kwargs: - - * callback - a function which can be passed on to - :func:`iris.io.run_callback` + Parameters + ---------- + filenames : + List of NIMROD filenames to load + callback : + A function which can be passed on to :func:`iris.io.run_callback` + Notes + ----- .. note:: The resultant cubes may not be in the same order as in the files. diff --git a/lib/iris/fileformats/pp_load_rules.py b/lib/iris/fileformats/pp_load_rules.py index 10da402520..e128ff0ad8 100644 --- a/lib/iris/fileformats/pp_load_rules.py +++ b/lib/iris/fileformats/pp_load_rules.py @@ -61,45 +61,34 @@ def _convert_vertical_coords( """Encode scalar or vector vertical level values from PP headers as CM data components. - Args: - - * lbcode: + Parameters + ---------- + lbcode : :class:`iris.fileformats.pp.SplittableInt` Scalar field :class:`iris.fileformats.pp.SplittableInt` value. - - * lbvc: + lbvc : Scalar field value. - - * blev: + blev : Scalar field value or :class:`numpy.ndarray` vector of field values. - - * lblev: + lblev : Scalar field value or :class:`numpy.ndarray` vector of field values. - - * stash: + stash : Scalar field :class:`iris.fileformats.pp.STASH` value. - - * bhlev: + bhlev : Scalar field value or :class:`numpy.ndarray` vector of field values. - - * bhrlev: + bhrlev : Scalar field value or :class:`numpy.ndarray` vector of field values. - - * brsvd1: + brsvd1 : Scalar field value or :class:`numpy.ndarray` vector of field values. - - * brsvd2: + brsvd2 : Scalar field value or :class:`numpy.ndarray` vector of field values. - - * brlev: + brlev : Scalar field value or :class:`numpy.ndarray` vector of field values. - - Kwargs: - - * dim: + dim : optional Associated dimension of the vertical coordinate. Defaults to None. - Returns: - A tuple containing a list of coords_and_dims, and a list of factories. + Returns + ------- + A tuple containing a list of coords_and_dims, and a list of factories. """ factories = [] @@ -311,9 +300,9 @@ def _reshape_vector_args(values_and_dims): can combine without broadcasting errors (provided that all inputs mapping to a dimension define the same associated length). - Args: - - * values_and_dims (iterable of (array-like, iterable of int)): + Parameters + ---------- + values_and_dims : iterable of (array-like, iterable of int) Input arrays with associated mapping dimension numbers. The length of each 'dims' must match the ndims of the 'value'. @@ -359,17 +348,15 @@ def _collapse_degenerate_points_and_bounds(points, bounds=None, rtol=1.0e-7): numbers from cftime.date2num, which has limited precision because of the way it calculates with floats of days. - Args: - - * points (:class:`numpy.ndarray`)): + Parameters + ---------- + points : :class:`numpy.ndarray` Array of points values. - - Kwargs: - - * bounds (:class:`numpy.ndarray`) + bounds : :class:`numpy.ndarray`, optional, default=None Array of bounds values. This array should have an additional vertex dimension (typically of length 2) when compared to the points array i.e. bounds.shape = points.shape + (nvertex,) + rtol : optional, default=1.0e-7 Returns ------- @@ -406,19 +393,16 @@ def _reduce_points_and_bounds(points, lower_and_upper_bounds=None): If the bounds arrays are also passed in, then all three arrays must have the same shape or be capable of being broadcast to match. - Args: - - * points (array-like): + Parameters + ---------- + points : array-like Coordinate point values. - - Kwargs: - - * lower_and_upper_bounds (pair of array-like, or None): + lower_and_upper_bounds : pair of array-like or None, optional Corresponding bounds values (lower, upper), if any. - Returns: - dims (iterable of ints), points(array), bounds(array) - + Returns + ------- + dims (iterable of ints), points(array), bounds(array) * 'dims' is the mapping from the result array dimensions to the original dimensions. However, when 'array' is scalar, 'dims' will be None (rather than an empty tuple). @@ -466,26 +450,21 @@ def _new_coord_and_dims( * the result coordinate may be an AuxCoord if a DimCoord cannot be made (e.g. if values are non-monotonic). - Args: - - * is_vector_operation (bool): + Parameters + ---------- + is_vector_operation : bool If True, perform 'vector' style operation. - - * points (array-like): + points : array-like Coordinate point values. - - * name (string): + name : str Standard name of coordinate. - - * units (string or cf_unit.Unit): + units : str or cf_unit.Unit Units of coordinate. - - Kwargs: - - * lower_and_upper_bounds (pair of array-like, or None): + lower_and_upper_bounds : pair of array-like or None, optional, default=None Corresponding bounds values (lower, upper), if any. - Returns: + Returns + ------- a new (coordinate, dims) pair. """ @@ -504,12 +483,15 @@ def _new_coord_and_dims( def _epoch_date_hours_internals(epoch_hours_unit, datetime): """Return an 'hours since epoch' number for a date. - Args: - * epoch_hours_unit (:class:`cf_unit.Unit'): + Parameters + ---------- + epoch_hours_unit : :class:`cf_unit.Unit' Unit defining the calendar and zero-time of conversion. - * datetime (:class:`datetime.datetime`-like): + datetime : :class:`datetime.datetime`-like Date object containing year / month / day attributes. + Notes + ----- This routine can also handle dates with a zero year, month or day : such dates were valid inputs to 'date2num' up to cftime version 1.0.1, but are now illegal : This routine interprets any zeros as being "1 year/month/day @@ -612,24 +594,21 @@ def _convert_time_coords( ): """Make time coordinates from the time metadata. - Args: - - * lbcode(:class:`iris.fileformats.pp.SplittableInt`): + Parameters + ---------- + lbcode : :class:`iris.fileformats.pp.SplittableInt` Scalar field value. - * lbtim (:class:`iris.fileformats.pp.SplittableInt`): + lbtim : :class:`iris.fileformats.pp.SplittableInt` Scalar field value. - * epoch_hours_unit (:class:`cf_units.Unit`): + epoch_hours_unit : :class:`cf_units.Unit` Epoch time reference unit. - * t1 (array-like or scalar): + t1 : array-like or scalar Scalar field value or an array of values. - * t2 (array-like or scalar): + t2 : array-like or scalar Scalar field value or an array of values. - * lbft (array-like or scalar): + lbft : array-like or scalar Scalar field value or an array of values. - - Kwargs: - - * t1_dims, t2_dims, lbft_dims (tuples of int): + t1_dims, t2_dims, lbft_dims : tuples of int, optional Cube dimension mappings for the array metadata. Each default to to (). The length of each dims tuple should equal the dimensionality of the corresponding array of values. @@ -824,13 +803,14 @@ def date2year(t_in): def _model_level_number(lblev): """Return model level number for an LBLEV value. - Args: - - * lblev (int): + Parameters + ---------- + lblev : int PP field LBLEV value. Returns: - Model level number (integer). + ------- + Model level number (int). """ # See Word no. 33 (LBLEV) in section 4 of UM Model Docs (F3). @@ -876,13 +856,13 @@ def _convert_scalar_pseudo_level_coords(lbuser5): def convert(f): """Converts a PP field into the corresponding items of Cube metadata. - Args: - - * f: - A :class:`iris.fileformats.pp.PPField` object. + Parameters + ---------- + f : :class:`iris.fileformats.pp.PPField` - Returns: - A :class:`iris.fileformats.rules.ConversionMetadata` object. + Returns + ------- + :class:`iris.fileformats.rules.ConversionMetadata` object. """ factories = [] diff --git a/lib/iris/fileformats/pp_save_rules.py b/lib/iris/fileformats/pp_save_rules.py index 60eef7ad96..ab9d1c9545 100644 --- a/lib/iris/fileformats/pp_save_rules.py +++ b/lib/iris/fileformats/pp_save_rules.py @@ -26,12 +26,16 @@ def _basic_coord_system_rules(cube, pp): """Rules for setting the coord system of the PP field. - Args: - cube: the cube being saved as a series of PP fields. + Parameters + ---------- + cube : + The cube being saved as a series of PP fields. pp: the current PP field having save rules applied. + pp : - Returns: - The PP field with updated metadata. + Returns + ------- + The PP field with updated metadata. """ if cube.coord_system("GeogCS") is not None or cube.coord_system(None) is None: @@ -76,12 +80,16 @@ def _um_version_rules(cube, pp): def _stash_rules(cube, pp): """Attributes rules for setting the STASH attribute of the PP field. - Args: - cube: the cube being saved as a series of PP fields. - pp: the current PP field having save rules applied. + Parameters + ---------- + cube : + The cube being saved as a series of PP fields. + pp : + The current PP field having save rules applied. - Returns: - The PP field with updated metadata. + Returns + ------- + The PP field with updated metadata. """ if "STASH" in cube.attributes: @@ -95,12 +103,16 @@ def _stash_rules(cube, pp): def _general_time_rules(cube, pp): """Rules for setting time metadata of the PP field. - Args: - cube: the cube being saved as a series of PP fields. - pp: the current PP field having save rules applied. + Parameters + ---------- + cube : + The cube being saved as a series of PP fields. + pp : + The current PP field having save rules applied. - Returns: - The PP field with updated metadata. + Returns + ------- + The PP field with updated metadata. """ time_coord = scalar_coord(cube, "time") @@ -365,12 +377,16 @@ def _general_time_rules(cube, pp): def _calendar_rules(cube, pp): """Rules for setting the calendar of the PP field. - Args: - cube: the cube being saved as a series of PP fields. - pp: the current PP field having save rules applied. + Parameters + ---------- + cube : + The cube being saved as a series of PP fields. + pp : + The current PP field having save rules applied. - Returns: - The PP field with updated metadata. + Returns + ------- + The PP field with updated metadata. """ time_coord = scalar_coord(cube, "time") @@ -387,12 +403,16 @@ def _calendar_rules(cube, pp): def _grid_and_pole_rules(cube, pp): """Rules for setting the horizontal grid and pole location of the PP field. - Args: - cube: the cube being saved as a series of PP fields. - pp: the current PP field having save rules applied. + Parameters + ---------- + cube : + The cube being saved as a series of PP fields. + pp : + The current PP field having save rules applied. - Returns: - The PP field with updated metadata. + Returns + ------- + The PP field with updated metadata. """ lon_coord = vector_coord(cube, "longitude") @@ -465,12 +485,16 @@ def _grid_and_pole_rules(cube, pp): def _non_std_cross_section_rules(cube, pp): """Rules for applying non-standard cross-sections to the PP field. - Args: - cube: the cube being saved as a series of PP fields. - pp: the current PP field having save rules applied. + Parameters + ---------- + cube: + The cube being saved as a series of PP fields. + pp: + The current PP field having save rules applied. - Returns: - The PP field with updated metadata. + Returns + ------- + The PP field with updated metadata. """ # Define commonly-used coords. @@ -594,12 +618,16 @@ def _lbproc_rules(cube, pp): Note: `pp.lbproc` must be set to 0 before these rules are run. - Args: - cube: the cube being saved as a series of PP fields. - pp: the current PP field having save rules applied. + Parameters + ---------- + cube: + The cube being saved as a series of PP fields. + pp: + The current PP field having save rules applied. - Returns: - The PP field with updated metadata. + Returns + ------- + The PP field with updated metadata. """ # Basic setting (this may be overridden by subsequent rules). @@ -636,12 +664,16 @@ def _lbproc_rules(cube, pp): def _vertical_rules(cube, pp): """Rules for setting vertical levels for the PP field. - Args: - cube: the cube being saved as a series of PP fields. - pp: the current PP field having save rules applied. + Parameters + ---------- + cube : + The cube being saved as a series of PP fields. + pp : + The current PP field having save rules applied. - Returns: - The PP field with updated metadata. + Returns + ------- + The PP field with updated metadata. """ # Define commonly-used coords. @@ -820,12 +852,16 @@ def _all_other_rules(cube, pp): * lbfc (field code) * lbrsvd[3] (ensemble member number) - Args: - cube: the cube being saved as a series of PP fields. - pp: the current PP field having save rules applied. + Parameters + ---------- + cube : + The cube being saved as a series of PP fields. + pp : + The current PP field having save rules applied. - Returns: - The PP field with updated metadata. + Returns + ------- + The PP field with updated metadata. """ # "CFNAME mega-rule." diff --git a/lib/iris/fileformats/rules.py b/lib/iris/fileformats/rules.py index e2bfd250fd..e092fa2b9b 100644 --- a/lib/iris/fileformats/rules.py +++ b/lib/iris/fileformats/rules.py @@ -253,16 +253,14 @@ class Loader(collections.namedtuple("Loader", _loader_attrs)): def __new__(cls, field_generator, field_generator_kwargs, converter): """Create a definition of a field-based Cube loader. - Args: - - * field_generator + Parameters + ---------- + field_generator : A callable that accepts a filename as its first argument and returns an iterable of field objects. - - * field_generator_kwargs + field_generator_kwargs : Additional arguments to be passed to the field_generator. - - * converter + converter : A callable that converts a field object into a Cube. """ @@ -388,17 +386,17 @@ def load_pairs_from_fields(fields, converter): """Convert an iterable of fields into an iterable of Cubes using the provided converter. - Args: - - * fields: + Parameters + ---------- + fields : An iterable of fields. - - * converter: + converter : An Iris converter function, suitable for use with the supplied fields. See the description in :class:`iris.fileformats.rules.Loader`. - Returns: - An iterable of (:class:`iris.cube.Cube`, field) pairs. + Returns + ------- + An iterable of (:class:`iris.cube.Cube`, field) pairs. """ return _load_pairs_from_fields_and_filenames( diff --git a/lib/iris/fileformats/um/_fast_load.py b/lib/iris/fileformats/um/_fast_load.py index 477a221727..6940bfed9c 100644 --- a/lib/iris/fileformats/um/_fast_load.py +++ b/lib/iris/fileformats/um/_fast_load.py @@ -49,12 +49,11 @@ class FieldCollation(BasicFieldCollation): def __init__(self, fields, filepath): """FieldCollation initialise. - Args: - - * fields (iterable of :class:`iris.fileformats.pp.PPField`): + Parameters + ---------- + fields : iterable of :class:`iris.fileformats.pp.PPField` The fields in the collation. - - * filepath (string): + filepath : str The path of the file the collation is loaded from. """ @@ -72,8 +71,9 @@ def data_field_indices(self): This records the original file location of the individual data fields contained, within the input datafile. - Returns: - An integer array of shape `self.vector_dims_shape`. + Returns + ------- + An integer array of shape `self.vector_dims_shape`. """ # Get shape : N.B. this calculates (and caches) the structure. @@ -157,15 +157,19 @@ def _convert_collation(collation): """Converts a FieldCollation into the corresponding items of Cube metadata. - Args: - - * collation: + Parameters + ---------- + collation : A FieldCollation object. - Returns: - A :class:`iris.fileformats.rules.ConversionMetadata` object. + Returns + ------- + A :class:`iris.fileformats.rules.ConversionMetadata` object. + Notes + ----- .. note: + This is the 'loader.converter', in the control structure passed to the generic rules code, :meth:`iris.fileformats.rules.load_cubes`. diff --git a/lib/iris/fileformats/um/_fast_load_structured_fields.py b/lib/iris/fileformats/um/_fast_load_structured_fields.py index 41ec8720bc..81bec94f79 100644 --- a/lib/iris/fileformats/um/_fast_load_structured_fields.py +++ b/lib/iris/fileformats/um/_fast_load_structured_fields.py @@ -47,9 +47,9 @@ class BasicFieldCollation: def __init__(self, fields): """BasicFieldCollation initialise. - Args: - - * fields (iterable of :class:`iris.fileformats.pp.PPField`): + Parameters + ---------- + fields : iterable of :class:`iris.fileformats.pp.PPField` The fields in the collation. """ @@ -267,37 +267,39 @@ def group_structured_fields( """Collect structured fields into identified groups whose fields can be combined to form a single cube. - Args: - - * field_iterator (iterator of :class:`iris.fileformats.pp.PPField`): + Parameters + ---------- + field_iterator : iterator of :class:`iris.fileformats.pp.PPField` A source of PP or FF fields. N.B. order is significant. - - Kwargs: - - * collation_class (class): + collation_class : class, optional, default=BasicFieldCollation Type of collation wrapper to create from each group of fields. - * collation_kwargs (dict): + **collation_kwargs : dict Additional constructor keywords for collation creation. - The function sorts and collates on phenomenon-relevant metadata only, - defined as the field components: 'lbuser[3]' (stash), 'lbproc' (statistic), - 'lbuser[6]' (model). - Each distinct combination of these defines a specific phenomenon (or - statistical aggregation of one), and those fields appear as a single - iteration result. - Implicitly, within each result group, *all* other metadata components should be either: - * the same for all fields, - * completely irrelevant, or - * used by a vectorised rule function (such as - :func:`iris.fileformats.pp_load_rules._convert_time_coords`). + * the same for all fields, + * completely irrelevant, or + * used by a vectorised rule function (such as + :func:`iris.fileformats.pp_load_rules._convert_time_coords`). - Returns: + Returns + ------- + Generator of 'collation_class' objects A generator of 'collation_class' objects, each of which contains a single collated group from the input fields. + Notes + ----- + The function sorts and collates on phenomenon-relevant metadata only, + defined as the field components: 'lbuser[3]' (stash), 'lbproc' (statistic), + 'lbuser[6]' (model). + + Each distinct combination of these defines a specific phenomenon (or + statistical aggregation of one), and those fields appear as a single + iteration result. + .. note:: At present, fields with different values of 'lbuser[4]' (pseudo-level) diff --git a/lib/iris/fileformats/um/_ff_replacement.py b/lib/iris/fileformats/um/_ff_replacement.py index d726f63a10..8ceb30bb92 100644 --- a/lib/iris/fileformats/um/_ff_replacement.py +++ b/lib/iris/fileformats/um/_ff_replacement.py @@ -19,21 +19,22 @@ def um_to_pp(filename, read_data=False, word_depth=None): Returns an iterator over the fields contained within the FieldsFile, returned as :class:`iris.fileformats.pp.PPField` instances. - Args: - - * filename (string): + Parameters + ---------- + filename : str Specify the name of the FieldsFile. - - Kwargs: - - * read_data (boolean): + read_data : bool, optional, default=read_data Specify whether to read the associated PPField data within the FieldsFile. Default value is False. + word_depth : optional, default=None - Returns: - Iteration of :class:`iris.fileformats.pp.PPField`. + Returns + ------- + Iteration of :class:`iris.fileformats.pp.PPField`. - For example:: + Examples + -------- + :: >>> for field in um.um_to_pp(filename): ... print(field) @@ -52,15 +53,17 @@ def um_to_pp(filename, read_data=False, word_depth=None): def load_cubes(filenames, callback, constraints=None, _loader_kwargs=None): """Loads cubes from filenames of UM fieldsfile-like files. - Args: - - * filenames - list of filenames to load - - Kwargs: - - * callback - a function which can be passed on to - :func:`iris.io.run_callback` - + Parameters + ---------- + filenames : + list of filenames to load + callback : + A function which can be passed on to :func:`iris.io.run_callback` + constraints : optional, default=None + _loader_kwargs : optional, default=None + + Notes + ----- .. note:: The resultant cubes may not be in the order that they are in the @@ -81,9 +84,10 @@ def load_cubes_32bit_ieee(filenames, callback, constraints=None): """Loads cubes from filenames of 32bit ieee converted UM fieldsfile-like files. - .. seealso:: - - :func:`load_cubes` for keyword details + See Also + -------- + :func:`load_cubes` + For keyword details """ return load_cubes( diff --git a/lib/iris/fileformats/um/_optimal_array_structuring.py b/lib/iris/fileformats/um/_optimal_array_structuring.py index ce2cba7d5c..1e58a33f41 100644 --- a/lib/iris/fileformats/um/_optimal_array_structuring.py +++ b/lib/iris/fileformats/um/_optimal_array_structuring.py @@ -18,13 +18,12 @@ def _optimal_dimensioning_structure(structure, element_priorities): in more than one structure options then dimension priorities as specified by `element_priorities` are used to determine optimal structure. - Args: - - * structure: + Parameters + ---------- + structure : A set of structure options, as provided by :class:\ `~iris.fileformats._structured_array_identification.GroupStructure`. - - * element_priorities: + element_priorities : A dictionary mapping structure element names to their priority as defined by their input order to :func:`~optimal_array_structure`. @@ -52,37 +51,40 @@ def _optimal_dimensioning_structure(structure, element_priorities): def optimal_array_structure(ordering_elements, actual_values_elements=None): """Calculate an optimal array replication structure for a set of vectors. - Args: - - * ordering_elements (iterable of (name, 1-d array)): + Parameters + ---------- + ordering_elements : iterable of (name, 1-d array) Input element names and value-vectors. Must all be the same length (but not necessarily type). Must have at least one. - Kwargs: + .. note:: - * actual_values_elements (iterable of (name, 1-d array)): + The 'ordering_elements' arg contains the pattern used to deduce a + structure. The order of this is significant, in that earlier + elements get priority when associating dimensions with specific + elements. + + actual_values_elements : iterable of (name, 1-d array), optional, default=None The 'real' values used to construct the result arrays, if different from 'ordering_elements'. Must contain all the same names (but not necessarily in the same order). - The 'ordering_elements' arg contains the pattern used to deduce a - structure. The order of this is significant, in that earlier elements get - priority when associating dimensions with specific elements. - - Returns: - dims_shape, primary_elements, element_arrays_and_dims, where: - - * 'dims_shape' is the shape of the vector dimensions chosen. - - * 'primary_elements' is a set of dimension names; the names of input - elements that are identified as dimensions. At most one for each - dimension. - - * 'element_arrays_and_dims' is a dictionary [name: (array, dims)], - for all elements that are not dimensionless. Each array is reduced - to the shape of its mapped dimension. - - For example:: + Returns + ------- + dims_shape + Shape of the vector dimensions chosen. + primary_elements + Set of dimension names; the names of input + elements that are identified as dimensions. At most one for each + dimension. + element_arrays_and_dims + A dictionary [name: (array, dims)], + for all elements that are not dimensionless. Each array is reduced + to the shape of its mapped dimension. + + Examples + -------- + :: >>> import iris.fileformats.um._optimal_array_structuring as optdims >>> elements_structure = [('a', np.array([1, 1, 1, 2, 2, 2])), diff --git a/lib/iris/iterate.py b/lib/iris/iterate.py index 41b3929464..12e619b79f 100644 --- a/lib/iris/iterate.py +++ b/lib/iris/iterate.py @@ -25,30 +25,28 @@ def izip(*cubes, **kwargs): resulting iterator will step through combinations of the associated coordinates. - Args: - - * cubes (:class:`iris.cube.Cube`): + Parameters + ---------- + cubes : :class:`iris.cube.Cube` One or more :class:`iris.cube.Cube` instances over which to iterate in step. Each cube should be provided as a separate argument e.g. ``iris.iterate.izip(cube_a, cube_b, cube_c, ...)``. - - Kwargs: - - * coords (string, coord or a list of strings/coords): + coords : str, coord or a list of strings/coords Coordinate names/coordinates of the desired subcubes (i.e. those that are not iterated over). They must all be orthogonal (i.e. point to different dimensions). - * ordered (Boolean): + ordered : bool, optional If True (default), the order of the coordinates in the resulting subcubes will match the order of the coordinates in the coords keyword argument. If False, the order of the coordinates will be preserved and will match that of the input cubes. - Returns: - An iterator over a collection of tuples that contain the resulting - subcubes. + Returns + ------- + An iterator over a collection of tuples that contain the resulting subcubes. - For example: + Examples + -------- >>> e_content, e_density = iris.load_cubes( ... iris.sample_data_path('space_weather.nc'), ... ['total electron content', 'electron density']) @@ -61,6 +59,7 @@ def izip(*cubes, **kwargs): ----- 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 3180f1e02a..078d9b73ba 100644 --- a/lib/iris/palette.py +++ b/lib/iris/palette.py @@ -2,9 +2,10 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Load, configure and register color map palettes and initialise -color map meta-data mappings. +"""Color map pallettes management. +Load, configure and register color map palettes and initialise +color map meta-data mappings. """ from functools import wraps @@ -37,13 +38,14 @@ def is_brewer(cmap): """Determine whether the color map is a Cynthia Brewer color map. - Args: - - * cmap: + Parameters + ---------- + cmap : The color map instance. - Returns: - Boolean. + Returns + ------- + bool """ result = False @@ -53,8 +55,11 @@ def is_brewer(cmap): def _default_cmap_norm(args, kwargs): - """This function injects default cmap and norm behaviour into the keyword + """Injects default cmap and norm behaviour into the keyword arguments. + + This function injects default cmap and norm behaviour into the keyword arguments, based on the cube referenced within the positional arguments. + """ cube = None @@ -103,16 +108,20 @@ def _default_cmap_norm(args, kwargs): def cmap_norm(cube): - """Determine the default :class:`matplotlib.colors.LinearSegmentedColormap` + """Determine the default. + + Determine the default :class:`matplotlib.colors.LinearSegmentedColormap` and :class:`iris.palette.SymmetricNormalize` instances associated with the cube. - Args: - - * cube (:class:`iris.cube.Cube`): + Parameters + ---------- + cube : :class:`iris.cube.Cube` Source cube to generate default palette from. - Returns: + Returns + ------- + tuple Tuple of :class:`matplotlib.colors.LinearSegmentedColormap` and :class:`iris.palette.SymmetricNormalize` @@ -127,25 +136,25 @@ def cmap_norm(cube): def auto_palette(func): - """Decorator wrapper function to control the default behaviour of the - matplotlib cmap and norm keyword arguments. + """Decorator wrapper function to control the default behaviour. - Args: + Decorator wrapper function to control the default behaviour of the + matplotlib cmap and norm keyword arguments. - * func (callable): + Parameters + ---------- + func : callable Callable function to be wrapped by the decorator. - Returns: - Closure wrapper function. + Returns + ------- + Closure wrapper function. """ @wraps(func) def wrapper_func(*args, **kwargs): - """Closure wrapper function to provide default keyword argument - behaviour. - - """ + """Closure wrapper function to provide default keyword argument behaviour.""" # Update the keyword arguments with defaults. args, kwargs = _default_cmap_norm(args, kwargs) # Call the wrapped function and return its result. @@ -211,7 +220,9 @@ def vmax(self, val): def _load_palette(): - """Load, configure and register color map palettes and initialise + """Load palette. + + Load, configure and register color map palettes and initialise color map metadata mappings. """ diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py index 94c26ef45f..bcf42d9be9 100644 --- a/lib/iris/tests/__init__.py +++ b/lib/iris/tests/__init__.py @@ -155,14 +155,11 @@ def assert_masked_array_equal(a, b, strict=False): """Check that masked arrays are equal. This requires the unmasked values and masks to be identical. - Args: - - * a, b (array-like): + Parameters + ---------- + a, b : array-like Two arrays to compare. - - Kwargs: - - * strict (bool): + strict : bool, optional If True, perform a complete mask and data array equality check. If False (default), the data array equality considers only unmasked elements. @@ -176,19 +173,15 @@ def assert_masked_array_almost_equal(a, b, decimal=6, strict=False): masks to be identical, and the unmasked values to be almost equal. - Args: - - * a, b (array-like): + Parameters + ---------- + a, b : array-like Two arrays to compare. - - Kwargs: - - * strict (bool): + strict : bool, optional If True, perform a complete mask and data array equality check. If False (default), the data array equality considers only unmasked elements. - - * decimal (int): + decimal : int, optional, default=6 Equality tolerance level for :meth:`numpy.testing.assert_array_almost_equal`, with the meaning 'abs(desired-actual) < 0.5 * 10**(-decimal)' @@ -278,11 +271,12 @@ def result_path(self, basename=None, ext=""): """Return the full path to a test result, generated from the \ calling file, class and, optionally, method. - Optional kwargs : - - * basename - File basename. If omitted, this is \ - generated from the calling method. - * ext - Appended file extension. + Parameters + ---------- + basename : optional, default=None + File basename. If omitted, this is generated from the calling method. + ext : str, optional, default="" + Appended file extension. """ if ext and not ext.startswith("."): @@ -333,20 +327,16 @@ def assertCDL(self, netcdf_filename, reference_filename=None, flags="-h"): If the environment variable IRIS_TEST_CREATE_MISSING is non-empty, the reference file is created if it doesn't exist. - Args: - - * netcdf_filename: + Parameters + ---------- + netcdf_filename : The path to the netCDF file. - - Kwargs: - - * reference_filename: + reference_filename : optional, default=None The relative path (relative to the test results directory). If omitted, the result is generated from the calling method's name, class, and module using :meth:`iris.tests.IrisTest.result_path`. - - * flags: + flags : str, optional Command-line flags for `ncdump`, as either a whitespace separated string or an iterable. Defaults to '-h'. @@ -401,20 +391,16 @@ def assertCML(self, cubes, reference_filename=None, checksum=True): If the environment variable IRIS_TEST_CREATE_MISSING is non-empty, the reference file is created if it doesn't exist. - Args: - - * cubes: + Parameters + ---------- + cubes : Either a Cube or a sequence of Cubes. - - Kwargs: - - * reference_filename: + reference_filename : optional, default=None The relative path (relative to the test results directory). If omitted, the result is generated from the calling method's name, class, and module using :meth:`iris.tests.IrisTest.result_path`. - - * checksum: + checksum : bool, optional When True, causes the CML to include a checksum for each Cube's data. Defaults to True. @@ -514,14 +500,11 @@ def assertString(self, string, reference_filename=None): If the environment variable IRIS_TEST_CREATE_MISSING is non-empty, the reference file is created if it doesn't exist. - Args: - - * string: + Parameters + ---------- + string : str The string to check. - - Kwargs: - - * reference_filename: + reference_filename : optional, default=None The relative path (relative to the test results directory). If omitted, the result is generated from the calling method's name, class, and module using @@ -630,16 +613,15 @@ def assertArrayAlmostEqual(self, a, b, decimal=6): def assertArrayAllClose(self, a, b, rtol=1.0e-7, atol=1.0e-8, **kwargs): """Check arrays are equal, within given relative + absolute tolerances. - Args: - - * a, b (array-like): + Parameters + ---------- + a, b : array-like Two arrays to compare. - - Kwargs: - - * rtol, atol (float): + rtol, atol : float, optional Relative and absolute tolerances to apply. + Other Parameters + ---------------- Any additional kwargs are passed to numpy.testing.assert_allclose. Performs pointwise toleranced comparison, and raises an assertion if @@ -776,10 +758,13 @@ def patch(self, *args, **kwargs): The patch is created with mock.patch(*args, **kwargs). - Returns: - The substitute object returned by patch.start(). + Returns + ------- + The substitute object returned by patch.start(). - For example:: + Examples + -------- + :: mock_call = self.patch('module.Class.call', return_value=1) module_Class_instance.call(3, 4) diff --git a/lib/iris/tests/integration/test_netcdf__loadsaveattrs.py b/lib/iris/tests/integration/test_netcdf__loadsaveattrs.py index dcf61a947f..226babc9fb 100644 --- a/lib/iris/tests/integration/test_netcdf__loadsaveattrs.py +++ b/lib/iris/tests/integration/test_netcdf__loadsaveattrs.py @@ -4,7 +4,8 @@ # See LICENSE in the root of the repository for full licensing details. """Integration tests for loading and saving netcdf file attributes. -Notes: +Notes +----- (1) attributes in netCDF files can be either "global attributes", or variable ("local") type. @@ -178,6 +179,7 @@ def make_tempdir(self, tmp_path_factory): N.B. "tmp_path_factory" is a standard PyTest fixture, which provides a dirpath *shared* by all tests. This is a bit quicker and more debuggable than having a directory per-testcase. + """ # Store the temporary directory path on the test instance self.tmpdir = str(tmp_path_factory.getbasetemp()) @@ -220,6 +222,7 @@ def create_testcase_files_or_cubes( Note: 'var_values_file' args are dictionaries. The named variables are created, with an attribute = the dictionary value, *except* that a dictionary value of None means that a local attribute is _not_ created on the variable. + """ # save attribute on the instance self.attrname = attr_name @@ -307,6 +310,8 @@ def run_testcase( create_cubes_or_files : str, default "files" create either cubes or testfiles. + Notes + ----- If ``create_cubes_or_files`` == "files", create one temporary netCDF file per values-list, and record in ``self.input_filepaths``. Else if ``create_cubes_or_files`` == "cubes", create sets of cubes with common diff --git a/lib/iris/tests/stock/mesh.py b/lib/iris/tests/stock/mesh.py index aafd8b6c20..3520436f66 100644 --- a/lib/iris/tests/stock/mesh.py +++ b/lib/iris/tests/stock/mesh.py @@ -27,16 +27,17 @@ def sample_mesh(n_nodes=None, n_faces=None, n_edges=None, lazy_values=False): Mesh has nodes, plus faces and/or edges, with face-coords and edge-coords, numbers of which can be controlled. - Args: - * n_nodes (int or None): + Parameters + ---------- + n_nodes : int or None Number of nodes in mesh. Default is 15. Cannot be 0. - * n_edges (int or None): + n_edges : int or None Number of edges in mesh. Default is 5. If not 0, edge coords and an 'edge_node_connectivity' are included. - * n_faces (int or None): + n_faces : int or None Number of faces in mesh. Default is 3. If not 0, face coords and a 'face_node_connectivity' are included. - * lazy_values (bool): + lazy_values : bool, default=False If True, all content values of coords and connectivities are lazy. """ @@ -124,25 +125,34 @@ def sample_meshcoord(mesh=None, location="face", axis="x", **extra_kwargs): def sample_mesh_cube(nomesh_faces=None, n_z=2, with_parts=False, **meshcoord_kwargs): """Create a 2d test cube with 1 'normal' and 1 unstructured dimension (with a Mesh). - Result contains : dimcoords for both dims; an auxcoord on the unstructured dim; 2 mesh-coords. - By default, the mesh is provided by :func:`sample_mesh`, so coordinates and connectivity are not realistic. + Result contains : dimcoords for both dims; an auxcoord on the unstructured + dim; 2 mesh-coords. - Kwargs: - * nomesh_faces (int or None): + By default, the mesh is provided by :func:`sample_mesh`, so coordinates + and connectivity are not realistic. + + Parameters + ---------- + nomesh_faces : int or None, optional, default=None If set, don't add MeshCoords, so dim 1 is just a plain anonymous dim. Set its length to the given value. - * n_z (int): + n_z : int, optional, default=2 Length of the 'normal' dim. If 0, it is *omitted*. - * with_parts (bool): + with_parts : bool, optional, default=False If set, return all the constituent component coords - * meshcoord_kwargs (dict): - Extra controls passed to :func:`sample_meshcoord` for MeshCoord creation, to allow user-specified - location/mesh. The 'axis' key is not available, as we always add both an 'x' and 'y' MeshCOord. - - Returns: - * cube : if with_parts not set - * (cube, parts) : if with_parts is set - 'parts' is (mesh, dim0-dimcoord, dim1-dimcoord, dim1-auxcoord, x-meshcoord [or None], y-meshcoord [or None]). + **meshcoord_kwargs : dict, optional + Extra controls passed to :func:`sample_meshcoord` for MeshCoord + creation, to allow user-specified location/mesh. The 'axis' key is + not available, as we always add both an 'x' and 'y' MeshCOord. + + Returns + ------- + cube + if with_parts not set + (cube, parts) + if with_parts is set + 'parts' is (mesh, dim0-dimcoord, dim1-dimcoord, dim1-auxcoord, + x-meshcoord [or None], y-meshcoord [or None]). """ nomesh = nomesh_faces is not None diff --git a/lib/iris/tests/test_concatenate.py b/lib/iris/tests/test_concatenate.py index f08680c698..0d13b17cf3 100644 --- a/lib/iris/tests/test_concatenate.py +++ b/lib/iris/tests/test_concatenate.py @@ -35,48 +35,37 @@ def _make_cube( ): """A convenience test function that creates a custom 2D cube. - Args: - - * x: - A (start, stop, step) tuple for specifying the - x-axis dimensional coordinate points. Bounds are - automatically guessed. - - * y: - A (start, stop, step) tuple for specifying the - y-axis dimensional coordinate points. Bounds are - automatically guessed. - - * data: + Parameters + ---------- + x : + A (start, stop, step) tuple for specifying the x-axis dimensional + coordinate points. Bounds are automatically guessed. + y : + A (start, stop, step) tuple for specifying the y-axis dimensional + coordinate points. Bounds are automatically guessed. + data : The data payload for the cube. - - Kwargs: - - * aux: + aux : optional, default=None A CSV string specifying which points only auxiliary coordinates to create. Accepts either of 'x', 'y', 'xy'. - - * cell_measure: + cell_measure : optional, default=None A CSV string specifying which points only cell measures coordinates to create. Accepts either of 'x', 'y', 'xy'. - - * ancil: + ancil : optional, default=None A CSV string specifying which points only ancillary variables coordinates to create. Accepts either of 'x', 'y', 'xy'. - - * derived: + derived : optional, default=None A CSV string specifying which points only derived coordinates coordinates to create. Accepts either of 'x', 'y', 'xy'. - - * offset: + offset : int, optional, default=0 Offset value to be added to the 'xy' auxiliary coordinate points. - - * scalar: + scalar : optional, default=None Create a 'height' scalar coordinate with the given value. - Returns: - The newly created 2D :class:`iris.cube.Cube`. + Returns + ------- + The newly created 2D :class:`iris.cube.Cube`. """ x_range = np.arange(*x, dtype=np.float32) @@ -170,39 +159,30 @@ def _make_cube( def _make_cube_3d(x, y, z, data, aux=None, offset=0): """A convenience test function that creates a custom 3D cube. - Args: - - * x: - A (start, stop, step) tuple for specifying the - x-axis dimensional coordinate points. Bounds are - automatically guessed. - - * y: - A (start, stop, step) tuple for specifying the - y-axis dimensional coordinate points. Bounds are - automatically guessed. - - * z: - A (start, stop, step) tuple for specifying the - z-axis dimensional coordinate points. Bounds are - automatically guessed. - - * data: + Parameters + ---------- + x : + A (start, stop, step) tuple for specifying the x-axis dimensional + coordinate points. Bounds are automatically guessed. + y : + A (start, stop, step) tuple for specifying the y-axis dimensional + coordinate points. Bounds are automatically guessed. + z : + A (start, stop, step) tuple for specifying the z-axis dimensional + coordinate points. Bounds are automatically guessed. + data : The data payload for the cube. - - Kwargs: - - * aux: + aux : optional, default=None A CSV string specifying which points only auxiliary coordinates to create. Accepts either of 'x', 'y', 'z', 'xy', 'xz', 'yz', 'xyz'. - - * offset: + offset : int, optional, default=0 Offset value to be added to non-1D auxiliary coordinate points. Returns: - The newly created 3D :class:`iris.cube.Cube`. + ------- + The newly created 3D :class:`iris.cube.Cube`. """ x_range = np.arange(*x, dtype=np.float32) diff --git a/lib/iris/tests/test_cube_to_pp.py b/lib/iris/tests/test_cube_to_pp.py index 704e82539b..e75edee9cd 100644 --- a/lib/iris/tests/test_cube_to_pp.py +++ b/lib/iris/tests/test_cube_to_pp.py @@ -268,8 +268,10 @@ class FakePPEnvironment: def geog_cs(self): """Return a GeogCS for this PPField. - Returns: - A GeogCS with the appropriate earth shape, meridian and pole position. + Returns + ------- + A GeogCS with the appropriate earth shape, meridian and pole position. + """ return iris.coord_systems.GeogCS(6371229.0) diff --git a/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py b/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py index 070cdcaf8b..a9f8a9b16d 100644 --- a/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py +++ b/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py @@ -45,17 +45,17 @@ def build_mesh( Mesh has faces edges, face-coords and edge-coords, numbers of which can be controlled. - Args: - - * n_nodes, n_faces, n_edges (int): + Parameters + ---------- + n_nodes, n_faces, n_edges : int Basic dimensions of mesh components. Zero means no such location. - * nodecoord_xyargs, edgecoord_xyargs, facecoord_xyargs (pair of dict): + nodecoord_xyargs, edgecoord_xyargs, facecoord_xyargs : pair of dict Pairs (x,y) of settings kwargs, applied after initial creation the relevant location coordinates. - * conn_role_kwargs (dict of string:dict): + conn_role_kwargs : dict of str Mapping from cf_role name to settings kwargs for connectivities, applied after initially creating them. - * mesh_kwargs (dict): + mesh_kwargs : dict Dictionary of key settings to apply to the Mesh, after creating it. """ @@ -129,11 +129,11 @@ def apply_xyargs(coords, xyargs): def make_mesh(basic=True, **kwargs): """Create a test mesh, with some built-in 'standard' settings. - Kwargs: - - * basic (bool): + Parameters + ---------- + basic : bool If true (default), create with 'standard' set of test properties. - * kwargs (dict): + **kwargs : dict Additional kwargs, passed through to 'build_mesh'. Items here override the 'standard' settings. @@ -193,13 +193,13 @@ def default_mesh(): def make_cube(mesh=None, location="face", **kwargs): """Create a test cube, based on a given mesh + location. - Kwargs: - - * mesh (:class:`iris.experimental.ugrid.mesh.Mesh` or None): + Parameters + ---------- + mesh : :class:`iris.experimental.ugrid.mesh.Mesh` or None, optional If None, use 'default_mesh()' - * location (string): + location : str, optional, default="face" Which mesh element to map the cube to. - * kwargs (dict): + **kwargs : dict, optional Additional property settings to apply to the cube (after creation). """ @@ -234,15 +234,15 @@ def add_height_dim(cube): def scan_dataset(filepath): """Snapshot a netcdf dataset (the key metadata). - Returns: - dimsdict, varsdict - * dimsdict (dict): - A map of dimension-name: length. - * varsdict (dict): - A map of each variable's properties, {var_name: propsdict} - Each propsdict is {attribute-name: value} over the var's ncattrs(). - Each propsdict ALSO contains a [_VAR_DIMS] entry listing the - variable's dims. + Returns + ------- + dimsdict : dict + A map of dimension-name: length. + varsdict : dict + A map of each variable's properties, {var_name: propsdict} + Each propsdict is {attribute-name: value} over the var's ncattrs(). + Each propsdict ALSO contains a [_VAR_DIMS] entry listing the + variable's dims. """ ds = _thread_safe_nc.DatasetWrapper(filepath) @@ -299,19 +299,23 @@ def vars_meshnames(vars): def vars_meshdim(vars, location, mesh_name=None): """Extract a dim-name for a given element location. - Args: - * vars (varsdict): - file varsdict, as returned from 'snapshot_dataset'. - * location (string): - a mesh location : 'node' / 'edge' / 'face' - * mesh_name (string or None): - If given, identifies the mesh var. - Otherwise, find a unique mesh var (i.e. there must be exactly 1). + Parameters + ---------- + vars : varsdict + file varsdict, as returned from 'snapshot_dataset'. + location : string + a mesh location : 'node' / 'edge' / 'face' + mesh_name : str or None, optional, default=None + If given, identifies the mesh var. + Otherwise, find a unique mesh var (i.e. there must be exactly 1). Returns: - dim_name (string) - The dim-name of the mesh dim for the given location. + ------- + dim_name : str + The dim-name of the mesh dim for the given location. + Notes + ----- TODO: relies on the element having coordinates, which in future will not always be the case. This can be fixed diff --git a/lib/iris/util.py b/lib/iris/util.py index 59a171fa04..686238fa61 100644 --- a/lib/iris/util.py +++ b/lib/iris/util.py @@ -34,15 +34,13 @@ def broadcast_to_shape(array, shape, dim_map): given shape. The result is a read-only view (see :func:`numpy.broadcast_to`). If you need to write to the resulting array, make a copy first. - Args: - - * array (:class:`numpy.ndarray`-like) + Parameters + ---------- + array : :class:`numpy.ndarray`-like An array to broadcast. - - * shape (:class:`list`, :class:`tuple` etc.): + shape : :class:`list`, :class:`tuple` etc The shape the array should be broadcast to. - - * dim_map (:class:`list`, :class:`tuple` etc.): + dim_map : :class:`list`, :class:`tuple` etc A mapping of the dimensions of *array* to their corresponding element in *shape*. *dim_map* must be the same length as the number of dimensions in *array*. Each element of *dim_map* @@ -101,15 +99,13 @@ def broadcast_to_shape(array, shape, dim_map): def delta(ndarray, dimension, circular=False): """Calculates the difference between values along a given dimension. - Args: - - * ndarray: + Parameters + ---------- + ndarray : The array over which to do the difference. - - * dimension: + dimension : The dimension over which to do the difference on ndarray. - - * circular: + circular : bool, optional, default=False If not False then return n results in the requested dimension with the delta between the last and first element included in the result otherwise the result will be of length n-1 (where n @@ -125,6 +121,8 @@ def delta(ndarray, dimension, circular=False): original array -180, -90, 0, 90 delta (with circular=360): 90, 90, 90, -270+360 + Notes + ----- .. note:: The difference algorithm implemented is forward difference: @@ -137,10 +135,10 @@ 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`. + .. note:: + + 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: @@ -165,23 +163,22 @@ def describe_diff(cube_a, cube_b, output_file=None): """Prints the differences that prevent compatibility between two cubes, as defined by :meth:`iris.cube.Cube.is_compatible()`. - Args: - - * cube_a: + Parameters + ---------- + cube_a : An instance of :class:`iris.cube.Cube` or :class:`iris.cube.CubeMetadata`. - - * cube_b: + cube_b : An instance of :class:`iris.cube.Cube` or :class:`iris.cube.CubeMetadata`. - - * output_file: + output_file : A :class:`file` or file-like object to receive output. Defaults to sys.stdout. - .. seealso:: - - :meth:`iris.cube.Cube.is_compatible()` + Notes + ----- + This function maintains laziness when called; it does not realise data. + See more at :doc:`/userguide/real_and_lazy_data`. .. note:: @@ -191,10 +188,9 @@ 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`. + See Also + -------- + :meth:`iris.cube.Cube.is_compatible()` """ @@ -239,21 +235,22 @@ def guess_coord_axis(coord): Heuristic categorisation of the coordinate into either label 'T', 'Z', 'Y', 'X' or None. - Args: - - * coord: + Parameters + ---------- + coord : The :class:`iris.coords.Coord`. - Returns: - 'T', 'Z', 'Y', 'X', or None. + 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`. - The ``guess_coord_axis`` behaviour can be skipped by setting the coordinate property ``ignore_axis`` - to ``False``. + The ``guess_coord_axis`` behaviour can be skipped by setting the coordinate + property ``ignore_axis`` to ``False``. """ @@ -288,25 +285,26 @@ def guess_coord_axis(coord): def rolling_window(a, window=1, step=1, axis=-1): """Make an ndarray with a rolling window of the last dimension. - Args: - - * a : array_like + Parameters + ---------- + a : array_like Array to add rolling window to - - Kwargs: - - * window : int + window : int, optional Size of rolling window - * step : int + step : int, optional Size of step between rolling windows - * axis : int + axis : int, optional Axis to take the rolling window over - Returns: + Returns + ------- + array Array that is a view of the original array with an added dimension of the size of the given window at axis + 1. - Examples:: + Examples + -------- + :: >>> x = np.arange(10).reshape((2, 5)) >>> rolling_window(x, 3) @@ -359,24 +357,21 @@ def rolling_window(a, window=1, step=1, axis=-1): def array_equal(array1, array2, withnans=False): """Returns whether two arrays have the same shape and elements. - Args: - - * array1, array2 (arraylike): + Parameters + ---------- + array1, array2 : arraylike args to be compared, normalised if necessary with :func:`np.asarray`. - - Kwargs: - - * withnans (bool): + withnans : bool, optional, default=False When unset (default), the result is False if either input contains NaN points. This is the normal floating-point arithmetic result. When set, return True if inputs contain the same value in all elements, _including_ any NaN values. + Notes + ----- 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`. """ @@ -436,23 +431,21 @@ def between(lh, rh, lh_inclusive=True, rh_inclusive=True): """Provides a convenient way of defining a 3 element inequality such as ``a < number < b``. - Arguments: - - * lh + Parameters + ---------- + lh : The left hand element of the inequality - * rh + rh : The right hand element of the inequality - - Keywords: - - * lh_inclusive - boolean + lh_inclusive : bool, optional Affects the left hand comparison operator to use in the inequality. True for ``<=`` false for ``<``. Defaults to True. - * rh_inclusive - boolean + rh_inclusive : bool, default=True Same as lh_inclusive but for right hand operator. - - For example:: + Examples + -------- + :: between_3_and_6 = between(3, 6) for i in range(10): @@ -482,16 +475,18 @@ def between(lh, rh, lh_inclusive=True, rh_inclusive=True): def reverse(cube_or_array, coords_or_dims): """Reverse the cube or array along the given dimensions. - Args: - - * cube_or_array: :class:`iris.cube.Cube` or :class:`numpy.ndarray` + Parameters + ---------- + cube_or_array : :class:`iris.cube.Cube` or :class:`numpy.ndarray` The cube or array to reverse. - * coords_or_dims: int, str, :class:`iris.coords.Coord` or sequence of these + coords_or_dims : int, str, :class:`iris.coords.Coord` or sequence of these Identify one or more dimensions to reverse. If cube_or_array is a numpy array, use int or a sequence of ints, as in the examples below. If cube_or_array is a Cube, a Coord or coordinate name (or sequence of these) may be specified instead. + Examples + -------- :: >>> import numpy as np @@ -579,11 +574,11 @@ def monotonic(array, strict=False, return_direction=False): Note that, the array must not contain missing data. - Kwargs: - - * strict (boolean) + Parameters + ---------- + strict : boolean, optional, default=False Flag to enable strict monotonic checking - * return_direction (boolean) + return_direction : bool, optional, default=False Flag to change return behaviour to return (monotonic_status, direction). Direction will be 1 for positive or -1 for negative. The direction is meaningless if the array is @@ -777,27 +772,27 @@ def _build_full_slice_given_keys(keys, ndim): def _slice_data_with_keys(data, keys): """Index an array-like object as "data[keys]", with orthogonal indexing. - Args: - - * data (array-like): + Parameters + ---------- + data : array-like array to index. - - * keys (list): + keys : list list of indexes, as received from a __getitem__ call. - This enforces an orthogonal interpretation of indexing, which means that - both 'real' (numpy) arrays and other array-likes index in the same way, - instead of numpy arrays doing 'fancy indexing'. - - Returns (dim_map, data_region), where : - - * dim_map (dict) : + Returns + ------- + dim_map : dict A dimension map, as returned by :func:`column_slices_generator`. i.e. "dim_map[old_dim_index]" --> "new_dim_index" or None. - - * data_region (array-like) : + data_region : array-like The sub-array. + Notes + ----- + This enforces an orthogonal interpretation of indexing, which means that + both 'real' (numpy) arrays and other array-likes index in the same way, + instead of numpy arrays doing 'fancy indexing'. + .. Note:: Avoids copying the data, where possible. @@ -987,9 +982,10 @@ def __lt__(self, other): def create_temp_filename(suffix=""): """Return a temporary file name. - Args: - - * suffix - Optional filename extension. + Parameters + ---------- + suffix : str, optional, default="" + Filename extension. """ temp_file = tempfile.mkstemp(suffix) @@ -1010,19 +1006,21 @@ def clip_string(the_str, clip_length=70, rider="..."): rider is added. If no graceful point can be found, then the string is clipped exactly where the user requested and the rider is added. - Args: - - * the_str + Parameters + ---------- + the_str : str The string to be clipped - * clip_length + clip_length : The length in characters that the input string should be clipped to. Defaults to a preconfigured value if not specified. - * rider + rider : str, optional, default="..." A series of characters appended at the end of the returned string to show it has been clipped. Defaults to a preconfigured value if not specified. - Returns: + Returns + ------- + str The string clipped to the required length with a rider appended. If the clip length was greater than the original string, the original string is returned unaltered. @@ -1083,28 +1081,28 @@ 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. - Args: - - * src_cube (:class:`iris.cube.Cube`) + Parameters + ---------- + src_cube : :class:`iris.cube.Cube` Source cube on which to generate a new axis. - - Kwargs: - - * scalar_coord (:class:`iris.coord.Coord` or 'string') + scalar_coord : :class:`iris.coord.Coord` or 'string', optional, default=None Scalar coordinate to promote to a dimension coordinate. - - * expand_extras (iterable) + expand_extras : iterable, optional Auxiliary coordinates, ancillary variables and cell measures which will be expanded so that they map to the new dimension as well as the existing dimensions. - Returns: + Returns + ------- + :class:`iris.cube.Cube` A new :class:`iris.cube.Cube` instance with one extra leading dimension (length 1). Chosen auxiliary coordinates, cell measures and ancillary variables will also be given an additional dimension, associated with the leading dimension of the cube. - For example:: + Examples + -------- + :: >>> cube.shape (360, 360) @@ -1207,15 +1205,19 @@ def squeeze(cube): """Removes any dimension of length one. If it has an associated DimCoord or AuxCoord, this becomes a scalar coord. - Args: - - * cube (:class:`iris.cube.Cube`) + Parameters + ---------- + cube : :class:`iris.cube.Cube` Source cube to remove length 1 dimension(s) from. - Returns: + Returns + ------- + :class:`iris.cube.Cube` A new :class:`iris.cube.Cube` instance without any dimensions of length 1. + Examples + -------- For example:: >>> cube.shape @@ -1246,21 +1248,24 @@ def file_is_newer_than(result_path, source_paths): re-built when one of them changes. This function can be used to test that by comparing file timestamps. - Args: - - * result_path (string): + Parameters + ---------- + result_path : str The filepath of a file containing some derived result data. - * source_paths (string or iterable of strings): + source_paths : str or iterable of str The path(s) to the original datafiles used to make the result. May include wildcards and '~' expansions (like Iris load paths), but not URIs. - Returns: + Returns + ------- + bool True if all the sources are older than the result, else False. - If any of the file paths describes no existing files, an exception will be raised. + Notes + ----- .. note:: There are obvious caveats to using file timestamps for this, as correct usage depends on how the sources might change. For example, a file @@ -1373,8 +1378,8 @@ def points_step(points): Returns ------- numeric, bool - A tuple containing the average difference between values, and whether the difference is regular. - + A tuple containing the average difference between values, and whether + the difference is regular. Notes ----- @@ -1404,9 +1409,9 @@ def unify_time_units(cubes): Each epoch is defined from the first suitable time coordinate found in the input cubes. - Arg: - - * cubes: + Parameters + ---------- + cubes : An iterable containing :class:`iris.cube.Cube` instances. Notes @@ -1437,21 +1442,18 @@ def _is_circular(points, modulus, bounds=None): If the bounds are provided then these are checked for circularity rather than the points. - Args: - - * points: + Parameters + ---------- + points : :class:`numpy.ndarray` :class:`numpy.ndarray` of point values. - - * modulus: + modulus : Circularity modulus value. - - Kwargs: - - * bounds: + bounds : :class:`numpy.ndarray`, optional :class:`numpy.ndarray` of bound values. - Returns: - Boolean. + Returns + ------- + bool """ circular = False @@ -1498,29 +1500,23 @@ def _is_circular(points, modulus, bounds=None): def promote_aux_coord_to_dim_coord(cube, name_or_coord): - """Promotes an AuxCoord on the cube to a DimCoord. This AuxCoord must be + r"""Promotes an AuxCoord on the cube to a DimCoord. This AuxCoord must be associated with a single cube dimension. If the AuxCoord is associated with a dimension that already has a DimCoord, that DimCoord gets demoted to an AuxCoord. - Args: - - * cube + Parameters + ---------- + cube : An instance of :class:`iris.cube.Cube` + name_or_coord : + * \(a) An instance of :class:`iris.coords.AuxCoord` + * \(b) the :attr:`standard_name`, :attr:`long_name`, or + :attr:`var_name` of an instance of an instance of + :class:`iris.coords.AuxCoord`. - * name_or_coord: - Either - - (a) An instance of :class:`iris.coords.AuxCoord` - - or - - (b) the :attr:`standard_name`, :attr:`long_name`, or - :attr:`var_name` of an instance of an instance of - :class:`iris.coords.AuxCoord`. - - For example, - + Examples + -------- .. testsetup:: promote import iris @@ -1560,7 +1556,6 @@ def promote_aux_coord_to_dim_coord(cube, name_or_coord): 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 @@ -1625,31 +1620,25 @@ def promote_aux_coord_to_dim_coord(cube, name_or_coord): def demote_dim_coord_to_aux_coord(cube, name_or_coord): - """Demotes a dimension coordinate on the cube to an auxiliary coordinate. + r"""Demotes a dimension coordinate on the cube to an auxiliary coordinate. The DimCoord is demoted to an auxiliary coordinate on the cube. The dimension of the cube that was associated with the DimCoord becomes anonymous. The class of the coordinate is left as DimCoord, it is not recast as an AuxCoord instance. - Args: - - * cube + Parameters + ---------- + cube : An instance of :class:`iris.cube.Cube` + name_or_coord : + * \(a) An instance of :class:`iris.coords.DimCoord` + * \(b) the :attr:`standard_name`, :attr:`long_name`, or + :attr:`var_name` of an instance of an instance of + :class:`iris.coords.DimCoord`. - * name_or_coord: - Either - - (a) An instance of :class:`iris.coords.DimCoord` - - or - - (b) the :attr:`standard_name`, :attr:`long_name`, or - :attr:`var_name` of an instance of an instance of - :class:`iris.coords.DimCoord`. - - For example, - + Examples + -------- .. testsetup:: demote import iris @@ -1742,19 +1731,15 @@ def find_discontiguities(cube, rel_tol=1e-5, abs_tol=1e-8): bounds array, returned as a boolean array (True for all cells which are discontiguous with the cell immediately above them or to their right). - Args: - - * cube (`iris.cube.Cube`): + Parameters + ---------- + cube : `iris.cube.Cube` The cube to be checked for discontinuities in its 'x' and 'y' coordinates. These coordinates must be 2D. - - Kwargs: - - * rel_tol (float): + rel_tol : float, optional, default=1e-5 The relative equality tolerance to apply in coordinate bounds checking. - - * abs_tol (float): + abs_tol : float, optional, default=1e-8 The absolute value tolerance to apply in coordinate bounds checking. @@ -1899,15 +1884,16 @@ def mask_cube(cube, points_to_mask, in_place=False, dim=None): Cube containing data that requires masking. points_to_mask : numpy.ndarray, dask.array.Array, iris.coords.Coord or iris.cube.Cube - Specifies booleans (or ones and zeros) indicating which points will be masked. + Specifies booleans (or ones and zeros) indicating which points will + be masked. in_place : bool, default=False - If `True`, masking is applied to the input cube. Otherwise a copy is masked - and returned. + If `True`, masking is applied to the input cube. Otherwise a copy is + masked and returned. dim : int, optional - If `points_to_mask` is a coord which does not exist on the cube, specify the - dimension to which it should be mapped. + If `points_to_mask` is a coord which does not exist on the cube, + specify the dimension to which it should be mapped. Returns ------- @@ -1957,9 +1943,9 @@ def equalise_attributes(cubes): given cubes. The cubes will then have identical attributes, and the removed attributes are returned. The given cubes are modified in-place. - Args: - - * cubes (iterable of :class:`iris.cube.Cube`): + Parameters + ---------- + cubes : iterable of :class:`iris.cube.Cube` A collection of cubes to compare and adjust. Returns From a8da1fbc83be85dbb5b1f9c9777c48afde029d8b Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Wed, 3 Jan 2024 09:16:03 +0000 Subject: [PATCH 03/26] ruff complliance for D406. (#5670) --- .ruff.toml | 1 - lib/iris/common/resolve.py | 6 +++--- lib/iris/cube.py | 2 +- lib/iris/fileformats/pp_load_rules.py | 2 +- lib/iris/tests/test_concatenate.py | 2 +- .../unit/fileformats/netcdf/saver/test_Saver__ugrid.py | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index eca1660fbf..939b7f0019 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -38,7 +38,6 @@ lint.ignore = [ "D205", # 1 blank line required between summary line and description "D401", # First line of docstring should be in imperative mood: ... "D404", # First word of the docstring should not be "This" - "D406", # Section name should end with a newline # pyupgrade (UP) # https://docs.astral.sh/ruff/rules/#pyupgrade-up diff --git a/lib/iris/common/resolve.py b/lib/iris/common/resolve.py index 3885a94a14..992e6134c4 100644 --- a/lib/iris/common/resolve.py +++ b/lib/iris/common/resolve.py @@ -205,7 +205,7 @@ class Resolve: >>> resolver = Resolve(cube1, cube2) >>> results = [resolver.cube(data) for data in payload] - """ # noqa: D214, D407, D410, D411 + """ # noqa: D214, D406, D407, D410, D411 def __init__(self, lhs=None, rhs=None): """Resolve the provided ``lhs`` :class:`~iris.cube.Cube` operand and @@ -2474,7 +2474,7 @@ def mapped(self): >>> resolver.map_rhs_to_lhs False - """ # noqa: D214, D407, D410, D411 + """ # noqa: D214, D406, D407, D410, D411 result = None if self.mapping is not None: result = self._src_cube.ndim == len(self.mapping) @@ -2535,5 +2535,5 @@ def shape(self): >>> Resolve(cube2, cube1).shape (240, 37, 49) - """ # noqa: D214, D407, D410, D411 + """ # noqa: D214, D406, D407, D410, D411 return self._broadcast_shape diff --git a/lib/iris/cube.py b/lib/iris/cube.py index d414cc3e09..d60dd342b4 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -4547,7 +4547,7 @@ def rolling_window(self, coord, aggregator, window, **kwargs): Notice that the forecast_period dimension now represents the 4 possible windows of size 3 from the original cube. - """ # noqa: D214, D407, D410, D411 + """ # noqa: D214, D406, D407, D410, D411 # Update weights kwargs (if necessary) to handle different types of # weights diff --git a/lib/iris/fileformats/pp_load_rules.py b/lib/iris/fileformats/pp_load_rules.py index e128ff0ad8..a74d9a234c 100644 --- a/lib/iris/fileformats/pp_load_rules.py +++ b/lib/iris/fileformats/pp_load_rules.py @@ -808,7 +808,7 @@ def _model_level_number(lblev): lblev : int PP field LBLEV value. - Returns: + Returns ------- Model level number (int). diff --git a/lib/iris/tests/test_concatenate.py b/lib/iris/tests/test_concatenate.py index 0d13b17cf3..cb26150d61 100644 --- a/lib/iris/tests/test_concatenate.py +++ b/lib/iris/tests/test_concatenate.py @@ -180,7 +180,7 @@ def _make_cube_3d(x, y, z, data, aux=None, offset=0): Offset value to be added to non-1D auxiliary coordinate points. - Returns: + Returns ------- The newly created 3D :class:`iris.cube.Cube`. diff --git a/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py b/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py index a9f8a9b16d..290cf0cfaf 100644 --- a/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py +++ b/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py @@ -309,7 +309,7 @@ def vars_meshdim(vars, location, mesh_name=None): If given, identifies the mesh var. Otherwise, find a unique mesh var (i.e. there must be exactly 1). - Returns: + Returns ------- dim_name : str The dim-name of the mesh dim for the given location. From fc15cb5856c1e51c5b5e7906e9be957a93d094b6 Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Wed, 3 Jan 2024 09:31:10 +0000 Subject: [PATCH 04/26] ruff compliance for D404. (#5671) --- .ruff.toml | 1 - lib/iris/_representation/cube_summary.py | 2 +- lib/iris/analysis/_area_weighted.py | 2 +- lib/iris/analysis/_interpolation.py | 4 +++- lib/iris/analysis/_regrid.py | 8 ++++++-- lib/iris/experimental/regrid.py | 14 ++++++++++---- lib/iris/experimental/ugrid/cf.py | 4 +++- lib/iris/fileformats/cf.py | 4 +++- lib/iris/fileformats/pp_load_rules.py | 4 +++- lib/iris/plot.py | 4 +++- lib/iris/tests/__init__.py | 4 +++- lib/iris/tests/system_test.py | 5 ++++- lib/iris/tests/test_coding_standards.py | 4 +++- lib/iris/tests/test_pp_cf.py | 2 +- lib/iris/tests/unit/cube/test_Cube.py | 4 +++- .../netcdf/loader/test__chunk_control.py | 4 +++- 16 files changed, 50 insertions(+), 20 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index 939b7f0019..6832346226 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -37,7 +37,6 @@ lint.ignore = [ "D202", # No blank lines allowed after function docstring "D205", # 1 blank line required between summary line and description "D401", # First line of docstring should be in imperative mood: ... - "D404", # First word of the docstring should not be "This" # pyupgrade (UP) # https://docs.astral.sh/ruff/rules/#pyupgrade-up diff --git a/lib/iris/_representation/cube_summary.py b/lib/iris/_representation/cube_summary.py index bae63ccb40..baceba497a 100644 --- a/lib/iris/_representation/cube_summary.py +++ b/lib/iris/_representation/cube_summary.py @@ -259,7 +259,7 @@ def __init__(self, title, cell_methods): class CubeSummary: - """This class provides a structure for output representations of an Iris cube.""" + """Provide a structure for output representations of an Iris cube.""" def __init__(self, cube, name_padding=35): self.header = FullHeader(cube, name_padding) diff --git a/lib/iris/analysis/_area_weighted.py b/lib/iris/analysis/_area_weighted.py index 007050008b..24c608e98e 100644 --- a/lib/iris/analysis/_area_weighted.py +++ b/lib/iris/analysis/_area_weighted.py @@ -18,7 +18,7 @@ class AreaWeightedRegridder: - """This class provides support for performing area-weighted regridding.""" + """Provide support for performing area-weighted regridding.""" def __init__(self, src_grid_cube, target_grid_cube, mdtol=1): """Create an area-weighted regridder for conversions between the source diff --git a/lib/iris/analysis/_interpolation.py b/lib/iris/analysis/_interpolation.py index 15f5ba7893..518b57e63a 100644 --- a/lib/iris/analysis/_interpolation.py +++ b/lib/iris/analysis/_interpolation.py @@ -164,7 +164,9 @@ def snapshot_grid(cube): class RectilinearInterpolator: - """This class provides support for performing nearest-neighbour or + """Provide support for performing nearest-neighbour or linear interpolation. + + This class provides support for performing nearest-neighbour or linear interpolation over one or more orthogonal dimensions. """ diff --git a/lib/iris/analysis/_regrid.py b/lib/iris/analysis/_regrid.py index 3beada7131..d4ccd6c203 100644 --- a/lib/iris/analysis/_regrid.py +++ b/lib/iris/analysis/_regrid.py @@ -369,7 +369,9 @@ def _regrid_weighted_curvilinear_to_rectilinear__perform(src_cube, regrid_info): class CurvilinearRegridder: - """This class provides support for performing point-in-cell regridding + """Provides support for performing point-in-cell regridding. + + This class provides support for performing point-in-cell regridding between a curvilinear source grid and a rectilinear target grid. """ @@ -485,7 +487,9 @@ def __call__(self, src): class RectilinearRegridder: - """This class provides support for performing nearest-neighbour or + """Provides support for performing nearest-neighbour or linear regridding. + + This class provides support for performing nearest-neighbour or linear regridding between source and target grids. """ diff --git a/lib/iris/experimental/regrid.py b/lib/iris/experimental/regrid.py index aa37d76fe0..b17c0cfeeb 100644 --- a/lib/iris/experimental/regrid.py +++ b/lib/iris/experimental/regrid.py @@ -200,7 +200,9 @@ def regrid_weighted_curvilinear_to_rectilinear(src_cube, weights, grid_cube): class PointInCell: - """This class describes the point-in-cell regridding scheme for use + """Describe the point-in-cell regridding scheme. + + This class describes the point-in-cell regridding scheme for use typically with :meth:`iris.cube.Cube.regrid()`. .. warning:: @@ -234,7 +236,7 @@ def __init__(self, weights=None): class _ProjectedUnstructuredRegridder: - """This class provides regridding that uses scipy.interpolate.griddata.""" + """Regridding that uses scipy.interpolate.griddata.""" def __init__(self, src_cube, tgt_grid_cube, method, projection=None): """Create a regridder for conversions between the source @@ -601,7 +603,9 @@ def __call__(self, src_cube): class ProjectedUnstructuredLinear: - """This class describes the linear regridding scheme which uses the + """Describe the linear regridding scheme. + + This class describes the linear regridding scheme which uses the scipy.interpolate.griddata to regrid unstructured data on to a grid. The source cube and the target cube will be projected into a common @@ -677,7 +681,9 @@ def regridder(self, src_cube, target_grid): class ProjectedUnstructuredNearest: - """This class describes the nearest regridding scheme which uses the + """Describe the nearest regridding scheme which uses scipy.interpolate.griddata. + + This class describes the nearest regridding scheme which uses the scipy.interpolate.griddata to regrid unstructured data on to a grid. The source cube and the target cube will be projected into a common diff --git a/lib/iris/experimental/ugrid/cf.py b/lib/iris/experimental/ugrid/cf.py index 10e76cc11b..bd4c076ba5 100644 --- a/lib/iris/experimental/ugrid/cf.py +++ b/lib/iris/experimental/ugrid/cf.py @@ -267,7 +267,9 @@ def non_data_variable_names(self): class CFUGridReader(cf.CFReader): - """This class allows the contents of a netCDF file to be interpreted according + """Allows the contents of a netCDF file to be. + + This class allows the contents of a netCDF file to be interpreted according to the 'NetCDF Climate and Forecast (CF) Metadata Conventions'. Specialisation of :class:`~iris.fileformats.cf.CFReader` that can also diff --git a/lib/iris/fileformats/cf.py b/lib/iris/fileformats/cf.py index 7bba1442da..905e64ebc1 100644 --- a/lib/iris/fileformats/cf.py +++ b/lib/iris/fileformats/cf.py @@ -1007,7 +1007,9 @@ def __repr__(self): ################################################################################ class CFReader: - """This class allows the contents of a netCDF file to be interpreted according + """Allows the contents of a netCDF file to be interpreted. + + This class allows the contents of a netCDF file to be interpreted according to the 'NetCDF Climate and Forecast (CF) Metadata Conventions'. """ diff --git a/lib/iris/fileformats/pp_load_rules.py b/lib/iris/fileformats/pp_load_rules.py index a74d9a234c..ea42aee92c 100644 --- a/lib/iris/fileformats/pp_load_rules.py +++ b/lib/iris/fileformats/pp_load_rules.py @@ -929,7 +929,9 @@ def convert(f): def _all_other_rules(f): - """This deals with all the other rules that have not been factored into any of + """Deals with all the other rules. + + Deals with all the other rules that have not been factored into any of the other convert_scalar_coordinate functions above. """ diff --git a/lib/iris/plot.py b/lib/iris/plot.py index 06dfe79aa9..23d11bbdd4 100644 --- a/lib/iris/plot.py +++ b/lib/iris/plot.py @@ -810,7 +810,9 @@ def _draw_1d_from_points(draw_method_name, arg_func, *args, **kwargs): def _draw_two_1d_from_points(draw_method_name, arg_func, *args, **kwargs): - """This function is equivalend to _draw_two_1d_from_points but expects two + """Draw two 1d frompoints (expects two y-axis variables rather than one). + + This function is equivalend to _draw_two_1d_from_points but expects two y-axis variables rather than one (such as is required for .fill_between). It can't be used where the y-axis variables are string coordinates. The y-axis variable provided first has precedence where the two differ on whether the diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py index bcf42d9be9..a1efe9d606 100644 --- a/lib/iris/tests/__init__.py +++ b/lib/iris/tests/__init__.py @@ -803,7 +803,9 @@ def assertArrayShapeStats(self, result, shape, mean, std_dev, rtol=1e-6): self.assertArrayAllClose(result.data.std(), std_dev, rtol=rtol) def assertDictEqual(self, lhs, rhs, msg=None): - """This method overrides unittest.TestCase.assertDictEqual (new in Python3.1) + """Dictionary Comparison. + + This method overrides unittest.TestCase.assertDictEqual (new in Python3.1) in order to cope with dictionary comparison where the value of a key may be a numpy array. diff --git a/lib/iris/tests/system_test.py b/lib/iris/tests/system_test.py index 9df43bf8f9..176da91ecb 100644 --- a/lib/iris/tests/system_test.py +++ b/lib/iris/tests/system_test.py @@ -4,7 +4,10 @@ # See LICENSE in the root of the repository for full licensing details. -"""This system test module is useful to identify if some of the key components required for Iris are available. +"""System test module. + +System test module is useful to identify if some of the key components required for +Iris are available. The system tests can be run with ``python setup.py test --system-tests``. diff --git a/lib/iris/tests/test_coding_standards.py b/lib/iris/tests/test_coding_standards.py index 44bd2dc868..9db9433938 100644 --- a/lib/iris/tests/test_coding_standards.py +++ b/lib/iris/tests/test_coding_standards.py @@ -64,7 +64,9 @@ def test_netcdf4_import(): def test_python_versions(): - """This test is designed to fail whenever Iris' supported Python versions are + """Test Python Versions. + + Test is designed to fail whenever Iris' supported Python versions are updated, insisting that versions are updated EVERYWHERE in-sync. """ latest_supported = "3.11" diff --git a/lib/iris/tests/test_pp_cf.py b/lib/iris/tests/test_pp_cf.py index 59bfe28965..1495fd65d1 100644 --- a/lib/iris/tests/test_pp_cf.py +++ b/lib/iris/tests/test_pp_cf.py @@ -68,7 +68,7 @@ class TestAll(tests.IrisTest, pp.PPTest): _ref_dir = ("usecases", "pp_to_cf_conversion") def _test_file(self, name): - """This is the main test routine that is called for each of the files listed below.""" + """Main test routine that is called for each of the files listed below.""" pp_path = self._src_pp_path(name) # 1) Load the PP and check the Cube diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index 27f1756770..b6adb0113c 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -956,7 +956,9 @@ def test_weights_dim_coord(self): class Test_slices_dim_order(tests.IrisTest): - """This class tests the capability of iris.cube.Cube.slices(), including its + """Test the capability of iris.cube.Cube.slices(). + + Test the capability of iris.cube.Cube.slices(), including its ability to correctly re-order the dimensions. """ diff --git a/lib/iris/tests/unit/fileformats/netcdf/loader/test__chunk_control.py b/lib/iris/tests/unit/fileformats/netcdf/loader/test__chunk_control.py index d032e2e576..bc7911578a 100644 --- a/lib/iris/tests/unit/fileformats/netcdf/loader/test__chunk_control.py +++ b/lib/iris/tests/unit/fileformats/netcdf/loader/test__chunk_control.py @@ -178,7 +178,9 @@ def test_no_chunks_from_file(tmp_filepath, save_cubelist_with_sigma): def test_as_dask(tmp_filepath, save_cubelist_with_sigma): - """This does not test return values, as we can't be sure + """Test as dask. + + No return values, as we can't be sure dask chunking behaviour won't change, or that it will differ from our own chunking behaviour. """ From adb97f06777ade82a39f644220ab538355b69c13 Mon Sep 17 00:00:00 2001 From: Bill Little Date: Wed, 3 Jan 2024 09:38:37 +0000 Subject: [PATCH 05/26] nep29 drop numpy 1.22 (#5668) * nep29 drop numpy 1.22 * whatsnew entry --- docs/src/whatsnew/latest.rst | 3 +++ requirements/py310.yml | 2 +- requirements/py311.yml | 2 +- requirements/py39.yml | 2 +- requirements/pypi-core.txt | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index f73d6b0090..d7e9a40648 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -113,6 +113,9 @@ This document explains the changes made to Iris for this release #. `@bjlittle`_ enforced the minimum pin of ``numpy>1.21`` in accordance with the `NEP29 Drop Schedule`_. (:pull:`5525`) +#. `@bjlittle`_ enforced the minimum pin of ``numpy>1.22`` in accordance with the `NEP29 Drop Schedule`_. + (:pull:`5668`) + 📚 Documentation ================ diff --git a/requirements/py310.yml b/requirements/py310.yml index ced05dd987..f0f8f97eea 100644 --- a/requirements/py310.yml +++ b/requirements/py310.yml @@ -18,7 +18,7 @@ dependencies: - libnetcdf !=4.9.1 - matplotlib-base >=3.5 - netcdf4 - - numpy >1.21, !=1.24.3 + - numpy >=1.23, !=1.24.3 - python-xxhash - pyproj - scipy diff --git a/requirements/py311.yml b/requirements/py311.yml index 5f2b23850e..b40e5f75e1 100644 --- a/requirements/py311.yml +++ b/requirements/py311.yml @@ -18,7 +18,7 @@ dependencies: - libnetcdf !=4.9.1 - matplotlib-base >=3.5 - netcdf4 - - numpy >1.21, !=1.24.3 + - numpy >=1.23, !=1.24.3 - python-xxhash - pyproj - scipy diff --git a/requirements/py39.yml b/requirements/py39.yml index a5b32748e3..884c568575 100644 --- a/requirements/py39.yml +++ b/requirements/py39.yml @@ -18,7 +18,7 @@ dependencies: - libnetcdf !=4.9.1 - matplotlib-base >=3.5 - netcdf4 - - numpy >1.21, !=1.24.3 + - numpy >=1.23, !=1.24.3 - python-xxhash - pyproj - scipy diff --git a/requirements/pypi-core.txt b/requirements/pypi-core.txt index e286bb97bc..e6dc005883 100644 --- a/requirements/pypi-core.txt +++ b/requirements/pypi-core.txt @@ -5,7 +5,7 @@ dask[array]>=2022.9.0 # libnetcdf!=4.9.1 (not available on PyPI) matplotlib>=3.5 netcdf4 -numpy>1.21,!=1.24.3 +numpy>=1.23,!=1.24.3 pyproj scipy shapely!=1.8.3 From cd414380f66ac29494a0cd106d96f0c554121612 Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Wed, 3 Jan 2024 11:07:13 +0000 Subject: [PATCH 06/26] ruff complliance for rule D202. (#5674) --- .ruff.toml | 1 - .../benchmarks/experimental/ugrid/regions_combine.py | 3 --- benchmarks/benchmarks/generate_data/stock.py | 2 -- benchmarks/benchmarks/sperf/combine_regions.py | 3 --- benchmarks/bm_runner.py | 1 - docs/gallery_code/general/plot_custom_file_loading.py | 6 +++--- docs/gallery_code/meteorology/plot_COP_maps.py | 5 +---- docs/gallery_tests/test_gallery_examples.py | 2 -- lib/iris/_concatenate.py | 1 - lib/iris/_lazy_data.py | 5 +++-- lib/iris/_merge.py | 10 ++++------ lib/iris/_representation/cube_printout.py | 1 - lib/iris/analysis/_regrid.py | 1 - lib/iris/analysis/cartography.py | 1 - lib/iris/analysis/geometry.py | 2 -- lib/iris/analysis/maths.py | 2 -- lib/iris/analysis/stats.py | 1 - lib/iris/common/resolve.py | 1 - lib/iris/coord_systems.py | 3 --- lib/iris/coords.py | 3 --- lib/iris/cube.py | 4 ---- lib/iris/experimental/ugrid/mesh.py | 1 - lib/iris/fileformats/_ff.py | 4 ---- lib/iris/fileformats/_nc_load_rules/actions.py | 1 - lib/iris/fileformats/_nc_load_rules/helpers.py | 9 --------- lib/iris/fileformats/abf.py | 1 - lib/iris/fileformats/cf.py | 3 --- lib/iris/fileformats/name_loaders.py | 4 ---- lib/iris/fileformats/nimrod.py | 1 - lib/iris/plot.py | 5 ----- lib/iris/quickplot.py | 1 - lib/iris/tests/stock/netcdf.py | 1 - lib/iris/tests/unit/analysis/test_MAX_RUN.py | 2 -- .../coord_categorisation/test_coord_categorisation.py | 1 - .../tests/unit/experimental/ugrid/mesh/test_Mesh.py | 1 - .../unit/fileformats/netcdf/saver/test_Saver__ugrid.py | 1 - lib/iris/tests/unit/plot/test_plot.py | 1 - lib/iris/util.py | 5 ----- 38 files changed, 11 insertions(+), 89 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index 6832346226..c35507b5c3 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -34,7 +34,6 @@ lint.ignore = [ "D100", # Missing docstring in public module "D103", # Missing docstring in public function "D200", # One-line docstring should fit on one line - "D202", # No blank lines allowed after function docstring "D205", # 1 blank line required between summary line and description "D401", # First line of docstring should be in imperative mood: ... diff --git a/benchmarks/benchmarks/experimental/ugrid/regions_combine.py b/benchmarks/benchmarks/experimental/ugrid/regions_combine.py index a4df9aa8c7..b47082590b 100644 --- a/benchmarks/benchmarks/experimental/ugrid/regions_combine.py +++ b/benchmarks/benchmarks/experimental/ugrid/regions_combine.py @@ -68,7 +68,6 @@ def _make_region_cubes(self, full_mesh_cube): def setup_cache(self): """Cache all the necessary source data on disk.""" - # Control dask, to minimise memory usage + allow largest data. self.fix_dask_settings() @@ -106,7 +105,6 @@ def setup(self, n_cubesphere, imaginary_data=True, create_result_cube=True): NOTE: various test classes override + extend this. """ - # Load source cubes (full-mesh and regions) with PARSE_UGRID_ON_LOAD.context(): self.full_mesh_cube = load_cube( @@ -143,7 +141,6 @@ def fix_dask_settings(self): which is optimised for space saving so we can test largest data. """ - import dask.config as dcfg # Use single-threaded, to avoid process-switching costs and minimise memory usage. diff --git a/benchmarks/benchmarks/generate_data/stock.py b/benchmarks/benchmarks/generate_data/stock.py index 058eac01b1..a04eff6701 100644 --- a/benchmarks/benchmarks/generate_data/stock.py +++ b/benchmarks/benchmarks/generate_data/stock.py @@ -56,7 +56,6 @@ def create_file__xios_2d_face_half_levels( todo: is create_file__xios_2d_face_half_levels still appropriate now we can properly save Mesh Cubes? """ - return _create_file__xios_common( func_name="create_file__xios_2d_face_half_levels", dataset_name=dataset_name, @@ -75,7 +74,6 @@ def create_file__xios_3d_face_half_levels( todo: is create_file__xios_3d_face_half_levels still appropriate now we can properly save Mesh Cubes? """ - return _create_file__xios_common( func_name="create_file__xios_3d_face_half_levels", dataset_name=dataset_name, diff --git a/benchmarks/benchmarks/sperf/combine_regions.py b/benchmarks/benchmarks/sperf/combine_regions.py index 1012ccd932..e591a120c9 100644 --- a/benchmarks/benchmarks/sperf/combine_regions.py +++ b/benchmarks/benchmarks/sperf/combine_regions.py @@ -64,7 +64,6 @@ def _make_region_cubes(self, full_mesh_cube): def setup_cache(self): """Cache all the necessary source data on disk.""" - # Control dask, to minimise memory usage + allow largest data. self.fix_dask_settings() @@ -102,7 +101,6 @@ def setup(self, n_cubesphere, imaginary_data=True, create_result_cube=True): NOTE: various test classes override + extend this. """ - # Load source cubes (full-mesh and regions) with PARSE_UGRID_ON_LOAD.context(): self.full_mesh_cube = load_cube( @@ -142,7 +140,6 @@ def fix_dask_settings(self): which is optimised for space saving so we can test largest data. """ - import dask.config as dcfg # Use single-threaded, to avoid process-switching costs and minimise memory usage. diff --git a/benchmarks/bm_runner.py b/benchmarks/bm_runner.py index 0195d259fe..406c8eb3ae 100644 --- a/benchmarks/bm_runner.py +++ b/benchmarks/bm_runner.py @@ -68,7 +68,6 @@ def _check_requirements(package: str) -> None: def _prep_data_gen_env() -> None: """Create/access a separate, unchanging environment for generating test data.""" - python_version = "3.11" data_gen_var = "DATA_GEN_PYTHON" if data_gen_var in environ: diff --git a/docs/gallery_code/general/plot_custom_file_loading.py b/docs/gallery_code/general/plot_custom_file_loading.py index 53781ba044..81aad4a15a 100644 --- a/docs/gallery_code/general/plot_custom_file_loading.py +++ b/docs/gallery_code/general/plot_custom_file_loading.py @@ -89,11 +89,12 @@ def load_NAME_III(filename): - """Loads the Met Office's NAME III grid output files returning headers, column + """Loads the Met Office's NAME III grid output files. + + Loads the Met Office's NAME III grid output files returning headers, column definitions and data arrays as 3 separate lists. """ - # Loading a file gives a generator of lines which can be progressed using # the next() function. This will come in handy as we wish to progress # through the file line by line. @@ -179,7 +180,6 @@ def load_NAME_III(filename): def NAME_to_cube(filenames, callback): """Returns a generator of cubes given a list of filenames and a callback.""" - for filename in filenames: header, column_headings, data_arrays = load_NAME_III(filename) diff --git a/docs/gallery_code/meteorology/plot_COP_maps.py b/docs/gallery_code/meteorology/plot_COP_maps.py index eda8a3a53a..5536823fb4 100644 --- a/docs/gallery_code/meteorology/plot_COP_maps.py +++ b/docs/gallery_code/meteorology/plot_COP_maps.py @@ -31,10 +31,7 @@ def cop_metadata_callback(cube, field, filename): - """A function which adds an "Experiment" coordinate which comes from the - filename. - """ - + """Function which adds an "Experiment" coordinate which comes from the filename.""" # Extract the experiment name (such as A1B or E1) from the filename (in # this case it is just the start of the file name, before the first "."). fname = os.path.basename(filename) # filename without path. diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index 93f361a62a..83f2c93217 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -16,7 +16,6 @@ def gallery_examples(): """Generator to yield all current gallery examples.""" - for example_file in GALLERY_DIR.glob("*/plot*.py"): yield example_file.stem @@ -30,7 +29,6 @@ def test_plot_example( iris_future_defaults, ): """Test that all figures from example code match KGO.""" - module = importlib.import_module(example) # Run example. diff --git a/lib/iris/_concatenate.py b/lib/iris/_concatenate.py index 97c2840958..b5c92fd6f9 100644 --- a/lib/iris/_concatenate.py +++ b/lib/iris/_concatenate.py @@ -759,7 +759,6 @@ def __init__(self, cube): @property def axis(self): """Return the nominated dimension of concatenation.""" - return self._axis def concatenate(self): diff --git a/lib/iris/_lazy_data.py b/lib/iris/_lazy_data.py index 81af368203..55a4222675 100644 --- a/lib/iris/_lazy_data.py +++ b/lib/iris/_lazy_data.py @@ -58,7 +58,9 @@ def _optimum_chunksize_internals( dims_fixed=None, dask_array_chunksize=dask.config.get("array.chunk-size"), ): - """Reduce or increase an initial chunk shape to get close to a chosen ideal + """Reduce or increase an initial chunk shap. + + Reduce or increase an initial chunk shape to get close to a chosen ideal size, while prioritising the splitting of the earlier (outer) dimensions and keeping intact the later (inner) ones. @@ -100,7 +102,6 @@ def _optimum_chunksize_internals( "chunks = [c[0] for c in normalise_chunks('auto', ...)]". """ - # Set the chunksize limit. if limit is None: # Fetch the default 'optimal' chunksize from the dask config. diff --git a/lib/iris/_merge.py b/lib/iris/_merge.py index 3bed7ef5ee..79427d401a 100644 --- a/lib/iris/_merge.py +++ b/lib/iris/_merge.py @@ -167,7 +167,6 @@ class _CoordPayload(namedtuple("CoordPayload", ["scalar", "vector", "factory_def def as_signature(self): """Construct and return a :class:`_CoordSignature` from the payload.""" - return _CoordSignature( self.scalar.defns, self.vector.dim_coords_and_dims, @@ -1072,11 +1071,12 @@ class ProtoCube: """ def __init__(self, cube): - """Create a new ProtoCube from the given cube and record the cube - as a source-cube. + """Create a new ProtoCube from the given cube. - """ + Create a new ProtoCube from the given cube and record the cube as a + source-cube. + """ # Default hint ordering for candidate dimension coordinates. self._hints = [ "time", @@ -1533,7 +1533,6 @@ def _nd_index(self, position): within the merged cube. """ - index = [] # Determine the index of the source-cube cell for each dimension. @@ -1634,7 +1633,6 @@ def _build_signature(self, cube): The cube signature. """ - return _CubeSignature( cube.metadata, cube.shape, diff --git a/lib/iris/_representation/cube_printout.py b/lib/iris/_representation/cube_printout.py index b1e5238eb0..fc8efb7cd6 100644 --- a/lib/iris/_representation/cube_printout.py +++ b/lib/iris/_representation/cube_printout.py @@ -268,7 +268,6 @@ def _decorated_table(table, name_padding=None): Note: 'name_padding' sets a minimum width for the name column (#0). """ - # Copy the input table + extract the header + its columns. table = table.copy() header = table.rows[0] diff --git a/lib/iris/analysis/_regrid.py b/lib/iris/analysis/_regrid.py index d4ccd6c203..0f50e47f5b 100644 --- a/lib/iris/analysis/_regrid.py +++ b/lib/iris/analysis/_regrid.py @@ -51,7 +51,6 @@ def _regrid_weighted_curvilinear_to_rectilinear__prepare(src_cube, weights, grid The 'regrid info' returned can be re-used over many cubes. """ - # Get the source cube x and y 2D auxiliary coordinates. sx, sy = src_cube.coord(axis="x"), src_cube.coord(axis="y") # Get the target grid cube x and y dimension coordinates. diff --git a/lib/iris/analysis/cartography.py b/lib/iris/analysis/cartography.py index 01c71b177a..68fad28d9c 100644 --- a/lib/iris/analysis/cartography.py +++ b/lib/iris/analysis/cartography.py @@ -1012,7 +1012,6 @@ def _transform_distance_vectors(u_dist, v_dist, ds, dx2, dy2): along the x and y directions of the target crs at each location. """ - # Scale input distance vectors --> source-coordinate differentials. u1, v1 = u_dist / ds.dx1, v_dist / ds.dy1 # Transform vectors into the target system. diff --git a/lib/iris/analysis/geometry.py b/lib/iris/analysis/geometry.py index a07ef61a76..0e44990155 100644 --- a/lib/iris/analysis/geometry.py +++ b/lib/iris/analysis/geometry.py @@ -26,7 +26,6 @@ def _extract_relevant_cube_slice(cube, geometry): If cube and geometry don't overlap, returns None. """ - # Validate the input parameters if not cube.coords(axis="x") or not cube.coords(axis="y"): raise ValueError("The cube must contain x and y axes.") @@ -177,7 +176,6 @@ def geometry_area_weights(cube, geometry, normalize=False): Default is False. """ - # extract smallest subcube containing geometry shape = cube.shape extraction_results = _extract_relevant_cube_slice(cube, geometry) diff --git a/lib/iris/analysis/maths.py b/lib/iris/analysis/maths.py index 0d865952ce..6cbdeb70ac 100644 --- a/lib/iris/analysis/maths.py +++ b/lib/iris/analysis/maths.py @@ -741,7 +741,6 @@ def apply_ufunc(ufunc, cube, other=None, new_unit=None, new_name=None, in_place= See more at :doc:`/userguide/real_and_lazy_data`. """ - if not isinstance(ufunc, np.ufunc): ufunc_name = getattr(ufunc, "__name__", "function passed to apply_ufunc") emsg = f"{ufunc_name} is not recognised, it is not an instance of numpy.ufunc" @@ -1090,7 +1089,6 @@ def ws_units_func(u_cube, v_cube): cs_cube = cs_ifunc(cube, axis=1) """ - self._data_func_name = getattr( data_func, "__name__", "data_func argument passed to IFunc" ) diff --git a/lib/iris/analysis/stats.py b/lib/iris/analysis/stats.py index 2f5b125e06..1fe958500b 100644 --- a/lib/iris/analysis/stats.py +++ b/lib/iris/analysis/stats.py @@ -71,7 +71,6 @@ def pearsonr( This operation is non-lazy. """ - # Assign larger cube to cube_1 if cube_b.ndim > cube_a.ndim: cube_1 = cube_b diff --git a/lib/iris/common/resolve.py b/lib/iris/common/resolve.py index 992e6134c4..b35397ee58 100644 --- a/lib/iris/common/resolve.py +++ b/lib/iris/common/resolve.py @@ -1295,7 +1295,6 @@ def _metadata_resolve(self): 'aux_coords' or 'dim_coords' of the participating cubes. """ - # Determine the cube dim, aux and scalar coordinate items # for each individual cube. self.lhs_cube_category = self._categorise_items(self.lhs_cube) diff --git a/lib/iris/coord_systems.py b/lib/iris/coord_systems.py index 33214ef5e0..d4d1aa66f7 100644 --- a/lib/iris/coord_systems.py +++ b/lib/iris/coord_systems.py @@ -1025,7 +1025,6 @@ def __init__( It is only valid to provide one of true_scale_lat and scale_factor_at_projection_origin """ - #: True latitude of planar origin in degrees. self.central_lat = float(central_lat) @@ -1140,7 +1139,6 @@ def __init__( """ - super().__init__( central_lat=central_lat, central_lon=central_lon, @@ -1200,7 +1198,6 @@ def __init__( secant_latitudes=(33, 45) """ - #: True latitude of planar origin in degrees. self.central_lat = _arg_default(central_lat, 39.0) diff --git a/lib/iris/coords.py b/lib/iris/coords.py index a1595530f9..14371ac3ee 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -1335,7 +1335,6 @@ def __common_cmp__(self, other, operator_method): Non-Cell vs Cell comparison is used to define Constraint matching. """ - if (isinstance(other, list) and len(other) == 1) or ( isinstance(other, np.ndarray) and other.shape == (1,) ): @@ -2019,7 +2018,6 @@ def contiguous_bounds(self): def is_monotonic(self): """Return True if, and only if, this Coord is monotonic.""" - if self.ndim != 1: raise iris.exceptions.CoordinateMultiDimError(self) @@ -2120,7 +2118,6 @@ def collapsed(self, dims_to_collapse=None): Replaces the points & bounds with a simple bounded region. """ - # Ensure dims_to_collapse is a tuple to be able to pass # through to numpy if isinstance(dims_to_collapse, (int, np.integer)): diff --git a/lib/iris/cube.py b/lib/iris/cube.py index d60dd342b4..04cee11969 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -242,7 +242,6 @@ def insert(self, index, cube): def xml(self, checksum=False, order=True, byteorder=True): """Return a string of the XML that this list of cubes represents.""" - doc = Document() cubes_xml_element = doc.createElement("cubes") cubes_xml_element.setAttribute("xmlns", XML_NAMESPACE_URI) @@ -1152,7 +1151,6 @@ def _sort_xml_attrs(cls, doc): def _walk_nodes(node): """Note: _walk_nodes is called recursively on child elements.""" - # we don't want to copy the children here, so take a shallow copy new_node = node.cloneNode(deep=False) @@ -1665,7 +1663,6 @@ def add_ancillary_variable(self, ancillary_variable, data_dims=None): Raises a ValueError if an ancillary variable with identical metadata already exists on the cube. """ - if self.ancillary_variables(ancillary_variable): raise iris.exceptions.CannotAddError( "Duplicate ancillary variables not permitted" @@ -4548,7 +4545,6 @@ def rolling_window(self, coord, aggregator, window, **kwargs): possible windows of size 3 from the original cube. """ # noqa: D214, D406, D407, D410, D411 - # Update weights kwargs (if necessary) to handle different types of # weights weights_info = None diff --git a/lib/iris/experimental/ugrid/mesh.py b/lib/iris/experimental/ugrid/mesh.py index dfd0d74552..79e67593d2 100644 --- a/lib/iris/experimental/ugrid/mesh.py +++ b/lib/iris/experimental/ugrid/mesh.py @@ -1440,7 +1440,6 @@ def connectivity( :class:`Mesh` that matched the given criteria. """ - result = self._connectivity_manager.filter( item=item, standard_name=standard_name, diff --git a/lib/iris/fileformats/_ff.py b/lib/iris/fileformats/_ff.py index 336c4aa699..5e65c92996 100644 --- a/lib/iris/fileformats/_ff.py +++ b/lib/iris/fileformats/_ff.py @@ -316,7 +316,6 @@ def __init__(self, filename, word_depth=DEFAULT_FF_WORD_DEPTH): FFHeader object. """ - #: File name of the FieldsFile. self.ff_filename = filename self._word_depth = word_depth @@ -411,7 +410,6 @@ def shape(self, name): Dimension tuple. """ - if name in _FF_HEADER_POINTERS: value = getattr(self, name)[1:] else: @@ -465,7 +463,6 @@ def __init__(self, filename, read_data=False, word_depth=DEFAULT_FF_WORD_DEPTH): ... print(field) """ - self._ff_header = FFHeader(filename, word_depth=word_depth) self._word_depth = word_depth self._filename = filename @@ -823,7 +820,6 @@ def _parse_binary_stream(file_like, dtype=np.float64, count=-1): object and generate as many values as possible. """ - # There are a wide range of types supported, we just need to know the byte # size of the object, so we just make sure we've go an instance of a # np.dtype diff --git a/lib/iris/fileformats/_nc_load_rules/actions.py b/lib/iris/fileformats/_nc_load_rules/actions.py index 92d46c6693..1532340d00 100644 --- a/lib/iris/fileformats/_nc_load_rules/actions.py +++ b/lib/iris/fileformats/_nc_load_rules/actions.py @@ -544,7 +544,6 @@ def run_actions(engine): The specific cube being translated is "engine.cube". """ - # default (all cubes) action, always runs action_default(engine) # This should run the default rules. diff --git a/lib/iris/fileformats/_nc_load_rules/helpers.py b/lib/iris/fileformats/_nc_load_rules/helpers.py index 31cc4aaa6c..6a135a211c 100644 --- a/lib/iris/fileformats/_nc_load_rules/helpers.py +++ b/lib/iris/fileformats/_nc_load_rules/helpers.py @@ -275,7 +275,6 @@ def _split_cell_methods(nc_cell_methods: str) -> List[re.Match]: Validation of anything other than being laid out in the expected format is left to the calling function. """ - # Find name candidates name_start_inds = [] for m in _CM_PARSE_NAME.finditer(nc_cell_methods): @@ -346,7 +345,6 @@ def parse_cell_methods(nc_cell_methods): results are not affected. """ - cell_methods = [] if nc_cell_methods is not None: for m in _split_cell_methods(nc_cell_methods): @@ -952,7 +950,6 @@ def get_attr_units(cf_var, attributes): ################################################################################ def get_names(cf_coord_var, coord_name, attributes): """Determine the standard_name, long_name and var_name attributes.""" - standard_name = getattr(cf_coord_var, CF_ATTR_STD_NAME, None) long_name = getattr(cf_coord_var, CF_ATTR_LONG_NAME, None) cf_name = str(cf_coord_var.cf_name) @@ -1058,7 +1055,6 @@ def build_dimension_coordinate( engine, cf_coord_var, coord_name=None, coord_system=None ): """Create a dimension coordinate (DimCoord) and add it to the cube.""" - cf_var = engine.cf_var cube = engine.cube attributes = {} @@ -1190,7 +1186,6 @@ def build_auxiliary_coordinate( engine, cf_coord_var, coord_name=None, coord_system=None ): """Create an auxiliary coordinate (AuxCoord) and add it to the cube.""" - cf_var = engine.cf_var cube = engine.cube attributes = {} @@ -1499,7 +1494,6 @@ def is_time_period(engine, cf_name): ################################################################################ def is_grid_mapping(engine, cf_name, grid_mapping): """Determine whether the CF grid mapping variable is of the appropriate type.""" - is_valid = False cf_var = engine.cf_var.cf_group[cf_name] attr_mapping_name = getattr(cf_var, CF_ATTR_GRID_MAPPING_NAME, None) @@ -1513,7 +1507,6 @@ def is_grid_mapping(engine, cf_name, grid_mapping): ################################################################################ def _is_rotated(engine, cf_name, cf_attr_value): """Determine whether the CF coordinate variable is rotated.""" - is_valid = False cf_var = engine.cf_var.cf_group[cf_name] attr_std_name = getattr(cf_var, CF_ATTR_STD_NAME, None) @@ -1547,7 +1540,6 @@ def has_supported_mercator_parameters(engine, cf_name): Determine whether the CF grid mapping variable has the supported values for the parameters of the Mercator projection. """ - is_valid = True cf_grid_var = engine.cf_var.cf_group[cf_name] @@ -1572,7 +1564,6 @@ def has_supported_polar_stereographic_parameters(engine, cf_name): """Determine whether the CF grid mapping variable has the supported values for the parameters of the Polar Stereographic projection. """ - is_valid = True cf_grid_var = engine.cf_var.cf_group[cf_name] diff --git a/lib/iris/fileformats/abf.py b/lib/iris/fileformats/abf.py index 3f7a6b18e0..13b0d8aa8d 100644 --- a/lib/iris/fileformats/abf.py +++ b/lib/iris/fileformats/abf.py @@ -116,7 +116,6 @@ def _read(self): def to_cube(self): """Return a new :class:`~iris.cube.Cube` from this ABFField.""" - cube = iris.cube.Cube(self.data) # Name. diff --git a/lib/iris/fileformats/cf.py b/lib/iris/fileformats/cf.py index 905e64ebc1..ec0d66f8c2 100644 --- a/lib/iris/fileformats/cf.py +++ b/lib/iris/fileformats/cf.py @@ -695,7 +695,6 @@ def cf_label_data(self, cf_data_var): str labels """ - if not isinstance(cf_data_var, CFDataVariable): raise TypeError( "cf_data_var argument should be of type CFDataVariable. Got %r." @@ -763,7 +762,6 @@ def cf_label_dimensions(self, cf_data_var): Tuple of label data dimension names. """ - if not isinstance(cf_data_var, CFDataVariable): raise TypeError( "cf_data_var argument should be of type CFDataVariable. Got %r." @@ -1086,7 +1084,6 @@ def __repr__(self): def _translate(self): """Classify the netCDF variables into CF-netCDF variables.""" - netcdf_variable_names = list(self._dataset.variables.keys()) # Identify all CF coordinate variables first. This must be done diff --git a/lib/iris/fileformats/name_loaders.py b/lib/iris/fileformats/name_loaders.py index 3f4b2d13c6..545b242994 100644 --- a/lib/iris/fileformats/name_loaders.py +++ b/lib/iris/fileformats/name_loaders.py @@ -130,7 +130,6 @@ def _build_lat_lon_for_NAME_field( """Return regular latitude and longitude coordinates extracted from the provided header dictionary. """ - if x_or_y == "X": start = header["X grid origin"] step = header["X grid resolution"] @@ -234,7 +233,6 @@ def _parse_units(units): An instance of :class:`cf_units.Unit`. """ - unit_mapper = { "Risks/m3": "1", # Used for Bluetongue "TCID50s/m3": "1", # Used for Foot and Mouth @@ -284,7 +282,6 @@ def _cf_height_from_name(z_coord, lower_bound=None, upper_bound=None): interpretation of the supplied field heading. """ - # NAMEII - integer/float support. # Match against height agl, asl and Pa. pattern = re.compile( @@ -955,7 +952,6 @@ def load_NAMEIII_version2(filename): A generator :class:`iris.cube.Cube` instances. """ - # loading a file gives a generator of lines which can be progressed # using the next() method. This will come in handy as we wish to # progress through the file line by line. diff --git a/lib/iris/fileformats/nimrod.py b/lib/iris/fileformats/nimrod.py index 8cf109eed5..778c7b3251 100644 --- a/lib/iris/fileformats/nimrod.py +++ b/lib/iris/fileformats/nimrod.py @@ -204,7 +204,6 @@ def _read_header_subset(self, infile, names, dtype): def _read_header(self, infile): """Load the 512 byte header (surrounded by 4-byte length).""" - leading_length = struct.unpack(">L", infile.read(4))[0] if leading_length != 512: raise TranslationError("Expected header leading_length of 512") diff --git a/lib/iris/plot.py b/lib/iris/plot.py index 23d11bbdd4..d8e9426035 100644 --- a/lib/iris/plot.py +++ b/lib/iris/plot.py @@ -234,7 +234,6 @@ def _broadcast_2d(u, v): def _string_coord_axis_tick_labels(string_axes, axes=None): """Apply tick labels for string coordinates.""" - ax = axes if axes else plt.gca() for axis, ticks in string_axes.items(): # Define a tick formatter. This will assign a label to all ticks @@ -860,7 +859,6 @@ def _replace_axes_with_cartopy_axes(cartopy_proj): instance of :class:`cartopy.mpl.geoaxes.GeoAxes` then no action is taken. """ - ax = plt.gca() if not isinstance(ax, cartopy.mpl.geoaxes.GeoAxes): fig = ax.get_figure() @@ -1229,7 +1227,6 @@ def orography_at_bounds(cube, facecolor="#888888", coords=None, axes=None): 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( "This operation is temporarily not provided " @@ -1268,7 +1265,6 @@ def orography_at_points(cube, facecolor="#888888", coords=None, axes=None): This function does not maintain laziness when called; it realises data. See more at :doc:`/userguide/real_and_lazy_data`. """ - style_args = {"facecolor": facecolor} def vert_plot(u_coord, orography, style_args): @@ -1843,7 +1839,6 @@ def citation(text, figure=None, axes=None): provided. """ - if text is not None and len(text): if figure is None and not axes: figure = plt.gcf() diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index fcb0b0d5b7..1fa2edd630 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -50,7 +50,6 @@ def _title(cube_or_coord, with_units): def _label(cube, mode, result=None, ndims=2, coords=None, axes=None): """Puts labels on the current plot using the given cube.""" - if axes is None: axes = plt.gca() diff --git a/lib/iris/tests/stock/netcdf.py b/lib/iris/tests/stock/netcdf.py index c1dd5cb631..5721433103 100644 --- a/lib/iris/tests/stock/netcdf.py +++ b/lib/iris/tests/stock/netcdf.py @@ -89,7 +89,6 @@ def _add_standard_data(nc_path, unlimited_dim_size=0): dimension size, 'dimension coordinates' and a possible unlimited dimension. """ - ds = _thread_safe_nc.DatasetWrapper(nc_path, "r+") unlimited_dim_names = [ diff --git a/lib/iris/tests/unit/analysis/test_MAX_RUN.py b/lib/iris/tests/unit/analysis/test_MAX_RUN.py index d7cc714609..9e314aad7e 100644 --- a/lib/iris/tests/unit/analysis/test_MAX_RUN.py +++ b/lib/iris/tests/unit/analysis/test_MAX_RUN.py @@ -26,7 +26,6 @@ def setUp(self): Uses 1 and 3 rather than 1 and 0 to check that lambda is being applied. """ - self.data_1ds = [ (np.array([3, 1, 1, 3, 3, 3]), 2), # One run (np.array([3, 1, 1, 3, 1, 3]), 2), # Two runs @@ -60,7 +59,6 @@ def setUp(self): Uses 1 and 3 rather than 1 and 0 to check that lambda is being applied. """ - self.data_1ds = [ ( ma.masked_array( diff --git a/lib/iris/tests/unit/coord_categorisation/test_coord_categorisation.py b/lib/iris/tests/unit/coord_categorisation/test_coord_categorisation.py index 2fc3db9b05..7730831e52 100644 --- a/lib/iris/tests/unit/coord_categorisation/test_coord_categorisation.py +++ b/lib/iris/tests/unit/coord_categorisation/test_coord_categorisation.py @@ -162,7 +162,6 @@ def test_add_season_nonstandard(cube, time_coord): ) def test_add_season_year(cube, time_coord, backwards, nonstandard): """Specific test to account for the extra use_year_at_season_start argument.""" - kwargs = dict( cube=cube, coord=time_coord, diff --git a/lib/iris/tests/unit/experimental/ugrid/mesh/test_Mesh.py b/lib/iris/tests/unit/experimental/ugrid/mesh/test_Mesh.py index bc0daf14bc..48f9910099 100644 --- a/lib/iris/tests/unit/experimental/ugrid/mesh/test_Mesh.py +++ b/lib/iris/tests/unit/experimental/ugrid/mesh/test_Mesh.py @@ -1181,7 +1181,6 @@ def test_face_dimension_set(self): def test_remove_connectivities(self): """Do what 1D test could not - test removal of optional connectivity.""" - # Add an optional connectivity. self.mesh.add_connectivities(self.FACE_FACE) # Attempt to remove a non-existent connectivity. diff --git a/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py b/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py index 290cf0cfaf..241ff5a5cc 100644 --- a/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py +++ b/lib/iris/tests/unit/fileformats/netcdf/saver/test_Saver__ugrid.py @@ -654,7 +654,6 @@ def test_alternate_cube_dim_order(self): def test_mixed_aux_coords(self): """``coordinates`` attribute should include mesh location coords and 'normal' coords.""" - cube = make_cube() mesh_dim = cube.mesh_dim() mesh_len = cube.shape[mesh_dim] diff --git a/lib/iris/tests/unit/plot/test_plot.py b/lib/iris/tests/unit/plot/test_plot.py index c4f65fb1a6..6adf1c4cf5 100644 --- a/lib/iris/tests/unit/plot/test_plot.py +++ b/lib/iris/tests/unit/plot/test_plot.py @@ -103,7 +103,6 @@ def check_paths(self, expected_path, expected_path_crs, lines, axes): plotted on the given geoaxes. """ - self.assertEqual( 1, len(lines), "Expected a single line, got {}".format(len(lines)) ) diff --git a/lib/iris/util.py b/lib/iris/util.py index 686238fa61..d030924a52 100644 --- a/lib/iris/util.py +++ b/lib/iris/util.py @@ -193,7 +193,6 @@ def describe_diff(cube_a, cube_b, output_file=None): :meth:`iris.cube.Cube.is_compatible()` """ - if output_file is None: output_file = sys.stdout @@ -253,7 +252,6 @@ def guess_coord_axis(coord): property ``ignore_axis`` to ``False``. """ - axis = None if hasattr(coord, "ignore_axis") and coord.ignore_axis is True: @@ -1030,7 +1028,6 @@ def clip_string(the_str, clip_length=70, rider="..."): 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: return the_str else: @@ -1064,7 +1061,6 @@ def format_array(arr): See more at :doc:`/userguide/real_and_lazy_data`. """ - max_line_len = 50 result = np.array2string( @@ -1232,7 +1228,6 @@ def squeeze(cube): See more at :doc:`/userguide/real_and_lazy_data`. """ - slices = [0 if cube.shape[dim] == 1 else slice(None) for dim in range(cube.ndim)] squeezed = cube[tuple(slices)] From cfa3644e236b38377b52a7242fcbe70a4faef159 Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Wed, 3 Jan 2024 15:06:49 +0000 Subject: [PATCH 07/26] ruff compliance for D106. (#5676) * ruff compliance for D106. * ruff compliance for D106. --- .ruff.toml | 1 - lib/iris/fileformats/netcdf/loader.py | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.ruff.toml b/.ruff.toml index c35507b5c3..f159f0afca 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -29,7 +29,6 @@ lint.ignore = [ "D101", # Missing docstring in public class "D102", # Missing docstring in public method "D104", # Missing docstring in public package - "D106", # Missing docstring in public nested class # (D-3) Temporary, before an initial review, either fix ocurrences or move to (2). "D100", # Missing docstring in public module "D103", # Missing docstring in public function diff --git a/lib/iris/fileformats/netcdf/loader.py b/lib/iris/fileformats/netcdf/loader.py index 31b1774f19..6f69b6e64d 100644 --- a/lib/iris/fileformats/netcdf/loader.py +++ b/lib/iris/fileformats/netcdf/loader.py @@ -662,7 +662,11 @@ def load_cubes(file_sources, callback=None, constraints=None): class ChunkControl(threading.local): + """Provide user control of Chunk Control.""" + class Modes(Enum): + """Modes Enums.""" + DEFAULT = auto() FROM_FILE = auto() AS_DASK = auto() From ccd4c48680aafb0201f08ed56e38f2d4f9f0c02a Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:53:28 +0000 Subject: [PATCH 08/26] ruff compliance for D200. (#5675) * ruff compliance for D200. * doctests update --- .ruff.toml | 1 - benchmarks/benchmarks/aux_factory.py | 4 +--- benchmarks/benchmarks/coords.py | 4 +--- benchmarks/benchmarks/cperf/equality.py | 3 +-- benchmarks/benchmarks/cperf/load.py | 3 +-- benchmarks/benchmarks/cperf/save.py | 3 +-- benchmarks/benchmarks/cube.py | 4 +--- benchmarks/benchmarks/experimental/__init__.py | 4 +--- benchmarks/benchmarks/experimental/ugrid/__init__.py | 4 +--- benchmarks/benchmarks/generate_data/ugrid.py | 3 +-- benchmarks/benchmarks/iterate.py | 4 +--- benchmarks/benchmarks/metadata_manager_factory.py | 4 +--- benchmarks/benchmarks/mixin.py | 4 +--- benchmarks/benchmarks/plot.py | 4 +--- benchmarks/benchmarks/regridding.py | 4 +--- benchmarks/benchmarks/sperf/combine_regions.py | 3 +-- benchmarks/benchmarks/sperf/equality.py | 3 +-- benchmarks/benchmarks/sperf/load.py | 3 +-- benchmarks/benchmarks/sperf/save.py | 3 +-- benchmarks/benchmarks/trajectory.py | 4 +--- benchmarks/bm_runner.py | 3 +-- docs/src/further_topics/filtering_warnings.rst | 12 ++++++------ lib/iris/_data_manager.py | 4 +--- lib/iris/_deprecation.py | 4 +--- lib/iris/_representation/__init__.py | 4 +--- lib/iris/_representation/cube_printout.py | 4 +--- lib/iris/_representation/cube_summary.py | 3 +-- lib/iris/analysis/cartography.py | 4 +--- lib/iris/analysis/maths.py | 4 +--- lib/iris/analysis/stats.py | 4 +--- lib/iris/common/__init__.py | 4 +--- lib/iris/common/lenient.py | 4 +--- lib/iris/common/metadata.py | 4 +--- lib/iris/common/mixin.py | 4 +--- lib/iris/coord_systems.py | 4 +--- lib/iris/coords.py | 4 +--- lib/iris/cube.py | 4 +--- lib/iris/exceptions.py | 4 +--- lib/iris/experimental/representation.py | 4 +--- lib/iris/experimental/ugrid/utils.py | 4 +--- lib/iris/fileformats/__init__.py | 4 +--- lib/iris/fileformats/_ff.py | 4 +--- lib/iris/fileformats/dot.py | 4 +--- lib/iris/fileformats/pp.py | 4 +--- lib/iris/fileformats/rules.py | 4 +--- lib/iris/iterate.py | 4 +--- lib/iris/symbols.py | 4 +--- lib/iris/tests/experimental/__init__.py | 4 +--- lib/iris/tests/experimental/regrid/__init__.py | 4 +--- ..._regrid_area_weighted_rectilinear_src_and_grid.py | 4 +--- .../regrid/test_regrid_conservative_via_esmpy.py | 4 +--- lib/iris/tests/graphics/recreate_imagerepo.py | 4 +--- .../integration/experimental/test_ugrid_save.py | 4 +--- lib/iris/tests/integration/merge/test_merge.py | 4 +--- .../tests/integration/netcdf/test_delayed_save.py | 3 +-- lib/iris/tests/integration/plot/test_animate.py | 4 +--- lib/iris/tests/integration/plot/test_netcdftime.py | 4 +--- lib/iris/tests/integration/plot/test_nzdateline.py | 4 +--- .../tests/integration/plot/test_plot_2d_coords.py | 4 +--- lib/iris/tests/integration/plot/test_vector_plots.py | 4 +--- lib/iris/tests/integration/um/test_fieldsfile.py | 4 +--- lib/iris/tests/stock/__init__.py | 4 +--- lib/iris/tests/test_cartography.py | 4 +--- lib/iris/tests/test_cdm.py | 4 +--- lib/iris/tests/test_cf.py | 4 +--- lib/iris/tests/test_concatenate.py | 4 +--- lib/iris/tests/test_constraints.py | 4 +--- lib/iris/tests/test_ff.py | 4 +--- lib/iris/tests/test_file_load.py | 4 +--- lib/iris/tests/test_file_save.py | 4 +--- lib/iris/tests/test_hybrid.py | 4 +--- lib/iris/tests/test_intersect.py | 4 +--- lib/iris/tests/test_io_init.py | 4 +--- lib/iris/tests/test_iterate.py | 4 +--- lib/iris/tests/test_load.py | 4 +--- lib/iris/tests/test_mapping.py | 4 +--- lib/iris/tests/test_merge.py | 4 +--- lib/iris/tests/test_netcdf.py | 4 +--- lib/iris/tests/test_pickling.py | 4 +--- lib/iris/tests/test_quickplot.py | 4 +--- lib/iris/tests/test_util.py | 4 +--- .../area_weighted/test_AreaWeightedRegridder.py | 4 +--- .../geometry/test__extract_relevant_cube_slice.py | 4 +--- .../interpolation/test_RectilinearInterpolator.py | 4 +--- .../analysis/interpolation/test_get_xy_dim_coords.py | 4 +--- .../tests/unit/analysis/maths/test__get_dtype.py | 4 +--- .../analysis/maths/test__inplace_common_checks.py | 4 +--- .../tests/unit/analysis/maths/test__output_dtype.py | 4 +--- .../tests/unit/analysis/test_PercentileAggregator.py | 4 +--- .../analysis/test_WeightedPercentileAggregator.py | 4 +--- .../unit/analysis/trajectory/test_Trajectory.py | 4 +--- .../unit/analysis/trajectory/test_interpolate.py | 4 +--- .../tests/unit/aux_factory/test_AuxCoordFactory.py | 4 +--- lib/iris/tests/unit/common/lenient/test_Lenient.py | 4 +--- lib/iris/tests/unit/common/lenient/test__Lenient.py | 4 +--- .../unit/common/lenient/test__lenient_client.py | 4 +--- .../unit/common/lenient/test__lenient_service.py | 4 +--- lib/iris/tests/unit/common/lenient/test__qualname.py | 4 +--- .../metadata/test_AncillaryVariableMetadata.py | 4 +--- .../tests/unit/common/metadata/test_BaseMetadata.py | 4 +--- .../unit/common/metadata/test_CellMeasureMetadata.py | 4 +--- .../tests/unit/common/metadata/test_CoordMetadata.py | 4 +--- .../tests/unit/common/metadata/test_CubeMetadata.py | 4 +--- .../unit/common/metadata/test__NamedTupleMeta.py | 4 +--- .../tests/unit/common/metadata/test_hexdigest.py | 4 +--- .../unit/common/metadata/test_metadata_filter.py | 4 +--- .../common/metadata/test_metadata_manager_factory.py | 4 +--- .../tests/unit/common/mixin/test_CFVariableMixin.py | 4 +--- .../unit/common/mixin/test_LimitedAttributeDict.py | 4 +--- .../common/mixin/test__get_valid_standard_name.py | 4 +--- lib/iris/tests/unit/common/resolve/test_Resolve.py | 4 +--- .../tests/unit/coord_categorisation/test_add_hour.py | 3 +-- .../test_coord_categorisation.py | 3 +-- .../tests/unit/coord_systems/test_AlbersEqualArea.py | 4 +--- .../coord_systems/test_LambertAzimuthalEqualArea.py | 4 +--- lib/iris/tests/unit/coords/test_CellMethod.py | 3 +-- lib/iris/tests/unit/data_manager/test_DataManager.py | 4 +--- .../tests/unit/experimental/stratify/test_relevel.py | 4 +--- .../unit/experimental/ugrid/load/test_load_mesh.py | 4 +--- .../unit/experimental/ugrid/load/test_load_meshes.py | 4 +--- .../unit/experimental/ugrid/mesh/test_MeshCoord.py | 4 +--- .../ugrid/mesh/test_Mesh__from_coords.py | 4 +--- .../ugrid/metadata/test_ConnectivityMetadata.py | 4 +--- .../ugrid/metadata/test_MeshCoordMetadata.py | 4 +--- .../experimental/ugrid/metadata/test_MeshMetadata.py | 4 +--- .../ugrid/utils/test_recombine_submeshes.py | 4 +--- lib/iris/tests/unit/fileformats/cf/test_CFReader.py | 4 +--- .../name_loaders/test__build_cell_methods.py | 4 +--- .../test__build_lat_lon_for_NAME_timeseries.py | 4 +--- .../name_loaders/test__calc_integration_period.py | 4 +--- .../fileformats/name_loaders/test__generate_cubes.py | 4 +--- .../fileformats/nc_load_rules/actions/__init__.py | 4 +--- .../fileformats/nc_load_rules/engine/test_engine.py | 4 +--- .../nc_load_rules/helpers/test_build_ancil_var.py | 4 +--- .../nc_load_rules/helpers/test_build_cell_measure.py | 4 +--- .../test_build_oblique_mercator_coordinate_system.py | 4 +--- .../nc_load_rules/helpers/test_parse_cell_methods.py | 4 +--- .../netcdf/saver/test__fillvalue_report.py | 3 +-- .../unit/fileformats/nimrod_load_rules/test_units.py | 4 +--- .../pp/test__data_bytes_to_shaped_array.py | 4 +--- .../pp_load_rules/test__all_other_rules.py | 4 +--- .../pp_load_rules/test__model_level_number.py | 4 +--- lib/iris/tests/unit/fileformats/test_rules.py | 4 +--- .../tests/unit/fileformats/um/fast_load/__init__.py | 4 +--- lib/iris/tests/unit/util/test_equalise_attributes.py | 4 +--- lib/iris/tests/unit/util/test_file_is_newer_than.py | 4 +--- lib/iris/util.py | 4 +--- 147 files changed, 151 insertions(+), 427 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index f159f0afca..b288769a7c 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -32,7 +32,6 @@ lint.ignore = [ # (D-3) Temporary, before an initial review, either fix ocurrences or move to (2). "D100", # Missing docstring in public module "D103", # Missing docstring in public function - "D200", # One-line docstring should fit on one line "D205", # 1 blank line required between summary line and description "D401", # First line of docstring should be in imperative mood: ... diff --git a/benchmarks/benchmarks/aux_factory.py b/benchmarks/benchmarks/aux_factory.py index 6f71e47086..e5ed710941 100644 --- a/benchmarks/benchmarks/aux_factory.py +++ b/benchmarks/benchmarks/aux_factory.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""AuxFactory benchmark tests. - -""" +"""AuxFactory benchmark tests.""" import numpy as np diff --git a/benchmarks/benchmarks/coords.py b/benchmarks/benchmarks/coords.py index f90ed1fd31..1d920ac357 100644 --- a/benchmarks/benchmarks/coords.py +++ b/benchmarks/benchmarks/coords.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Coord benchmark tests. - -""" +"""Coord benchmark tests.""" import numpy as np diff --git a/benchmarks/benchmarks/cperf/equality.py b/benchmarks/benchmarks/cperf/equality.py index a25cf99128..97ab9d9b5f 100644 --- a/benchmarks/benchmarks/cperf/equality.py +++ b/benchmarks/benchmarks/cperf/equality.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Equality benchmarks for the CPerf scheme of the UK Met Office's NG-VAT project. -""" +"""Equality benchmarks for the CPerf scheme of the UK Met Office's NG-VAT project.""" from .. import on_demand_benchmark from . import SingleDiagnosticMixin diff --git a/benchmarks/benchmarks/cperf/load.py b/benchmarks/benchmarks/cperf/load.py index 2d3c0b5c6b..bcb1ff117b 100644 --- a/benchmarks/benchmarks/cperf/load.py +++ b/benchmarks/benchmarks/cperf/load.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""File loading benchmarks for the CPerf scheme of the UK Met Office's NG-VAT project. -""" +"""File loading benchmarks for the CPerf scheme of the UK Met Office's NG-VAT project.""" from .. import on_demand_benchmark from . import SingleDiagnosticMixin diff --git a/benchmarks/benchmarks/cperf/save.py b/benchmarks/benchmarks/cperf/save.py index 528f878265..28898225d6 100644 --- a/benchmarks/benchmarks/cperf/save.py +++ b/benchmarks/benchmarks/cperf/save.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""File saving benchmarks for the CPerf scheme of the UK Met Office's NG-VAT project. -""" +"""File saving benchmarks for the CPerf scheme of the UK Met Office's NG-VAT project.""" from iris import save diff --git a/benchmarks/benchmarks/cube.py b/benchmarks/benchmarks/cube.py index ef42e03077..d017e5477e 100644 --- a/benchmarks/benchmarks/cube.py +++ b/benchmarks/benchmarks/cube.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Cube benchmark tests. - -""" +"""Cube benchmark tests.""" import numpy as np diff --git a/benchmarks/benchmarks/experimental/__init__.py b/benchmarks/benchmarks/experimental/__init__.py index d1f34cdb15..ce727a7286 100644 --- a/benchmarks/benchmarks/experimental/__init__.py +++ b/benchmarks/benchmarks/experimental/__init__.py @@ -2,6 +2,4 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Benchmark tests for the experimental module. - -""" +"""Benchmark tests for the experimental module.""" diff --git a/benchmarks/benchmarks/experimental/ugrid/__init__.py b/benchmarks/benchmarks/experimental/ugrid/__init__.py index 322fe9acc0..960734e1c6 100644 --- a/benchmarks/benchmarks/experimental/ugrid/__init__.py +++ b/benchmarks/benchmarks/experimental/ugrid/__init__.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Benchmark tests for the experimental.ugrid module. - -""" +"""Benchmark tests for the experimental.ugrid module.""" from copy import deepcopy diff --git a/benchmarks/benchmarks/generate_data/ugrid.py b/benchmarks/benchmarks/generate_data/ugrid.py index 8cca53c907..d96e991c59 100644 --- a/benchmarks/benchmarks/generate_data/ugrid.py +++ b/benchmarks/benchmarks/generate_data/ugrid.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Scripts for generating supporting data for UGRID-related benchmarking. -""" +"""Scripts for generating supporting data for UGRID-related benchmarking.""" from iris import load_cube as iris_loadcube from iris.experimental.ugrid import PARSE_UGRID_ON_LOAD diff --git a/benchmarks/benchmarks/iterate.py b/benchmarks/benchmarks/iterate.py index 800911f21a..9353cf42ee 100644 --- a/benchmarks/benchmarks/iterate.py +++ b/benchmarks/benchmarks/iterate.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Iterate benchmark tests. - -""" +"""Iterate benchmark tests.""" import numpy as np from iris import coords, cube, iterate diff --git a/benchmarks/benchmarks/metadata_manager_factory.py b/benchmarks/benchmarks/metadata_manager_factory.py index 8e4de9949b..01a2b661b8 100644 --- a/benchmarks/benchmarks/metadata_manager_factory.py +++ b/benchmarks/benchmarks/metadata_manager_factory.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""metadata_manager_factory benchmark tests. - -""" +"""metadata_manager_factory benchmark tests.""" from iris.common import ( AncillaryVariableMetadata, diff --git a/benchmarks/benchmarks/mixin.py b/benchmarks/benchmarks/mixin.py index de5127253f..90fb017b12 100644 --- a/benchmarks/benchmarks/mixin.py +++ b/benchmarks/benchmarks/mixin.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Mixin benchmark tests. - -""" +"""Mixin benchmark tests.""" import numpy as np diff --git a/benchmarks/benchmarks/plot.py b/benchmarks/benchmarks/plot.py index b5bc064e84..9b008ec41c 100644 --- a/benchmarks/benchmarks/plot.py +++ b/benchmarks/benchmarks/plot.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Plot benchmark tests. - -""" +"""Plot benchmark tests.""" import matplotlib as mpl import numpy as np diff --git a/benchmarks/benchmarks/regridding.py b/benchmarks/benchmarks/regridding.py index 8e1c5e33df..b311c94717 100644 --- a/benchmarks/benchmarks/regridding.py +++ b/benchmarks/benchmarks/regridding.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Regridding benchmark test. - -""" +"""Regridding benchmark test.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/benchmarks/benchmarks/sperf/combine_regions.py b/benchmarks/benchmarks/sperf/combine_regions.py index e591a120c9..27a3560d51 100644 --- a/benchmarks/benchmarks/sperf/combine_regions.py +++ b/benchmarks/benchmarks/sperf/combine_regions.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Region combine benchmarks for the SPerf scheme of the UK Met Office's NG-VAT project. -""" +"""Region combine benchmarks for the SPerf scheme of the UK Met Office's NG-VAT project.""" import os.path from dask import array as da diff --git a/benchmarks/benchmarks/sperf/equality.py b/benchmarks/benchmarks/sperf/equality.py index 813cfad6bf..4d6e43d8b9 100644 --- a/benchmarks/benchmarks/sperf/equality.py +++ b/benchmarks/benchmarks/sperf/equality.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Equality benchmarks for the SPerf scheme of the UK Met Office's NG-VAT project. -""" +"""Equality benchmarks for the SPerf scheme of the UK Met Office's NG-VAT project.""" from .. import on_demand_benchmark from . import FileMixin diff --git a/benchmarks/benchmarks/sperf/load.py b/benchmarks/benchmarks/sperf/load.py index d3e9ea7ac9..f3c5ef1136 100644 --- a/benchmarks/benchmarks/sperf/load.py +++ b/benchmarks/benchmarks/sperf/load.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""File loading benchmarks for the SPerf scheme of the UK Met Office's NG-VAT project. -""" +"""File loading benchmarks for the SPerf scheme of the UK Met Office's NG-VAT project.""" from .. import on_demand_benchmark from . import FileMixin diff --git a/benchmarks/benchmarks/sperf/save.py b/benchmarks/benchmarks/sperf/save.py index 2999e81227..3fb8133659 100644 --- a/benchmarks/benchmarks/sperf/save.py +++ b/benchmarks/benchmarks/sperf/save.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""File saving benchmarks for the SPerf scheme of the UK Met Office's NG-VAT project. -""" +"""File saving benchmarks for the SPerf scheme of the UK Met Office's NG-VAT project.""" import os.path from iris import save diff --git a/benchmarks/benchmarks/trajectory.py b/benchmarks/benchmarks/trajectory.py index 4214ed3f6e..ec2958b6a8 100644 --- a/benchmarks/benchmarks/trajectory.py +++ b/benchmarks/benchmarks/trajectory.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Trajectory benchmark test. - -""" +"""Trajectory benchmark test.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/benchmarks/bm_runner.py b/benchmarks/bm_runner.py index 406c8eb3ae..741ecb8580 100644 --- a/benchmarks/bm_runner.py +++ b/benchmarks/bm_runner.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Argparse conveniences for executing common types of benchmark runs. -""" +"""Argparse conveniences for executing common types of benchmark runs.""" from abc import ABC, abstractmethod import argparse diff --git a/docs/src/further_topics/filtering_warnings.rst b/docs/src/further_topics/filtering_warnings.rst index c71cae433a..ef743fa9f1 100644 --- a/docs/src/further_topics/filtering_warnings.rst +++ b/docs/src/further_topics/filtering_warnings.rst @@ -47,9 +47,9 @@ Warnings: >>> my_operation() ... - iris/coord_systems.py:434: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + iris/coord_systems.py:432: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) - iris/coord_systems.py:772: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. + iris/coord_systems.py:770: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. warnings.warn( Warnings can be suppressed using the Python warnings filter with the ``ignore`` @@ -110,7 +110,7 @@ You can target specific Warning messages, e.g. ... warnings.filterwarnings("ignore", message="Discarding false_easting") ... my_operation() ... - iris/coord_systems.py:434: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + iris/coord_systems.py:432: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) :: @@ -128,9 +128,9 @@ Or you can target Warnings raised by specific lines of specific modules, e.g. ... warnings.filterwarnings("ignore", module="iris.coord_systems", lineno=449) ... my_operation() ... - iris/coord_systems.py:434: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + iris/coord_systems.py:432: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) - iris/coord_systems.py:772: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. + iris/coord_systems.py:770: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. warnings.warn( :: @@ -190,7 +190,7 @@ module during execution: ... ) ... my_operation() ... - iris/coord_systems.py:434: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + iris/coord_systems.py:432: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) ---- diff --git a/lib/iris/_data_manager.py b/lib/iris/_data_manager.py index 785440d094..45f1a6b3e2 100644 --- a/lib/iris/_data_manager.py +++ b/lib/iris/_data_manager.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Management of common state and behaviour for cube and coordinate data. - -""" +"""Management of common state and behaviour for cube and coordinate data.""" import copy diff --git a/lib/iris/_deprecation.py b/lib/iris/_deprecation.py index 711e4081cd..b771883a71 100644 --- a/lib/iris/_deprecation.py +++ b/lib/iris/_deprecation.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Utilities for producing runtime deprecation messages. - -""" +"""Utilities for producing runtime deprecation messages.""" import warnings diff --git a/lib/iris/_representation/__init__.py b/lib/iris/_representation/__init__.py index cc312b5c9c..74de095995 100644 --- a/lib/iris/_representation/__init__.py +++ b/lib/iris/_representation/__init__.py @@ -2,6 +2,4 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Code to make printouts and other representations (e.g. html) of Iris objects. - -""" +"""Code to make printouts and other representations (e.g. html) of Iris objects.""" diff --git a/lib/iris/_representation/cube_printout.py b/lib/iris/_representation/cube_printout.py index fc8efb7cd6..9cbf43f300 100644 --- a/lib/iris/_representation/cube_printout.py +++ b/lib/iris/_representation/cube_printout.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Provides text printouts of Iris cubes. - -""" +"""Provides text printouts of Iris cubes.""" from copy import deepcopy from iris._representation.cube_summary import CubeSummary diff --git a/lib/iris/_representation/cube_summary.py b/lib/iris/_representation/cube_summary.py index baceba497a..64a6aadbf3 100644 --- a/lib/iris/_representation/cube_summary.py +++ b/lib/iris/_representation/cube_summary.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Provides objects describing cube summaries. -""" +"""Provides objects describing cube summaries.""" import re from iris.common.metadata import hexdigest diff --git a/lib/iris/analysis/cartography.py b/lib/iris/analysis/cartography.py index 68fad28d9c..78b903c971 100644 --- a/lib/iris/analysis/cartography.py +++ b/lib/iris/analysis/cartography.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Various utilities and numeric transformations relevant to cartography. - -""" +"""Various utilities and numeric transformations relevant to cartography.""" from collections import namedtuple import copy diff --git a/lib/iris/analysis/maths.py b/lib/iris/analysis/maths.py index 6cbdeb70ac..50b8b21a28 100644 --- a/lib/iris/analysis/maths.py +++ b/lib/iris/analysis/maths.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Basic mathematical and statistical operations. - -""" +"""Basic mathematical and statistical operations.""" from functools import lru_cache import inspect diff --git a/lib/iris/analysis/stats.py b/lib/iris/analysis/stats.py index 1fe958500b..33eb171336 100644 --- a/lib/iris/analysis/stats.py +++ b/lib/iris/analysis/stats.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Statistical operations between cubes. - -""" +"""Statistical operations between cubes.""" import numpy as np import numpy.ma as ma diff --git a/lib/iris/common/__init__.py b/lib/iris/common/__init__.py index 983238f17d..f9ad2bf207 100644 --- a/lib/iris/common/__init__.py +++ b/lib/iris/common/__init__.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""A package for provisioning common Iris infrastructure. - -""" +"""A package for provisioning common Iris infrastructure.""" from .lenient import * from .metadata import * diff --git a/lib/iris/common/lenient.py b/lib/iris/common/lenient.py index 821559c44b..d8fb5e8bfc 100644 --- a/lib/iris/common/lenient.py +++ b/lib/iris/common/lenient.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Provides the infrastructure to support lenient client/service behaviour. - -""" +"""Provides the infrastructure to support lenient client/service behaviour.""" from collections.abc import Iterable from contextlib import contextmanager diff --git a/lib/iris/common/metadata.py b/lib/iris/common/metadata.py index 212691e046..27b3329621 100644 --- a/lib/iris/common/metadata.py +++ b/lib/iris/common/metadata.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Provides the infrastructure to support the common metadata API. - -""" +"""Provides the infrastructure to support the common metadata API.""" from abc import ABCMeta diff --git a/lib/iris/common/mixin.py b/lib/iris/common/mixin.py index 08ad224ad6..762d1b1fe6 100644 --- a/lib/iris/common/mixin.py +++ b/lib/iris/common/mixin.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Provides common metadata mixin behaviour. - -""" +"""Provides common metadata mixin behaviour.""" from collections.abc import Mapping from functools import wraps diff --git a/lib/iris/coord_systems.py b/lib/iris/coord_systems.py index d4d1aa66f7..7f0af71548 100644 --- a/lib/iris/coord_systems.py +++ b/lib/iris/coord_systems.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Definitions of coordinate systems. - -""" +"""Definitions of coordinate systems.""" from abc import ABCMeta, abstractmethod from functools import cached_property diff --git a/lib/iris/coords.py b/lib/iris/coords.py index 14371ac3ee..4274872e66 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Definitions of coordinates and other dimensional metadata. - -""" +"""Definitions of coordinates and other dimensional metadata.""" from abc import ABCMeta, abstractmethod from collections import namedtuple diff --git a/lib/iris/cube.py b/lib/iris/cube.py index 04cee11969..691349f170 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -3,9 +3,7 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Classes for representing multi-dimensional data with metadata. - -""" +"""Classes for representing multi-dimensional data with metadata.""" from collections import OrderedDict import copy diff --git a/lib/iris/exceptions.py b/lib/iris/exceptions.py index 36523b8ed6..c869c1c6c8 100644 --- a/lib/iris/exceptions.py +++ b/lib/iris/exceptions.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Exceptions specific to the Iris package. - -""" +"""Exceptions specific to the Iris package.""" class IrisError(Exception): diff --git a/lib/iris/experimental/representation.py b/lib/iris/experimental/representation.py index fd063a5475..6b25023fa2 100644 --- a/lib/iris/experimental/representation.py +++ b/lib/iris/experimental/representation.py @@ -3,9 +3,7 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Definitions of how Iris objects should be represented. - -""" +"""Definitions of how Iris objects should be represented.""" from html import escape import re diff --git a/lib/iris/experimental/ugrid/utils.py b/lib/iris/experimental/ugrid/utils.py index fc0464077a..fce1036c6d 100644 --- a/lib/iris/experimental/ugrid/utils.py +++ b/lib/iris/experimental/ugrid/utils.py @@ -3,9 +3,7 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Utility operations specific to unstructured data. - -""" +"""Utility operations specific to unstructured data.""" from typing import AnyStr, Iterable, Union import dask.array as da diff --git a/lib/iris/fileformats/__init__.py b/lib/iris/fileformats/__init__.py index cd967881c7..174c4d390c 100644 --- a/lib/iris/fileformats/__init__.py +++ b/lib/iris/fileformats/__init__.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""A package for converting cubes to and from specific file formats. - -""" +"""A package for converting cubes to and from specific file formats.""" from iris.io.format_picker import ( DataSourceObjectProtocol, diff --git a/lib/iris/fileformats/_ff.py b/lib/iris/fileformats/_ff.py index 5e65c92996..3edd29c410 100644 --- a/lib/iris/fileformats/_ff.py +++ b/lib/iris/fileformats/_ff.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Provides UK Met Office Fields File (FF) format specific capabilities. - -""" +"""Provides UK Met Office Fields File (FF) format specific capabilities.""" import os import warnings diff --git a/lib/iris/fileformats/dot.py b/lib/iris/fileformats/dot.py index 83336a2249..cd875b3e4a 100644 --- a/lib/iris/fileformats/dot.py +++ b/lib/iris/fileformats/dot.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Provides Creation and saving of DOT graphs for a :class:`iris.cube.Cube`. - -""" +"""Provides Creation and saving of DOT graphs for a :class:`iris.cube.Cube`.""" import os import subprocess diff --git a/lib/iris/fileformats/pp.py b/lib/iris/fileformats/pp.py index a654bfde6f..8ac49b827d 100644 --- a/lib/iris/fileformats/pp.py +++ b/lib/iris/fileformats/pp.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Provides UK Met Office Post Process (PP) format specific capabilities. - -""" +"""Provides UK Met Office Post Process (PP) format specific capabilities.""" from abc import ABCMeta, abstractmethod import collections diff --git a/lib/iris/fileformats/rules.py b/lib/iris/fileformats/rules.py index e092fa2b9b..4467ae1cfa 100644 --- a/lib/iris/fileformats/rules.py +++ b/lib/iris/fileformats/rules.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Generalised mechanisms for metadata translation and cube construction. - -""" +"""Generalised mechanisms for metadata translation and cube construction.""" import collections import warnings diff --git a/lib/iris/iterate.py b/lib/iris/iterate.py index 12e619b79f..1d8ae49d06 100644 --- a/lib/iris/iterate.py +++ b/lib/iris/iterate.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Cube functions for iteration in step. - -""" +"""Cube functions for iteration in step.""" from collections.abc import Iterator import itertools diff --git a/lib/iris/symbols.py b/lib/iris/symbols.py index b55471dadd..0e53588a66 100644 --- a/lib/iris/symbols.py +++ b/lib/iris/symbols.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Contains symbol definitions for use with :func:`iris.plot.symbols`. - -""" +"""Contains symbol definitions for use with :func:`iris.plot.symbols`.""" import itertools import math diff --git a/lib/iris/tests/experimental/__init__.py b/lib/iris/tests/experimental/__init__.py index 951fca1eae..01a9ee6bdc 100644 --- a/lib/iris/tests/experimental/__init__.py +++ b/lib/iris/tests/experimental/__init__.py @@ -2,6 +2,4 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Experimental code is tested in this package. - -""" +"""Experimental code is tested in this package.""" diff --git a/lib/iris/tests/experimental/regrid/__init__.py b/lib/iris/tests/experimental/regrid/__init__.py index be5871a5a6..e3983bc695 100644 --- a/lib/iris/tests/experimental/regrid/__init__.py +++ b/lib/iris/tests/experimental/regrid/__init__.py @@ -2,6 +2,4 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Regridding code is tested in this package. - -""" +"""Regridding code is tested in this package.""" diff --git a/lib/iris/tests/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py b/lib/iris/tests/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py index b68c8f1625..68fa47f25c 100644 --- a/lib/iris/tests/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py +++ b/lib/iris/tests/experimental/regrid/test_regrid_area_weighted_rectilinear_src_and_grid.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test area weighted regridding. - -""" +"""Test area weighted regridding.""" # import iris tests first so that some things can be initialised # before importing anything else. diff --git a/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py b/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py index c74bab37fb..e06809f3c0 100644 --- a/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py +++ b/lib/iris/tests/experimental/regrid/test_regrid_conservative_via_esmpy.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Tests for :func:`iris.experimental.regrid.regrid_conservative_via_esmpy`. - -""" +"""Tests for :func:`iris.experimental.regrid.regrid_conservative_via_esmpy`.""" # import iris tests first so that some things can be initialised # before importing anything else. diff --git a/lib/iris/tests/graphics/recreate_imagerepo.py b/lib/iris/tests/graphics/recreate_imagerepo.py index ae12eb447d..5261f0cc29 100755 --- a/lib/iris/tests/graphics/recreate_imagerepo.py +++ b/lib/iris/tests/graphics/recreate_imagerepo.py @@ -3,9 +3,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Updates imagerepo.json based on the baseline images. - -""" +"""Updates imagerepo.json based on the baseline images.""" import argparse from pathlib import Path diff --git a/lib/iris/tests/integration/experimental/test_ugrid_save.py b/lib/iris/tests/integration/experimental/test_ugrid_save.py index cbff1d767f..8350a2004f 100644 --- a/lib/iris/tests/integration/experimental/test_ugrid_save.py +++ b/lib/iris/tests/integration/experimental/test_ugrid_save.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Integration tests for NetCDF-UGRID file saving. - -""" +"""Integration tests for NetCDF-UGRID file saving.""" # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/integration/merge/test_merge.py b/lib/iris/tests/integration/merge/test_merge.py index 4e8562cb60..7e1acd4ad6 100644 --- a/lib/iris/tests/integration/merge/test_merge.py +++ b/lib/iris/tests/integration/merge/test_merge.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Integration tests for merging cubes. - -""" +"""Integration tests for merging cubes.""" # import iris tests first so that some things can be initialised # before importing anything else. diff --git a/lib/iris/tests/integration/netcdf/test_delayed_save.py b/lib/iris/tests/integration/netcdf/test_delayed_save.py index d76d57c3e1..62bfac7b45 100644 --- a/lib/iris/tests/integration/netcdf/test_delayed_save.py +++ b/lib/iris/tests/integration/netcdf/test_delayed_save.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Integration tests for delayed saving. -""" +"""Integration tests for delayed saving.""" import re import warnings diff --git a/lib/iris/tests/integration/plot/test_animate.py b/lib/iris/tests/integration/plot/test_animate.py index 53a6b38797..4afee0c463 100644 --- a/lib/iris/tests/integration/plot/test_animate.py +++ b/lib/iris/tests/integration/plot/test_animate.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Integration tests for :func:`iris.plot.animate`. - -""" +"""Integration tests for :func:`iris.plot.animate`.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/integration/plot/test_netcdftime.py b/lib/iris/tests/integration/plot/test_netcdftime.py index dbe67efd35..750de9fdf3 100644 --- a/lib/iris/tests/integration/plot/test_netcdftime.py +++ b/lib/iris/tests/integration/plot/test_netcdftime.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test plot of time coord with non-standard calendar. - -""" +"""Test plot of time coord with non-standard calendar.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/integration/plot/test_nzdateline.py b/lib/iris/tests/integration/plot/test_nzdateline.py index 5a83ac5d89..cb119f5b27 100644 --- a/lib/iris/tests/integration/plot/test_nzdateline.py +++ b/lib/iris/tests/integration/plot/test_nzdateline.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test set up of limited area map extents which bridge the date line. - -""" +"""Test set up of limited area map extents which bridge the date line.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/integration/plot/test_plot_2d_coords.py b/lib/iris/tests/integration/plot/test_plot_2d_coords.py index dafddd064d..43cd051f46 100644 --- a/lib/iris/tests/integration/plot/test_plot_2d_coords.py +++ b/lib/iris/tests/integration/plot/test_plot_2d_coords.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test plots with two dimensional coordinates. - -""" +"""Test plots with two dimensional coordinates.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/integration/plot/test_vector_plots.py b/lib/iris/tests/integration/plot/test_vector_plots.py index 08170f6f89..5419dc182f 100644 --- a/lib/iris/tests/integration/plot/test_vector_plots.py +++ b/lib/iris/tests/integration/plot/test_vector_plots.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test some key usages of :func:`iris.plot.quiver`. - -""" +"""Test some key usages of :func:`iris.plot.quiver`.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/integration/um/test_fieldsfile.py b/lib/iris/tests/integration/um/test_fieldsfile.py index 18c28ee1c7..969a343c4f 100644 --- a/lib/iris/tests/integration/um/test_fieldsfile.py +++ b/lib/iris/tests/integration/um/test_fieldsfile.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the fast loading of structured Fieldsfiles. - -""" +"""Test the fast loading of structured Fieldsfiles.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/stock/__init__.py b/lib/iris/tests/stock/__init__.py index 894cc1d02c..8c1154af72 100644 --- a/lib/iris/tests/stock/__init__.py +++ b/lib/iris/tests/stock/__init__.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""A collection of routines which create standard Cubes/files for test purposes. - -""" +"""A collection of routines which create standard Cubes/files for test purposes.""" import iris.tests as tests # isort:skip from datetime import datetime diff --git a/lib/iris/tests/test_cartography.py b/lib/iris/tests/test_cartography.py index 0d4845757b..56ac3d52c7 100644 --- a/lib/iris/tests/test_cartography.py +++ b/lib/iris/tests/test_cartography.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Tests elements of the cartography module. - -""" +"""Tests elements of the cartography module.""" # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/test_cdm.py b/lib/iris/tests/test_cdm.py index 5f8b247b79..a634d35158 100644 --- a/lib/iris/tests/test_cdm.py +++ b/lib/iris/tests/test_cdm.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test cube indexing, slicing, and extracting, and also the dot graphs. - -""" +"""Test cube indexing, slicing, and extracting, and also the dot graphs.""" # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/test_cf.py b/lib/iris/tests/test_cf.py index 99b39af4f1..89ad0e3f2b 100644 --- a/lib/iris/tests/test_cf.py +++ b/lib/iris/tests/test_cf.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the cf module. - -""" +"""Test the cf module.""" # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/test_concatenate.py b/lib/iris/tests/test_concatenate.py index cb26150d61..d4be638087 100644 --- a/lib/iris/tests/test_concatenate.py +++ b/lib/iris/tests/test_concatenate.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the cube concatenate mechanism. - -""" +"""Test the cube concatenate mechanism.""" # import iris tests first so that some things can be initialised # before importing anything else. diff --git a/lib/iris/tests/test_constraints.py b/lib/iris/tests/test_constraints.py index 4fa34ee63d..f7dab288b6 100644 --- a/lib/iris/tests/test_constraints.py +++ b/lib/iris/tests/test_constraints.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the constrained cube loading mechanism. - -""" +"""Test the constrained cube loading mechanism.""" # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/test_ff.py b/lib/iris/tests/test_ff.py index c4868c8d15..fdfa274bdf 100644 --- a/lib/iris/tests/test_ff.py +++ b/lib/iris/tests/test_ff.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the Fieldsfile file loading plugin and FFHeader. - -""" +"""Test the Fieldsfile file loading plugin and FFHeader.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/test_file_load.py b/lib/iris/tests/test_file_load.py index 65bd6e4025..e1510532a1 100644 --- a/lib/iris/tests/test_file_load.py +++ b/lib/iris/tests/test_file_load.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the file loading mechanism. - -""" +"""Test the file loading mechanism.""" # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/test_file_save.py b/lib/iris/tests/test_file_save.py index f3fe60549f..ab0b74c1c2 100644 --- a/lib/iris/tests/test_file_save.py +++ b/lib/iris/tests/test_file_save.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the file saving mechanism. - -""" +"""Test the file saving mechanism.""" # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/test_hybrid.py b/lib/iris/tests/test_hybrid.py index f8913f4fbd..da7cabe765 100644 --- a/lib/iris/tests/test_hybrid.py +++ b/lib/iris/tests/test_hybrid.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the hybrid vertical coordinate representations. - -""" +"""Test the hybrid vertical coordinate representations.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/test_intersect.py b/lib/iris/tests/test_intersect.py index f6287ef1f7..e28c99dea4 100644 --- a/lib/iris/tests/test_intersect.py +++ b/lib/iris/tests/test_intersect.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the intersection of Coords. - -""" +"""Test the intersection of Coords.""" # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/test_io_init.py b/lib/iris/tests/test_io_init.py index 10654e5f64..f8cfaee2bf 100644 --- a/lib/iris/tests/test_io_init.py +++ b/lib/iris/tests/test_io_init.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the io/__init__.py module. - -""" +"""Test the io/__init__.py module.""" # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/test_iterate.py b/lib/iris/tests/test_iterate.py index 627d90e0bc..662707c327 100644 --- a/lib/iris/tests/test_iterate.py +++ b/lib/iris/tests/test_iterate.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the iteration of cubes in step. - -""" +"""Test the iteration of cubes in step.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/test_load.py b/lib/iris/tests/test_load.py index c77854b541..b84ab32add 100644 --- a/lib/iris/tests/test_load.py +++ b/lib/iris/tests/test_load.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the main loading API. - -""" +"""Test the main loading API.""" # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/test_mapping.py b/lib/iris/tests/test_mapping.py index 53563dd193..4f59bf8d31 100644 --- a/lib/iris/tests/test_mapping.py +++ b/lib/iris/tests/test_mapping.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Tests map creation. - -""" +"""Tests map creation.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/test_merge.py b/lib/iris/tests/test_merge.py index a9b1069e95..1fc6fd8b10 100644 --- a/lib/iris/tests/test_merge.py +++ b/lib/iris/tests/test_merge.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the cube merging mechanism. - -""" +"""Test the cube merging mechanism.""" # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/test_netcdf.py b/lib/iris/tests/test_netcdf.py index 8509f4edca..049ff55369 100644 --- a/lib/iris/tests/test_netcdf.py +++ b/lib/iris/tests/test_netcdf.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test CF-NetCDF file loading and saving. - -""" +"""Test CF-NetCDF file loading and saving.""" # Import iris tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/test_pickling.py b/lib/iris/tests/test_pickling.py index 7bea687231..311e6ec9aa 100644 --- a/lib/iris/tests/test_pickling.py +++ b/lib/iris/tests/test_pickling.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test pickling of Iris objects. - -""" +"""Test pickling of Iris objects.""" # Import iris tests first so that some things can be initialised # before importing anything else. diff --git a/lib/iris/tests/test_quickplot.py b/lib/iris/tests/test_quickplot.py index f6a5d210e0..fdd534a2c5 100644 --- a/lib/iris/tests/test_quickplot.py +++ b/lib/iris/tests/test_quickplot.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Tests the high-level plotting interface. - -""" +"""Tests the high-level plotting interface.""" # import iris tests first so that some things can be initialised before importing anything else import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/test_util.py b/lib/iris/tests/test_util.py index d9cebf224f..56774f89f8 100644 --- a/lib/iris/tests/test_util.py +++ b/lib/iris/tests/test_util.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test iris.util. - -""" +"""Test iris.util.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/unit/analysis/area_weighted/test_AreaWeightedRegridder.py b/lib/iris/tests/unit/analysis/area_weighted/test_AreaWeightedRegridder.py index 93354d4278..82f6fe693d 100644 --- a/lib/iris/tests/unit/analysis/area_weighted/test_AreaWeightedRegridder.py +++ b/lib/iris/tests/unit/analysis/area_weighted/test_AreaWeightedRegridder.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :class:`iris.analysis._area_weighted.AreaWeightedRegridder`. - -""" +"""Unit tests for :class:`iris.analysis._area_weighted.AreaWeightedRegridder`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/analysis/geometry/test__extract_relevant_cube_slice.py b/lib/iris/tests/unit/analysis/geometry/test__extract_relevant_cube_slice.py index 44695b81c3..7cb4d80f49 100644 --- a/lib/iris/tests/unit/analysis/geometry/test__extract_relevant_cube_slice.py +++ b/lib/iris/tests/unit/analysis/geometry/test__extract_relevant_cube_slice.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :func:`iris.analysis.geometry._extract_relevant_cube_slice`. - -""" +"""Unit tests for :func:`iris.analysis.geometry._extract_relevant_cube_slice`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/analysis/interpolation/test_RectilinearInterpolator.py b/lib/iris/tests/unit/analysis/interpolation/test_RectilinearInterpolator.py index b37fa1de62..ed6e230840 100644 --- a/lib/iris/tests/unit/analysis/interpolation/test_RectilinearInterpolator.py +++ b/lib/iris/tests/unit/analysis/interpolation/test_RectilinearInterpolator.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :class:`iris.analysis._interpolation.RectilinearInterpolator`. - -""" +"""Unit tests for :class:`iris.analysis._interpolation.RectilinearInterpolator`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/analysis/interpolation/test_get_xy_dim_coords.py b/lib/iris/tests/unit/analysis/interpolation/test_get_xy_dim_coords.py index 6300b81d1a..ae47159df3 100644 --- a/lib/iris/tests/unit/analysis/interpolation/test_get_xy_dim_coords.py +++ b/lib/iris/tests/unit/analysis/interpolation/test_get_xy_dim_coords.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :func:`iris.analysis._interpolation.get_xy_dim_coords`. - -""" +"""Unit tests for :func:`iris.analysis._interpolation.get_xy_dim_coords`.""" # import iris tests first so that some things can be initialised # before importing anything else. diff --git a/lib/iris/tests/unit/analysis/maths/test__get_dtype.py b/lib/iris/tests/unit/analysis/maths/test__get_dtype.py index 4388913d54..643d7e43d7 100644 --- a/lib/iris/tests/unit/analysis/maths/test__get_dtype.py +++ b/lib/iris/tests/unit/analysis/maths/test__get_dtype.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the function :func:`iris.analysis.maths._get_dtype`. - -""" +"""Unit tests for the function :func:`iris.analysis.maths._get_dtype`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/analysis/maths/test__inplace_common_checks.py b/lib/iris/tests/unit/analysis/maths/test__inplace_common_checks.py index 42317b7efd..7ce6bc79c1 100644 --- a/lib/iris/tests/unit/analysis/maths/test__inplace_common_checks.py +++ b/lib/iris/tests/unit/analysis/maths/test__inplace_common_checks.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the function :func:`iris.analysis.maths._inplace_common_checks`. - -""" +"""Unit tests for the function :func:`iris.analysis.maths._inplace_common_checks`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/analysis/maths/test__output_dtype.py b/lib/iris/tests/unit/analysis/maths/test__output_dtype.py index b14db4120a..4e5845b73f 100644 --- a/lib/iris/tests/unit/analysis/maths/test__output_dtype.py +++ b/lib/iris/tests/unit/analysis/maths/test__output_dtype.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the function :func:`iris.analysis.maths._output_dtype`. - -""" +"""Unit tests for the function :func:`iris.analysis.maths._output_dtype`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/analysis/test_PercentileAggregator.py b/lib/iris/tests/unit/analysis/test_PercentileAggregator.py index 84628c9ae5..9099ac42fe 100644 --- a/lib/iris/tests/unit/analysis/test_PercentileAggregator.py +++ b/lib/iris/tests/unit/analysis/test_PercentileAggregator.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.analysis.PercentileAggregator` class instance. - -""" +"""Unit tests for the :class:`iris.analysis.PercentileAggregator` class instance.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/analysis/test_WeightedPercentileAggregator.py b/lib/iris/tests/unit/analysis/test_WeightedPercentileAggregator.py index 0531a5aa3d..1d047db6b6 100644 --- a/lib/iris/tests/unit/analysis/test_WeightedPercentileAggregator.py +++ b/lib/iris/tests/unit/analysis/test_WeightedPercentileAggregator.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.analysis.PercentileAggregator` class instance. - -""" +"""Unit tests for the :class:`iris.analysis.PercentileAggregator` class instance.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/analysis/trajectory/test_Trajectory.py b/lib/iris/tests/unit/analysis/trajectory/test_Trajectory.py index 7f01a816fa..abf0e86513 100644 --- a/lib/iris/tests/unit/analysis/trajectory/test_Trajectory.py +++ b/lib/iris/tests/unit/analysis/trajectory/test_Trajectory.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :class:`iris.analysis.trajectory.Trajectory`. - -""" +"""Unit tests for :class:`iris.analysis.trajectory.Trajectory`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/analysis/trajectory/test_interpolate.py b/lib/iris/tests/unit/analysis/trajectory/test_interpolate.py index 05a2d666cc..c171b18f6e 100644 --- a/lib/iris/tests/unit/analysis/trajectory/test_interpolate.py +++ b/lib/iris/tests/unit/analysis/trajectory/test_interpolate.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :meth:`iris.analysis.trajectory.interpolate`. - -""" +"""Unit tests for :meth:`iris.analysis.trajectory.interpolate`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/aux_factory/test_AuxCoordFactory.py b/lib/iris/tests/unit/aux_factory/test_AuxCoordFactory.py index 6029f2c518..5e136395b5 100644 --- a/lib/iris/tests/unit/aux_factory/test_AuxCoordFactory.py +++ b/lib/iris/tests/unit/aux_factory/test_AuxCoordFactory.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for `iris.aux_factory.AuxCoordFactory`. - -""" +"""Unit tests for `iris.aux_factory.AuxCoordFactory`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/lenient/test_Lenient.py b/lib/iris/tests/unit/common/lenient/test_Lenient.py index abafcc1a3e..375a745ce8 100644 --- a/lib/iris/tests/unit/common/lenient/test_Lenient.py +++ b/lib/iris/tests/unit/common/lenient/test_Lenient.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.common.lenient.Lenient`. - -""" +"""Unit tests for the :class:`iris.common.lenient.Lenient`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/lenient/test__Lenient.py b/lib/iris/tests/unit/common/lenient/test__Lenient.py index 0ed947e513..814359fbaf 100644 --- a/lib/iris/tests/unit/common/lenient/test__Lenient.py +++ b/lib/iris/tests/unit/common/lenient/test__Lenient.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.common.lenient._Lenient`. - -""" +"""Unit tests for the :class:`iris.common.lenient._Lenient`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/lenient/test__lenient_client.py b/lib/iris/tests/unit/common/lenient/test__lenient_client.py index 54e2aca185..509b183003 100644 --- a/lib/iris/tests/unit/common/lenient/test__lenient_client.py +++ b/lib/iris/tests/unit/common/lenient/test__lenient_client.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :func:`iris.common.lenient._lenient_client`. - -""" +"""Unit tests for the :func:`iris.common.lenient._lenient_client`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/lenient/test__lenient_service.py b/lib/iris/tests/unit/common/lenient/test__lenient_service.py index a916779c79..c0ed8df403 100644 --- a/lib/iris/tests/unit/common/lenient/test__lenient_service.py +++ b/lib/iris/tests/unit/common/lenient/test__lenient_service.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :func:`iris.common.lenient._lenient_service`. - -""" +"""Unit tests for the :func:`iris.common.lenient._lenient_service`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/lenient/test__qualname.py b/lib/iris/tests/unit/common/lenient/test__qualname.py index 47b779f6da..49576814d4 100644 --- a/lib/iris/tests/unit/common/lenient/test__qualname.py +++ b/lib/iris/tests/unit/common/lenient/test__qualname.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :func:`iris.common.lenient._qualname`. - -""" +"""Unit tests for the :func:`iris.common.lenient._qualname`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/metadata/test_AncillaryVariableMetadata.py b/lib/iris/tests/unit/common/metadata/test_AncillaryVariableMetadata.py index 2bc9cd9191..b7304f4301 100644 --- a/lib/iris/tests/unit/common/metadata/test_AncillaryVariableMetadata.py +++ b/lib/iris/tests/unit/common/metadata/test_AncillaryVariableMetadata.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.common.metadata.AncillaryVariableMetadata`. - -""" +"""Unit tests for the :class:`iris.common.metadata.AncillaryVariableMetadata`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py b/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py index 60bde320a5..73886882de 100644 --- a/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py +++ b/lib/iris/tests/unit/common/metadata/test_BaseMetadata.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.common.metadata.BaseMetadata`. - -""" +"""Unit tests for the :class:`iris.common.metadata.BaseMetadata`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/metadata/test_CellMeasureMetadata.py b/lib/iris/tests/unit/common/metadata/test_CellMeasureMetadata.py index 4801f99385..3618d2ace5 100644 --- a/lib/iris/tests/unit/common/metadata/test_CellMeasureMetadata.py +++ b/lib/iris/tests/unit/common/metadata/test_CellMeasureMetadata.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.common.metadata.CellMeasureMetadata`. - -""" +"""Unit tests for the :class:`iris.common.metadata.CellMeasureMetadata`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/metadata/test_CoordMetadata.py b/lib/iris/tests/unit/common/metadata/test_CoordMetadata.py index b5cdeaca47..010838b7fc 100644 --- a/lib/iris/tests/unit/common/metadata/test_CoordMetadata.py +++ b/lib/iris/tests/unit/common/metadata/test_CoordMetadata.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.common.metadata.CoordMetadata`. - -""" +"""Unit tests for the :class:`iris.common.metadata.CoordMetadata`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/metadata/test_CubeMetadata.py b/lib/iris/tests/unit/common/metadata/test_CubeMetadata.py index 0bcb553729..92af65da5c 100644 --- a/lib/iris/tests/unit/common/metadata/test_CubeMetadata.py +++ b/lib/iris/tests/unit/common/metadata/test_CubeMetadata.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.common.metadata.CubeMetadata`. - -""" +"""Unit tests for the :class:`iris.common.metadata.CubeMetadata`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/metadata/test__NamedTupleMeta.py b/lib/iris/tests/unit/common/metadata/test__NamedTupleMeta.py index bdf48029e4..5099645082 100644 --- a/lib/iris/tests/unit/common/metadata/test__NamedTupleMeta.py +++ b/lib/iris/tests/unit/common/metadata/test__NamedTupleMeta.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.common.metadata._NamedTupleMeta`. - -""" +"""Unit tests for the :class:`iris.common.metadata._NamedTupleMeta`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/metadata/test_hexdigest.py b/lib/iris/tests/unit/common/metadata/test_hexdigest.py index 035e051440..1a0a0e0120 100644 --- a/lib/iris/tests/unit/common/metadata/test_hexdigest.py +++ b/lib/iris/tests/unit/common/metadata/test_hexdigest.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :func:`iris.common.metadata.hexdigest`. - -""" +"""Unit tests for the :func:`iris.common.metadata.hexdigest`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/metadata/test_metadata_filter.py b/lib/iris/tests/unit/common/metadata/test_metadata_filter.py index c77d0dc357..586a5fe5f8 100644 --- a/lib/iris/tests/unit/common/metadata/test_metadata_filter.py +++ b/lib/iris/tests/unit/common/metadata/test_metadata_filter.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :func:`iris.common.metadata_filter`. - -""" +"""Unit tests for the :func:`iris.common.metadata_filter`.""" import numpy as np diff --git a/lib/iris/tests/unit/common/metadata/test_metadata_manager_factory.py b/lib/iris/tests/unit/common/metadata/test_metadata_manager_factory.py index 3eda14e635..e9ec42e04b 100644 --- a/lib/iris/tests/unit/common/metadata/test_metadata_manager_factory.py +++ b/lib/iris/tests/unit/common/metadata/test_metadata_manager_factory.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :func:`iris.common.metadata.metadata_manager_factory`. - -""" +"""Unit tests for the :func:`iris.common.metadata.metadata_manager_factory`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/mixin/test_CFVariableMixin.py b/lib/iris/tests/unit/common/mixin/test_CFVariableMixin.py index 2e858a74bf..020f18a358 100644 --- a/lib/iris/tests/unit/common/mixin/test_CFVariableMixin.py +++ b/lib/iris/tests/unit/common/mixin/test_CFVariableMixin.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.common.mixin.CFVariableMixin`. - -""" +"""Unit tests for the :class:`iris.common.mixin.CFVariableMixin`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/mixin/test_LimitedAttributeDict.py b/lib/iris/tests/unit/common/mixin/test_LimitedAttributeDict.py index 85d4cfe9a3..f538279bb1 100644 --- a/lib/iris/tests/unit/common/mixin/test_LimitedAttributeDict.py +++ b/lib/iris/tests/unit/common/mixin/test_LimitedAttributeDict.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.common.mixin.LimitedAttributeDict`. - -""" +"""Unit tests for the :class:`iris.common.mixin.LimitedAttributeDict`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/mixin/test__get_valid_standard_name.py b/lib/iris/tests/unit/common/mixin/test__get_valid_standard_name.py index d7b929eeb3..67ba108333 100644 --- a/lib/iris/tests/unit/common/mixin/test__get_valid_standard_name.py +++ b/lib/iris/tests/unit/common/mixin/test__get_valid_standard_name.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :func:`iris.common.mixin._get_valid_standard_name`. - -""" +"""Unit tests for the :func:`iris.common.mixin._get_valid_standard_name`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/common/resolve/test_Resolve.py b/lib/iris/tests/unit/common/resolve/test_Resolve.py index 96b12f149a..0bad967acb 100644 --- a/lib/iris/tests/unit/common/resolve/test_Resolve.py +++ b/lib/iris/tests/unit/common/resolve/test_Resolve.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.common.resolve.Resolve`. - -""" +"""Unit tests for the :class:`iris.common.resolve.Resolve`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/coord_categorisation/test_add_hour.py b/lib/iris/tests/unit/coord_categorisation/test_add_hour.py index 05a0f3e474..c6b0a53656 100644 --- a/lib/iris/tests/unit/coord_categorisation/test_add_hour.py +++ b/lib/iris/tests/unit/coord_categorisation/test_add_hour.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test coordinate categorisation function add_hour. -""" +"""Test coordinate categorisation function add_hour.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/unit/coord_categorisation/test_coord_categorisation.py b/lib/iris/tests/unit/coord_categorisation/test_coord_categorisation.py index 7730831e52..daf4b7e3f2 100644 --- a/lib/iris/tests/unit/coord_categorisation/test_coord_categorisation.py +++ b/lib/iris/tests/unit/coord_categorisation/test_coord_categorisation.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test the coordinate categorisation functions. -""" +"""Test the coordinate categorisation functions.""" import warnings diff --git a/lib/iris/tests/unit/coord_systems/test_AlbersEqualArea.py b/lib/iris/tests/unit/coord_systems/test_AlbersEqualArea.py index 768cca70b7..6c28562133 100644 --- a/lib/iris/tests/unit/coord_systems/test_AlbersEqualArea.py +++ b/lib/iris/tests/unit/coord_systems/test_AlbersEqualArea.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.coord_systems.AlbersEqualArea` class. - -""" +"""Unit tests for the :class:`iris.coord_systems.AlbersEqualArea` class.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/coord_systems/test_LambertAzimuthalEqualArea.py b/lib/iris/tests/unit/coord_systems/test_LambertAzimuthalEqualArea.py index a1d978811d..06b6aad5d3 100644 --- a/lib/iris/tests/unit/coord_systems/test_LambertAzimuthalEqualArea.py +++ b/lib/iris/tests/unit/coord_systems/test_LambertAzimuthalEqualArea.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.coord_systems.LambertAzimuthalEqualArea` class. - -""" +"""Unit tests for the :class:`iris.coord_systems.LambertAzimuthalEqualArea` class.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/coords/test_CellMethod.py b/lib/iris/tests/unit/coords/test_CellMethod.py index 58a10aff50..f2a468ecf1 100644 --- a/lib/iris/tests/unit/coords/test_CellMethod.py +++ b/lib/iris/tests/unit/coords/test_CellMethod.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.coords.CellMethod`. -""" +"""Unit tests for the :class:`iris.coords.CellMethod`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/data_manager/test_DataManager.py b/lib/iris/tests/unit/data_manager/test_DataManager.py index f35c2fcfcb..b419e556a7 100644 --- a/lib/iris/tests/unit/data_manager/test_DataManager.py +++ b/lib/iris/tests/unit/data_manager/test_DataManager.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris._data_manager.DataManager`. - -""" +"""Unit tests for the :class:`iris._data_manager.DataManager`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/experimental/stratify/test_relevel.py b/lib/iris/tests/unit/experimental/stratify/test_relevel.py index f587019f3a..1f0a5618aa 100644 --- a/lib/iris/tests/unit/experimental/stratify/test_relevel.py +++ b/lib/iris/tests/unit/experimental/stratify/test_relevel.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :func:`iris.experimental.stratify.relevel` function. - -""" +"""Unit tests for the :func:`iris.experimental.stratify.relevel` function.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/experimental/ugrid/load/test_load_mesh.py b/lib/iris/tests/unit/experimental/ugrid/load/test_load_mesh.py index 09e15915db..382a36fa71 100644 --- a/lib/iris/tests/unit/experimental/ugrid/load/test_load_mesh.py +++ b/lib/iris/tests/unit/experimental/ugrid/load/test_load_mesh.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :func:`iris.experimental.ugrid.load.load_mesh` function. - -""" +"""Unit tests for the :func:`iris.experimental.ugrid.load.load_mesh` function.""" # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/unit/experimental/ugrid/load/test_load_meshes.py b/lib/iris/tests/unit/experimental/ugrid/load/test_load_meshes.py index d0cfdd4309..8932989252 100644 --- a/lib/iris/tests/unit/experimental/ugrid/load/test_load_meshes.py +++ b/lib/iris/tests/unit/experimental/ugrid/load/test_load_meshes.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :func:`iris.experimental.ugrid.load.load_meshes` function. - -""" +"""Unit tests for the :func:`iris.experimental.ugrid.load.load_meshes` function.""" # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/unit/experimental/ugrid/mesh/test_MeshCoord.py b/lib/iris/tests/unit/experimental/ugrid/mesh/test_MeshCoord.py index bf5500c7ed..2282bc07b9 100644 --- a/lib/iris/tests/unit/experimental/ugrid/mesh/test_MeshCoord.py +++ b/lib/iris/tests/unit/experimental/ugrid/mesh/test_MeshCoord.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.experimental.ugrid.mesh.MeshCoord`. - -""" +"""Unit tests for the :class:`iris.experimental.ugrid.mesh.MeshCoord`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/unit/experimental/ugrid/mesh/test_Mesh__from_coords.py b/lib/iris/tests/unit/experimental/ugrid/mesh/test_Mesh__from_coords.py index 4d12a73a9e..31c5dbfcc0 100644 --- a/lib/iris/tests/unit/experimental/ugrid/mesh/test_Mesh__from_coords.py +++ b/lib/iris/tests/unit/experimental/ugrid/mesh/test_Mesh__from_coords.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :meth:`iris.experimental.ugrid.mesh.Mesh.from_coords`. - -""" +"""Unit tests for the :meth:`iris.experimental.ugrid.mesh.Mesh.from_coords`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/unit/experimental/ugrid/metadata/test_ConnectivityMetadata.py b/lib/iris/tests/unit/experimental/ugrid/metadata/test_ConnectivityMetadata.py index b0d4d70cbe..fa62a9f7e2 100644 --- a/lib/iris/tests/unit/experimental/ugrid/metadata/test_ConnectivityMetadata.py +++ b/lib/iris/tests/unit/experimental/ugrid/metadata/test_ConnectivityMetadata.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.experimental.ugrid.metadata.ConnectivityMetadata`. - -""" +"""Unit tests for the :class:`iris.experimental.ugrid.metadata.ConnectivityMetadata`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/unit/experimental/ugrid/metadata/test_MeshCoordMetadata.py b/lib/iris/tests/unit/experimental/ugrid/metadata/test_MeshCoordMetadata.py index dbf1446b52..fc9242a8f9 100644 --- a/lib/iris/tests/unit/experimental/ugrid/metadata/test_MeshCoordMetadata.py +++ b/lib/iris/tests/unit/experimental/ugrid/metadata/test_MeshCoordMetadata.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.experimental.ugrid.metadata.MeshCoordMetadata`. - -""" +"""Unit tests for the :class:`iris.experimental.ugrid.metadata.MeshCoordMetadata`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/unit/experimental/ugrid/metadata/test_MeshMetadata.py b/lib/iris/tests/unit/experimental/ugrid/metadata/test_MeshMetadata.py index 98e918c342..080d94c188 100644 --- a/lib/iris/tests/unit/experimental/ugrid/metadata/test_MeshMetadata.py +++ b/lib/iris/tests/unit/experimental/ugrid/metadata/test_MeshMetadata.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :class:`iris.experimental.ugrid.metadata.MeshMetadata`. - -""" +"""Unit tests for the :class:`iris.experimental.ugrid.metadata.MeshMetadata`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/unit/experimental/ugrid/utils/test_recombine_submeshes.py b/lib/iris/tests/unit/experimental/ugrid/utils/test_recombine_submeshes.py index 9fcb775433..f01dc345fa 100644 --- a/lib/iris/tests/unit/experimental/ugrid/utils/test_recombine_submeshes.py +++ b/lib/iris/tests/unit/experimental/ugrid/utils/test_recombine_submeshes.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :func:`iris.experimental.ugrid.utils.recombine_submeshes`. - -""" +"""Unit tests for :func:`iris.experimental.ugrid.utils.recombine_submeshes`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. import iris.tests as tests # isort:skip diff --git a/lib/iris/tests/unit/fileformats/cf/test_CFReader.py b/lib/iris/tests/unit/fileformats/cf/test_CFReader.py index 0e6805d104..667c679bfb 100644 --- a/lib/iris/tests/unit/fileformats/cf/test_CFReader.py +++ b/lib/iris/tests/unit/fileformats/cf/test_CFReader.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the `iris.fileformats.cf.CFReader` class. - -""" +"""Unit tests for the `iris.fileformats.cf.CFReader` class.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/fileformats/name_loaders/test__build_cell_methods.py b/lib/iris/tests/unit/fileformats/name_loaders/test__build_cell_methods.py index 2d9faa90e5..98dc5000bc 100644 --- a/lib/iris/tests/unit/fileformats/name_loaders/test__build_cell_methods.py +++ b/lib/iris/tests/unit/fileformats/name_loaders/test__build_cell_methods.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :func:`iris.fileformats.name_loaders._build_cell_methods`. - -""" +"""Unit tests for :func:`iris.fileformats.name_loaders._build_cell_methods`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/fileformats/name_loaders/test__build_lat_lon_for_NAME_timeseries.py b/lib/iris/tests/unit/fileformats/name_loaders/test__build_lat_lon_for_NAME_timeseries.py index 0a020e6142..9cc7ec356a 100644 --- a/lib/iris/tests/unit/fileformats/name_loaders/test__build_lat_lon_for_NAME_timeseries.py +++ b/lib/iris/tests/unit/fileformats/name_loaders/test__build_lat_lon_for_NAME_timeseries.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :func:`iris.analysis.name_loaders._build_lat_lon_for_NAME_timeseries`. - -""" +"""Unit tests for :func:`iris.analysis.name_loaders._build_lat_lon_for_NAME_timeseries`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/fileformats/name_loaders/test__calc_integration_period.py b/lib/iris/tests/unit/fileformats/name_loaders/test__calc_integration_period.py index fb28ad911b..35ca2760b8 100644 --- a/lib/iris/tests/unit/fileformats/name_loaders/test__calc_integration_period.py +++ b/lib/iris/tests/unit/fileformats/name_loaders/test__calc_integration_period.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :func:`iris.fileformats.name_loaders.__calc_integration_period`. - -""" +"""Unit tests for :func:`iris.fileformats.name_loaders.__calc_integration_period`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/fileformats/name_loaders/test__generate_cubes.py b/lib/iris/tests/unit/fileformats/name_loaders/test__generate_cubes.py index f41c52c105..fc00db9663 100644 --- a/lib/iris/tests/unit/fileformats/name_loaders/test__generate_cubes.py +++ b/lib/iris/tests/unit/fileformats/name_loaders/test__generate_cubes.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :func:`iris.analysis.name_loaders._generate_cubes`. - -""" +"""Unit tests for :func:`iris.analysis.name_loaders._generate_cubes`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/fileformats/nc_load_rules/actions/__init__.py b/lib/iris/tests/unit/fileformats/nc_load_rules/actions/__init__.py index 8107a869f4..ac20e95682 100644 --- a/lib/iris/tests/unit/fileformats/nc_load_rules/actions/__init__.py +++ b/lib/iris/tests/unit/fileformats/nc_load_rules/actions/__init__.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the module :mod:`iris.fileformats._nc_load_rules.actions`. - -""" +"""Unit tests for the module :mod:`iris.fileformats._nc_load_rules.actions`.""" from pathlib import Path import shutil import tempfile diff --git a/lib/iris/tests/unit/fileformats/nc_load_rules/engine/test_engine.py b/lib/iris/tests/unit/fileformats/nc_load_rules/engine/test_engine.py index e54c6938bc..7aaca67326 100644 --- a/lib/iris/tests/unit/fileformats/nc_load_rules/engine/test_engine.py +++ b/lib/iris/tests/unit/fileformats/nc_load_rules/engine/test_engine.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :mod:`iris.fileformats._nc_load_rules.engine` module. - -""" +"""Unit tests for the :mod:`iris.fileformats._nc_load_rules.engine` module.""" from unittest import mock from iris.fileformats._nc_load_rules.engine import Engine, FactEntity diff --git a/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_ancil_var.py b/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_ancil_var.py index 5ee0c2d992..0193ef68d5 100644 --- a/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_ancil_var.py +++ b/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_ancil_var.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test function :func:`iris.fileformats._nc_load_rules.helpers.build_ancil_var`. - -""" +"""Test function :func:`iris.fileformats._nc_load_rules.helpers.build_ancil_var`.""" from unittest import mock diff --git a/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_cell_measure.py b/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_cell_measure.py index 74e7d5117d..bdd057b537 100644 --- a/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_cell_measure.py +++ b/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_cell_measure.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test function :func:`iris.fileformats._nc_load_rules.helpers.build_cell_measure`. - -""" +"""Test function :func:`iris.fileformats._nc_load_rules.helpers.build_cell_measure`.""" from unittest import mock diff --git a/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_oblique_mercator_coordinate_system.py b/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_oblique_mercator_coordinate_system.py index 4554ef601d..3e12e33762 100644 --- a/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_oblique_mercator_coordinate_system.py +++ b/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_build_oblique_mercator_coordinate_system.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test function :func:`iris.fileformats._nc_load_rules.helpers.build_oblique_mercator_coordinate_system`. - -""" +"""Test function :func:`iris.fileformats._nc_load_rules.helpers.build_oblique_mercator_coordinate_system`.""" from typing import List, NamedTuple, Type from unittest import mock diff --git a/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_parse_cell_methods.py b/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_parse_cell_methods.py index abbe71012d..500ecd51d8 100644 --- a/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_parse_cell_methods.py +++ b/lib/iris/tests/unit/fileformats/nc_load_rules/helpers/test_parse_cell_methods.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :func:`iris.fileformats.netcdf.parse_cell_methods`. - -""" +"""Unit tests for :func:`iris.fileformats.netcdf.parse_cell_methods`.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/unit/fileformats/netcdf/saver/test__fillvalue_report.py b/lib/iris/tests/unit/fileformats/netcdf/saver/test__fillvalue_report.py index 77fd0cb0ca..c0046e547a 100644 --- a/lib/iris/tests/unit/fileformats/netcdf/saver/test__fillvalue_report.py +++ b/lib/iris/tests/unit/fileformats/netcdf/saver/test__fillvalue_report.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :func:`iris.fileformats.netcdf.saver._fillvalue_report`. -""" +"""Unit tests for :func:`iris.fileformats.netcdf.saver._fillvalue_report`.""" import warnings import numpy as np diff --git a/lib/iris/tests/unit/fileformats/nimrod_load_rules/test_units.py b/lib/iris/tests/unit/fileformats/nimrod_load_rules/test_units.py index 03ec3f5f65..2767807377 100644 --- a/lib/iris/tests/unit/fileformats/nimrod_load_rules/test_units.py +++ b/lib/iris/tests/unit/fileformats/nimrod_load_rules/test_units.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the `iris.fileformats.nimrod_load_rules.units` function. - -""" +"""Unit tests for the `iris.fileformats.nimrod_load_rules.units` function.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py b/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py index 1dbb2097fb..3bd8fcb8d7 100644 --- a/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py +++ b/lib/iris/tests/unit/fileformats/pp/test__data_bytes_to_shaped_array.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the `iris.fileformats.pp._data_bytes_to_shaped_array` function. - -""" +"""Unit tests for the `iris.fileformats.pp._data_bytes_to_shaped_array` function.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__all_other_rules.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__all_other_rules.py index 58b7c1f384..aa6b79e9a0 100644 --- a/lib/iris/tests/unit/fileformats/pp_load_rules/test__all_other_rules.py +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__all_other_rules.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the `iris.fileformats.pp_load_rules._all_other_rules` function. - -""" +"""Unit tests for the `iris.fileformats.pp_load_rules._all_other_rules` function.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__model_level_number.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__model_level_number.py index fd3d236625..65c6bc8442 100644 --- a/lib/iris/tests/unit/fileformats/pp_load_rules/test__model_level_number.py +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__model_level_number.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for :func:`iris.fileformats.pp_load_rules._model_level_number`. - -""" +"""Unit tests for :func:`iris.fileformats.pp_load_rules._model_level_number`.""" # Import iris.tests first so that some things can be initialised before # importing anything else. diff --git a/lib/iris/tests/unit/fileformats/test_rules.py b/lib/iris/tests/unit/fileformats/test_rules.py index f8be75f8fc..d39b6a997d 100644 --- a/lib/iris/tests/unit/fileformats/test_rules.py +++ b/lib/iris/tests/unit/fileformats/test_rules.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test iris.fileformats.rules.py - metadata translation rules. - -""" +"""Test iris.fileformats.rules.py - metadata translation rules.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py b/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py index 89897d173b..1737fcb6cd 100644 --- a/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py +++ b/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py @@ -2,6 +2,4 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the module :mod:`iris.fileformats.um._fast_load`. - -""" +"""Unit tests for the module :mod:`iris.fileformats.um._fast_load`.""" diff --git a/lib/iris/tests/unit/util/test_equalise_attributes.py b/lib/iris/tests/unit/util/test_equalise_attributes.py index 4a900d2cbb..9b09c84dd4 100644 --- a/lib/iris/tests/unit/util/test_equalise_attributes.py +++ b/lib/iris/tests/unit/util/test_equalise_attributes.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Unit tests for the :func:`iris.util.equalise_attributes` function. - -""" +"""Unit tests for the :func:`iris.util.equalise_attributes` function.""" # import iris tests first so that some things can be initialised # before importing anything else. diff --git a/lib/iris/tests/unit/util/test_file_is_newer_than.py b/lib/iris/tests/unit/util/test_file_is_newer_than.py index 93385ed0e0..567b2a1439 100644 --- a/lib/iris/tests/unit/util/test_file_is_newer_than.py +++ b/lib/iris/tests/unit/util/test_file_is_newer_than.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Test function :func:`iris.util.test_file_is_newer`. - -""" +"""Test function :func:`iris.util.test_file_is_newer`.""" # import iris tests first so that some things can be initialised before # importing anything else diff --git a/lib/iris/util.py b/lib/iris/util.py index d030924a52..7d87492c7f 100644 --- a/lib/iris/util.py +++ b/lib/iris/util.py @@ -2,9 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Miscellaneous utility functions. - -""" +"""Miscellaneous utility functions.""" from abc import ABCMeta, abstractmethod from collections.abc import Hashable, Iterable From ddb2c430189eb0eddfbc8ac28e3d773a010862d8 Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:57:15 +0000 Subject: [PATCH 09/26] ruff compliance for D417, D106 (#5677) * ruff compliance for D106. * ruff compliance for D106. * ruff compliance for D417 and D104. --- .ruff.toml | 2 -- docs/gallery_tests/__init__.py | 2 ++ docs/src/developers_guide/documenting/__init__.py | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index b288769a7c..540de5239a 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -25,10 +25,8 @@ lint.ignore = [ # (D-1) Permanent "D105", # Missing docstring in magic method # (D-2) Temporary, to be removed when we are more compliant. Rare cases mmove to (1). - "D417", # Missing argument descriptions in the docstring "D101", # Missing docstring in public class "D102", # Missing docstring in public method - "D104", # Missing docstring in public package # (D-3) Temporary, before an initial review, either fix ocurrences or move to (2). "D100", # Missing docstring in public module "D103", # Missing docstring in public function diff --git a/docs/gallery_tests/__init__.py b/docs/gallery_tests/__init__.py index 091e997248..9468138e04 100644 --- a/docs/gallery_tests/__init__.py +++ b/docs/gallery_tests/__init__.py @@ -2,3 +2,5 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. + +"""Gallery Tests.""" diff --git a/docs/src/developers_guide/documenting/__init__.py b/docs/src/developers_guide/documenting/__init__.py index e69de29bb2..6e031999e7 100644 --- a/docs/src/developers_guide/documenting/__init__.py +++ b/docs/src/developers_guide/documenting/__init__.py @@ -0,0 +1 @@ +# noqa: D104 From 8aa0442007bca98ac18935b7682c1041ce8b840e Mon Sep 17 00:00:00 2001 From: Bill Little Date: Sat, 6 Jan 2024 11:42:29 +0000 Subject: [PATCH 10/26] move tests.pp to tests.__init__ (#5679) --- lib/iris/tests/__init__.py | 88 ++++++++++++++++++++++++++++ lib/iris/tests/pp.py | 96 ------------------------------- lib/iris/tests/test_cdm.py | 3 +- lib/iris/tests/test_cube_to_pp.py | 5 +- lib/iris/tests/test_pp_cf.py | 3 +- 5 files changed, 92 insertions(+), 103 deletions(-) delete mode 100644 lib/iris/tests/pp.py diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py index a1efe9d606..77a9fcdd67 100644 --- a/lib/iris/tests/__init__.py +++ b/lib/iris/tests/__init__.py @@ -42,6 +42,7 @@ import iris.config import iris.cube +import iris.fileformats import iris.tests.graphics as graphics import iris.util @@ -883,6 +884,93 @@ class GraphicsTest(graphics.GraphicsTestMixin, IrisTest): pass +class PPTest: + """A mixin class to provide PP-specific utilities to subclasses of tests.IrisTest.""" + + @contextlib.contextmanager + def cube_save_test( + self, + reference_txt_path, + reference_cubes=None, + reference_pp_path=None, + **kwargs, + ): + """A context manager for testing the saving of Cubes to PP files. + + Args: + + * reference_txt_path: + The path of the file containing the textual PP reference data. + + Kwargs: + + * reference_cubes: + The cube(s) from which the textual PP reference can be re-built if necessary. + * reference_pp_path: + The location of a PP file from which the textual PP reference can be re-built if necessary. + NB. The "reference_cubes" argument takes precedence over this argument. + + The return value from the context manager is the name of a temporary file + into which the PP data to be tested should be saved. + + Example:: + with self.cube_save_test(reference_txt_path, reference_cubes=cubes) as temp_pp_path: + iris.save(cubes, temp_pp_path) + + """ + # Watch out for a missing reference text file + if not os.path.isfile(reference_txt_path): + if reference_cubes: + temp_pp_path = iris.util.create_temp_filename(".pp") + try: + iris.save(reference_cubes, temp_pp_path, **kwargs) + self._create_reference_txt(reference_txt_path, temp_pp_path) + finally: + os.remove(temp_pp_path) + elif reference_pp_path: + self._create_reference_txt(reference_txt_path, reference_pp_path) + else: + raise ValueError( + "Missing all of reference txt file, cubes, and PP path." + ) + + temp_pp_path = iris.util.create_temp_filename(".pp") + try: + # This value is returned to the target of the "with" statement's "as" clause. + yield temp_pp_path + + # Load deferred data for all of the fields (but don't do anything with it) + pp_fields = list(iris.fileformats.pp.load(temp_pp_path)) + for pp_field in pp_fields: + pp_field.data + with open(reference_txt_path, "r") as reference_fh: + reference = "".join(reference_fh) + self._assert_str_same( + reference + "\n", + str(pp_fields) + "\n", + reference_txt_path, + type_comparison_name="PP files", + ) + finally: + os.remove(temp_pp_path) + + def _create_reference_txt(self, txt_path, pp_path): + # Load the reference data + pp_fields = list(iris.fileformats.pp.load(pp_path)) + for pp_field in pp_fields: + pp_field.data + + # Clear any header words we don't use + unused = ("lbexp", "lbegin", "lbnrec", "lbproj", "lbtyp") + for pp_field in pp_fields: + for word_name in unused: + setattr(pp_field, word_name, 0) + + # Save the textual representation of the PP fields + with open(txt_path, "w") as txt_file: + txt_file.writelines(str(pp_fields)) + + def skip_data(fn): """Decorator to choose whether to run tests, based on the availability of external data. diff --git a/lib/iris/tests/pp.py b/lib/iris/tests/pp.py deleted file mode 100644 index b0af72d5ee..0000000000 --- a/lib/iris/tests/pp.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the BSD license. -# See LICENSE in the root of the repository for full licensing details. - -import contextlib -import os.path - -import iris - - -class PPTest: - """A mixin class to provide PP-specific utilities to subclasses of tests.IrisTest.""" - - @contextlib.contextmanager - def cube_save_test( - self, - reference_txt_path, - reference_cubes=None, - reference_pp_path=None, - **kwargs, - ): - """A context manager for testing the saving of Cubes to PP files. - - Args: - - * reference_txt_path: - The path of the file containing the textual PP reference data. - - Kwargs: - - * reference_cubes: - The cube(s) from which the textual PP reference can be re-built if necessary. - * reference_pp_path: - The location of a PP file from which the textual PP reference can be re-built if necessary. - NB. The "reference_cubes" argument takes precedence over this argument. - - The return value from the context manager is the name of a temporary file - into which the PP data to be tested should be saved. - - Example:: - with self.cube_save_test(reference_txt_path, reference_cubes=cubes) as temp_pp_path: - iris.save(cubes, temp_pp_path) - - """ - # Watch out for a missing reference text file - if not os.path.isfile(reference_txt_path): - if reference_cubes: - temp_pp_path = iris.util.create_temp_filename(".pp") - try: - iris.save(reference_cubes, temp_pp_path, **kwargs) - self._create_reference_txt(reference_txt_path, temp_pp_path) - finally: - os.remove(temp_pp_path) - elif reference_pp_path: - self._create_reference_txt(reference_txt_path, reference_pp_path) - else: - raise ValueError( - "Missing all of reference txt file, cubes, and PP path." - ) - - temp_pp_path = iris.util.create_temp_filename(".pp") - try: - # This value is returned to the target of the "with" statement's "as" clause. - yield temp_pp_path - - # Load deferred data for all of the fields (but don't do anything with it) - pp_fields = list(iris.fileformats.pp.load(temp_pp_path)) - for pp_field in pp_fields: - pp_field.data - with open(reference_txt_path, "r") as reference_fh: - reference = "".join(reference_fh) - self._assert_str_same( - reference + "\n", - str(pp_fields) + "\n", - reference_txt_path, - type_comparison_name="PP files", - ) - finally: - os.remove(temp_pp_path) - - def _create_reference_txt(self, txt_path, pp_path): - # Load the reference data - pp_fields = list(iris.fileformats.pp.load(pp_path)) - for pp_field in pp_fields: - pp_field.data - - # Clear any header words we don't use - unused = ("lbexp", "lbegin", "lbnrec", "lbproj", "lbtyp") - for pp_field in pp_fields: - for word_name in unused: - setattr(pp_field, word_name, 0) - - # Save the textual representation of the PP fields - with open(txt_path, "w") as txt_file: - txt_file.writelines(str(pp_fields)) diff --git a/lib/iris/tests/test_cdm.py b/lib/iris/tests/test_cdm.py index a634d35158..937df0bc2a 100644 --- a/lib/iris/tests/test_cdm.py +++ b/lib/iris/tests/test_cdm.py @@ -21,7 +21,6 @@ import iris.cube import iris.fileformats import iris.fileformats.dot -import iris.tests.pp as pp import iris.tests.stock @@ -1285,7 +1284,7 @@ def test_non_string_attributes(self): @tests.skip_data -class TestMaskedData(tests.IrisTest, pp.PPTest): +class TestMaskedData(tests.IrisTest, tests.PPTest): def _load_3d_cube(self): # This 3D data set has a missing a slice with SOME missing values. # The missing data is in the pressure = 1000 hPa, forcast_period = 0, diff --git a/lib/iris/tests/test_cube_to_pp.py b/lib/iris/tests/test_cube_to_pp.py index e75edee9cd..6ae4567f49 100644 --- a/lib/iris/tests/test_cube_to_pp.py +++ b/lib/iris/tests/test_cube_to_pp.py @@ -17,7 +17,6 @@ import iris.coords import iris.fileformats.pp from iris.fileformats.pp import PPField3 -import iris.tests.pp as pp import iris.tests.stock as stock import iris.util @@ -36,7 +35,7 @@ def itab_callback(cube, field, filename): @tests.skip_data -class TestPPSave(tests.IrisTest, pp.PPTest): +class TestPPSave(tests.IrisTest, tests.PPTest): def test_no_forecast_time(self): cube = stock.lat_lon_cube() coord = iris.coords.DimCoord( @@ -276,7 +275,7 @@ def geog_cs(self): return iris.coord_systems.GeogCS(6371229.0) -class TestPPSaveRules(tests.IrisTest, pp.PPTest): +class TestPPSaveRules(tests.IrisTest, tests.PPTest): def test_default_coord_system(self): GeogCS = iris.coord_systems.GeogCS cube = iris.tests.stock.lat_lon_cube() diff --git a/lib/iris/tests/test_pp_cf.py b/lib/iris/tests/test_pp_cf.py index 1495fd65d1..8b0af5a5c3 100644 --- a/lib/iris/tests/test_pp_cf.py +++ b/lib/iris/tests/test_pp_cf.py @@ -13,7 +13,6 @@ import iris.coords from iris.fileformats.netcdf import _thread_safe_nc from iris.fileformats.pp import STASH -import iris.tests.pp as pp import iris.util @@ -64,7 +63,7 @@ def callback_aaxzc_n10r13xy_b_pp(cube, field, filename): @tests.skip_data -class TestAll(tests.IrisTest, pp.PPTest): +class TestAll(tests.IrisTest, tests.PPTest): _ref_dir = ("usecases", "pp_to_cf_conversion") def _test_file(self, name): From f966738da762eb5db50ac5f985ccf4b65d919ab3 Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:59:43 +0000 Subject: [PATCH 11/26] ruff complliance for D100. (#5678) --- .ruff.toml | 1 - benchmarks/benchmarks/import_iris.py | 3 +++ docs/gallery_tests/test_gallery_examples.py | 2 ++ docs/src/conf.py | 2 ++ .../developers_guide/documenting/docstrings_attribute.py | 3 +++ .../documenting/docstrings_sample_routine.py | 3 +++ .../userguide/plotting_examples/1d_quickplot_simple.py | 2 ++ docs/src/userguide/plotting_examples/1d_simple.py | 2 ++ docs/src/userguide/plotting_examples/1d_with_legend.py | 2 ++ docs/src/userguide/plotting_examples/brewer.py | 2 ++ docs/src/userguide/plotting_examples/cube_blockplot.py | 2 ++ .../plotting_examples/cube_brewer_cite_contourf.py | 2 ++ .../userguide/plotting_examples/cube_brewer_contourf.py | 2 ++ docs/src/userguide/plotting_examples/cube_contour.py | 5 +++++ docs/src/userguide/plotting_examples/cube_contourf.py | 5 +++++ docs/src/userguide/regridding_plots/interpolate_column.py | 2 ++ .../src/userguide/regridding_plots/regridded_to_global.py | 2 ++ .../regridding_plots/regridded_to_global_area_weighted.py | 2 ++ .../userguide/regridding_plots/regridded_to_rotated.py | 2 ++ docs/src/userguide/regridding_plots/regridding_plot.py | 2 ++ lib/iris/fileformats/pp_load_rules.py | 3 ++- lib/iris/fileformats/pp_save_rules.py | 2 ++ pyproject.toml | 8 ++++++++ setup.py | 2 ++ 24 files changed, 61 insertions(+), 2 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index 540de5239a..ff7ce543be 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -28,7 +28,6 @@ lint.ignore = [ "D101", # Missing docstring in public class "D102", # Missing docstring in public method # (D-3) Temporary, before an initial review, either fix ocurrences or move to (2). - "D100", # Missing docstring in public module "D103", # Missing docstring in public function "D205", # 1 blank line required between summary line and description "D401", # First line of docstring should be in imperative mood: ... diff --git a/benchmarks/benchmarks/import_iris.py b/benchmarks/benchmarks/import_iris.py index fbae82fee6..51679ce7df 100644 --- a/benchmarks/benchmarks/import_iris.py +++ b/benchmarks/benchmarks/import_iris.py @@ -2,6 +2,9 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. + +"""import iris benchmarking.""" + from importlib import import_module, reload ################ diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index 83f2c93217..37f2858ee9 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -3,6 +3,8 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. +"""Test all the gallery examples.""" + import importlib import matplotlib.pyplot as plt diff --git a/docs/src/conf.py b/docs/src/conf.py index dab4c9052d..97be2776ef 100644 --- a/docs/src/conf.py +++ b/docs/src/conf.py @@ -17,6 +17,8 @@ # serve to show the default. # ---------------------------------------------------------------------------- +"""sphinx config.""" + import datetime from importlib.metadata import version as get_version import ntpath diff --git a/docs/src/developers_guide/documenting/docstrings_attribute.py b/docs/src/developers_guide/documenting/docstrings_attribute.py index 3044145b20..9b85ecb201 100644 --- a/docs/src/developers_guide/documenting/docstrings_attribute.py +++ b/docs/src/developers_guide/documenting/docstrings_attribute.py @@ -1,3 +1,6 @@ +"""docstring attribute example.""" + + class ExampleClass: """Class Summary.""" diff --git a/docs/src/developers_guide/documenting/docstrings_sample_routine.py b/docs/src/developers_guide/documenting/docstrings_sample_routine.py index d565e6a8df..4c26bc3569 100644 --- a/docs/src/developers_guide/documenting/docstrings_sample_routine.py +++ b/docs/src/developers_guide/documenting/docstrings_sample_routine.py @@ -1,3 +1,6 @@ +"""docstring routine example.""" + + def sample_routine(arg1, arg2, kwarg1="foo", kwarg2=None): """Purpose section text goes here. diff --git a/docs/src/userguide/plotting_examples/1d_quickplot_simple.py b/docs/src/userguide/plotting_examples/1d_quickplot_simple.py index 725ff69f11..58d0918dcb 100644 --- a/docs/src/userguide/plotting_examples/1d_quickplot_simple.py +++ b/docs/src/userguide/plotting_examples/1d_quickplot_simple.py @@ -1,3 +1,5 @@ +"""Simple 1D plot using iris.quickplot.plot().""" + import matplotlib.pyplot as plt import iris diff --git a/docs/src/userguide/plotting_examples/1d_simple.py b/docs/src/userguide/plotting_examples/1d_simple.py index 249412f44f..4511a0fbe1 100644 --- a/docs/src/userguide/plotting_examples/1d_simple.py +++ b/docs/src/userguide/plotting_examples/1d_simple.py @@ -1,3 +1,5 @@ +"""Simple 1D plot using iris.plot.plot().""" + import matplotlib.pyplot as plt import iris diff --git a/docs/src/userguide/plotting_examples/1d_with_legend.py b/docs/src/userguide/plotting_examples/1d_with_legend.py index 6b29fc9e76..b325657766 100644 --- a/docs/src/userguide/plotting_examples/1d_with_legend.py +++ b/docs/src/userguide/plotting_examples/1d_with_legend.py @@ -1,3 +1,5 @@ +"""Simple 1D plot using iris.plot.plot() with a legend.""" + import matplotlib.pyplot as plt import iris diff --git a/docs/src/userguide/plotting_examples/brewer.py b/docs/src/userguide/plotting_examples/brewer.py index 905296279d..e42ad57cc0 100644 --- a/docs/src/userguide/plotting_examples/brewer.py +++ b/docs/src/userguide/plotting_examples/brewer.py @@ -1,3 +1,5 @@ +"""Plot a chart of all Brewer colour schemes.""" + import matplotlib.pyplot as plt import numpy as np diff --git a/docs/src/userguide/plotting_examples/cube_blockplot.py b/docs/src/userguide/plotting_examples/cube_blockplot.py index 50a2d1f4d7..1f4d3985a3 100644 --- a/docs/src/userguide/plotting_examples/cube_blockplot.py +++ b/docs/src/userguide/plotting_examples/cube_blockplot.py @@ -1,3 +1,5 @@ +"""Cube block plot using using iris.plot.pcolormesh().""" + import matplotlib.pyplot as plt import iris diff --git a/docs/src/userguide/plotting_examples/cube_brewer_cite_contourf.py b/docs/src/userguide/plotting_examples/cube_brewer_cite_contourf.py index 6e3996660c..4e28510e43 100644 --- a/docs/src/userguide/plotting_examples/cube_brewer_cite_contourf.py +++ b/docs/src/userguide/plotting_examples/cube_brewer_cite_contourf.py @@ -1,3 +1,5 @@ +"""Addind a citation for a plot using iris.plot.citation().""" + import matplotlib.pyplot as plt import iris diff --git a/docs/src/userguide/plotting_examples/cube_brewer_contourf.py b/docs/src/userguide/plotting_examples/cube_brewer_contourf.py index d562443f07..94692c924c 100644 --- a/docs/src/userguide/plotting_examples/cube_brewer_contourf.py +++ b/docs/src/userguide/plotting_examples/cube_brewer_contourf.py @@ -1,3 +1,5 @@ +"""Plot a cube with a Brewer colour palette using iris.quickplot.contourf().""" + import matplotlib.cm as mpl_cm import matplotlib.pyplot as plt diff --git a/docs/src/userguide/plotting_examples/cube_contour.py b/docs/src/userguide/plotting_examples/cube_contour.py index 7a9fe6ef09..0d8c1e02aa 100644 --- a/docs/src/userguide/plotting_examples/cube_contour.py +++ b/docs/src/userguide/plotting_examples/cube_contour.py @@ -1,3 +1,8 @@ +"""Simple contour plot of a cube. + +Can use iris.plot.contour() or iris.quicplot.contour(). + +""" import matplotlib.pyplot as plt import iris diff --git a/docs/src/userguide/plotting_examples/cube_contourf.py b/docs/src/userguide/plotting_examples/cube_contourf.py index 5989e42c71..531dd45d25 100644 --- a/docs/src/userguide/plotting_examples/cube_contourf.py +++ b/docs/src/userguide/plotting_examples/cube_contourf.py @@ -1,3 +1,8 @@ +"""Simple filled contour plot of a cube. + +Can use iris.plot.contour() or iris.quickplot.contour(). + +""" import matplotlib.pyplot as plt import iris diff --git a/docs/src/userguide/regridding_plots/interpolate_column.py b/docs/src/userguide/regridding_plots/interpolate_column.py index ec1f37a3b2..681af0c998 100644 --- a/docs/src/userguide/regridding_plots/interpolate_column.py +++ b/docs/src/userguide/regridding_plots/interpolate_column.py @@ -1,3 +1,5 @@ +"""Interpolate using iris.analysis.Linear().""" + import matplotlib.pyplot as plt import numpy as np diff --git a/docs/src/userguide/regridding_plots/regridded_to_global.py b/docs/src/userguide/regridding_plots/regridded_to_global.py index 5ce6513ef0..8e43f1471a 100644 --- a/docs/src/userguide/regridding_plots/regridded_to_global.py +++ b/docs/src/userguide/regridding_plots/regridded_to_global.py @@ -1,3 +1,5 @@ +"""Interpolate using iris.analysis.Linear().""" + import matplotlib.pyplot as plt import iris diff --git a/docs/src/userguide/regridding_plots/regridded_to_global_area_weighted.py b/docs/src/userguide/regridding_plots/regridded_to_global_area_weighted.py index f53e624e03..6c906ba87b 100644 --- a/docs/src/userguide/regridding_plots/regridded_to_global_area_weighted.py +++ b/docs/src/userguide/regridding_plots/regridded_to_global_area_weighted.py @@ -1,3 +1,5 @@ +"""Regrid using iris.analysis.AreaWeighted.""" + import matplotlib.colors import matplotlib.pyplot as plt import numpy as np diff --git a/docs/src/userguide/regridding_plots/regridded_to_rotated.py b/docs/src/userguide/regridding_plots/regridded_to_rotated.py index cb54a016cb..31afdb7da1 100644 --- a/docs/src/userguide/regridding_plots/regridded_to_rotated.py +++ b/docs/src/userguide/regridding_plots/regridded_to_rotated.py @@ -1,3 +1,5 @@ +"""Rotated pole.""" + import matplotlib.pyplot as plt import iris diff --git a/docs/src/userguide/regridding_plots/regridding_plot.py b/docs/src/userguide/regridding_plots/regridding_plot.py index c559e0e3e7..ed45822a51 100644 --- a/docs/src/userguide/regridding_plots/regridding_plot.py +++ b/docs/src/userguide/regridding_plots/regridding_plot.py @@ -1,3 +1,5 @@ +"""Plot regridded data.""" + import matplotlib.pyplot as plt import iris diff --git a/lib/iris/fileformats/pp_load_rules.py b/lib/iris/fileformats/pp_load_rules.py index ea42aee92c..7c164edd41 100644 --- a/lib/iris/fileformats/pp_load_rules.py +++ b/lib/iris/fileformats/pp_load_rules.py @@ -3,10 +3,11 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. - # Historically this was auto-generated from # SciTools/iris-code-generators:tools/gen_rules.py +"""PP Load Rules.""" + import calendar from functools import wraps diff --git a/lib/iris/fileformats/pp_save_rules.py b/lib/iris/fileformats/pp_save_rules.py index ab9d1c9545..9bcfd8d92f 100644 --- a/lib/iris/fileformats/pp_save_rules.py +++ b/lib/iris/fileformats/pp_save_rules.py @@ -3,6 +3,8 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. +"""PP Save Rules.""" + import warnings import cftime diff --git a/pyproject.toml b/pyproject.toml index d0c2816e93..37384a3c3e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -103,6 +103,14 @@ ignore = [ force-sort-within-sections = true known-first-party = ["iris"] +[tool.ruff.lint.per-file-ignores] +# All test scripts +"test_*.py" = [ + # https://docs.astral.sh/ruff/rules/undocumented-public-module/ + "D100", # Missing docstring in public module +] + + [tool.ruff.lint.pydocstyle] convention = "numpy" diff --git a/setup.py b/setup.py index 6e58a7999d..1027085e81 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,5 @@ +"""Iris setup.""" + import os import sys From 2bfaebda62b22d3203cfa737a5f017d68800a5c8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 18:43:38 +0000 Subject: [PATCH 12/26] [pre-commit.ci] pre-commit autoupdate (#5682) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.1.9 → v0.1.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.9...v0.1.11) - [github.com/PyCQA/flake8: 6.1.0 → 7.0.0](https://github.com/PyCQA/flake8/compare/6.1.0...7.0.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e63924c78f..ded673f008 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,7 +29,7 @@ repos: - id: no-commit-to-branch - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.1.9" + rev: "v0.1.11" hooks: - id: ruff types: [file, python] @@ -45,7 +45,7 @@ repos: additional_dependencies: [tomli] - repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 types: [file, python] From d528fce10a0a67460938cba95f2be1642a801ae1 Mon Sep 17 00:00:00 2001 From: Martin Yeo <40734014+trexfeathers@users.noreply.github.com> Date: Wed, 10 Jan 2024 14:10:36 +0000 Subject: [PATCH 13/26] Make further topics obviously different (#5684) * Make further topics obviously different. * Revert "Make further topics obviously different." This reverts commit 3ef38cc6f4d6f557167cbcdfa4f2688fedd690f5. * Remove pydata_sphinx_theme collapse_navigation. * What's New entry. --- docs/src/conf.py | 1 - docs/src/whatsnew/latest.rst | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/src/conf.py b/docs/src/conf.py index 97be2776ef..0fa493bde1 100644 --- a/docs/src/conf.py +++ b/docs/src/conf.py @@ -291,7 +291,6 @@ def _dotv(version): html_theme_options = { "footer_start": ["copyright", "sphinx-version"], "footer_end": ["custom_footer"], - "collapse_navigation": True, "navigation_depth": 3, "show_prev_next": True, "navbar_align": "content", diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index d7e9a40648..fc755165be 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -142,6 +142,13 @@ This document explains the changes made to Iris for this release #. `@bouweandela`_ updated all hyperlinks to https. (:pull:`5621`) +#. `@ESadek-MO`_ created an index page for :ref:`further_topics_index`, and + relocated all 'Technical Papers' into + :ref:`further_topics_index`. (:pull:`5602`) + +#. `@trexfeathers`_ made drop-down icons visible to show which pages link to + 'sub-pages'. (:pull:`5684`) + 💼 Internal =========== From 1f01d1b9e4e76b852f7ac85b51ee7ba88a07746e Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Thu, 11 Jan 2024 11:46:50 +0000 Subject: [PATCH 14/26] fix typo (#5689) --- docs/src/whatsnew/latest.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index fc755165be..c7e4f2e470 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -24,7 +24,7 @@ This document explains the changes made to Iris for this release 📢 Announcements ================ -#. `@lbdreyer`_ relicensed Iris from LGPL-3 to BSD-3. (:pull: `5577`) +#. `@lbdreyer`_ relicensed Iris from LGPL-3 to BSD-3. (:pull:`5577`) #. `@HGWright`_, `@bjlittle`_ and `@trexfeathers`_ (reviewers) added a CITATION.cff file to Iris and updated the :ref:`citation documentation ` From b11af454c928dc5ec82c2c95aa804e69e4531fe2 Mon Sep 17 00:00:00 2001 From: Martin Yeo <40734014+trexfeathers@users.noreply.github.com> Date: Thu, 11 Jan 2024 14:24:26 +0000 Subject: [PATCH 15/26] Better documentation for Cube names in curl (#5680) * Better documentation for Cube names in curl. * Fix typo. --- docs/src/whatsnew/latest.rst | 4 ++++ lib/iris/analysis/calculus.py | 33 +++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index c7e4f2e470..da3e7e22df 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -149,6 +149,10 @@ This document explains the changes made to Iris for this release #. `@trexfeathers`_ made drop-down icons visible to show which pages link to 'sub-pages'. (:pull:`5684`) +#. `@trexfeathers`_ improved the documentation of acceptable + :class:`~iris.cube.Cube` standard names in + :func:`iris.analysis.calculus.curl`. (:pull:`5680`) + 💼 Internal =========== diff --git a/lib/iris/analysis/calculus.py b/lib/iris/analysis/calculus.py index 4dd3171fae..aaee22d9c8 100644 --- a/lib/iris/analysis/calculus.py +++ b/lib/iris/analysis/calculus.py @@ -25,7 +25,7 @@ from iris.exceptions import IrisUserWarning from iris.util import delta -__all__ = ["cube_delta", "curl", "differentiate"] +__all__ = ["DIRECTIONAL_NAMES", "cube_delta", "curl", "differentiate"] def _construct_delta_coord(coord): @@ -471,6 +471,9 @@ def curl(i_cube, j_cube, k_cube=None): Calculate the 2-dimensional or 3-dimensional spherical or cartesian curl of the given vector of cubes. + The cube standard names must match one of the combinations in + :data:`DIRECTIONAL_NAMES`. + As well as the standard x and y coordinates, this function requires each cube to possess a vertical or z-like coordinate (representing some form of height or pressure). This can be a scalar or dimension coordinate. @@ -734,12 +737,27 @@ def curl(i_cube, j_cube, k_cube=None): return result +#: Acceptable X-Y-Z standard name combinations that +#: :func:`curl` can use (via :func:`spatial_vectors_with_phenom_name`). +DIRECTIONAL_NAMES: tuple[tuple[str, str, str], ...] = ( + ("u", "v", "w"), + ("x", "y", "z"), + ("i", "j", "k"), + ("eastward", "northward", "upward"), + ("easterly", "northerly", "vertical"), + ("easterly", "northerly", "radial"), +) + + def spatial_vectors_with_phenom_name(i_cube, j_cube, k_cube=None): """Given spatially dependent cubes, return a list of the spatial coordinate names. Given 2 or 3 spatially dependent cubes, return a list of the spatial coordinate names with appropriate phenomenon name. + The cube standard names must match one of the combinations in + :data:`DIRECTIONAL_NAMES`. + This routine is designed to identify the vector quantites which each of the cubes provided represent and return a list of their 3d spatial dimension names and associated phenomenon. @@ -757,15 +775,6 @@ def spatial_vectors_with_phenom_name(i_cube, j_cube, k_cube=None): """ - directional_names = ( - ("u", "v", "w"), - ("x", "y", "z"), - ("i", "j", "k"), - ("eastward", "northward", "upward"), - ("easterly", "northerly", "vertical"), - ("easterly", "northerly", "radial"), - ) - # Create a list of the standard_names of our incoming cubes # (excluding the k_cube if it is None). cube_standard_names = [ @@ -795,7 +804,7 @@ def spatial_vectors_with_phenom_name(i_cube, j_cube, k_cube=None): # Get the appropriate direction list from the cube_directions we # have got from the standard name. direction = None - for possible_direction in directional_names: + for possible_direction in DIRECTIONAL_NAMES: # If this possible direction (minus the k_cube if it is none) # matches direction from the given cubes use it. if possible_direction[0 : len(cube_directions)] == cube_directions: @@ -804,7 +813,7 @@ def spatial_vectors_with_phenom_name(i_cube, j_cube, k_cube=None): # If we didn't get a match, raise an Exception if direction is None: direction_string = "; ".join( - ", ".join(possible_direction) for possible_direction in directional_names + ", ".join(possible_direction) for possible_direction in DIRECTIONAL_NAMES ) raise ValueError( "{} are not recognised vector cube_directions. " From 1d71bd4d0f445548235ecd3a1671982ba81302f7 Mon Sep 17 00:00:00 2001 From: Elias <110238618+ESadek-MO@users.noreply.github.com> Date: Thu, 11 Jan 2024 17:25:08 +0000 Subject: [PATCH 16/26] Removed use of catch_warnings (#5685) * made changes, moving warnings out of for loop * added in original functionality flip * fixed msg not being assigned * fixed test * Updated tests to better document nuances * corrected dummy warning * review comments * review comments * added a msg = None --- .../fileformats/_nc_load_rules/helpers.py | 36 +++++++++---------- .../tests/integration/netcdf/test_general.py | 35 ++++++++++++++++++ 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/lib/iris/fileformats/_nc_load_rules/helpers.py b/lib/iris/fileformats/_nc_load_rules/helpers.py index 6a135a211c..894bb31af8 100644 --- a/lib/iris/fileformats/_nc_load_rules/helpers.py +++ b/lib/iris/fileformats/_nc_load_rules/helpers.py @@ -327,7 +327,7 @@ class UnknownCellMethodWarning(iris.exceptions.IrisUnknownCellMethodWarning): pass -def parse_cell_methods(nc_cell_methods): +def parse_cell_methods(nc_cell_methods, cf_name=None): """Parse a CF cell_methods attribute string into a tuple of zero or more CellMethod instances. @@ -345,6 +345,7 @@ def parse_cell_methods(nc_cell_methods): results are not affected. """ + msg = None cell_methods = [] if nc_cell_methods is not None: for m in _split_cell_methods(nc_cell_methods): @@ -356,10 +357,16 @@ def parse_cell_methods(nc_cell_methods): method_words = method.split() if method_words[0].lower() not in _CM_KNOWN_METHODS: msg = "NetCDF variable contains unknown cell method {!r}" - warnings.warn( - msg.format("{}".format(method_words[0])), - category=UnknownCellMethodWarning, - ) + msg = msg.format(method_words[0]) + if cf_name: + name = "{}".format(cf_name) + msg = msg.replace("variable", "variable {!r}".format(name)) + else: + warnings.warn( + msg, + category=UnknownCellMethodWarning, + ) + msg = None d[_CM_METHOD] = method name = d[_CM_NAME] name = name.replace(" ", "") @@ -417,6 +424,9 @@ def parse_cell_methods(nc_cell_methods): comments=d[_CM_COMMENT], ) cell_methods.append(cell_method) + # only prints one warning, rather than each loop + if msg: + warnings.warn(msg, category=UnknownCellMethodWarning) return tuple(cell_methods) @@ -447,21 +457,7 @@ def build_cube_metadata(engine): # Incorporate cell methods nc_att_cell_methods = getattr(cf_var, CF_ATTR_CELL_METHODS, None) - with warnings.catch_warnings(record=True) as warning_records: - cube.cell_methods = parse_cell_methods(nc_att_cell_methods) - # Filter to get the warning we are interested in. - warning_records = [ - record - for record in warning_records - if issubclass(record.category, UnknownCellMethodWarning) - ] - if len(warning_records) > 0: - # Output an enhanced warning message. - warn_record = warning_records[0] - name = "{}".format(cf_var.cf_name) - msg = warn_record.message.args[0] - msg = msg.replace("variable", "variable {!r}".format(name)) - warnings.warn(message=msg, category=UnknownCellMethodWarning) + cube.cell_methods = parse_cell_methods(nc_att_cell_methods, cf_var.cf_name) # Set the cube global attributes. for attr_name, attr_value in cf_var.cf_group.global_attributes.items(): diff --git a/lib/iris/tests/integration/netcdf/test_general.py b/lib/iris/tests/integration/netcdf/test_general.py index 8c27742185..751c160805 100644 --- a/lib/iris/tests/integration/netcdf/test_general.py +++ b/lib/iris/tests/integration/netcdf/test_general.py @@ -484,5 +484,40 @@ def test_path_string_save_same(self): self.assertCDL(tempfile_frompath) +@tests.skip_data +class TestWarningRepeats(tests.IrisTest): + def test_datum_once(self): + """Tests for warnings being duplicated. + + Notes + ----- + This test relies on `iris.load` throwing a warning. This warning might + be removed in the future, in which case `assert len(record) == 2 should` + be change to `assert len(record) == 1`. + + toa_brightness_temperature.nc has an AuxCoord with lazy data, and triggers a + specific part of dask which contains a `catch_warnings()` call which + causes warnings to be repeated, and so has been removed from the + `fnames` list until a solution is found for such a file. + + """ + # + fnames = [ + "false_east_north_merc.nc", + "non_unit_scale_factor_merc.nc", + # toa_brightness_temperature.nc, + ] + fpaths = [ + tests.get_data_path(("NetCDF", "mercator", fname)) for fname in fnames + ] + + with warnings.catch_warnings(record=True) as record: + warnings.simplefilter("default") + for fpath in fpaths: + iris.load(fpath) + warnings.warn("Dummy warning", category=iris.exceptions.IrisUserWarning) + assert len(record) == 2 + + if __name__ == "__main__": tests.main() From 1e2a85ae14dc4552dae860d6079d157b39d1a9ca Mon Sep 17 00:00:00 2001 From: Elias <110238618+ESadek-MO@users.noreply.github.com> Date: Fri, 12 Jan 2024 16:22:42 +0000 Subject: [PATCH 17/26] Added whatsnew to warnings PR (#5696) * added whatsnew * fixed mod link --- docs/src/whatsnew/latest.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index da3e7e22df..dfc1019683 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -83,6 +83,10 @@ This document explains the changes made to Iris for this release #. `@rcomer`_ and `@trexfeathers`_ (reviewer) added handling for realization coordinates when saving pp files (:issue:`4747`, :pull:`5568`) +#. `@ESadek-MO`_ has updated + :mod:`iris.fileformats._nc_load_rules.helpers` to lessen warning duplication. + (:issue:`5536`, :pull:`5685`) + 💣 Incompatible Changes ======================= From d95c9e26e541d301978c93c1ce7643aee1039c98 Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Fri, 12 Jan 2024 23:10:12 +0000 Subject: [PATCH 18/26] ruff compliance for D205. (#5681) * ruff complliance for D205 (wip) * wip * wip * wip * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * various minor fixes. * fix doctest. * gallery noqa and minor fixes. * removed comments * Update lib/iris/_data_manager.py Co-authored-by: Bill Little * Update lib/iris/_lazy_data.py Co-authored-by: Bill Little * Update lib/iris/_merge.py Co-authored-by: Bill Little * Update lib/iris/_representation/cube_printout.py Co-authored-by: Bill Little * Update lib/iris/_representation/cube_printout.py Co-authored-by: Bill Little * Update lib/iris/analysis/_interpolation.py Co-authored-by: Bill Little * Update lib/iris/coords.py Co-authored-by: Bill Little * Update lib/iris/experimental/ugrid/mesh.py Co-authored-by: Bill Little * Apply suggestions from code review Co-authored-by: Bill Little * minor tweaks. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bill Little --- .ruff.toml | 1 - benchmarks/asv_delegated_conda.py | 9 +- benchmarks/benchmarks/__init__.py | 4 +- benchmarks/benchmarks/aux_factory.py | 4 +- benchmarks/benchmarks/coords.py | 4 +- benchmarks/benchmarks/cperf/equality.py | 9 +- benchmarks/benchmarks/cperf/load.py | 3 +- benchmarks/benchmarks/cperf/save.py | 1 + benchmarks/benchmarks/cube.py | 4 +- .../benchmarks/experimental/ugrid/__init__.py | 4 +- .../experimental/ugrid/regions_combine.py | 20 +- benchmarks/benchmarks/generate_data/ugrid.py | 12 +- benchmarks/benchmarks/import_iris.py | 3 +- .../benchmarks/sperf/combine_regions.py | 6 +- benchmarks/benchmarks/sperf/equality.py | 6 +- .../general/plot_SOI_filtering.py | 5 +- .../general/plot_anomaly_log_colouring.py | 5 +- docs/gallery_code/general/plot_coriolis.py | 5 +- .../general/plot_cross_section.py | 5 +- .../general/plot_custom_aggregation.py | 24 +-- .../general/plot_custom_file_loading.py | 29 +-- docs/gallery_code/general/plot_global_map.py | 5 +- docs/gallery_code/general/plot_inset.py | 5 +- .../general/plot_lineplot_with_legend.py | 7 +- .../gallery_code/general/plot_polar_stereo.py | 5 +- .../general/plot_polynomial_fit.py | 5 +- .../plot_projections_and_annotations.py | 5 +- .../general/plot_rotated_pole_mapping.py | 13 +- docs/gallery_code/general/plot_zonal_means.py | 10 +- docs/gallery_code/meteorology/plot_COP_1d.py | 5 +- .../gallery_code/meteorology/plot_COP_maps.py | 5 +- docs/gallery_code/meteorology/plot_TEC.py | 5 +- .../meteorology/plot_deriving_phenomena.py | 9 +- .../meteorology/plot_hovmoller.py | 5 +- .../meteorology/plot_lagged_ensemble.py | 9 +- .../meteorology/plot_wind_barbs.py | 5 +- .../meteorology/plot_wind_speed.py | 5 +- .../oceanography/plot_atlantic_profiles.py | 5 +- .../oceanography/plot_load_nemo.py | 6 +- .../oceanography/plot_orca_projection.py | 5 +- docs/gallery_tests/conftest.py | 8 +- .../src/further_topics/filtering_warnings.rst | 12 +- lib/iris/_concatenate.py | 86 +++++---- lib/iris/_data_manager.py | 26 +-- lib/iris/_lazy_data.py | 6 +- lib/iris/_merge.py | 100 ++++++---- lib/iris/_representation/cube_printout.py | 8 +- lib/iris/analysis/_area_weighted.py | 6 +- lib/iris/analysis/_grid_angles.py | 9 +- lib/iris/analysis/_interpolation.py | 34 ++-- lib/iris/analysis/_regrid.py | 21 +- lib/iris/analysis/cartography.py | 27 ++- lib/iris/analysis/geometry.py | 11 +- lib/iris/analysis/maths.py | 35 +++- lib/iris/analysis/stats.py | 3 +- lib/iris/analysis/trajectory.py | 29 +-- lib/iris/common/_split_attribute_dicts.py | 3 +- lib/iris/common/lenient.py | 49 +++-- lib/iris/common/metadata.py | 34 ++-- lib/iris/common/resolve.py | 117 ++++++++--- lib/iris/coord_categorisation.py | 20 +- lib/iris/coord_systems.py | 36 ++-- lib/iris/coords.py | 142 ++++++-------- lib/iris/cube.py | 179 ++++++++--------- lib/iris/exceptions.py | 35 ++-- lib/iris/experimental/raster.py | 49 +++-- lib/iris/experimental/regrid.py | 36 ++-- lib/iris/experimental/representation.py | 31 +-- lib/iris/experimental/stratify.py | 13 +- lib/iris/experimental/ugrid/__init__.py | 5 +- lib/iris/experimental/ugrid/cf.py | 21 +- lib/iris/experimental/ugrid/load.py | 28 ++- lib/iris/experimental/ugrid/mesh.py | 182 +++++++++++------- lib/iris/experimental/ugrid/save.py | 3 +- lib/iris/fileformats/_ff.py | 26 +-- lib/iris/fileformats/_nc_load_rules/engine.py | 9 +- .../fileformats/_nc_load_rules/helpers.py | 107 ++++------ .../_structured_array_identification.py | 56 ++++-- lib/iris/fileformats/cf.py | 66 ++++--- lib/iris/fileformats/dot.py | 45 +++-- lib/iris/fileformats/name.py | 7 +- lib/iris/fileformats/name_loaders.py | 29 ++- lib/iris/fileformats/nimrod_load_rules.py | 23 ++- lib/iris/fileformats/pp.py | 118 ++++++------ lib/iris/fileformats/pp_load_rules.py | 14 +- lib/iris/fileformats/rules.py | 15 +- lib/iris/fileformats/um/_fast_load.py | 10 +- .../um/_fast_load_structured_fields.py | 8 +- lib/iris/fileformats/um/_ff_replacement.py | 3 +- .../um/_optimal_array_structuring.py | 4 +- lib/iris/iterate.py | 8 +- lib/iris/plot.py | 27 ++- lib/iris/quickplot.py | 8 +- lib/iris/symbols.py | 5 +- lib/iris/util.py | 108 +++++++---- noxfile.py | 5 +- pyproject.toml | 5 +- setup.py | 6 +- 98 files changed, 1422 insertions(+), 976 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index ff7ce543be..5a39e2bbf8 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -29,7 +29,6 @@ lint.ignore = [ "D102", # Missing docstring in public method # (D-3) Temporary, before an initial review, either fix ocurrences or move to (2). "D103", # Missing docstring in public function - "D205", # 1 blank line required between summary line and description "D401", # First line of docstring should be in imperative mood: ... # pyupgrade (UP) diff --git a/benchmarks/asv_delegated_conda.py b/benchmarks/asv_delegated_conda.py index b0bdd6b64b..c8070b063a 100644 --- a/benchmarks/asv_delegated_conda.py +++ b/benchmarks/asv_delegated_conda.py @@ -2,8 +2,9 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""ASV plug-in providing an alternative :class:`asv.plugins.conda.Conda` -subclass that manages the Conda environment via custom user scripts. +"""ASV plug-in providing an alternative :class:`asv.plugins.conda.Conda` subclass. + +Manages the Conda environment via custom user scripts. """ @@ -42,7 +43,9 @@ def __init__( requirements: dict, tagged_env_vars: dict, ) -> None: - """Parameters + """__init__. + + Parameters ---------- conf : Config instance diff --git a/benchmarks/benchmarks/__init__.py b/benchmarks/benchmarks/__init__.py index 14edb2eda7..de03ff3fea 100644 --- a/benchmarks/benchmarks/__init__.py +++ b/benchmarks/benchmarks/__init__.py @@ -36,7 +36,9 @@ def disable_repeat_between_setup(benchmark_object): class TrackAddedMemoryAllocation: - """Context manager which measures by how much process resident memory grew, + """Measures by how much process resident memory grew, during execution. + + Context manager which measures by how much process resident memory grew, during execution of its enclosed code block. Obviously limited as to what it actually measures : Relies on the current diff --git a/benchmarks/benchmarks/aux_factory.py b/benchmarks/benchmarks/aux_factory.py index e5ed710941..2da93351ee 100644 --- a/benchmarks/benchmarks/aux_factory.py +++ b/benchmarks/benchmarks/aux_factory.py @@ -16,7 +16,9 @@ class FactoryCommon: # * make class an ABC # * remove NotImplementedError # * combine setup_common into setup - """A base class running a generalised suite of benchmarks for any factory. + """Run a generalised suite of benchmarks for any factory. + + A base class running a generalised suite of benchmarks for any factory. Factory to be specified in a subclass. ASV will run the benchmarks within this class for any subclasses. diff --git a/benchmarks/benchmarks/coords.py b/benchmarks/benchmarks/coords.py index 1d920ac357..d1f7631e00 100644 --- a/benchmarks/benchmarks/coords.py +++ b/benchmarks/benchmarks/coords.py @@ -23,7 +23,9 @@ class CoordCommon: # * make class an ABC # * remove NotImplementedError # * combine setup_common into setup - """A base class running a generalised suite of benchmarks for any coord. + """Run a generalised suite of benchmarks for any coord. + + A base class running a generalised suite of benchmarks for any coord. Coord to be specified in a subclass. ASV will run the benchmarks within this class for any subclasses. diff --git a/benchmarks/benchmarks/cperf/equality.py b/benchmarks/benchmarks/cperf/equality.py index 97ab9d9b5f..16f8c10aab 100644 --- a/benchmarks/benchmarks/cperf/equality.py +++ b/benchmarks/benchmarks/cperf/equality.py @@ -8,8 +8,11 @@ class EqualityMixin(SingleDiagnosticMixin): - r"""Uses :class:`SingleDiagnosticMixin` as the realistic case will be comparing + r"""Use :class:`SingleDiagnosticMixin` as the realistic case. + + Uses :class:`SingleDiagnosticMixin` as the realistic case will be comparing :class:`~iris.cube.Cube`\\ s that have been loaded from file. + """ # Cut down the parent parameters. @@ -23,9 +26,7 @@ def setup(self, file_type, three_d=False, three_times=False): @on_demand_benchmark class CubeEquality(EqualityMixin): - r"""Benchmark time and memory costs of comparing LFRic and UM - :class:`~iris.cube.Cube`\\ s. - """ + r"""Benchmark time & memory costs of comparing LFRic & UM :class:`~iris.cube.Cube`\\ s.""" def _comparison(self): _ = self.cube == self.other_cube diff --git a/benchmarks/benchmarks/cperf/load.py b/benchmarks/benchmarks/cperf/load.py index bcb1ff117b..9ace3ad56b 100644 --- a/benchmarks/benchmarks/cperf/load.py +++ b/benchmarks/benchmarks/cperf/load.py @@ -10,7 +10,8 @@ @on_demand_benchmark class SingleDiagnosticLoad(SingleDiagnosticMixin): def time_load(self, _, __, ___): - """The 'real world comparison' + """The 'real world comparison'. + * UM coords are always realised (DimCoords). * LFRic coords are not realised by default (MeshCoords). diff --git a/benchmarks/benchmarks/cperf/save.py b/benchmarks/benchmarks/cperf/save.py index 28898225d6..2d60f920c4 100644 --- a/benchmarks/benchmarks/cperf/save.py +++ b/benchmarks/benchmarks/cperf/save.py @@ -14,6 +14,7 @@ @on_demand_benchmark class NetcdfSave: """Benchmark time and memory costs of saving ~large-ish data cubes to netcdf. + Parametrised by file type. """ diff --git a/benchmarks/benchmarks/cube.py b/benchmarks/benchmarks/cube.py index d017e5477e..fc07d55111 100644 --- a/benchmarks/benchmarks/cube.py +++ b/benchmarks/benchmarks/cube.py @@ -28,7 +28,9 @@ class ComponentCommon: # * make class an ABC # * remove NotImplementedError # * combine setup_common into setup - """A base class running a generalised suite of benchmarks for cubes that + """Run a generalised suite of benchmarks for cubes. + + A base class running a generalised suite of benchmarks for cubes that include a specified component (e.g. Coord, CellMeasure etc.). Component to be specified in a subclass. diff --git a/benchmarks/benchmarks/experimental/ugrid/__init__.py b/benchmarks/benchmarks/experimental/ugrid/__init__.py index 960734e1c6..c2335990aa 100644 --- a/benchmarks/benchmarks/experimental/ugrid/__init__.py +++ b/benchmarks/benchmarks/experimental/ugrid/__init__.py @@ -15,7 +15,9 @@ class UGridCommon: - """A base class running a generalised suite of benchmarks for any ugrid object. + """Run a generalised suite of benchmarks for any ugrid object. + + A base class running a generalised suite of benchmarks for any ugrid object. Object to be specified in a subclass. ASV will run the benchmarks within this class for any subclasses. diff --git a/benchmarks/benchmarks/experimental/ugrid/regions_combine.py b/benchmarks/benchmarks/experimental/ugrid/regions_combine.py index b47082590b..36feb65cbe 100644 --- a/benchmarks/benchmarks/experimental/ugrid/regions_combine.py +++ b/benchmarks/benchmarks/experimental/ugrid/regions_combine.py @@ -2,14 +2,18 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Benchmarks stages of operation of the function +"""Benchmarks stages of operation. + +Benchmarks stages of operation of the function :func:`iris.experimental.ugrid.utils.recombine_submeshes`. Where possible benchmarks should be parameterised for two sizes of input data: - * minimal: enables detection of regressions in parts of the run-time that do - NOT scale with data size. - * large: large enough to exclusively detect regressions in parts of the - run-time that scale with data size. + +* minimal: enables detection of regressions in parts of the run-time that do + NOT scale with data size. + +* large: large enough to exclusively detect regressions in parts of the + run-time that scale with data size. """ import os @@ -193,10 +197,13 @@ def track_addedmem_compute_data(self, n_cubesphere): class CombineRegionsSaveData(MixinCombineRegions): - """Test saving *only*, having replaced the input cube data with 'imaginary' + """Test saving *only*. + + Test saving *only*, having replaced the input cube data with 'imaginary' array data, so that input data is not loaded from disk during the save operation. + """ def time_save(self, n_cubesphere): @@ -219,6 +226,7 @@ def track_filesize_saved(self, n_cubesphere): class CombineRegionsFileStreamedCalc(MixinCombineRegions): """Test the whole cost of file-to-file streaming. + Uses the combined cube which is based on lazy data loading from the region cubes on disk. """ diff --git a/benchmarks/benchmarks/generate_data/ugrid.py b/benchmarks/benchmarks/generate_data/ugrid.py index d96e991c59..0ac349d882 100644 --- a/benchmarks/benchmarks/generate_data/ugrid.py +++ b/benchmarks/benchmarks/generate_data/ugrid.py @@ -14,7 +14,9 @@ def generate_cube_like_2d_cubesphere(n_cube: int, with_mesh: bool, output_path: str): - """Construct and save to file an LFRIc cubesphere-like cube for a given + """Construct and save to file an LFRIc cubesphere-like cube. + + Construct and save to file an LFRIc cubesphere-like cube for a given cubesphere size, *or* a simpler structured (UM-like) cube of equivalent size. @@ -54,7 +56,9 @@ def generate_cube_like_2d_cubesphere(n_cube: int, with_mesh: bool, output_path: def make_cube_like_2d_cubesphere(n_cube: int, with_mesh: bool): - """Generate an LFRIc cubesphere-like cube for a given cubesphere size, + """Generate an LFRIc cubesphere-like cube. + + Generate an LFRIc cubesphere-like cube for a given cubesphere size, *or* a simpler structured (UM-like) cube of equivalent size. All the cube data, coords and mesh content are LAZY, and produced without @@ -155,7 +159,9 @@ def _external(xy_dims_, save_path_): def make_cubesphere_testfile(c_size, n_levels=0, n_times=1): - """Build a C cubesphere testfile in a given directory, with a standard naming. + """Build a C cubesphere testfile in a given directory. + + Build a C cubesphere testfile in a given directory, with a standard naming. If n_levels > 0 specified: 3d file with the specified number of levels. Return the file path. diff --git a/benchmarks/benchmarks/import_iris.py b/benchmarks/benchmarks/import_iris.py index 51679ce7df..566ffca78b 100644 --- a/benchmarks/benchmarks/import_iris.py +++ b/benchmarks/benchmarks/import_iris.py @@ -31,8 +31,7 @@ class Iris: @staticmethod def _import(module_name, reset_colormaps=False): - """Have experimented with adding sleep() commands into the imported - modules. + """Have experimented with adding sleep() commands into the imported modules. The results reveal: diff --git a/benchmarks/benchmarks/sperf/combine_regions.py b/benchmarks/benchmarks/sperf/combine_regions.py index 27a3560d51..adc51ef6dc 100644 --- a/benchmarks/benchmarks/sperf/combine_regions.py +++ b/benchmarks/benchmarks/sperf/combine_regions.py @@ -195,7 +195,9 @@ def track_addedmem_compute_data(self, n_cubesphere): @on_demand_benchmark class SaveData(Mixin): - """Test saving *only*, having replaced the input cube data with 'imaginary' + """Test saving *only*. + + Test saving *only*, having replaced the input cube data with 'imaginary' array data, so that input data is not loaded from disk during the save operation. @@ -217,8 +219,10 @@ def track_filesize_saved(self, n_cubesphere): @on_demand_benchmark class FileStreamedCalc(Mixin): """Test the whole cost of file-to-file streaming. + Uses the combined cube which is based on lazy data loading from the region cubes on disk. + """ def setup(self, n_cubesphere, imaginary_data=False, create_result_cube=True): diff --git a/benchmarks/benchmarks/sperf/equality.py b/benchmarks/benchmarks/sperf/equality.py index 4d6e43d8b9..339687a22c 100644 --- a/benchmarks/benchmarks/sperf/equality.py +++ b/benchmarks/benchmarks/sperf/equality.py @@ -9,8 +9,10 @@ @on_demand_benchmark class CubeEquality(FileMixin): - r"""Benchmark time and memory costs of comparing :class:`~iris.cube.Cube`\\ s - with attached :class:`~iris.experimental.ugrid.mesh.Mesh`\\ es. + r"""Benchmark time and memory costs. + + Benchmark time and memory costs of comparing :class:`~iris.cube.Cube`\\ s + with attached :class:`~iris.experimental.ugrid.mesh.Mesh`\\ es. Uses :class:`FileMixin` as the realistic case will be comparing :class:`~iris.cube.Cube`\\ s that have been loaded from file. diff --git a/docs/gallery_code/general/plot_SOI_filtering.py b/docs/gallery_code/general/plot_SOI_filtering.py index 5082162068..32fe7c6ff7 100644 --- a/docs/gallery_code/general/plot_SOI_filtering.py +++ b/docs/gallery_code/general/plot_SOI_filtering.py @@ -1,4 +1,5 @@ -"""Applying a Filter to a Time-Series +""" +Applying a Filter to a Time-Series ================================== This example demonstrates low pass filtering a time-series by applying a @@ -17,7 +18,7 @@ Trenberth K. E. (1984) Signal Versus Noise in the Southern Oscillation. Monthly Weather Review, Vol 112, pp 326-332 -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt import numpy as np diff --git a/docs/gallery_code/general/plot_anomaly_log_colouring.py b/docs/gallery_code/general/plot_anomaly_log_colouring.py index 98751b0dbf..16210173c5 100644 --- a/docs/gallery_code/general/plot_anomaly_log_colouring.py +++ b/docs/gallery_code/general/plot_anomaly_log_colouring.py @@ -1,4 +1,5 @@ -"""Colouring Anomaly Data With Logarithmic Scaling +""" +Colouring Anomaly Data With Logarithmic Scaling =============================================== In this example, we need to plot anomaly data where the values have a @@ -22,7 +23,7 @@ and :obj:`matplotlib.pyplot.pcolormesh`). See also: https://en.wikipedia.org/wiki/False_color#Pseudocolor. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import cartopy.crs as ccrs import matplotlib.colors as mcols diff --git a/docs/gallery_code/general/plot_coriolis.py b/docs/gallery_code/general/plot_coriolis.py index 3d5aa853e3..905108abfd 100644 --- a/docs/gallery_code/general/plot_coriolis.py +++ b/docs/gallery_code/general/plot_coriolis.py @@ -1,11 +1,12 @@ -"""Deriving the Coriolis Frequency Over the Globe +""" +Deriving the Coriolis Frequency Over the Globe ============================================== This code computes the Coriolis frequency and stores it in a cube with associated metadata. It then plots the Coriolis frequency on an orthographic projection. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import cartopy.crs as ccrs import matplotlib.pyplot as plt diff --git a/docs/gallery_code/general/plot_cross_section.py b/docs/gallery_code/general/plot_cross_section.py index 8eac3955b1..8e5bee85ed 100644 --- a/docs/gallery_code/general/plot_cross_section.py +++ b/docs/gallery_code/general/plot_cross_section.py @@ -1,10 +1,11 @@ -"""Cross Section Plots +""" +Cross Section Plots =================== This example demonstrates contour plots of a cross-sectioned multi-dimensional cube which features a hybrid height vertical coordinate system. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt diff --git a/docs/gallery_code/general/plot_custom_aggregation.py b/docs/gallery_code/general/plot_custom_aggregation.py index 521d0069b9..540f785ed6 100644 --- a/docs/gallery_code/general/plot_custom_aggregation.py +++ b/docs/gallery_code/general/plot_custom_aggregation.py @@ -1,4 +1,5 @@ -"""Calculating a Custom Statistic +""" +Calculating a Custom Statistic ============================== This example shows how to define and use a custom @@ -11,7 +12,7 @@ over North America, and we want to calculate in how many years these exceed a certain temperature over a spell of 5 years or more. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt import numpy as np @@ -27,25 +28,24 @@ # Note: in order to meet the requirements of iris.analysis.Aggregator, it must # do the calculation over an arbitrary (given) data axis. def count_spells(data, threshold, axis, spell_length): - """Function to calculate the number of points in a sequence where the value + """Calculate the number of points in a sequence. + + Function to calculate the number of points in a sequence where the value has exceeded a threshold value for at least a certain number of timepoints. Generalised to operate on multiple time sequences arranged on a specific axis of a multidimensional array. - Args: - - * data (array): + Parameters + ---------- + data : array raw data to be compared with value threshold. - - * threshold (float): + threshold : float threshold point for 'significant' datapoints. - - * axis (int): + axis : int number of the array dimension mapping the time sequences. (Can also be negative, e.g. '-1' means last dimension) - - * spell_length (int): + spell_length : int number of consecutive times at which value > threshold to "count". """ diff --git a/docs/gallery_code/general/plot_custom_file_loading.py b/docs/gallery_code/general/plot_custom_file_loading.py index 81aad4a15a..c7a560ff0f 100644 --- a/docs/gallery_code/general/plot_custom_file_loading.py +++ b/docs/gallery_code/general/plot_custom_file_loading.py @@ -1,5 +1,6 @@ -"""Loading a Cube From a Custom File Format -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +""" +Loading a Cube From a Custom File Format +======================================== This example shows how a custom text file can be loaded using the standard Iris load mechanism. @@ -8,25 +9,25 @@ ` for the file format. To create a format specification we need to define the following: -* format_name - Some text that describes the format specification we are +* **format_name** - Some text that describes the format specification we are creating -* file_element - FileElement object describing the element which identifies +* **file_element** - FileElement object describing the element which identifies this FormatSpecification. Possible values are: - ``iris.io.format_picker.MagicNumber(n, o)`` - The n bytes from the file at offset o. + * ``iris.io.format_picker.MagicNumber(n, o)`` + The n bytes from the file at offset o. - ``iris.io.format_picker.FileExtension()`` - The file's extension. + * ``iris.io.format_picker.FileExtension()`` + The file extension. - ``iris.io.format_picker.LeadingLine()`` - The first line of the file. + * ``iris.io.format_picker.LeadingLine()`` + The first line of the file. -* file_element_value - The value that the file_element should take if a file +* **file_element_value** - The value that the file_element should take if a file matches this FormatSpecification -* handler (optional) - A generator function that will be called when the file +* **handler** (optional) - A generator function that will be called when the file specification has been identified. This function is provided by the user and provides the means to parse the whole file. If no handler function is provided, then identification is still possible without any handling. @@ -40,7 +41,7 @@ The handler function must be defined as generator which yields each cube as they are produced. -* priority (optional) - Integer giving a priority for considering this +* **priority** (optional) - Integer giving a priority for considering this specification where higher priority means sooner consideration In the following example, the function :func:`load_NAME_III` has been defined @@ -52,7 +53,7 @@ function which automatically invokes the ``FormatSpecification`` we defined. The cube returned from the load function is then used to produce a plot. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import datetime diff --git a/docs/gallery_code/general/plot_global_map.py b/docs/gallery_code/general/plot_global_map.py index 9634fc1458..60ac200a43 100644 --- a/docs/gallery_code/general/plot_global_map.py +++ b/docs/gallery_code/general/plot_global_map.py @@ -1,10 +1,11 @@ -"""Quickplot of a 2D Cube on a Map +""" +Quickplot of a 2D Cube on a Map =============================== This example demonstrates a contour plot of global air temperature. The plot title and the labels for the axes are automatically derived from the metadata. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import cartopy.crs as ccrs import matplotlib.pyplot as plt diff --git a/docs/gallery_code/general/plot_inset.py b/docs/gallery_code/general/plot_inset.py index 7b7e04c7d3..5edd375743 100644 --- a/docs/gallery_code/general/plot_inset.py +++ b/docs/gallery_code/general/plot_inset.py @@ -1,11 +1,12 @@ -"""Test Data Showing Inset Plots +""" +Test Data Showing Inset Plots ============================= This example demonstrates the use of a single 3D data cube with time, latitude and longitude dimensions to plot a temperature series for a single latitude coordinate, with an inset plot of the data region. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import cartopy.crs as ccrs import matplotlib.pyplot as plt diff --git a/docs/gallery_code/general/plot_lineplot_with_legend.py b/docs/gallery_code/general/plot_lineplot_with_legend.py index 981e9694ec..d1b3acd912 100644 --- a/docs/gallery_code/general/plot_lineplot_with_legend.py +++ b/docs/gallery_code/general/plot_lineplot_with_legend.py @@ -1,7 +1,8 @@ -"""Multi-Line Temperature Profile Plot -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +""" +Multi-Line Temperature Profile Plot +=================================== -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt diff --git a/docs/gallery_code/general/plot_polar_stereo.py b/docs/gallery_code/general/plot_polar_stereo.py index 0cb4e533fa..99abbd0ae0 100644 --- a/docs/gallery_code/general/plot_polar_stereo.py +++ b/docs/gallery_code/general/plot_polar_stereo.py @@ -1,10 +1,11 @@ -"""Example of a Polar Stereographic Plot +""" +Example of a Polar Stereographic Plot ===================================== Demonstrates plotting data that are defined on a polar stereographic projection. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt diff --git a/docs/gallery_code/general/plot_polynomial_fit.py b/docs/gallery_code/general/plot_polynomial_fit.py index 951f17209e..37cc4e283b 100644 --- a/docs/gallery_code/general/plot_polynomial_fit.py +++ b/docs/gallery_code/general/plot_polynomial_fit.py @@ -1,11 +1,12 @@ -"""Fitting a Polynomial +""" +Fitting a Polynomial ==================== This example demonstrates computing a polynomial fit to 1D data from an Iris cube, adding the fit to the cube's metadata, and plotting both the 1D data and the fit. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt import numpy as np diff --git a/docs/gallery_code/general/plot_projections_and_annotations.py b/docs/gallery_code/general/plot_projections_and_annotations.py index 1a4701837a..6e8ba5a5af 100644 --- a/docs/gallery_code/general/plot_projections_and_annotations.py +++ b/docs/gallery_code/general/plot_projections_and_annotations.py @@ -1,4 +1,5 @@ -"""Plotting in Different Projections +""" +Plotting in Different Projections ================================= This example shows how to overlay data and graphics in different projections, @@ -11,7 +12,7 @@ We plot these over a specified region, in two different map projections. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import cartopy.crs as ccrs import matplotlib.pyplot as plt diff --git a/docs/gallery_code/general/plot_rotated_pole_mapping.py b/docs/gallery_code/general/plot_rotated_pole_mapping.py index 3674e89e28..60b187ee56 100644 --- a/docs/gallery_code/general/plot_rotated_pole_mapping.py +++ b/docs/gallery_code/general/plot_rotated_pole_mapping.py @@ -1,15 +1,16 @@ -"""Rotated Pole Mapping +""" +Rotated Pole Mapping ===================== This example uses several visualisation methods to achieve an array of differing images, including: - * Visualisation of point based data - * Contouring of point based data - * Block plot of contiguous bounded data - * Non native projection and a Natural Earth shaded relief image underlay +* Visualisation of point based data +* Contouring of point based data +* Block plot of contiguous bounded data +* Non native projection and a Natural Earth shaded relief image underlay -""" # noqa: D400 +""" # noqa: D205, D212, D400 import cartopy.crs as ccrs import matplotlib.pyplot as plt diff --git a/docs/gallery_code/general/plot_zonal_means.py b/docs/gallery_code/general/plot_zonal_means.py index 47a7127d06..d4ec1eb1fc 100644 --- a/docs/gallery_code/general/plot_zonal_means.py +++ b/docs/gallery_code/general/plot_zonal_means.py @@ -1,7 +1,11 @@ -"""Zonal Mean Diagram of Air Temperature +""" +Zonal Mean Diagram of Air Temperature ===================================== -This example demonstrates aligning a linear plot and a cartographic plot using Matplotlib. -""" # noqa: D400 + +This example demonstrates aligning a linear plot and a cartographic plot +using Matplotlib. + +""" # noqa: D205, D212, D400 import cartopy.crs as ccrs import matplotlib.pyplot as plt diff --git a/docs/gallery_code/meteorology/plot_COP_1d.py b/docs/gallery_code/meteorology/plot_COP_1d.py index d5ef2a9990..84addd140a 100644 --- a/docs/gallery_code/meteorology/plot_COP_1d.py +++ b/docs/gallery_code/meteorology/plot_COP_1d.py @@ -1,4 +1,5 @@ -"""Global Average Annual Temperature Plot +""" +Global Average Annual Temperature Plot ====================================== Produces a time-series plot of North American temperature forecasts for 2 @@ -25,7 +26,7 @@ Further details on the aggregation functionality being used in this example can be found in :ref:`cube-statistics`. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt import numpy as np diff --git a/docs/gallery_code/meteorology/plot_COP_maps.py b/docs/gallery_code/meteorology/plot_COP_maps.py index 5536823fb4..43f25425e5 100644 --- a/docs/gallery_code/meteorology/plot_COP_maps.py +++ b/docs/gallery_code/meteorology/plot_COP_maps.py @@ -1,4 +1,5 @@ -"""Global Average Annual Temperature Maps +""" +Global Average Annual Temperature Maps ====================================== Produces maps of global temperature forecasts from the A1B and E1 scenarios. @@ -18,7 +19,7 @@ Analyses, and Scenarios. Eos Trans. AGU, Vol 90, No. 21, doi:10.1029/2009EO210001. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import os.path diff --git a/docs/gallery_code/meteorology/plot_TEC.py b/docs/gallery_code/meteorology/plot_TEC.py index cb642af588..e6269eaf9b 100644 --- a/docs/gallery_code/meteorology/plot_TEC.py +++ b/docs/gallery_code/meteorology/plot_TEC.py @@ -1,4 +1,5 @@ -"""Ionosphere Space Weather +""" +Ionosphere Space Weather ======================== This space weather example plots a filled contour of rotated pole point @@ -8,7 +9,7 @@ The plot exhibits an interesting outline effect due to excluding data values below a certain threshold. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt import numpy.ma as ma diff --git a/docs/gallery_code/meteorology/plot_deriving_phenomena.py b/docs/gallery_code/meteorology/plot_deriving_phenomena.py index ef78d2f1c9..81a05be9b9 100644 --- a/docs/gallery_code/meteorology/plot_deriving_phenomena.py +++ b/docs/gallery_code/meteorology/plot_deriving_phenomena.py @@ -1,4 +1,5 @@ -"""Deriving Exner Pressure and Air Temperature +""" +Deriving Exner Pressure and Air Temperature =========================================== This example shows some processing of cubes in order to derive further related @@ -7,7 +8,7 @@ specific humidity. Finally, the two new cubes are presented side-by-side in a plot. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt import matplotlib.ticker @@ -20,7 +21,9 @@ def limit_colorbar_ticks(contour_object): - """Takes a contour object which has an associated colorbar and limits the + """Limit colobar number of ticks. + + Take a contour object which has an associated colorbar and limits the number of ticks on the colorbar to 4. """ diff --git a/docs/gallery_code/meteorology/plot_hovmoller.py b/docs/gallery_code/meteorology/plot_hovmoller.py index 6c1f1a800a..829b370d78 100644 --- a/docs/gallery_code/meteorology/plot_hovmoller.py +++ b/docs/gallery_code/meteorology/plot_hovmoller.py @@ -1,4 +1,5 @@ -"""Hovmoller Diagram of Monthly Surface Temperature +""" +Hovmoller Diagram of Monthly Surface Temperature ================================================ This example demonstrates the creation of a Hovmoller diagram with fine control @@ -6,7 +7,7 @@ and has been pre-processed to calculate the monthly mean sea surface temperature. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.dates as mdates import matplotlib.pyplot as plt diff --git a/docs/gallery_code/meteorology/plot_lagged_ensemble.py b/docs/gallery_code/meteorology/plot_lagged_ensemble.py index a8887238d4..7c34572136 100644 --- a/docs/gallery_code/meteorology/plot_lagged_ensemble.py +++ b/docs/gallery_code/meteorology/plot_lagged_ensemble.py @@ -1,4 +1,5 @@ -"""Seasonal Ensemble Model Plots +""" +Seasonal Ensemble Model Plots ============================= This example demonstrates the loading of a lagged ensemble dataset from the @@ -15,7 +16,7 @@ better approach would be to take the climatological mean, calibrated to the model, from each ensemble member. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt import matplotlib.ticker @@ -26,7 +27,9 @@ def realization_metadata(cube, field, fname): - """A function which modifies the cube's metadata to add a "realization" + """Modify the cube's metadata to add a "realization" coordinate. + + A function which modifies the cube's metadata to add a "realization" (ensemble member) coordinate from the filename if one doesn't already exist in the cube. diff --git a/docs/gallery_code/meteorology/plot_wind_barbs.py b/docs/gallery_code/meteorology/plot_wind_barbs.py index 9745a40db2..4126d1f995 100644 --- a/docs/gallery_code/meteorology/plot_wind_barbs.py +++ b/docs/gallery_code/meteorology/plot_wind_barbs.py @@ -1,4 +1,5 @@ -"""Plotting Wind Direction Using Barbs +""" +Plotting Wind Direction Using Barbs =================================== This example demonstrates using barbs to plot wind speed contours and wind @@ -8,7 +9,7 @@ The magnitude of the wind in the original data is low and so doesn't illustrate the full range of barbs. The wind is scaled to simulate a storm that better illustrates the range of barbs that are available. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt diff --git a/docs/gallery_code/meteorology/plot_wind_speed.py b/docs/gallery_code/meteorology/plot_wind_speed.py index dde87824fd..5310ad937d 100644 --- a/docs/gallery_code/meteorology/plot_wind_speed.py +++ b/docs/gallery_code/meteorology/plot_wind_speed.py @@ -1,4 +1,5 @@ -"""Plotting Wind Direction Using Quiver +""" +Plotting Wind Direction Using Quiver ==================================== This example demonstrates using quiver to plot wind speed contours and wind @@ -8,7 +9,7 @@ For the second plot, the data used for the arrows is normalised to produce arrows with a uniform size on the plot. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import cartopy.feature as cfeat import matplotlib.pyplot as plt diff --git a/docs/gallery_code/oceanography/plot_atlantic_profiles.py b/docs/gallery_code/oceanography/plot_atlantic_profiles.py index 736ddbe7fb..a43fb7f8cb 100644 --- a/docs/gallery_code/oceanography/plot_atlantic_profiles.py +++ b/docs/gallery_code/oceanography/plot_atlantic_profiles.py @@ -1,4 +1,5 @@ -"""Oceanographic Profiles and T-S Diagrams +""" +Oceanographic Profiles and T-S Diagrams ======================================= This example demonstrates how to plot vertical profiles of different @@ -13,7 +14,7 @@ presence of the attribute positive=down on the depth coordinate. This means depth values intuitively increase downward on the y-axis. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt diff --git a/docs/gallery_code/oceanography/plot_load_nemo.py b/docs/gallery_code/oceanography/plot_load_nemo.py index 77c95e2353..36ff363a15 100644 --- a/docs/gallery_code/oceanography/plot_load_nemo.py +++ b/docs/gallery_code/oceanography/plot_load_nemo.py @@ -1,11 +1,13 @@ -"""Load a Time Series of Data From the NEMO Model +""" +Load a Time Series of Data From the NEMO Model ============================================== This example demonstrates how to load multiple files containing data output by the NEMO model and combine them into a time series in a single cube. The different time dimensions in these files can prevent Iris from concatenating them without the intervention shown here. -""" # noqa: D400 + +""" # noqa: D205, D212, D400 import matplotlib.pyplot as plt diff --git a/docs/gallery_code/oceanography/plot_orca_projection.py b/docs/gallery_code/oceanography/plot_orca_projection.py index 33e3ecac46..bb68056cb3 100644 --- a/docs/gallery_code/oceanography/plot_orca_projection.py +++ b/docs/gallery_code/oceanography/plot_orca_projection.py @@ -1,4 +1,5 @@ -"""Tri-Polar Grid Projected Plotting +""" +Tri-Polar Grid Projected Plotting ================================= This example demonstrates cell plots of data on the semi-structured ORCA2 model @@ -9,7 +10,7 @@ Second four pcolormesh plots are created from this projected dataset, using different projections for the output image. -""" # noqa: D400 +""" # noqa: D205, D212, D400 import cartopy.crs as ccrs import matplotlib.pyplot as plt diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index b1b83b7f42..ff352f5d01 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -31,7 +31,9 @@ def image_setup_teardown(): @pytest.fixture def import_patches(monkeypatch): - """Replace plt.show() with a function that does nothing, also add all the + """Replace plt.show() with a function that does nothing, also add to sys.path. + + Replace plt.show() with a function that does nothing, also add all the gallery examples to sys.path. """ @@ -50,7 +52,9 @@ def no_show(): @pytest.fixture def iris_future_defaults(): - """Create a fixture which resets all the iris.FUTURE settings to the defaults, + """Create a fixture which resets all the iris.FUTURE settings to the defaults. + + Create a fixture which resets all the iris.FUTURE settings to the defaults, as otherwise changes made in one test can affect subsequent ones. """ diff --git a/docs/src/further_topics/filtering_warnings.rst b/docs/src/further_topics/filtering_warnings.rst index ef743fa9f1..fb1e09e98e 100644 --- a/docs/src/further_topics/filtering_warnings.rst +++ b/docs/src/further_topics/filtering_warnings.rst @@ -47,9 +47,9 @@ Warnings: >>> my_operation() ... - iris/coord_systems.py:432: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + iris/coord_systems.py:442: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) - iris/coord_systems.py:770: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. + iris/coord_systems.py:782: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. warnings.warn( Warnings can be suppressed using the Python warnings filter with the ``ignore`` @@ -110,7 +110,7 @@ You can target specific Warning messages, e.g. ... warnings.filterwarnings("ignore", message="Discarding false_easting") ... my_operation() ... - iris/coord_systems.py:432: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + iris/coord_systems.py:442: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) :: @@ -128,9 +128,9 @@ Or you can target Warnings raised by specific lines of specific modules, e.g. ... warnings.filterwarnings("ignore", module="iris.coord_systems", lineno=449) ... my_operation() ... - iris/coord_systems.py:432: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + iris/coord_systems.py:442: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) - iris/coord_systems.py:770: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. + iris/coord_systems.py:782: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. warnings.warn( :: @@ -190,7 +190,7 @@ module during execution: ... ) ... my_operation() ... - iris/coord_systems.py:432: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + iris/coord_systems.py:442: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) ---- diff --git a/lib/iris/_concatenate.py b/lib/iris/_concatenate.py index b5c92fd6f9..8be766ea85 100644 --- a/lib/iris/_concatenate.py +++ b/lib/iris/_concatenate.py @@ -34,7 +34,9 @@ class _CoordAndDims(namedtuple("CoordAndDims", ["coord", "dims"])): - """Container for a coordinate and the associated data dimension(s) + """Container for a coordinate and the associated data dimension(s). + + Container for a coordinate and the associated data dimension(s) spanned over a :class:`iris.cube.Cube`. Parameters @@ -54,8 +56,7 @@ class _CoordMetaData( ["defn", "dims", "points_dtype", "bounds_dtype", "kwargs"], ) ): - """Container for the metadata that defines a dimension or auxiliary - coordinate. + """Container for the metadata that defines a dimension or auxiliary coordinate. Parameters ---------- @@ -150,7 +151,9 @@ def name(self): class _DerivedCoordAndDims( namedtuple("DerivedCoordAndDims", ["coord", "dims", "aux_factory"]) ): - """Container for a derived coordinate, the associated AuxCoordFactory, and the + """Container for a derived coordinate and dimnesions(s). + + Container for a derived coordinate, the associated AuxCoordFactory, and the associated data dimension(s) spanned over a :class:`iris.cube.Cube`. Parameters @@ -175,8 +178,7 @@ def __eq__(self, other): class _OtherMetaData(namedtuple("OtherMetaData", ["defn", "dims"])): - """Container for the metadata that defines a cell measure or ancillary - variable. + """Container for the metadata that defines a cell measure or ancillary variable. Parameters ---------- @@ -229,7 +231,9 @@ def name(self): class _SkeletonCube(namedtuple("SkeletonCube", ["signature", "data"])): - """Basis of a source-cube, containing the associated coordinate metadata, + """Basis of a source-cube. + + Basis of a source-cube, containing the associated coordinate metadata, coordinates and cube data payload. Parameters @@ -260,8 +264,7 @@ class _Extent(namedtuple("Extent", ["min", "max"])): class _CoordExtent(namedtuple("CoordExtent", ["points", "bounds"])): - """Container representing the points and bounds extent of a one dimensional - coordinate. + """Container representing the points and bounds extent of a one dimensional coordinate. Parameters ---------- @@ -374,13 +377,17 @@ def _none_sort(item): class _CubeSignature: - """Template for identifying a specific type of :class:`iris.cube.Cube` based + """Template for identifying a specific type of :class:`iris.cube.Cube`. + + Template for identifying a specific type of :class:`iris.cube.Cube` based on its metadata, coordinates and cell_measures. """ def __init__(self, cube): - """Represents the cube metadata and associated coordinate metadata that + """Represents the cube metadata and associated coordinate metadata. + + Represents the cube metadata and associated coordinate metadata that allows suitable cubes for concatenation to be identified. Parameters @@ -472,7 +479,9 @@ def name_key_func(factory): self.derived_coords_and_dims.append(coord_and_dims) def _coordinate_differences(self, other, attr, reason="metadata"): - """Determine the names of the coordinates that differ between `self` and + """Determine the names of the coordinates that differ. + + Determine the names of the coordinates that differ between `self` and `other` for a coordinate attribute on a _CubeSignature. Parameters @@ -599,13 +608,12 @@ def match(self, other, error_on_mismatch): class _CoordSignature: - """Template for identifying a specific type of :class:`iris.cube.Cube` based - on its coordinates. - - """ + """Template for identifying a specific type of :class:`iris.cube.Cube` based on its coordinates.""" def __init__(self, cube_signature): - """Represents the coordinate metadata required to identify suitable + """Represent the coordinate metadata. + + Represent the coordinate metadata required to identify suitable non-overlapping :class:`iris.cube.Cube` source-cubes for concatenation over a common single dimension. @@ -657,8 +665,7 @@ def _cmp(coord, other): return result, candidate_axis def candidate_axis(self, other): - """Determine the candidate axis of concatenation with the - given coordinate signature. + """Determine the candidate axis of concatenation with the given coordinate signature. If a candidate axis is found, then the coordinate signatures are compatible. @@ -723,13 +730,12 @@ def _calculate_extents(self): class _ProtoCube: - """Framework for concatenating multiple source-cubes over one - common dimension. - - """ + """Framework for concatenating multiple source-cubes over one common dimension.""" def __init__(self, cube): - """Create a new _ProtoCube from the given cube and record the cube + """Create a new _ProtoCube and record the cube as a source-cube. + + Create a new _ProtoCube from the given cube and record the cube as a source-cube. Parameters @@ -762,7 +768,9 @@ def axis(self): return self._axis def concatenate(self): - """Concatenates all the source-cubes registered with the + """Concatenates all the source-cubes registered with the :class:`_ProtoCube`. + + Concatenates all the source-cubes registered with the :class:`_ProtoCube` over the nominated common dimension. Returns @@ -992,8 +1000,7 @@ def register( return match def _add_skeleton(self, coord_signature, data): - """Create and add the source-cube skeleton to the - :class:`_ProtoCube`. + """Create and add the source-cube skeleton to the :class:`_ProtoCube`. Parameters ---------- @@ -1010,7 +1017,9 @@ def _add_skeleton(self, coord_signature, data): self._skeletons.append(skeleton) def _build_aux_coordinates(self): - """Generate the auxiliary coordinates with associated dimension(s) + """Generate the auxiliary coordinates with associated dimension(s) mapping. + + Generate the auxiliary coordinates with associated dimension(s) mapping for the new concatenated cube. Returns @@ -1082,7 +1091,9 @@ def _build_scalar_coordinates(self): return scalar_coords def _build_cell_measures(self): - """Generate the cell measures with associated dimension(s) + """Generate the cell measures with associated dimension(s) mapping. + + Generate the cell measures with associated dimension(s) mapping for the new concatenated cube. Returns @@ -1120,7 +1131,9 @@ def _build_cell_measures(self): return cell_measures_and_dims def _build_ancillary_variables(self): - """Generate the ancillary variables with associated dimension(s) + """Generate the ancillary variables with associated dimension(s) mapping. + + Generate the ancillary variables with associated dimension(s) mapping for the new concatenated cube. Returns @@ -1243,11 +1256,14 @@ def _build_data(self): return data def _build_dim_coordinates(self): - """Generate the dimension coordinates with associated dimension + """Generate the dimension coordinates. + + Generate the dimension coordinates with associated dimension mapping for the new concatenated cube. - Return: - A list of dimension coordinate and dimension tuple pairs. + Returns + ------- + A list of dimension coordinate and dimension tuple pairs. """ # Setup convenience hooks. @@ -1291,7 +1307,9 @@ def _build_dim_coordinates(self): return dim_coords_and_dims def _sequence(self, extent, axis): - """Determine whether the given extent can be sequenced along with + """Determine whether the extent can be sequenced. + + Determine whether the given extent can be sequenced along with all the extents of the source-cubes already registered with this :class:`_ProtoCube` into non-overlapping segments for the given axis. diff --git a/lib/iris/_data_manager.py b/lib/iris/_data_manager.py index 45f1a6b3e2..da7a19c95b 100644 --- a/lib/iris/_data_manager.py +++ b/lib/iris/_data_manager.py @@ -37,10 +37,7 @@ def __init__(self, data): self._assert_axioms() def __copy__(self): - """Forbid :class:`~iris._data_manager.DataManager` instance - shallow-copy support. - - """ + """Forbid :class:`~iris._data_manager.DataManager` instance shallow-copy support.""" name = type(self).__name__ emsg = ( "Shallow-copy of {!r} is not permitted. Use " @@ -49,8 +46,7 @@ def __copy__(self): raise copy.Error(emsg.format(name, name)) def __deepcopy__(self, memo): - """Allow :class:`~iris._data_manager.DataManager` instance - deepcopy support. + """Allow :class:`~iris._data_manager.DataManager` instance deepcopy support. Parameters ---------- @@ -62,6 +58,8 @@ def __deepcopy__(self, memo): def __eq__(self, other): """Perform :class:`~iris._data_manager.DataManager` instance equality. + + Perform :class:`~iris._data_manager.DataManager` instance equality. Note that, this is explicitly not a lazy operation and will load any lazy payload to determine the equality result. @@ -95,6 +93,8 @@ def __eq__(self, other): def __ne__(self, other): """Perform :class:`~iris._data_manager.DataManager` instance inequality. + + Perform :class:`~iris._data_manager.DataManager` instance inequality. Note that, this is explicitly not a lazy operation and will load any lazy payload to determine the inequality result. @@ -133,8 +133,7 @@ def _assert_axioms(self): assert state, emsg.format("" if is_lazy else "no ", "" if is_real else "no ") def _deepcopy(self, memo, data=None): - """Perform a deepcopy of the :class:`~iris._data_manager.DataManager` - instance. + """Perform a deepcopy of the :class:`~iris._data_manager.DataManager` instance. Parameters ---------- @@ -204,7 +203,9 @@ def data(self): @data.setter def data(self, data): - """Replaces the currently managed data with the specified data, which must + """Replace the currently managed data with the specified data. + + Replace the currently managed data with the specified data, which must be of an equivalent shape. Note that, the only shape promotion permitted is for 0-dimensional @@ -268,8 +269,7 @@ def shape(self): return self.core_data().shape def copy(self, data=None): - """Returns a deep copy of this :class:`~iris._data_manager.DataManager` - instance. + """Returns a deep copy of this :class:`~iris._data_manager.DataManager` instance. Parameters ---------- @@ -285,7 +285,9 @@ def copy(self, data=None): return self._deepcopy(memo, data=data) def core_data(self): - """If real data is being managed, then return the :class:`~numpy.ndarray` + """Provide real data or lazy data. + + If real data is being managed, then return the :class:`~numpy.ndarray` or :class:`numpy.ma.core.MaskedArray`. Otherwise, return the lazy :class:`~dask.array.core.Array`. diff --git a/lib/iris/_lazy_data.py b/lib/iris/_lazy_data.py index 55a4222675..b430a4d682 100644 --- a/lib/iris/_lazy_data.py +++ b/lib/iris/_lazy_data.py @@ -42,7 +42,9 @@ def is_lazy_data(data): def is_lazy_masked_data(data): - """Return True if the argument is both an Iris 'lazy' data array and the + """Determine whether managed data is lazy and masked. + + Return True if the argument is both an Iris 'lazy' data array and the underlying array is of masked type. Otherwise return False. """ @@ -326,6 +328,8 @@ def _co_realise_lazy_arrays(arrays): def as_concrete_data(data): """Return the actual content of a lazy array, as a numpy array. + + Return the actual content of a lazy array, as a numpy array. If the input data is a NumPy `ndarray` or masked array, return it unchanged. diff --git a/lib/iris/_merge.py b/lib/iris/_merge.py index 79427d401a..e31a4cabc7 100644 --- a/lib/iris/_merge.py +++ b/lib/iris/_merge.py @@ -77,7 +77,9 @@ class _CoordMetaData( class _CoordAndDims(namedtuple("CoordAndDims", ["coord", "dims"])): - """Container for a coordinate and the associated data dimension/s + """Container for a coordinate and the associated data dimension/s. + + Container for a coordinate and the associated data dimension/s spanned over a :class:`iris.cube.Cube`. Parameters @@ -96,7 +98,9 @@ class _CoordAndDims(namedtuple("CoordAndDims", ["coord", "dims"])): class _ScalarCoordPayload( namedtuple("ScalarCoordPayload", ["defns", "values", "metadata"]) ): - """Container for all scalar coordinate data and metadata represented + """Container for the payload. + + Container for all scalar coordinate data and metadata represented within a :class:`iris.cube.Cube`. All scalar coordinate related data is sorted into ascending order @@ -123,7 +127,9 @@ class _ScalarCoordPayload( class _VectorCoordPayload( namedtuple("VectorCoordPayload", ["dim_coords_and_dims", "aux_coords_and_dims"]) ): - """Container for all vector coordinate data and metadata represented + """Container for the payload. + + Container for all vector coordinate data and metadata represented within a :class:`iris.cube.Cube`. Parameters @@ -145,7 +151,9 @@ class _VectorCoordPayload( class _CoordPayload(namedtuple("CoordPayload", ["scalar", "vector", "factory_defns"])): - """Container for all the scalar and vector coordinate data and + """Container for the payload. + + Container for all the scalar and vector coordinate data and metadata, and auxiliary coordinate factories represented within a :class:`iris.cube.Cube`. @@ -200,7 +208,9 @@ def _coords_msgs(msgs, coord_group, defns_a, defns_b): ) def match_signature(self, signature, error_on_mismatch): - """Return whether this _CoordPayload matches the corresponding + """Check if _CoordPayload matches the corresponding aspects of a _CoordSignature. + + Return whether this _CoordPayload matches the corresponding aspects of a _CoordSignature. Parameters @@ -273,7 +283,9 @@ class _CoordSignature( ], ) ): - """Criterion for identifying a specific type of :class:`iris.cube.Cube` + """Criterion for identifying a specific type of :class:`iris.cube.Cube`. + + Criterion for identifying a specific type of :class:`iris.cube.Cube` based on its scalar and vector coordinate data and metadata, and auxiliary coordinate factories. @@ -311,8 +323,7 @@ class _CubeSignature( ], ) ): - """Criterion for identifying a specific type of :class:`iris.cube.Cube` - based on its metadata. + """Criterion for identifying specific type of :class:`iris.cube.Cube` based on its metadata. Parameters ---------- @@ -435,7 +446,9 @@ def match(self, other, error_on_mismatch): class _Skeleton(namedtuple("Skeleton", ["scalar_values", "data"])): - """Basis of a source-cube, containing the associated scalar coordinate values + """Basis of a source-cube. + + Basis of a source-cube, containing the associated scalar coordinate values and data payload of a :class:`iris.cube.Cube`. Parameters @@ -470,7 +483,9 @@ class _FactoryDefn(namedtuple("_FactoryDefn", ["class_", "dependency_defns"])): class _Relation(namedtuple("Relation", ["separable", "inseparable"])): - """Categorisation of the candidate dimensions belonging to a + """Categorisation of the candidate dimensions. + + Categorisation of the candidate dimensions belonging to a :class:`ProtoCube` into separable 'independent' dimensions, and inseparable dependent dimensions. @@ -490,7 +505,9 @@ class _Relation(namedtuple("Relation", ["separable", "inseparable"])): def _is_combination(name): - """Determine whether the candidate dimension is an 'invented' combination + """Determine whether the candidate dimension is an 'invented' combination. + + Determine whether the candidate dimension is an 'invented' combination of candidate dimensions. Parameters @@ -507,7 +524,9 @@ def _is_combination(name): def build_indexes(positions): - r"""Construct a mapping for each candidate dimension that maps for each + r"""Construct a mapping for each candidate dimension. + + Construct a mapping for each candidate dimension that maps for each of its scalar values the set of values for each of the other candidate dimensions. @@ -600,7 +619,9 @@ def _separable_pair(name, index): def _separable(name, indexes): - """Determine the candidate dimensions that are separable and + """Determine the candidate dimensions that are separable and inseparable. + + Determine the candidate dimensions that are separable and inseparable relative to the provided candidate dimension. A candidate dimension X and Y are separable if each scalar @@ -635,7 +656,9 @@ def _separable(name, indexes): def derive_relation_matrix(indexes): - """Construct a mapping for each candidate dimension that specifies + """Construct a mapping for each candidate dimension. + + Construct a mapping for each candidate dimension that specifies which of the other candidate dimensions are separable or inseparable. A candidate dimension X and Y are separable if each scalar value of @@ -737,7 +760,9 @@ def _derive_separable_group(relation_matrix, group): def _is_dependent(dependent, independent, positions, function_mapping=None): - """Determine whether there exists a one-to-one functional relationship + """Determine whether there exists a one-to-one functional relationship. + + Determine whether there exists a one-to-one functional relationship between the independent candidate dimension/s and the dependent candidate dimension. @@ -782,7 +807,9 @@ def _is_dependent(dependent, independent, positions, function_mapping=None): def _derive_consistent_groups(relation_matrix, separable_group): - """Determine the largest combinations of candidate dimensions within the + """Determine the largest combinations of candidate dimensions. + + Determine the largest combinations of candidate dimensions within the separable group that are self consistently separable from one another. If the candidate dimension A is separable from the candidate dimensions @@ -830,7 +857,9 @@ def _derive_consistent_groups(relation_matrix, separable_group): def _build_separable_group( space, group, separable_consistent_groups, positions, function_matrix ): - """Update the space with the first separable consistent group that + """Update the space with the first separable consistent group. + + Update the space with the first separable consistent group that satisfies a valid functional relationship with all other candidate dimensions in the group. @@ -891,7 +920,9 @@ def _build_separable_group( def _build_inseparable_group(space, group, positions, function_matrix): - """Update the space with the first valid scalar functional relationship + """Update the space with the first valid scalar functional relationship. + + Update the space with the first valid scalar functional relationship between a candidate dimension within the group and all other candidate dimensions. @@ -956,7 +987,9 @@ def _build_inseparable_group(space, group, positions, function_matrix): def _build_combination_group(space, group, positions, function_matrix): - """Update the space with the new combined or invented dimension + """Update the space with the new combined or invented dimension. + + Update the space with the new combined or invented dimension that each member of this inseparable group depends on. As no functional relationship between members of the group can be @@ -1065,10 +1098,7 @@ def derive_space(groups, relation_matrix, positions, function_matrix=None): class ProtoCube: - """Framework for merging source-cubes into one or more higher - dimensional cubes. - - """ + """Framework for merging source-cubes into one or more higher dimensional cubes.""" def __init__(self, cube): """Create a new ProtoCube from the given cube. @@ -1152,8 +1182,7 @@ def _report_duplicate(self, nd_indexes, group_by_nd_index): raise iris.exceptions.DuplicateDataError(msg) def merge(self, unique=True): - """Returns the list of cubes resulting from merging the registered - source-cubes. + """Returns the list of cubes resulting from merging the registered source-cubes. Parameters ---------- @@ -1251,7 +1280,9 @@ def merge(self, unique=True): return merged_cubes def register(self, cube, error_on_mismatch=False): - """Add a compatible :class:`iris.cube.Cube` as a source-cube for + """Add a compatible :class:`iris.cube.Cube` as a source for merging. + + Add a compatible :class:`iris.cube.Cube` as a source-cube for merging under this :class:`ProtoCube`. A cube will be deemed compatible based on the signature of the @@ -1316,7 +1347,9 @@ def _guess_axis(self, name): return axis def _define_space(self, space, positions, indexes, function_matrix): - """Given the derived :class:`ProtoCube` space, define this space in + """Define space. + + Given the derived :class:`ProtoCube` space, define this space in terms of its dimensionality, shape, coordinates and associated coordinate to space dimension mappings. @@ -1489,7 +1522,9 @@ def name_in_independents(): self._shape.extend(signature.data_shape) def _get_cube(self, data): - """Return a fully constructed cube for the given data, containing + """Generate fully constructed cube. + + Return a fully constructed cube for the given data, containing all its coordinates and metadata. """ @@ -1529,10 +1564,7 @@ def _get_cube(self, data): return cube def _nd_index(self, position): - """Returns the n-dimensional index of this source-cube (position), - within the merged cube. - - """ + """Returns the n-dimensional index of thr source-cube, within the merged cube.""" index = [] # Determine the index of the source-cube cell for each dimension. @@ -1550,7 +1582,9 @@ def _nd_index(self, position): return tuple(index) def _build_coordinates(self): - """Build the dimension and auxiliary coordinates for the final + """Build the dimension and auxiliary coordinates. + + Build the dimension and auxiliary coordinates for the final merged cube given that the final dimensionality of the target merged cube is known and the associated dimension/s that each coordinate maps onto in that merged cube. diff --git a/lib/iris/_representation/cube_printout.py b/lib/iris/_representation/cube_printout.py index 9cbf43f300..3031014faa 100644 --- a/lib/iris/_representation/cube_printout.py +++ b/lib/iris/_representation/cube_printout.py @@ -9,7 +9,9 @@ class Table: - """A container of text strings in rows + columns, that can format its content + """A container of text strings in rows and columns. + + A container of text strings in rows + columns, that can format its content into a string per row, with contents in columns of fixed width. Supports left- or right- aligned columns, alignment being set "per row". @@ -116,7 +118,9 @@ def __str__(self): class CubePrinter: - """An object created from a + """An object created from a cube summary. + + An object created from a :class:`iris._representation.CubeSummary`, which provides text printout of a :class:`iris.cube.Cube`. diff --git a/lib/iris/analysis/_area_weighted.py b/lib/iris/analysis/_area_weighted.py index 24c608e98e..af07b5e069 100644 --- a/lib/iris/analysis/_area_weighted.py +++ b/lib/iris/analysis/_area_weighted.py @@ -21,8 +21,7 @@ class AreaWeightedRegridder: """Provide support for performing area-weighted regridding.""" def __init__(self, src_grid_cube, target_grid_cube, mdtol=1): - """Create an area-weighted regridder for conversions between the source - and target grids. + """Create an area-weighted regridder for conversions between the source and target grids. Parameters ---------- @@ -75,8 +74,7 @@ def __init__(self, src_grid_cube, target_grid_cube, mdtol=1): ) = _regrid_info def __call__(self, cube): - """Regrid this :class:`~iris.cube.Cube` onto the target grid of - this :class:`AreaWeightedRegridder`. + """Regrid :class:`~iris.cube.Cube` onto target grid :class:`AreaWeightedRegridder`. The given cube must be defined with the same grid as the source grid used to create this :class:`AreaWeightedRegridder`. diff --git a/lib/iris/analysis/_grid_angles.py b/lib/iris/analysis/_grid_angles.py index d50f55125f..109e83d73b 100644 --- a/lib/iris/analysis/_grid_angles.py +++ b/lib/iris/analysis/_grid_angles.py @@ -2,7 +2,10 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Code to implement vector rotation by angles, and inferring gridcell angles + +"""Implement vector rotation by angles. + +Code to implement vector rotation by angles, and inferring gridcell angles from coordinate points and bounds. """ @@ -67,7 +70,9 @@ def _latlon_from_xyz(xyz): def _angle(p, q, r): - """Estimate grid-angles to true-Eastward direction from positions in the same + """Estimate grid-angles to true-Eastward direction. + + Estimate grid-angles to true-Eastward direction from positions in the same grid row, but at increasing column (grid-Eastward) positions. {P, Q, R} are locations of consecutive points in the same grid row. diff --git a/lib/iris/analysis/_interpolation.py b/lib/iris/analysis/_interpolation.py index 518b57e63a..04e1e39074 100644 --- a/lib/iris/analysis/_interpolation.py +++ b/lib/iris/analysis/_interpolation.py @@ -57,7 +57,8 @@ def convert_date(date): def extend_circular_coord(coord, points): - """Return coordinates points with a shape extended by one + """Return coordinate points with a shape extended by one. + This is common when dealing with circular coordinates. """ @@ -67,7 +68,9 @@ def extend_circular_coord(coord, points): def extend_circular_coord_and_data(coord, data, coord_dim): - """Return coordinate points and a data array with a shape extended by one + """Return coordinate points and data with a shape extended by one in the provided axis. + + Return coordinate points and a data array with a shape extended by one in the coord_dim axis. This is common when dealing with circular coordinates. @@ -155,10 +158,7 @@ def get_xy_coords(cube, dim_coords=False): def snapshot_grid(cube): - """Helper function that returns deep copies of lateral (dimension) coordinates - from a cube. - - """ + """Helper function that returns deep copies of lateral (dimension) coordinates from a cube.""" x, y = get_xy_dim_coords(cube) return x.copy(), y.copy() @@ -251,10 +251,7 @@ def extrapolation_mode(self): return self._mode def _account_for_circular(self, points, data): - """Extend the given data array, and re-centralise coordinate points - for circular (1D) coordinates. - - """ + """Extend data array, and re-centralise coordinate points for circular (1D) coordinates.""" from iris.analysis.cartography import wrap_lons for circular, modulus, index, dim, offset in self._circulars: @@ -383,7 +380,9 @@ def _resample_coord(self, sample_points, coord, coord_dims): return new_coord def _setup(self): - """Perform initial start-up configuration and validation based on the + """Perform initial start-up configuration and validation. + + Perform initial start-up configuration and validation based on the cube and the specified coordinates to be interpolated over. """ @@ -434,7 +433,9 @@ def _setup(self): self._validate() def _validate(self): - """Perform all sanity checks to ensure that the interpolation request + """Perform checks to ensure interpolation request is valid. + + Perform all sanity checks to ensure that the interpolation request over the cube with the specified coordinates is valid and can be performed. @@ -458,10 +459,7 @@ def _validate(self): raise ValueError(msg.format(coord.name())) def _interpolated_dtype(self, dtype): - """Determine the minimum base dtype required by the - underlying interpolator. - - """ + """Determine the minimum base dtype required by the underlying interpolator.""" if self._method == "nearest": result = dtype else: @@ -469,7 +467,9 @@ def _interpolated_dtype(self, dtype): return result def _points(self, sample_points, data, data_dims=None): - """Interpolate the given data values at the specified list of orthogonal + """Interpolate at the specified points. + + Interpolate the given data values at the specified list of orthogonal (coord, points) pairs. Parameters diff --git a/lib/iris/analysis/_regrid.py b/lib/iris/analysis/_regrid.py index 0f50e47f5b..77b3a306d8 100644 --- a/lib/iris/analysis/_regrid.py +++ b/lib/iris/analysis/_regrid.py @@ -376,8 +376,7 @@ class CurvilinearRegridder: """ def __init__(self, src_grid_cube, target_grid_cube, weights=None): - """Create a regridder for conversions between the source - and target grids. + """Create a regridder for conversions between the source and target grids. Parameters ---------- @@ -408,8 +407,7 @@ def __init__(self, src_grid_cube, target_grid_cube, weights=None): @staticmethod def _get_horizontal_coord(cube, axis): - """Gets the horizontal coordinate on the supplied cube along the - specified axis. + """Gets the horizontal coordinate on the supplied cube along the specified axis. Parameters ---------- @@ -433,7 +431,9 @@ def _get_horizontal_coord(cube, axis): return coords[0] def __call__(self, src): - """Regrid the supplied :class:`~iris.cube.Cube` on to the target grid of + """Regrid onto the target grid. + + Regrid the supplied :class:`~iris.cube.Cube` on to the target grid of this :class:`_CurvilinearRegridder`. The given cube must be defined with the same grid as the source @@ -494,8 +494,7 @@ class RectilinearRegridder: """ def __init__(self, src_grid_cube, tgt_grid_cube, method, extrapolation_mode): - """Create a regridder for conversions between the source - and target grids. + """Create a regridder for conversions between the source and target grids. Parameters ---------- @@ -556,7 +555,9 @@ def extrapolation_mode(self): @staticmethod def _sample_grid(src_coord_system, grid_x_coord, grid_y_coord): - """Convert the rectilinear grid coordinates to a curvilinear grid in + """Convert the rectilinear grid to a curvilinear grid. + + Convert the rectilinear grid coordinates to a curvilinear grid in the source coordinate system. The `grid_x_coord` and `grid_y_coord` must share a common coordinate @@ -851,7 +852,9 @@ def _check_units(self, coord): raise ValueError(msg) def __call__(self, src): - """Regrid this :class:`~iris.cube.Cube` on to the target grid of + """Regrid onto target grid. + + Regrid this :class:`~iris.cube.Cube` on to the target grid of this :class:`RectilinearRegridder`. The given cube must be defined with the same grid as the source diff --git a/lib/iris/analysis/cartography.py b/lib/iris/analysis/cartography.py index 78b903c971..1ce760db5d 100644 --- a/lib/iris/analysis/cartography.py +++ b/lib/iris/analysis/cartography.py @@ -83,7 +83,12 @@ def wrap_lons(lons, base, period): def unrotate_pole(rotated_lons, rotated_lats, pole_lon, pole_lat): - """Convert arrays of rotated-pole longitudes and latitudes to unrotated + """Convert rotated-pole to unrotated longitudes and latitudes. + + ``pole_lat`` should describe the location of the rotated pole that + describes the arrays of rotated-pole longitudes and latitudes. + + Convert arrays of rotated-pole longitudes and latitudes to unrotated arrays of longitudes and latitudes. The values of ``pole_lon`` and ``pole_lat`` should describe the location of the rotated pole that describes the arrays of rotated-pole longitudes and latitudes. @@ -128,8 +133,9 @@ def unrotate_pole(rotated_lons, rotated_lats, pole_lon, pole_lat): def rotate_pole(lons, lats, pole_lon, pole_lat): - """Convert arrays of longitudes and latitudes to arrays of rotated-pole - longitudes and latitudes. The values of ``pole_lon`` and ``pole_lat`` + """Convert unrotated longitudes and latitudes to rotated-pole. + + The values of ``pole_lon`` and ``pole_lat`` should describe the rotated pole that the arrays of longitudes and latitudes are to be rotated onto. @@ -490,7 +496,9 @@ def area_weights(cube, normalize=False): def cosine_latitude_weights(cube): - r"""Returns an array of latitude weights, with the same dimensions as + r"""Calculate cosine latitude weights, with the same dimensions as the cube. + + Return an array of latitude weights, with the same dimensions as the cube. The weights are the cosine of latitude. These are n-dimensional latitude weights repeated over the dimensions @@ -881,8 +889,7 @@ def project(cube, target_proj, nx=None, ny=None): def _transform_xy(crs_from, x, y, crs_to): - """Shorthand function to transform 2d points between coordinate - reference systems. + """Shorthand function to transform 2d points between coordinate reference systems. Parameters ---------- @@ -989,7 +996,9 @@ def _crs_distance_differentials(crs, x, y): def _transform_distance_vectors(u_dist, v_dist, ds, dx2, dy2): - """Transform distance vectors from one coordinate reference system to + """Transform distance vectors to another coordinate reference system. + + Transform distance vectors from one coordinate reference system to another, preserving magnitude and physical direction. Parameters @@ -1022,7 +1031,9 @@ def _transform_distance_vectors(u_dist, v_dist, ds, dx2, dy2): def _transform_distance_vectors_tolerance_mask(src_crs, x, y, tgt_crs, ds, dx2, dy2): - """Return a mask that can be applied to data array to mask elements + """Return a mask that can be applied to data array to mask elements. + + Return a mask that can be applied to data array to mask elements where the magnitude of vectors are not preserved due to numerical errors introduced by the transformation between coordinate systems. diff --git a/lib/iris/analysis/geometry.py b/lib/iris/analysis/geometry.py index 0e44990155..a76498bf45 100644 --- a/lib/iris/analysis/geometry.py +++ b/lib/iris/analysis/geometry.py @@ -18,10 +18,11 @@ def _extract_relevant_cube_slice(cube, geometry): - """Given a shapely geometry object, this helper method returns - the tuple + """Calculate geometry intersection with spatial region defined by cube. + + This helper method returns the tuple (subcube, x_coord_of_subcube, y_coord_of_subcube, - (min_x_index, min_y_index, max_x_index, max_y_index)). + (min_x_index, min_y_index, max_x_index, max_y_index)). If cube and geometry don't overlap, returns None. @@ -134,7 +135,9 @@ def _extract_relevant_cube_slice(cube, geometry): def geometry_area_weights(cube, geometry, normalize=False): - """Returns the array of weights corresponding to the area of overlap between + """Return the array of weights corresponding to the area of overlap. + + Return the array of weights corresponding to the area of overlap between the cells of cube's horizontal grid, and the given shapely geometry. The returned array is suitable for use with :const:`iris.analysis.MEAN`. diff --git a/lib/iris/analysis/maths.py b/lib/iris/analysis/maths.py index 50b8b21a28..61dc033883 100644 --- a/lib/iris/analysis/maths.py +++ b/lib/iris/analysis/maths.py @@ -30,7 +30,9 @@ @lru_cache(maxsize=128, typed=True) def _output_dtype(op, first_dtype, second_dtype=None, in_place=False): - """Get the numpy dtype corresponding to the result of applying a unary or + """Get the numpy dtype. + + Get the numpy dtype corresponding to the result of applying a unary or binary operation to arguments of specified dtype. Parameters @@ -204,7 +206,9 @@ def _assert_is_cube(cube): @_lenient_client(services=SERVICES) def add(cube, other, dim=None, in_place=False): - """Calculate the sum of two cubes, or the sum of a cube and a coordinate or + """Calculate the sum. + + Calculate the sum of two cubes, or the sum of a cube and a coordinate or array or scalar value. When summing two cubes, they must both have the same coordinate systems and @@ -257,7 +261,9 @@ def add(cube, other, dim=None, in_place=False): @_lenient_client(services=SERVICES) def subtract(cube, other, dim=None, in_place=False): - """Calculate the difference between two cubes, or the difference between + """Calculate the difference. + + Calculate the difference between two cubes, or the difference between a cube and a coordinate or array or scalar value. When differencing two cubes, they must both have the same coordinate systems @@ -317,8 +323,7 @@ def _add_subtract_common( dim=None, in_place=False, ): - """Function which shares common code between addition and subtraction - of cubes. + """Function which shares common code between addition and subtraction of cubes. Parameters ---------- @@ -366,7 +371,9 @@ def _add_subtract_common( @_lenient_client(services=SERVICES) def multiply(cube, other, dim=None, in_place=False): - """Calculate the product of two cubes, or the product of a cube and a coordinate + """Calculate the product. + + Calculate the product of two cubes, or the product of a cube and a coordinate or array or scalar value. When multiplying two cubes, they must both have the same coordinate systems @@ -431,7 +438,9 @@ def multiply(cube, other, dim=None, in_place=False): def _inplace_common_checks(cube, other, math_op): - """Check whether an inplace math operation can take place between `cube` and + """Check if an inplace math operation can take place. + + Check whether an inplace math operation can take place between `cube` and `other`. It cannot if `cube` has integer data and `other` has float data as the operation will always produce float data that cannot be 'safely' cast back to the integer data of `cube`. @@ -450,7 +459,9 @@ def _inplace_common_checks(cube, other, math_op): @_lenient_client(services=SERVICES) def divide(cube, other, dim=None, in_place=False): - """Calculate the ratio of two cubes, or the ratio of a cube and a coordinate + """Calculate the ratio. + + Calculate the ratio of two cubes, or the ratio of a cube and a coordinate or array or scalar value. When dividing a cube by another cube, they must both have the same coordinate @@ -692,7 +703,9 @@ def log10(cube, in_place=False): def apply_ufunc(ufunc, cube, other=None, new_unit=None, new_name=None, in_place=False): - """Apply a `numpy universal function + """Apply a `numpy universal function `_ to a cube. + + Apply a `numpy universal function `_ to a cube or pair of cubes. @@ -958,7 +971,9 @@ def _broadcast_cube_coord_data(cube, other, operation_name, dim=None): def _sanitise_metadata(cube, unit): - """As part of the maths metadata contract, clear the necessary or + """Clear appropriate metadata from the resultant cube. + + As part of the maths metadata contract, clear the necessary or unsupported metadata from the resultant cube of the maths operation. """ diff --git a/lib/iris/analysis/stats.py b/lib/iris/analysis/stats.py index 33eb171336..34c37b8b11 100644 --- a/lib/iris/analysis/stats.py +++ b/lib/iris/analysis/stats.py @@ -19,8 +19,7 @@ def pearsonr( mdtol=1.0, common_mask=False, ): - """Calculate the Pearson's r correlation coefficient over specified - dimensions. + """Calculate the Pearson's r correlation coefficient over specified dimensions. Parameters ---------- diff --git a/lib/iris/analysis/trajectory.py b/lib/iris/analysis/trajectory.py index c46fa2ebea..61871fdc51 100644 --- a/lib/iris/analysis/trajectory.py +++ b/lib/iris/analysis/trajectory.py @@ -2,10 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Defines a Trajectory class, and a routine to extract a sub-cube along a -trajectory. - -""" +"""Defines a Trajectory class, and a routine to extract a sub-cube along a trajectory.""" import math @@ -115,8 +112,7 @@ def __repr__(self): ) def _get_interp_points(self): - """Translate `self.sampled_points` to the format expected by the - interpolator. + """Translate `self.sampled_points` to the format expected by the interpolator. Returns ------- @@ -132,7 +128,9 @@ def _get_interp_points(self): return [(k, v) for k, v in points.items()] def _src_cube_anon_dims(self, cube): - """A helper method to locate the index of anonymous dimensions on the + """A helper method to locate the index of anonymous dimensions. + + A helper method to locate the index of anonymous dimensions on the interpolation target, ``cube``. Returns @@ -144,7 +142,9 @@ def _src_cube_anon_dims(self, cube): return list(set(range(cube.ndim)) - set(named_dims)) def interpolate(self, cube, method=None): - """Calls :func:`~iris.analysis.trajectory.interpolate` to interpolate + """Interpolate ``cube`` on the defined trajectory. + + Call :func:`~iris.analysis.trajectory.interpolate` to interpolate ``cube`` on the defined trajectory. Assumes that the coordinate names supplied in the waypoints @@ -480,6 +480,7 @@ def _ll_to_cart(lon, lat): def _cartesian_sample_points(sample_points, sample_point_coord_names): """Replace geographic lat/lon with cartesian xyz. + Generates coords suitable for nearest point calculations with `scipy.spatial.cKDTree`. @@ -529,7 +530,9 @@ def _cartesian_sample_points(sample_points, sample_point_coord_names): def _nearest_neighbour_indices_ndcoords(cube, sample_points, cache=None): - """Returns the indices to select the data value(s) closest to the given + """Calculate the cube nearest neighbour indices for the samples. + + Return the indices to select the data value(s) closest to the given coordinate point values. 'sample_points' is of the form [[coord-or-coord-name, point-value(s)]*]. @@ -696,7 +699,9 @@ def _nearest_neighbour_indices_ndcoords(cube, sample_points, cache=None): class UnstructuredNearestNeigbourRegridder: - """Encapsulate the operation of :meth:`iris.analysis.trajectory.interpolate` + """Encapsulate the operation of :meth:`iris.analysis.trajectory.interpolate`. + + Encapsulate the operation of :meth:`iris.analysis.trajectory.interpolate` with given source and target grids. This is the type used by the :class:`~iris.analysis.UnstructuredNearest` @@ -707,7 +712,9 @@ class UnstructuredNearestNeigbourRegridder: # TODO: cache the necessary bits of the operation so reuse can actually # be more efficient. def __init__(self, src_cube, target_grid_cube): - """A nearest-neighbour regridder to perform regridding from the source + """A nearest-neighbour regridder. + + A nearest-neighbour regridder to perform regridding from the source grid to the target grid. This can then be applied to any source data with the same structure as diff --git a/lib/iris/common/_split_attribute_dicts.py b/lib/iris/common/_split_attribute_dicts.py index 95dbcbb7b3..b59ad37269 100644 --- a/lib/iris/common/_split_attribute_dicts.py +++ b/lib/iris/common/_split_attribute_dicts.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Dictionary operations for dealing with the CubeAttrsDict "split"-style attribute -dictionaries. +"""Dictionary operations for dealing with the CubeAttrsDict "split"-style attribute dictionaries. The idea here is to convert a split-dictionary into a "plain" one for calculations, whose keys are all pairs of the form ('global', ) or ('local', ). diff --git a/lib/iris/common/lenient.py b/lib/iris/common/lenient.py index d8fb5e8bfc..0180716ac6 100644 --- a/lib/iris/common/lenient.py +++ b/lib/iris/common/lenient.py @@ -28,24 +28,26 @@ def _lenient_client(*dargs, services=None): - """Decorator that allows a client function/method to declare at runtime that + """Decorator implementing the lenient client protocol. + + Decorator that allows a client function/method to declare at runtime that it is executing and requires lenient behaviour from a prior registered lenient service function/method. - This decorator supports being called with no arguments e.g., + This decorator supports being called with no arguments e.g:: @_lenient_client() def func(): pass - This is equivalent to using it as a simple naked decorator e.g., + This is equivalent to using it as a simple naked decorator e.g:: @_lenient_client def func() pass Alternatively, this decorator supports the lenient client explicitly - declaring the lenient services that it wishes to use e.g., + declaring the lenient services that it wishes to use e.g:: @_lenient_client(services=(service1, service2, ...) def func(): @@ -87,7 +89,9 @@ def func(): @wraps(func) def lenient_client_inner_naked(*args, **kwargs): - """Closure wrapper function to register the wrapped function/method + """Closure wrapper function. + + Closure wrapper function to register the wrapped function/method as active at runtime before executing it. """ @@ -107,7 +111,9 @@ def lenient_client_inner_naked(*args, **kwargs): def lenient_client_outer(func): @wraps(func) def lenient_client_inner(*args, **kwargs): - """Closure wrapper function to register the wrapped function/method + """Closure wrapper function. + + Closure wrapper function to register the wrapped function/method as active at runtime before executing it. """ @@ -123,18 +129,20 @@ def lenient_client_inner(*args, **kwargs): def _lenient_service(*dargs): - """Decorator that allows a function/method to declare that it supports lenient + """Decorator implementing the lenient service protocol. + + Decorator that allows a function/method to declare that it supports lenient behaviour as a service. Registration is at Python interpreter parse time. - The decorator supports being called with no arguments e.g., + The decorator supports being called with no arguments e.g:: @_lenient_service() def func(): pass - This is equivalent to using it as a simple naked decorator e.g., + This is equivalent to using it as a simple naked decorator e.g:: @_lenient_service def func(): @@ -281,7 +289,9 @@ def _init(self): @contextmanager def context(self, **kwargs): - """Return a context manager which allows temporary modification of the + """Context manager supporting temporary modification of lenient state. + + Return a context manager which allows temporary modification of the lenient option state within the scope of the context manager. On entry to the context manager, all provided keyword arguments are @@ -320,7 +330,9 @@ def configure_state(state): class _Lenient(threading.local): def __init__(self, *args, **kwargs): - """A container for managing the run-time lenient services and client + """A container for managing the run-time lenient services and client options. + + A container for managing the run-time lenient services and client options for pre-defined functions/methods. Parameters @@ -354,7 +366,9 @@ def __init__(self, *args, **kwargs): self.register_client(client, services) def __call__(self, func): - """Determine whether it is valid for the function/method to provide a + """Determine whether it is valid for the function/method to provide a lenient service. + + Determine whether it is valid for the function/method to provide a lenient service at runtime to the actively executing lenient client. Parameters @@ -433,7 +447,9 @@ def __setitem__(self, name, value): @contextmanager def context(self, *args, **kwargs): - """Return a context manager which allows temporary modification of + """Context manager supporting temporary modification of lenient state. + + Return a context manager which allows temporary modification of the lenient option state for the active thread. On entry to the context manager, all provided keyword arguments are @@ -526,7 +542,9 @@ def enable(self, state): self.__dict__["enable"] = state def register_client(self, func, services, append=False): - """Add the provided mapping of lenient client function/method to + """Add the lenient client to service mapping. + + Add the provided mapping of lenient client function/method to required lenient service function/methods. Parameters @@ -565,8 +583,7 @@ def register_client(self, func, services, append=False): self.__dict__[func] = services def register_service(self, func): - """Add the provided function/method as providing a lenient service and - activate it. + """Add the provided function/method as providing a lenient service and activate it. Parameters ---------- diff --git a/lib/iris/common/metadata.py b/lib/iris/common/metadata.py index 27b3329621..71d51fe6d7 100644 --- a/lib/iris/common/metadata.py +++ b/lib/iris/common/metadata.py @@ -94,7 +94,9 @@ def hexdigest(item): class _NamedTupleMeta(ABCMeta): - """Meta-class to support the convenience of creating a namedtuple from + """Meta-class convenience for creating a namedtuple. + + Meta-class to support the convenience of creating a namedtuple from names/members of the metadata class hierarchy. """ @@ -575,8 +577,7 @@ def _is_attributes(field, left, right): @lenient_service def combine(self, other, lenient=None): - """Return a new metadata instance created by combining each of the - associated metadata members. + """Return a new metadata instance created by combining each of the associated metadata members. Parameters ---------- @@ -598,7 +599,9 @@ def combine(self, other, lenient=None): @lenient_service def difference(self, other, lenient=None): - """Return a new metadata instance created by performing a difference + """Perform lenient metadata difference operation. + + Return a new metadata instance created by performing a difference comparison between each of the associated metadata members. A metadata member returned with a value of "None" indicates that there @@ -650,7 +653,9 @@ def equal(self, other, lenient=None): @classmethod def from_metadata(cls, other): - """Convert the provided metadata instance from a different type + """Convert metadata instance to this metadata type. + + Convert the provided metadata instance from a different type to this metadata type, using only the relevant metadata members. Non-common metadata members are set to ``None``. @@ -721,7 +726,9 @@ def _check(item): @classmethod def token(cls, name): - """Determine whether the provided name is a valid NetCDF name and thus + """Verify validity of provided NetCDF name. + + Determine whether the provided name is a valid NetCDF name and thus safe to represent a single parsable token. Parameters @@ -1124,7 +1131,9 @@ def _difference_lenient(self, other): @property def _names(self): - """A tuple containing the value of each name participating in the identity + """A tuple containing the value of each name participating in the identity of a cube. + + A tuple containing the value of each name participating in the identity of a :class:`iris.cube.Cube`. This includes the standard name, long name, NetCDF variable name, and the STASH from the attributes dictionary. @@ -1335,8 +1344,7 @@ def metadata_filter( attributes=None, axis=None, ): - """Filter a collection of objects by their metadata to fit the given metadata - criteria. + """Filter a collection of objects by their metadata to fit the given metadata criteria. Criteria can be either specific properties or other objects with metadata to be matched. @@ -1492,7 +1500,9 @@ def __ne__(self, other): return match def __reduce__(self): - """Dynamically created classes at runtime cannot be pickled, due to not + """Use the __reduce__ interface to allow 'pickle' to recreate this class instance. + + Dynamically created classes at runtime cannot be pickled, due to not being defined at the top level of a module. As a result, we require to use the __reduce__ interface to allow 'pickle' to recreate this class instance, and dump and load instance state successfully. @@ -1551,7 +1561,9 @@ def values(self): def metadata_manager_factory(cls, **kwargs): - """A class instance factory function responsible for manufacturing + """Factory function for manufacturing metadata instances. + + A class instance factory function responsible for manufacturing metadata instances dynamically at runtime. The factory instances returned by the factory are capable of managing diff --git a/lib/iris/common/resolve.py b/lib/iris/common/resolve.py index b35397ee58..1ded7e2603 100644 --- a/lib/iris/common/resolve.py +++ b/lib/iris/common/resolve.py @@ -2,7 +2,9 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Provides the infrastructure to support the analysis, identification and +"""Resolve metadata common between two cubes. + +Provides the infrastructure to support the analysis, identification and combination of metadata common between two :class:`~iris.cube.Cube` operands into a single resultant :class:`~iris.cube.Cube`, which will be auto-transposed, and with the appropriate broadcast shape. @@ -97,7 +99,9 @@ def create_coord(self, metadata): class Resolve: - """At present, :class:`~iris.common.resolve.Resolve` is used by Iris solely + """Resolve the metadata of two cubes into one cube. + + At present, :class:`~iris.common.resolve.Resolve` is used by Iris solely during cube maths to combine a left-hand :class:`~iris.cube.Cube` operand and a right-hand :class:`~iris.cube.Cube` operand into a resultant :class:`~iris.cube.Cube` with common metadata, suitably auto-transposed @@ -208,7 +212,9 @@ class Resolve: """ # noqa: D214, D406, D407, D410, D411 def __init__(self, lhs=None, rhs=None): - """Resolve the provided ``lhs`` :class:`~iris.cube.Cube` operand and + """Resolve the cube operands. + + Resolve the provided ``lhs`` :class:`~iris.cube.Cube` operand and ``rhs`` :class:`~iris.cube.Cube` operand to determine the metadata that is common between them, and the auto-transposed, broadcast shape of the resultant :class:`~iris.cube.Cube`. @@ -323,7 +329,9 @@ def __init__(self, lhs=None, rhs=None): self(lhs, rhs) def __call__(self, lhs, rhs): - """Resolve the ``lhs`` :class:`~iris.cube.Cube` operand and ``rhs`` + """Resolve the cube operands. + + Resolve the ``lhs`` :class:`~iris.cube.Cube` operand and ``rhs`` :class:`~iris.cube.Cube` operand metadata. Involves determining all the common coordinate metadata shared between @@ -378,7 +386,9 @@ def __call__(self, lhs, rhs): return self def _as_compatible_cubes(self): - """Determine whether the ``src`` and ``tgt`` :class:`~iris.cube.Cube` can + """Transpose and/or broadcast operands. + + Determine whether the ``src`` and ``tgt`` :class:`~iris.cube.Cube` can be transposed and/or broadcast successfully together. If compatible, the ``_broadcast_shape`` of the resultant resolved cube is @@ -487,7 +497,9 @@ def _aux_coverage( common_aux_metadata, common_scalar_metadata, ): - """Determine the dimensions covered by each of the local and common + """Perform auxiliary coordinate coverage. + + Determine the dimensions covered by each of the local and common auxiliary coordinates of the provided :class:`~iris.cube.Cube`. The cube dimensions not covered by any of the auxiliary coordinates is @@ -554,7 +566,9 @@ def _aux_coverage( @staticmethod def _aux_mapping(src_coverage, tgt_coverage): - """Establish the mapping of dimensions from the ``src`` to ``tgt`` + """Perform auxiliary coordinate dimension mapping. + + Establish the mapping of dimensions from the ``src`` to ``tgt`` :class:`~iris.cube.Cube` using the auxiliary coordinate metadata common between each of the operands. @@ -620,7 +634,9 @@ def _aux_mapping(src_coverage, tgt_coverage): @staticmethod def _categorise_items(cube): - """Inspect the provided :class:`~iris.cube.Cube` and group its + """Categorise the cube metadata. + + Inspect the provided :class:`~iris.cube.Cube` and group its coordinates and associated metadata into dimension, auxiliary and scalar categories. @@ -668,7 +684,9 @@ def _create_prepared_item( bounds=None, container=None, ): - """Convenience method that creates a :class:`~iris.common.resolve._PreparedItem` + """Package metadata in preparation for resolution. + + Convenience method that creates a :class:`~iris.common.resolve._PreparedItem` containing the data and metadata required to construct and attach a coordinate to the resultant resolved cube. @@ -790,7 +808,9 @@ def _show(items, heading): @staticmethod def _dim_coverage(cube, cube_items_dim, common_dim_metadata): - """Determine the dimensions covered by each of the local and common + """Perform dimension coordinate coverage. + + Determine the dimensions covered by each of the local and common dimension coordinates of the provided :class:`~iris.cube.Cube`. The cube dimensions not covered by any of the dimension coordinates is @@ -840,7 +860,9 @@ def _dim_coverage(cube, cube_items_dim, common_dim_metadata): @staticmethod def _dim_mapping(src_coverage, tgt_coverage): - """Establish the mapping of dimensions from the ``src`` to ``tgt`` + """Perform dimension coordinate dimension mapping. + + Establish the mapping of dimensions from the ``src`` to ``tgt`` :class:`~iris.cube.Cube` using the dimension coordinate metadata common between each of the operands. @@ -897,7 +919,9 @@ def _free_mapping( src_aux_coverage, tgt_aux_coverage, ): - """Attempt to update the :attr:`~iris.common.resolve.Resolve.mapping` with + """Associate free dimensions to covered dimensions. + + Attempt to update the :attr:`~iris.common.resolve.Resolve.mapping` with ``src`` to ``tgt`` :class:`~iris.cube.Cube` mappings from unmapped ``src`` dimensions that are free from coordinate metadata coverage to ``tgt`` dimensions that have local metadata coverage (i.e., is not common between @@ -1071,7 +1095,9 @@ def _pop(item, items): logger.debug(f"mapping free dimensions gives, mapping={self.mapping}") def _metadata_coverage(self): - """Using the pre-categorised metadata of the cubes, determine the dimensions + """Determine free and covered dimensions. + + Using the pre-categorised metadata of the cubes, determine the dimensions covered by their associated dimension and auxiliary coordinates, and which dimensions are free of metadata coverage. @@ -1117,7 +1143,9 @@ def _metadata_coverage(self): ) def _metadata_mapping(self): - """Ensure that each ``src`` :class:`~iris.cube.Cube` dimension is mapped to an associated + """Identify equivalent dimensions using metadata. + + Ensure that each ``src`` :class:`~iris.cube.Cube` dimension is mapped to an associated ``tgt`` :class:`~iris.cube.Cube` dimension using the common dim and aux coordinate metadata. If the common metadata does not result in a full mapping of ``src`` to ``tgt`` dimensions @@ -1225,7 +1253,9 @@ def _metadata_mapping(self): self._as_compatible_cubes() def _metadata_prepare(self): - """Populate the :attr:`~iris.common.resolve.Resolve.prepared_category` and + """Consolidate metadata for resolved cube. + + Populate the :attr:`~iris.common.resolve.Resolve.prepared_category` and :attr:`~iris.common.resolve.Resolve.prepared_factories` with the necessary metadata to be constructed and attached to the resulting resolved :class:`~iris.cube.Cube`. @@ -1285,7 +1315,9 @@ def _metadata_prepare(self): self._prepare_factory_payload(src_cube, src_category_local) def _metadata_resolve(self): - """Categorise the coordinate metadata of the cubes into three distinct + """Categorise the coordinate metadata. + + Categorise the coordinate metadata of the cubes into three distinct groups; metadata from coordinates only available (local) on the LHS cube, metadata from coordinates only available (local) on the RHS cube, and metadata from coordinates common to both the LHS and RHS @@ -1393,7 +1425,9 @@ def _prepare_common_aux_payload( prepared_items, ignore_mismatch=None, ): - """Populate the ``prepared_items`` with a :class:`~iris.common.resolve._PreparedItem` containing + """Consolidate common auxiliary coordinate metadata. + + Populate the ``prepared_items`` with a :class:`~iris.common.resolve._PreparedItem` containing the necessary metadata for each auxiliary coordinate to be constructed and attached to the resulting resolved :class:`~iris.cube.Cube`. @@ -1516,7 +1550,9 @@ def _prepare_common_aux_payload( def _prepare_common_dim_payload( self, src_coverage, tgt_coverage, ignore_mismatch=None ): - """Populate the ``items_dim`` member of :attr:`~iris.common.resolve.Resolve.prepared_category_items` + """Consolidate common dimension coordinate metadata. + + Populate the ``items_dim`` member of :attr:`~iris.common.resolve.Resolve.prepared_category_items` with a :class:`~iris.common.resolve._PreparedItem` containing the necessary metadata for each :class:`~iris.coords.DimCoord` to be constructed and attached to the resulting resolved :class:`~iris.cube.Cube`. @@ -1575,7 +1611,9 @@ def _prepare_common_dim_payload( def _get_prepared_item( self, metadata, category_local, from_src=True, from_local=False ): - """Find the :attr:`~iris.common.resolve._PreparedItem` from the + """Find the :attr:`~iris.common.resolve._PreparedItem`. + + Find the :attr:`~iris.common.resolve._PreparedItem` from the :attr:`~iris.common.resolve.Resolve.prepared_category` that matches the provided ``metadata``. Alternatively, the ``category_local`` is searched to find a :class:`~iris.common.resolve._Item` @@ -1651,9 +1689,12 @@ def _get_prepared_item( return result def _prepare_factory_payload(self, cube, category_local, from_src=True): - """Populate the :attr:`~iris.common.resolve.Resolve.prepared_factories` with a :class:`~iris.common.resolve._PreparedFactory` - containing the necessary metadata for each ``src`` and/or ``tgt`` auxiliary factory to be constructed and - attached to the resulting resolved :class:`~iris.cube.Cube`. + """Consolidate common factory metadata. + + Populate the :attr:`~iris.common.resolve.Resolve.prepared_factories` with a + :class:`~iris.common.resolve._PreparedFactory` containing the necessary + metadata for each ``src`` and/or ``tgt`` auxiliary factory to be constructed + and attached to the resulting resolved :class:`~iris.cube.Cube`. .. note:: @@ -1727,7 +1768,9 @@ def _prepare_factory_payload(self, cube, category_local, from_src=True): logger.debug(dmsg) def _prepare_local_payload_aux(self, src_aux_coverage, tgt_aux_coverage): - """Populate the ``items_aux`` member of :attr:`~iris.common.resolve.Resolve.prepared_category_items` + """Consolidate local auxiliary coordinate metadata. + + Populate the ``items_aux`` member of :attr:`~iris.common.resolve.Resolve.prepared_category_items` with a :class:`~iris.common.resolve._PreparedItem` containing the necessary metadata for each ``src`` or ``tgt`` local auxiliary coordinate to be constructed and attached to the resulting resolved :class:`~iris.cube.Cube`. @@ -1802,7 +1845,9 @@ def _prepare_local_payload_aux(self, src_aux_coverage, tgt_aux_coverage): logger.debug(dmsg) def _prepare_local_payload_dim(self, src_dim_coverage, tgt_dim_coverage): - """Populate the ``items_dim`` member of :attr:`~iris.common.resolve.Resolve.prepared_category_items` + """Consolidate local dimension coordinate metadata. + + Populate the ``items_dim`` member of :attr:`~iris.common.resolve.Resolve.prepared_category_items` with a :class:`~iris.common.resolve._PreparedItem` containing the necessary metadata for each ``src`` or ``tgt`` local :class:`~iris.coords.DimCoord` to be constructed and attached to the resulting resolved :class:`~iris.cube.Cube`. @@ -1879,7 +1924,9 @@ def _prepare_local_payload_dim(self, src_dim_coverage, tgt_dim_coverage): self.prepared_category.items_dim.append(prepared_item) def _prepare_local_payload_scalar(self, src_aux_coverage, tgt_aux_coverage): - """Populate the ``items_scalar`` member of :attr:`~iris.common.resolve.Resolve.prepared_category_items` + """Consolidate local scalar coordinate metadata. + + Populate the ``items_scalar`` member of :attr:`~iris.common.resolve.Resolve.prepared_category_items` with a :class:`~iris.common.resolve._PreparedItem` containing the necessary metadata for each ``src`` or ``tgt`` local scalar coordinate to be constructed and attached to the resulting resolved :class:`~iris.cube.Cube`. @@ -1933,7 +1980,9 @@ def _prepare_local_payload( tgt_dim_coverage, tgt_aux_coverage, ): - """Populate the :attr:`~iris.common.resolve.Resolve.prepared_category_items` with a + """Consolidate the local metadata. + + Populate the :attr:`~iris.common.resolve.Resolve.prepared_category_items` with a :class:`~iris.common.resolve._PreparedItem` containing the necessary metadata from the ``src`` and/or ``tgt`` :class:`~iris.cube.Cube` for each coordinate to be constructed and attached to the resulting resolved :class:`~iris.cube.Cube`. @@ -1966,7 +2015,9 @@ def _prepare_local_payload( def _prepare_points_and_bounds( self, src_coord, tgt_coord, src_dims, tgt_dims, ignore_mismatch=None ): - """Compare the points and bounds of the ``src`` and ``tgt`` coordinates to ensure + """Consolidate points and bounds. + + Compare the points and bounds of the ``src`` and ``tgt`` coordinates to ensure that they are equivalent, taking into account broadcasting when appropriate. .. note:: @@ -2238,7 +2289,9 @@ def _tgt_cube_prepare(self, data): cube.remove_ancillary_variable(av) def cube(self, data, in_place=False): - """Create the resultant :class:`~iris.cube.Cube` from the resolved ``lhs`` + """Create the resultant resolved cube. + + Create the resultant :class:`~iris.cube.Cube` from the resolved ``lhs`` and ``rhs`` :class:`~iris.cube.Cube` operands, using the provided ``data``. @@ -2403,7 +2456,9 @@ def cube(self, data, in_place=False): @property def mapped(self): - """Boolean state representing whether **all** ``src`` :class:`~iris.cube.Cube` + """Whether all ``src`` dimensions have been mapped. + + Boolean state representing whether **all** ``src`` :class:`~iris.cube.Cube` dimensions have been associated with relevant ``tgt`` :class:`~iris.cube.Cube` dimensions. @@ -2481,7 +2536,9 @@ def mapped(self): @property def shape(self): - """Proposed shape of the final resolved cube given the ``lhs`` + """Proposed shape of the final resolved cube. + + Proposed shape of the final resolved cube given the ``lhs`` :class:`~iris.cube.Cube` operand and the ``rhs`` :class:`~iris.cube.Cube` operand. diff --git a/lib/iris/coord_categorisation.py b/lib/iris/coord_categorisation.py index a17dba6519..14330487b6 100644 --- a/lib/iris/coord_categorisation.py +++ b/lib/iris/coord_categorisation.py @@ -147,10 +147,7 @@ def add_day_of_month(cube, coord, name="day_of_month"): def add_day_of_year(cube, coord, name="day_of_year"): - """Add a categorical day-of-year coordinate, values 1..365 - (1..366 in leap years). - - """ + """Add a categorical day-of-year coordinate, values 1..365 (1..366 in leap years).""" # Note: cftime.datetime objects return a normal tuple from timetuple(), # unlike datetime.datetime objects that return a namedtuple. # Index the time tuple (element 7 is day of year) instead of using named @@ -207,10 +204,7 @@ def add_hour(cube, coord, name="hour"): def _months_in_season(season): - """Returns a list of month numbers corresponding to each month in the - given season. - - """ + """Returns a list of month numbers corresponding to each month in the given season.""" cyclic_months = "jfmamjjasondjfmamjjasond" m0 = cyclic_months.find(season.lower()) if m0 < 0: @@ -300,8 +294,7 @@ def _month_season_numbers(seasons): def add_season(cube, coord, name="season", seasons=("djf", "mam", "jja", "son")): - """Add a categorical season-of-year coordinate, with user specified - seasons. + """Add a categorical season-of-year coordinate, with user specified seasons. Parameters ---------- @@ -336,7 +329,9 @@ def _season(coord, value): def add_season_number( cube, coord, name="season_number", seasons=("djf", "mam", "jja", "son") ): - """Add a categorical season-of-year coordinate, values 0..N-1 where + """Add a categorical season-of-year coordinate. + + Add a categorical season-of-year coordinate, values 0..N-1 where N is the number of user specified seasons. Parameters @@ -416,8 +411,7 @@ def _season_year(coord, value): def add_season_membership(cube, coord, season, name="season_membership"): - """Add a categorical season membership coordinate for a user specified - season. + """Add a categorical season membership coordinate for a user specified season. The coordinate has the value True for every time that is within the given season, and the value False otherwise. diff --git a/lib/iris/coord_systems.py b/lib/iris/coord_systems.py index 7f0af71548..b96f6166c0 100644 --- a/lib/iris/coord_systems.py +++ b/lib/iris/coord_systems.py @@ -115,10 +115,7 @@ def _ellipsoid_to_globe(ellipsoid, globe_default): @abstractmethod def as_cartopy_crs(self): - """Return a cartopy CRS representing our native coordinate - system. - - """ + """Return a cartopy CRS representing our native coordinate system.""" pass @abstractmethod @@ -141,7 +138,9 @@ def as_cartopy_projection(self): class GeogCS(CoordSystem): - """A geographic (ellipsoidal) coordinate system, defined by the shape of + """A geographic (ellipsoidal) coordinate system. + + A geographic (ellipsoidal) coordinate system, defined by the shape of the Earth and a prime meridian. """ @@ -362,7 +361,9 @@ class that invalidates the cache. return ccrs.Geodetic(self._globe) def _wipe_cached_properties(self): - """Wipes the cached properties on the object as part of any update to a + """Wipes the cached properties on the object. + + Wipes the cached properties on the object as part of any update to a value that invalidates the cache. """ try: @@ -383,9 +384,12 @@ def semi_major_axis(self): @semi_major_axis.setter def semi_major_axis(self, value): - """Setting this property to a different value invalidates the current datum + """Assign semi_major_axis. + + Setting this property to a different value invalidates the current datum (if any) because a datum encodes a specific semi-major axis. This also invalidates the cached `cartopy.Globe` and `cartopy.CRS`. + """ value = float(value) if not np.isclose(self.semi_major_axis, value): @@ -402,9 +406,12 @@ def semi_minor_axis(self): @semi_minor_axis.setter def semi_minor_axis(self, value): - """Setting this property to a different value invalidates the current datum + """Assign semi_minor_axis. + + Setting this property to a different value invalidates the current datum (if any) because a datum encodes a specific semi-minor axis. This also invalidates the cached `cartopy.Globe` and `cartopy.CRS`. + """ value = float(value) if not np.isclose(self.semi_minor_axis, value): @@ -421,8 +428,11 @@ def inverse_flattening(self): @inverse_flattening.setter def inverse_flattening(self, value): - """Setting this property to a different value does not affect the behaviour + """Assign inverse_flattening. + + Setting this property to a different value does not affect the behaviour of this object any further than the value of this property. + """ wmsg = ( "Setting inverse_flattening does not affect other properties of " @@ -443,10 +453,13 @@ def datum(self): @datum.setter def datum(self, value): - """Setting this property to a different value invalidates the current + """Assign datum. + + Setting this property to a different value invalidates the current values of the ellipsoid measurements because a datum encodes its own ellipse. This also invalidates the cached `cartopy.Globe` and `cartopy.CRS`. + """ if self._datum != value: self._semi_major_axis = None @@ -483,8 +496,7 @@ def __init__( north_pole_grid_longitude=None, ellipsoid=None, ): - """Constructs a coordinate system with rotated pole, on an - optional :class:`GeogCS`. + """Constructs a coordinate system with rotated pole, on an optional :class:`GeogCS`. Args: diff --git a/lib/iris/coords.py b/lib/iris/coords.py index 4274872e66..caa421d11c 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -119,8 +119,7 @@ def __init__( self._bounds_dm = None # Only ever set on Coord-derived instances. def __getitem__(self, keys): - """Returns a new dimensional metadata whose values are obtained by - conventional array indexing. + """Returns a new dimensional metadata whose values are obtained by conventional array indexing. .. note:: @@ -239,10 +238,7 @@ def _lazy_values(self): return self._values_dm.lazy_data() def _core_values(self): - """The values array of this dimensional metadata which may be a NumPy - array or a dask array. - - """ + """The values array of this dimensional metadata which may be a NumPy array or a dask array.""" result = self._values_dm.core_data() if not _lazy.is_lazy_data(result): result = result.view() @@ -250,10 +246,7 @@ def _core_values(self): return result def _has_lazy_values(self): - """Returns a boolean indicating whether the metadata's values array is a - lazy dask array or not. - - """ + """Indicates whether the metadata's values array is a lazy dask array or not.""" return self._values_dm.has_lazy_data() def summary( @@ -752,10 +745,7 @@ def pointwise_convert(values): self.units = unit def is_compatible(self, other, ignore=None): - """Return whether the current dimensional metadata object is compatible - with another. - - """ + """Return whether the current dimensional metadata object is compatible with another.""" compatible = self.name() == other.name() and self.units == other.units if compatible: @@ -773,25 +763,16 @@ def is_compatible(self, other, ignore=None): @property def dtype(self): - """The NumPy dtype of the current dimensional metadata object, as - specified by its values. - - """ + """The NumPy dtype of the current dimensional metadata object, as specified by its values.""" return self._values_dm.dtype @property def ndim(self): - """Return the number of dimensions of the current dimensional metadata - object. - - """ + """Return the number of dimensions of the current dimensional metadata object.""" return self._values_dm.ndim def has_bounds(self): - """Return a boolean indicating whether the current dimensional metadata - object has a bounds array. - - """ + """Indicates whether the current dimensional metadata object has a bounds array.""" # Allows for code to handle unbounded dimensional metadata agnostic of # whether the metadata is a coordinate or not. return False @@ -802,7 +783,9 @@ def shape(self): return self._values_dm.shape def xml_element(self, doc): - """Create the :class:`xml.dom.minidom.Element` that describes this + """Create XML element. + + Create the :class:`xml.dom.minidom.Element` that describes this :class:`_DimensionalMetadata`. Parameters @@ -897,10 +880,7 @@ def _xml_array_repr(data): return result def _value_type_name(self): - """A simple, readable name for the data type of the dimensional metadata - values. - - """ + """A simple, readable name for the data type of the dimensional metadata values.""" dtype = self._core_values().dtype kind = dtype.kind if kind in "SU": @@ -983,17 +963,16 @@ def lazy_data(self): return super()._lazy_values() def core_data(self): - """The data array at the core of this ancillary variable, which may be a + """The data array at the core of this ancillary variable. + + The data array at the core of this ancillary variable, which may be a NumPy array or a dask array. """ return super()._core_values() def has_lazy_data(self): - """Return a boolean indicating whether the ancillary variable's data array - is a lazy dask array or not. - - """ + """Indicates whether the ancillary variable's data array is a lazy dask array or not.""" return super()._has_lazy_values() def cube_dims(self, cube): @@ -1006,7 +985,9 @@ def cube_dims(self, cube): class CellMeasure(AncillaryVariable): - """A CF Cell Measure, providing area or volume properties of a cell + """A CF Cell Measure, providing area or volume properties of a cell. + + A CF Cell Measure, providing area or volume properties of a cell where these cannot be inferred from the Coordinates and Coordinate Reference System. @@ -1084,8 +1065,7 @@ def cube_dims(self, cube): return cube.cell_measure_dims(self) def xml_element(self, doc): - """Create the :class:`xml.dom.minidom.Element` that describes this - :class:`CellMeasure`. + """Create the :class:`xml.dom.minidom.Element` that describes this :class:`CellMeasure`. Parameters ---------- @@ -1131,8 +1111,7 @@ def __new__( min_inclusive=True, max_inclusive=True, ): - """Create a CoordExtent for the specified coordinate and range of - values. + """Create a CoordExtent for the specified coordinate and range of values. Parameters ---------- @@ -1212,7 +1191,9 @@ def _get_2d_coord_bound_grid(bounds): class Cell(namedtuple("Cell", ["point", "bound"])): - """An immutable representation of a single cell of a coordinate, including the + """A coordinate cell containing a single point, or point and bounds. + + An immutable representation of a single cell of a coordinate, including the sample point and/or boundary position. Notes on cell comparison: @@ -1296,10 +1277,7 @@ def __hash__(self): return hash((self.point, bound)) def __eq__(self, other): - """Compares Cell equality depending on the type of the object to be - compared. - - """ + """Compares Cell equality depending on the type of the object to be compared.""" if isinstance(other, (int, float, np.number)) or hasattr(other, "timetuple"): if self.bound is not None: return self.contains_point(other) @@ -1326,7 +1304,9 @@ def __ne__(self, other): return result def __common_cmp__(self, other, operator_method): - """Common method called by the rich comparison operators. The method of + """Common equality comparison. + + Common method called by the rich comparison operators. The method of checking equality depends on the type of the object to be compared. Cell vs Cell comparison is used to define a strict order. @@ -1431,8 +1411,7 @@ def __str__(self): return str(self.point) def contains_point(self, point): - """For a bounded cell, returns whether the given point lies within the - bounds. + """For a bounded cell, returns whether the given point lies within the bounds. .. note:: The test carried out is equivalent to min(bound) <= point <= max(bound). @@ -1600,7 +1579,9 @@ def points(self, points): @property def bounds(self): - """The coordinate bounds values, as a NumPy array, + """Coordinate bounds values. + + The coordinate bounds values, as a NumPy array, or None if no bound values are defined. .. note:: The shape of the bound array should be: ``points.shape + @@ -1639,7 +1620,9 @@ def coord_system(self, value): @property def climatological(self): - """A boolean that controls whether the coordinate is a climatological + """Flag for representing a climatological time axis. + + A boolean that controls whether the coordinate is a climatological time axis, in which case the bounds represent a climatological period rather than a normal period. @@ -1674,8 +1657,7 @@ def climatological(self, value): @property def ignore_axis(self): - """A boolean that controls whether guess_coord_axis acts on this - coordinate. + """A boolean that controls whether guess_coord_axis acts on this coordinate. Defaults to False, and when set to True it will be skipped by guess_coord_axis. @@ -1729,17 +1711,11 @@ def lazy_bounds(self): return lazy_bounds def core_points(self): - """The points array at the core of this coord, which may be a NumPy array - or a dask array. - - """ + """The points array at the core of this coord, which may be a NumPy array or a dask array.""" return super()._core_values() def core_bounds(self): - """The points array at the core of this coord, which may be a NumPy array - or a dask array. - - """ + """The points array at the core of this coord, which may be a NumPy array or a dask array.""" result = None if self.has_bounds(): result = self._bounds_dm.core_data() @@ -1748,14 +1724,13 @@ def core_bounds(self): return result def has_lazy_points(self): - """Return a boolean indicating whether the coord's points array is a - lazy dask array or not. - - """ + """Return a boolean whether the coord's points array is a lazy dask array or not.""" return super()._has_lazy_values() def has_lazy_bounds(self): - """Return a boolean indicating whether the coord's bounds array is a + """Whether coordinate bounds are lazy. + + Return a boolean indicating whether the coord's bounds array is a lazy dask array or not. """ @@ -1782,8 +1757,7 @@ def cube_dims(self, cube): return cube.coord_dims(self) def convert_units(self, unit): - r"""Change the coordinate's units, converting the values in its points - and bounds arrays. + r"""Change the coordinate's units, converting the values in its points and bounds arrays. For example, if a coordinate's :attr:`~iris.coords.Coord.units` attribute is set to radians then:: @@ -1941,7 +1915,9 @@ def mod360_adjust(compare_axis): return contiguous, diffs def is_contiguous(self, rtol=1e-05, atol=1e-08): - """Return True if, and only if, this Coord is bounded with contiguous + """Whether coordinate has contiguous bounds. + + Return True if, and only if, this Coord is bounded with contiguous bounds to within the specified relative and absolute tolerances. 1D coords are contiguous if the upper bound of a cell aligns, @@ -1971,7 +1947,9 @@ def is_contiguous(self, rtol=1e-05, atol=1e-08): return contiguous def contiguous_bounds(self): - """Returns the N+1 bound values for a contiguous bounded 1D coordinate + """Contiguous bounds of 1D coordinate. + + Return the N+1 bound values for a contiguous bounded 1D coordinate of length N, or the (N+1, M+1) bound values for a contiguous bounded 2D coordinate of shape (N, M). @@ -2065,7 +2043,9 @@ def is_compatible(self, other, ignore=None): @property def bounds_dtype(self): - """The NumPy dtype of the coord's bounds. Will be `None` if the coord + """The NumPy dtype of the coordinates bounds. + + The NumPy dtype of the coord's bounds. Will be `None` if the coord does not have bounds. """ @@ -2087,8 +2067,11 @@ def has_bounds(self): return self._bounds_dm is not None def cell(self, index): - """Return the single :class:`Cell` instance which results from slicing the + """The point/bound cell at the given coordinate index. + + Return the single :class:`Cell` instance which results from slicing the points/bounds with the given index. + """ index = iris.util._build_full_slice_given_keys(index, self.ndim) @@ -2111,8 +2094,7 @@ def cell(self, index): return Cell(point, bound) def collapsed(self, dims_to_collapse=None): - """Returns a copy of this coordinate, which has been collapsed along - the specified dimensions. + """Return a copy of this coordinate, which has been collapsed along the specified dimensions. Replaces the points & bounds with a simple bounded region. """ @@ -2444,8 +2426,7 @@ def nearest_neighbour_index(self, point): return result_index def xml_element(self, doc): - """Create the :class:`xml.dom.minidom.Element` that describes this - :class:`Coord`. + """Create the :class:`xml.dom.minidom.Element` that describes this :class:`Coord`. Parameters ---------- @@ -2503,8 +2484,7 @@ def from_regular( climatological=False, with_bounds=False, ): - """Create a :class:`DimCoord` with regularly spaced points, and - optionally bounds. + """Create a :class:`DimCoord` with regularly spaced points, and optionally bounds. The majority of the arguments are defined as for :class:`Coord`, but those which differ are defined below. @@ -2839,8 +2819,7 @@ def is_monotonic(self): return True def xml_element(self, doc): - """Create the :class:`xml.dom.minidom.Element` that describes this - :class:`DimCoord`. + """Create the :class:`xml.dom.minidom.Element` that describes this :class:`DimCoord`. Parameters ---------- @@ -3016,8 +2995,7 @@ def __add__(self, other): return NotImplemented def xml_element(self, doc): - """Create the :class:`xml.dom.minidom.Element` that describes this - :class:`CellMethod`. + """Create the :class:`xml.dom.minidom.Element` that describes this :class:`CellMethod`. Parameters ---------- diff --git a/lib/iris/cube.py b/lib/iris/cube.py index 691349f170..df0f719aca 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -66,17 +66,13 @@ def __len__(self): return len(self.cubes) def add(self, cube): - """Adds the appropriate (sub)cube to the list of cubes where it - matches the constraint. - - """ + """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: self.cubes.append(sub_cube) def merged(self, unique=False): - """Returns a new :class:`_CubeFilter` by merging the list of - cubes. + """Returns a new :class:`_CubeFilter` by merging the list of cubes. Parameters ---------- @@ -93,10 +89,7 @@ class _CubeFilterCollection: @staticmethod def from_cubes(cubes, constraints=None): - """Creates a new collection from an iterable of cubes, and some - optional constraints. - - """ + """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] collection = _CubeFilterCollection(pairs) @@ -108,26 +101,19 @@ def __init__(self, pairs): self.pairs = pairs def add_cube(self, cube): - """Adds the given :class:`~iris.cube.Cube` to all of the relevant - constraint pairs. - - """ + """Adds the given :class:`~iris.cube.Cube` to all of the relevant constraint pairs.""" for pair in self.pairs: pair.add(cube) def cubes(self): - """Returns all the cubes in this collection concatenated into a - single :class:`CubeList`. - - """ + """Returns all the cubes in this collection concatenated into a single :class:`CubeList`.""" result = CubeList() for pair in self.pairs: result.extend(pair.cubes) return result def merged(self, unique=False): - """Returns a new :class:`_CubeFilterCollection` by merging all the cube - lists of this collection. + """Return a new :class:`_CubeFilterCollection` by merging all the cube lists of this collection. Parameters ---------- @@ -140,10 +126,7 @@ def merged(self, unique=False): class CubeList(list): - """All the functionality of a standard :class:`list` with added "Cube" - context. - - """ + """All the functionality of a standard :class:`list` with added "Cube" context.""" def __init__(self, *args, **kwargs): """Given an iterable of cubes, return a CubeList instance.""" @@ -258,8 +241,7 @@ def xml(self, checksum=False, order=True, byteorder=True): return doc.toprettyxml(indent=" ") def extract(self, constraints): - """Filter each of the cubes which can be filtered by the given - 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 @@ -276,6 +258,8 @@ def extract(self, constraints): def extract_cube(self, constraint): """Extract a single cube from a CubeList, and return it. + + Extract a single cube from a CubeList, and return it. Raise an error if the extract produces no cubes, or more than one. Parameters @@ -296,6 +280,8 @@ def extract_cube(self, constraint): def extract_cubes(self, constraints): """Extract specific cubes from a CubeList, one for each given constraint. + + Extract specific cubes from a CubeList, one for each given constraint. Each constraint must produce exactly one cube, otherwise an error is raised. @@ -351,7 +337,9 @@ def _extract_and_merge(cubes, constraints, strict=False, return_single_cube=Fals return result def extract_overlapping(self, coord_names): - """Returns a :class:`CubeList` of cubes extracted over regions + """Return a :class:`CubeList` of cubes extracted over regions. + + Return a :class:`CubeList` of cubes extracted over regions where the coordinates overlap, for the coordinates in coord_names. @@ -378,8 +366,7 @@ def overlap_fn(cell): return self.extract(iris.Constraint(coord_values=coord_values)) def merge_cube(self): - """Return the merged contents of the :class:`CubeList` as a single - :class:`Cube`. + """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 @@ -414,8 +401,7 @@ def merge_cube(self): return merged_cube def merge(self, unique=True): - """Returns the :class:`CubeList` resulting from merging this - :class:`CubeList`. + """Returns the :class:`CubeList` resulting from merging this :class:`CubeList`. Parameters ---------- @@ -517,8 +503,7 @@ def concatenate_cube( check_ancils=True, check_derived_coords=True, ): - """Return the concatenated contents of the :class:`CubeList` as a single - :class:`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 @@ -754,7 +739,9 @@ def _is_single_item(testee): class CubeAttrsDict(MutableMapping): - r"""A :class:`dict`\\-like object for :attr:`iris.cube.Cube.attributes`, + r"""A :class:`dict`\\-like object for :attr:`iris.cube.Cube.attributes`. + + A :class:`dict`\\-like object for :attr:`iris.cube.Cube.attributes`, providing unified user access to combined cube "local" and "global" attributes dictionaries, with the access behaviour of an ordinary (single) dictionary. @@ -1128,7 +1115,9 @@ class Cube(CFVariableMixin): @classmethod def _sort_xml_attrs(cls, doc): - """Takes an xml document and returns a copy with all element + """Return a copy with all element attributes sorted in alphabetical order. + + Take 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 @@ -1330,7 +1319,9 @@ def __init__( @property def _names(self): - """A tuple containing the value of each name participating in the identity + """Tuple containing the value of each name participating in the identity of a :class:`iris.cube.Cube`. + + A tuple containing the value of each name participating in the identity of a :class:`iris.cube.Cube`. This includes the standard name, long name, NetCDF variable name, and the STASH from the attributes dictionary. @@ -1347,14 +1338,18 @@ def attributes(self) -> CubeAttrsDict: @attributes.setter def attributes(self, attributes: Optional[Mapping]): - """An override to CfVariableMixin.attributes.setter, which ensures that Cube + """An override to CfVariableMixin.attributes.setter. + + An override to CfVariableMixin.attributes.setter, which ensures that Cube attributes are stored in a way which distinguishes global + local ones. """ self._metadata_manager.attributes = CubeAttrsDict(attributes or {}) def _dimensional_metadata(self, name_or_dimensional_metadata): - """Return a single _DimensionalMetadata instance that matches the given + """Return a single _DimensionalMetadata instance that matches. + + Return a single _DimensionalMetadata instance that matches the given name_or_dimensional_metadata. If one is not found, raise an error. """ @@ -1850,8 +1845,7 @@ def replace_coord(self, new_coord): factory.update(old_coord, new_coord) def coord_dims(self, coord): - """Returns a tuple of the data dimensions relevant to the given - coordinate. + """Return 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 @@ -1911,8 +1905,7 @@ def matcher(factory): return match def cell_measure_dims(self, cell_measure): - """Returns a tuple of the data dimensions relevant to the given - CellMeasure. + """Return a tuple of the data dimensions relevant to the given CellMeasure. Parameters ---------- @@ -1934,8 +1927,7 @@ def cell_measure_dims(self, cell_measure): return matches[0] def ancillary_variable_dims(self, ancillary_variable): - """Returns a tuple of the data dimensions relevant to the given - AncillaryVariable. + """Returns a tuple of the data dimensions relevant to the given AncillaryVariable. Parameters ---------- @@ -1961,7 +1953,9 @@ def ancillary_variable_dims(self, ancillary_variable): return matches[0] def aux_factory(self, name=None, standard_name=None, long_name=None, var_name=None): - """Returns the single coordinate factory that matches the criteria, + """Return the single coordinate factory that matches the criteria. + + Return the single coordinate factory that matches the criteria, or raises an error if not found. Parameters @@ -2038,8 +2032,7 @@ def coords( dim_coords=None, mesh_coords=None, ): - r"""Return a list of coordinates from the :class:`Cube` that match the - provided criteria. + r"""Return a list of coordinates from the :class:`Cube` that match the provided criteria. Parameters ---------- @@ -2195,8 +2188,7 @@ def coord( dim_coords=None, mesh_coords=None, ): - r"""Return a single coordinate from the :class:`Cube` that matches the - provided criteria. + r"""Return a single coordinate from the :class:`Cube` that matches the provided criteria. Parameters ---------- @@ -2363,7 +2355,9 @@ def _any_meshcoord(self): @property def mesh(self): - r"""Return the unstructured :class:`~iris.experimental.ugrid.Mesh` + r"""Return the unstructured :class:`~iris.experimental.ugrid.Mesh` associated with the cube. + + Return the unstructured :class:`~iris.experimental.ugrid.Mesh` associated with the cube, if the cube has any :class:`~iris.experimental.ugrid.MeshCoord`\\ s, or ``None`` if it has none. @@ -2383,7 +2377,9 @@ def mesh(self): @property def location(self): - r"""Return the mesh "location" of the cube data, if the cube has any + r"""Return the mesh "location" of the cube data. + + 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. @@ -2401,7 +2397,9 @@ def location(self): return result def mesh_dim(self): - r"""Return the cube dimension of the mesh, if the cube has any + r"""Return the cube dimension of the mesh. + + Return the cube dimension of the mesh, if the cube has any :class:`~iris.experimental.ugrid.MeshCoord`\\ s, or ``None`` if it has none. @@ -2458,8 +2456,7 @@ def cell_measures(self, name_or_cell_measure=None): return cell_measures def cell_measure(self, name_or_cell_measure=None): - """Return a single cell_measure given the same arguments as - :meth:`Cube.cell_measures`. + """Return a single cell_measure given the same arguments as :meth:`Cube.cell_measures`. Notes ----- @@ -2507,8 +2504,7 @@ def cell_measure(self, name_or_cell_measure=None): return cell_measures[0] def ancillary_variables(self, name_or_ancillary_variable=None): - """Return a list of ancillary variable in this cube fitting the given - criteria. + """Return a list of ancillary variable in this cube fitting the given criteria. Parameters ---------- @@ -2547,8 +2543,7 @@ def ancillary_variables(self, name_or_ancillary_variable=None): return ancillary_variables def ancillary_variable(self, name_or_ancillary_variable=None): - """Return a single ancillary_variable given the same arguments as - :meth:`Cube.ancillary_variables`. + """Return a single ancillary_variable given the same arguments as :meth:`Cube.ancillary_variables`. Notes ----- @@ -2600,7 +2595,9 @@ def ancillary_variable(self, name_or_ancillary_variable=None): @property def cell_methods(self): - """Tuple of :class:`iris.coords.CellMethod` representing the processing + """Tuple of :class:`iris.coords.CellMethod`. + + Tuple of :class:`iris.coords.CellMethod` representing the processing done on the phenomenon. """ @@ -2626,7 +2623,9 @@ def cell_methods(self, cell_methods: Iterable): self._metadata_manager.cell_methods = cell_methods def core_data(self): - """Retrieve the data array of this :class:`~iris.cube.Cube` in its + """Retrieve the data array of this :class:`~iris.cube.Cube`. + + 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 @@ -2644,10 +2643,7 @@ def shape(self): @property def dtype(self): - """The data type of the values in the data array of this - :class:`~iris.cube.Cube`. - - """ + """The data type of the values in the data array of this :class:`~iris.cube.Cube`.""" return self._data_manager.dtype @property @@ -2656,7 +2652,9 @@ def ndim(self): return self._data_manager.ndim def lazy_data(self): - """Return a "lazy array" representing the Cube data. A lazy array + """Return a "lazy array" representing the Cube data. + + 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. @@ -2679,8 +2677,7 @@ def lazy_data(self): @property def data(self): - """The :class:`numpy.ndarray` representing the multi-dimensional data of - the cube. + """The :class:`numpy.ndarray` representing the multi-dimensional data of the cube. Notes ----- @@ -2753,10 +2750,7 @@ def dim_coords(self): @property def aux_coords(self): - """Return a tuple of all the auxiliary coordinates, ordered by - dimension(s). - - """ + """Return a tuple of all the auxiliary coordinates, ordered by dimension(s).""" return tuple( ( coord @@ -2769,10 +2763,7 @@ def aux_coords(self): @property def derived_coords(self): - """Return a tuple of all the coordinates generated by the coordinate - factories. - - """ + """Return a tuple of all the coordinates generated by the coordinate factories.""" return tuple( factory.make_coord(self.coord_dims) for factory in sorted( @@ -2786,7 +2777,9 @@ def aux_factories(self): 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 + """String summary of the Cube. + + String summary of the Cube with name+units, a list of dim coord names versus length and, optionally, a summary of all other components. Parameters @@ -2823,7 +2816,9 @@ def _repr_html_(self): __iter__ = None def __getitem__(self, keys): - """Cube indexing (through use of square bracket notation) has been + """Cube indexing has been implemented at the data level. + + Cube indexing (through use of square bracket notation) has been implemented at the data level. That is, the indices provided to this 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 @@ -2930,7 +2925,9 @@ def new_ancillary_variable_dims(av_): return cube def subset(self, coord): - """Get a subset of the cube by providing the desired resultant + """Get a subset of the cube by providing the desired resultant coordinate. + + 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. @@ -2985,8 +2982,7 @@ def extract(self, constraint): return constraint.extract(self) def intersection(self, *args, **kwargs): - """Return the intersection of the cube with specified coordinate - ranges. + """Return the intersection of the cube with specified coordinate ranges. Coordinate ranges can be specified as: @@ -3440,7 +3436,9 @@ def slices_over(self, ref_to_slice): return self.slices(opposite_dims, ordered=False) def slices(self, ref_to_slice, ordered=True): - """Return an iterator of all subcubes given the coordinates or dimension + """Return an iterator of all subcubes given the coordinates or dimension indices. + + Return an iterator of all subcubes given the coordinates or dimension indices desired to be present in each subcube. Parameters @@ -3930,8 +3928,7 @@ def __neg__(self): # END OPERATOR OVERLOADS def collapsed(self, coords, aggregator, **kwargs): - """Collapse one or more dimensions over the cube given the coordinate/s - and an aggregation. + """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`. @@ -4455,7 +4452,9 @@ def aggregated_by(self, coords, aggregator, climatological=False, **kwargs): return aggregateby_cube def rolling_window(self, coord, aggregator, window, **kwargs): - """Perform rolling window aggregation on a cube given a coordinate, an + """Perform rolling window aggregation on a cube. + + Perform rolling window aggregation on a cube given a coordinate, an aggregation method and a window size. Parameters @@ -4660,7 +4659,9 @@ def rolling_window(self, coord, aggregator, window, **kwargs): return result def interpolate(self, sample_points, scheme, collapse_scalar=True): - """Interpolate from this :class:`~iris.cube.Cube` to the given + """Interpolate from this :class:`~iris.cube.Cube` to the given sample points. + + Interpolate from this :class:`~iris.cube.Cube` to the given sample points using the given interpolation scheme. Parameters @@ -4745,7 +4746,9 @@ def interpolate(self, sample_points, scheme, collapse_scalar=True): return interp(points, collapse_scalar=collapse_scalar) def regrid(self, grid, scheme): - r"""Regrid this :class:`~iris.cube.Cube` on to the given target `grid` + r"""Regrid this :class:`~iris.cube.Cube` on to the given target `grid`. + + Regrid this :class:`~iris.cube.Cube` on to the given target `grid` using the given regridding `scheme`. Parameters @@ -4863,7 +4866,9 @@ def keys(self): def sorted_axes(axes): - """Returns the axis names sorted alphabetically, with the exception that + """Returns the axis names sorted alphabetically. + + Returns the axis names sorted alphabetically, with the exception that 't', 'z', 'y', and, 'x' are sorted to the end. """ diff --git a/lib/iris/exceptions.py b/lib/iris/exceptions.py index c869c1c6c8..854785ef56 100644 --- a/lib/iris/exceptions.py +++ b/lib/iris/exceptions.py @@ -67,10 +67,7 @@ class InvalidCubeError(IrisError): class ConstraintMismatchError(IrisError): - """Raised when a constraint operation has failed to find the correct number - of results. - - """ + """Raised when a constraint operation has failed to find the correct number of results.""" pass @@ -98,18 +95,17 @@ class IgnoreCubeException(IrisError): class ConcatenateError(IrisError): - """Raised when concatenate is expected to produce a single cube, but fails to - do so. - - """ + """Raised when concatenate is expected to produce a single cube, but fails to do so.""" def __init__(self, differences): - """Creates a ConcatenateError with a list of textual descriptions of - the differences which prevented a concatenate. + """Create a ConcatenateError with a list of textual descriptions of differences. - Args: + Create a ConcatenateError with a list of textual descriptions of + the differences which prevented a concatenate. - * differences: + Parameters + ---------- + differences : list of str The list of strings which describe the differences. """ @@ -122,18 +118,17 @@ def __str__(self): class MergeError(IrisError): - """Raised when merge is expected to produce a single cube, but fails to - do so. - - """ + """Raised when merge is expected to produce a single cube, but fails to do so.""" def __init__(self, differences): - """Creates a MergeError with a list of textual descriptions of - the differences which prevented a merge. + """Create a MergeError with a list of textual descriptions of the differences. - Args: + Creates a MergeError with a list of textual descriptions of + the differences which prevented a merge. - * differences: + Parameters + ---------- + differences : list of str The list of strings which describe the differences. """ diff --git a/lib/iris/experimental/raster.py b/lib/iris/experimental/raster.py index 16421947f6..8d37e39df3 100644 --- a/lib/iris/experimental/raster.py +++ b/lib/iris/experimental/raster.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Experimental module for importing/exporting raster data from Iris cubes using -the GDAL library. +"""Experimental module for importing/exporting raster data from Iris cubes using the GDAL library. See also: `GDAL - Geospatial Data Abstraction Library `_. @@ -42,20 +41,31 @@ def _gdal_write_array(x_min, x_step, y_max, y_step, coord_system, data, fname, ftype): """Use GDAL WriteArray to export data as a 32-bit raster image. + Requires the array data to be of the form: North-at-top and West-on-left. - Args: - * x_min: Minimum X coordinate bounds value. - * x_step: Change in X coordinate per cell. - * y_max: Maximum Y coordinate bounds value. - * y_step: Change in Y coordinate per cell. - * coord_system (iris.coord_systems.CoordSystem): - Coordinate system for X and Y. - * data (numpy.ndarray): 2d array of values to export - * fname (string): Output file name. - * ftype (string): Export file type. - + Parameters + ---------- + x_min : + Minimum X coordinate bounds value. + x_step : + Change in X coordinate per cell. + y_max : + Maximum Y coordinate bounds value. + y_step : + Change in Y coordinate per cell. + coord_system : iris.coord_systems.CoordSystem + Coordinate system for X and Y. + data : numpy.ndarray + 2d array of values to export + fname : str + Output file name. + ftype : str + Export file type. + + Notes + ----- .. note:: Projection information is currently not written to the output. @@ -107,11 +117,16 @@ def export_geotiff(cube, fname): Developers to discuss how to retain it (which could include reversing the deprecation). - Args: - * cube (Cube): The 2D regularly gridded cube slice to be exported. - The cube must have regular, contiguous bounds. - * fname (string): Output file name. + Parameters + ---------- + cube : Cube + The 2D regularly gridded cube slice to be exported. + The cube must have regular, contiguous bounds. + fname : str + Output file name. + Notes + ----- .. note:: For more details on GeoTiff specification and PixelIsArea, see: diff --git a/lib/iris/experimental/regrid.py b/lib/iris/experimental/regrid.py index b17c0cfeeb..dac191c64d 100644 --- a/lib/iris/experimental/regrid.py +++ b/lib/iris/experimental/regrid.py @@ -51,7 +51,9 @@ def regrid_area_weighted_rectilinear_src_and_grid(src_cube, grid_cube, mdtol=0): - """Return a new cube with data values calculated using the area weighted + """Regrid using the area weighted mean of data values. + + Return a new cube with data values calculated using the area weighted mean of data values from src_grid regridded onto the horizontal grid of grid_cube. @@ -123,7 +125,9 @@ def regrid_area_weighted_rectilinear_src_and_grid(src_cube, grid_cube, mdtol=0): def regrid_weighted_curvilinear_to_rectilinear(src_cube, weights, grid_cube): - r"""Return a new cube with the data values calculated using the weighted + r"""Regrid using the weighted mean and the weights. + + Return a new cube with the data values calculated using the weighted mean of data values from :data:`src_cube` and the weights from :data:`weights` regridded onto the horizontal grid of :data:`grid_cube`. @@ -215,8 +219,7 @@ class PointInCell: """ def __init__(self, weights=None): - """Point-in-cell regridding scheme suitable for regridding over one - or more orthogonal coordinates. + """Point-in-cell regridding scheme for regridding over one or more orthogonal coordinates. .. warning:: @@ -239,8 +242,7 @@ class _ProjectedUnstructuredRegridder: """Regridding that uses scipy.interpolate.griddata.""" def __init__(self, src_cube, tgt_grid_cube, method, projection=None): - """Create a regridder for conversions between the source - and target grids. + """Create a regridder for conversions between the source and target grids. Parameters ---------- @@ -393,8 +395,7 @@ def _create_cube( grid_y_coord, regrid_callback, ): - """Return a new Cube for the result of regridding the source Cube onto - the new grid. + """Return a new Cube for the result of regridding the source Cube onto the new grid. All the metadata and coordinates of the result Cube are copied from the source Cube, with two exceptions: @@ -520,7 +521,9 @@ def regrid_reference_surface( return result def __call__(self, src_cube): - """Regrid this :class:`~iris.cube.Cube` on to the target grid of + """Regrid to the target grid. + + Regrid this :class:`~iris.cube.Cube` on to the target grid of this :class:`UnstructuredProjectedRegridder`. The given cube must be defined with the same grid as the source @@ -614,7 +617,9 @@ class ProjectedUnstructuredLinear: """ def __init__(self, projection=None): - """Linear regridding scheme that uses scipy.interpolate.griddata on + """Linear regridding scheme. + + Linear regridding scheme that uses scipy.interpolate.griddata on projected unstructured data. .. note:: @@ -644,7 +649,9 @@ def __init__(self, projection=None): warn_deprecated(wmsg) def regridder(self, src_cube, target_grid): - """Creates a linear regridder to perform regridding, using + """Create a linear regridder to perform regridding. + + Creates a linear regridder to perform regridding, using scipy.interpolate.griddata from unstructured source points to the target grid. The regridding calculation is performed in the given projection. @@ -698,8 +705,7 @@ class ProjectedUnstructuredNearest: """ def __init__(self, projection=None): - """Nearest regridding scheme that uses scipy.interpolate.griddata on - projected unstructured data. + """Nearest regridding scheme that uses scipy.interpolate.griddata on projected unstructured data. .. note:: @@ -730,7 +736,9 @@ def __init__(self, projection=None): warn_deprecated(wmsg) def regridder(self, src_cube, target_grid): - """Creates a nearest-neighbour regridder to perform regridding, using + """Creates a nearest-neighbour regridder to perform regridding. + + Creates a nearest-neighbour regridder to perform regridding, using scipy.interpolate.griddata from unstructured source points to the target grid. The regridding calculation is performed in the given projection. diff --git a/lib/iris/experimental/representation.py b/lib/iris/experimental/representation.py index 6b25023fa2..85923a12d8 100644 --- a/lib/iris/experimental/representation.py +++ b/lib/iris/experimental/representation.py @@ -116,7 +116,9 @@ def __init__(self, cube): self.units = escape(str(self.cube.units)) def _get_dim_names(self): - """Get dimension-describing coordinate names, or '--' if no coordinate] + """Get dimension-describing coordinate names. + + Get dimension-describing coordinate names, or '--' if no coordinate] describes the dimension. Note: borrows from `cube.summary`. @@ -146,7 +148,9 @@ def _get_lines(self): return self.cube_str.split("\n") def _get_bits(self, bits): - """Parse the body content (`bits`) of the cube string in preparation for + """Parse the body content (`bits`) of the cube string. + + Parse the body content (`bits`) of the cube string in preparation for being converted into table rows. """ @@ -175,7 +179,9 @@ def _get_bits(self, bits): self.sections_data[str_heading_name] = content def _make_header(self): - """Make the table header. This is similar to the summary of the cube, + """Make the table header. + + Make the table header. This is similar to the summary of the cube, but does not include dim shapes. These are included on the next table row down, and produced with `make_shapes_row`. @@ -199,16 +205,19 @@ def _make_shapes_row(self): return "\n".join(cell for cell in cells) def _make_row(self, title, body=None, col_span=0): - """Produce one row for the table body; i.e. + """Produce one row for the table body. + + For example:: + Coord namex-.... - `body` contains the content for each cell not in the left-most (title) - column. - If None, indicates this row is a title row (see below). - `title` contains the row heading. If `body` is None, indicates - that the row contains a sub-heading; - e.g. 'Dimension coordinates:'. - `col_span` indicates how many columns the string should span. + * `body` contains the content for each cell not in the left-most (title) + column. + If None, indicates this row is a title row (see below). + * `title` contains the row heading. If `body` is None, indicates + that the row contains a sub-heading; + e.g. 'Dimension coordinates:'. + * `col_span` indicates how many columns the string should span. """ row = [''] diff --git a/lib/iris/experimental/stratify.py b/lib/iris/experimental/stratify.py index d79102cc08..a6ac06a8d2 100644 --- a/lib/iris/experimental/stratify.py +++ b/lib/iris/experimental/stratify.py @@ -2,10 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Routines for putting data on new strata (aka. isosurfaces), often in the -Z direction. - -""" +"""Routines for putting data on new strata (aka. isosurfaces), often in the Z direction.""" from functools import partial @@ -52,7 +49,9 @@ def _copy_coords_without_z_dim(src, tgt, z_dim): def relevel(cube, src_levels, tgt_levels, axis=None, interpolator=None): - """Interpolate the cube onto the specified target levels, given the + """Perform vertical interpolation. + + Interpolate the cube onto the specified target levels, given the source levels of the cube. For example, suppose we have two datasets `P(i,j,k)` and `H(i,j,k)` @@ -64,8 +63,8 @@ def relevel(cube, src_levels, tgt_levels, axis=None, interpolator=None): that are generally monotonic in the direction of interpolation, such as height/pressure or salinity/depth. - Args: - + Parameters + ---------- cube : :class:`~iris.cube.Cube` The phenomenon data to be re-levelled. diff --git a/lib/iris/experimental/ugrid/__init__.py b/lib/iris/experimental/ugrid/__init__.py index 7cae55a1bd..ccdf05a387 100644 --- a/lib/iris/experimental/ugrid/__init__.py +++ b/lib/iris/experimental/ugrid/__init__.py @@ -3,8 +3,9 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Infra-structure for unstructured mesh support, based on -CF UGRID Conventions (v1.0), https://ugrid-conventions.github.io/ugrid-conventions/. +"""Infra-structure for unstructured mesh support. + +Based on CF UGRID Conventions (v1.0), https://ugrid-conventions.github.io/ugrid-conventions/. .. note:: diff --git a/lib/iris/experimental/ugrid/cf.py b/lib/iris/experimental/ugrid/cf.py index bd4c076ba5..d00fd6ef24 100644 --- a/lib/iris/experimental/ugrid/cf.py +++ b/lib/iris/experimental/ugrid/cf.py @@ -16,7 +16,9 @@ class CFUGridConnectivityVariable(cf.CFVariable): - """A CF_UGRID connectivity variable points to an index variable identifying + """A CF_UGRID connectivity variable. + + A CF_UGRID connectivity variable points to an index variable identifying for every element (edge/face/volume) the indices of its corner nodes. The connectivity array will thus be a matrix of size n-elements x n-corners. For the indexing one may use either 0- or 1-based indexing; the convention @@ -86,7 +88,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): class CFUGridAuxiliaryCoordinateVariable(cf.CFVariable): - """A CF-UGRID auxiliary coordinate variable is a CF-netCDF auxiliary + """A CF-UGRID auxiliary coordinate variable. + + A CF-UGRID auxiliary coordinate variable is a CF-netCDF auxiliary coordinate variable representing the element (node/edge/face/volume) locations (latitude, longitude or other spatial coordinates, and optional elevation or other coordinates). These auxiliary coordinate variables will @@ -163,7 +167,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): class CFUGridMeshVariable(cf.CFVariable): - """A CF-UGRID mesh variable is a dummy variable for storing topology + """A CF-UGRID mesh variable is a dummy variable for storing topology information as attributes. + + A CF-UGRID mesh variable is a dummy variable for storing topology information as attributes. The mesh variable has the ``cf_role`` 'mesh_topology'. @@ -230,7 +236,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): class CFUGridGroup(cf.CFGroup): - """Represents a collection of 'NetCDF Climate and Forecast (CF) Metadata + """Represents a collection of CF Metadata Conventions variables and netCDF global attributes. + + Represents a collection of 'NetCDF Climate and Forecast (CF) Metadata Conventions' variables and netCDF global attributes. Specialisation of :class:`~iris.fileformats.cf.CFGroup` that includes extra @@ -255,10 +263,7 @@ def meshes(self): @property def non_data_variable_names(self): - """:class:`set` of the names of the CF-netCDF/CF-UGRID variables that are - not the data pay-load. - - """ + """:class:`set` of names of the CF-netCDF/CF-UGRID variables that are not the data pay-load.""" extra_variables = (self.connectivities, self.ugrid_coords, self.meshes) extra_result = set() for variable in extra_variables: diff --git a/lib/iris/experimental/ugrid/load.py b/lib/iris/experimental/ugrid/load.py index 07cc20a65a..0ed1757353 100644 --- a/lib/iris/experimental/ugrid/load.py +++ b/lib/iris/experimental/ugrid/load.py @@ -3,7 +3,9 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -r"""Extensions to Iris' NetCDF loading to allow the construction of +r"""Allow the construction of :class:`~iris.experimental.ugrid.mesh.Mesh`\\ es. + +Extensions to Iris' NetCDF loading to allow the construction of :class:`~iris.experimental.ugrid.mesh.Mesh`\\ es from UGRID data in the file. Eventual destination: :mod:`iris.fileformats.netcdf`. @@ -48,7 +50,9 @@ class _WarnComboCfDefaultingIgnoring(_WarnComboCfDefaulting, IrisIgnoringWarning class ParseUGridOnLoad(threading.local): def __init__(self): - """A flag for dictating whether to use the experimental UGRID-aware + """Thead-safe state to enable UGRID-aware NetCDF loading. + + A flag for dictating whether to use the experimental UGRID-aware version of Iris NetCDF loading. Object is thread-safe. Use via the run-time switch @@ -230,7 +234,9 @@ def load_meshes(uris, var_name=None): def _build_aux_coord(coord_var, file_path): - """Construct a :class:`~iris.coords.AuxCoord` from a given + """Construct a :class:`~iris.coords.AuxCoord`. + + Construct a :class:`~iris.coords.AuxCoord` from a given :class:`~iris.experimental.ugrid.cf.CFUGridAuxiliaryCoordinateVariable`, and guess its mesh axis. @@ -283,7 +289,9 @@ def _build_aux_coord(coord_var, file_path): def _build_connectivity(connectivity_var, file_path, element_dims): - """Construct a :class:`~iris.experimental.ugrid.mesh.Connectivity` from a + """Construct a :class:`~iris.experimental.ugrid.mesh.Connectivity`. + + Construct a :class:`~iris.experimental.ugrid.mesh.Connectivity` from a given :class:`~iris.experimental.ugrid.cf.CFUGridConnectivityVariable`, and identify the name of its first dimension. @@ -325,10 +333,12 @@ def _build_connectivity(connectivity_var, file_path, element_dims): def _build_mesh(cf, mesh_var, file_path): - """Construct a :class:`~iris.experimental.ugrid.mesh.Mesh` from a given + """Construct a :class:`~iris.experimental.ugrid.mesh.Mesh`. + + Construct a :class:`~iris.experimental.ugrid.mesh.Mesh` from a given :class:`~iris.experimental.ugrid.cf.CFUGridMeshVariable`. - todo: integrate with standard loading API post-pyke. + TODO: integrate with standard loading API post-pyke. """ # TODO: integrate with standard saving API when no longer 'experimental'. @@ -458,11 +468,13 @@ def _build_mesh(cf, mesh_var, file_path): def _build_mesh_coords(mesh, cf_var): - """Construct a tuple of :class:`~iris.experimental.ugrid.mesh.MeshCoord` using + """Construct a tuple of :class:`~iris.experimental.ugrid.mesh.MeshCoord`. + + Construct a tuple of :class:`~iris.experimental.ugrid.mesh.MeshCoord` using from a given :class:`~iris.experimental.ugrid.mesh.Mesh` and :class:`~iris.fileformats.cf.CFVariable`. - todo: integrate with standard loading API post-pyke. + TODO: integrate with standard loading API post-pyke. """ # TODO: integrate with standard saving API when no longer 'experimental'. diff --git a/lib/iris/experimental/ugrid/mesh.py b/lib/iris/experimental/ugrid/mesh.py index 79e67593d2..b12178da83 100644 --- a/lib/iris/experimental/ugrid/mesh.py +++ b/lib/iris/experimental/ugrid/mesh.py @@ -3,7 +3,7 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Iris' data model representation of CF UGrid's Mesh and its constituent parts. +"""Iris data model representation of CF UGrid's Mesh and its constituent parts. Eventual destination: dedicated module in :mod:`iris` root. @@ -84,7 +84,9 @@ class Connectivity(_DimensionalMetadata): - """A CF-UGRID topology connectivity, describing the topological relationship + """CF-UGRID topology. + + A CF-UGRID topology connectivity, describing the topological relationship between two types of mesh element. One or more connectivities make up a CF-UGRID topology - a constituent of a CF-UGRID mesh. @@ -215,8 +217,8 @@ def _values(self, values): @property def cf_role(self): - """The category of topological relationship that this connectivity - describes. + """The category of topological relationship that this connectivity describes. + **Read-only** - validity of :attr:`indices` is dependent on :attr:`cf_role`. A new :class:`Connectivity` must therefore be defined if a different :attr:`cf_role` is needed. @@ -226,7 +228,9 @@ def cf_role(self): @property def location(self): - """Derived from the connectivity's :attr:`cf_role` - the first part, e.g. + """Derived from the connectivity's :attr:`cf_role`. + + Derived from the connectivity's :attr:`cf_role` - the first part, e.g. ``face`` in ``face_node_connectivity``. Refers to the elements that vary along the :attr:`location_axis` of the connectivity's :attr:`indices` array. @@ -236,7 +240,9 @@ def location(self): @property def connected(self): - """Derived from the connectivity's :attr:`cf_role` - the second part, e.g. + """Derived from the connectivity's :attr:`cf_role`. + + Derived from the connectivity's :attr:`cf_role` - the second part, e.g. ``node`` in ``face_node_connectivity``. Refers to the elements indexed by the values in the connectivity's :attr:`indices` array. @@ -245,8 +251,8 @@ def connected(self): @property def start_index(self): - """The base value of the connectivity's :attr:`indices` array; either - ``0`` or ``1``. + """The base value of the connectivity's :attr:`indices` array; either ``0`` or ``1``. + **Read-only** - validity of :attr:`indices` is dependent on :attr:`start_index`. A new :class:`Connectivity` must therefore be defined if a different :attr:`start_index` is needed. @@ -256,7 +262,9 @@ def start_index(self): @property def location_axis(self): - """The axis of the connectivity's :attr:`indices` array that varies + """The axis of the connectivity's :attr:`indices` array. + + The axis of the connectivity's :attr:`indices` array that varies over the connectivity's :attr:`location` elements. Either ``0`` or ``1``. **Read-only** - validity of :attr:`indices` is dependent on :attr:`location_axis`. Use :meth:`transpose` to create a new, transposed @@ -267,7 +275,9 @@ def location_axis(self): @property def connected_axis(self): - """Derived as the alternate value of :attr:`location_axis` - each must + """Derived as the alternate value of :attr:`location_axis`. + + Derived as the alternate value of :attr:`location_axis` - each must equal either ``0`` or ``1``. The axis of the connectivity's :attr:`indices` array that varies over the :attr:`connected` elements associated with each :attr:`location` element. @@ -277,11 +287,14 @@ def connected_axis(self): @property def indices(self): - """The index values describing the topological relationship of the + """The index values describing the topological relationship of the connectivity. + + The index values describing the topological relationship of the connectivity, as a NumPy array. Masked points indicate a :attr:`location` element with fewer :attr:`connected` elements than other :attr:`location` elements described in this array - unused index 'slots' are masked. + **Read-only** - index values are only meaningful when combined with an appropriate :attr:`cf_role`, :attr:`start_index` and :attr:`location_axis`. A new :class:`Connectivity` must therefore be @@ -392,7 +405,9 @@ def indices_error(message): ) def validate_indices(self): - """Perform a thorough validity check of this connectivity's + """Perform a thorough validity check of this connectivity's :attr:`indices`. + + Perform a thorough validity check of this connectivity's :attr:`indices`. Includes checking the number of :attr:`connected` elements associated with each :attr:`location` element (specified using masks on the :attr:`indices` array) against the :attr:`cf_role`. @@ -436,7 +451,9 @@ def __eq__(self, other): return eq def transpose(self): - """Create a new :class:`Connectivity`, identical to this one but with the + """Transpose :class:`Connectivity`. + + Create a new :class:`Connectivity`, identical to this one but with the :attr:`indices` array transposed and the :attr:`location_axis` value flipped. Returns @@ -477,7 +494,9 @@ def lazy_indices(self): return super()._lazy_values() def core_indices(self): - """The indices array at the core of this connectivity, which may be a + """The indices array at the core of this connectivity. + + The indices array at the core of this connectivity, which may be a NumPy array or a Dask array. Returns @@ -488,8 +507,7 @@ def core_indices(self): return super()._core_values() def has_lazy_indices(self): - """Return a boolean indicating whether the connectivity's :attr:`indices` - array is a lazy Dask array or not. + """Check if the connectivity's :attr:`indices` array is a lazy Dask array or not. Returns ------- @@ -499,7 +517,9 @@ def has_lazy_indices(self): return super()._has_lazy_values() def lazy_location_lengths(self): - """Return a lazy array representing the number of :attr:`connected` + """Return a lazy array representing the number of :attr:`connected` elements. + + Return a lazy array representing the number of :attr:`connected` elements associated with each of the connectivity's :attr:`location` elements, accounting for masks if present. @@ -524,7 +544,9 @@ def lazy_location_lengths(self): return max_location_size - location_mask_counts def location_lengths(self): - """Return a NumPy array representing the number of :attr:`connected` + """Return a NumPy array representing the number of :attr:`connected` elements. + + Return a NumPy array representing the number of :attr:`connected` elements associated with each of the connectivity's :attr:`location` elements, accounting for masks if present. @@ -554,7 +576,9 @@ def xml_element(self, doc): class Mesh(CFVariableMixin): - """A container representing the UGRID ``cf_role`` ``mesh_topology``, supporting + """A container representing the UGRID ``cf_role`` ``mesh_topology``. + + A container representing the UGRID ``cf_role`` ``mesh_topology``, supporting 1D network, 2D triangular, and 2D flexible mesh topologies. .. note:: @@ -669,8 +693,7 @@ def normalise(element, axis): @classmethod def from_coords(cls, *coords): - r"""Construct a :class:`Mesh` by derivation from one or more - :class:`~iris.coords.Coord`\\ s. + r"""Construct a :class:`Mesh` by derivation from one or more :class:`~iris.coords.Coord`\\ s. The :attr:`~Mesh.topology_dimension`, :class:`~iris.coords.Coord` membership and :class:`Connectivity` membership are all determined @@ -1069,10 +1092,7 @@ def _set_dimension_names(self, node, edge, face, reset=False): @property def all_connectivities(self): - """All the :class:`~iris.experimental.ugrid.mesh.Connectivity` instances - of the :class:`Mesh`. - - """ + """All the :class:`~iris.experimental.ugrid.mesh.Connectivity` instances of the :class:`Mesh`.""" return self._connectivity_manager.all_members @property @@ -1082,7 +1102,9 @@ def all_coords(self): @property def boundary_node_connectivity(self): - """The *optional* UGRID ``boundary_node_connectivity`` + """The *optional* UGRID ``boundary_node_connectivity`` :class:`~iris.experimental.ugrid.mesh.Connectivity`. + + The *optional* UGRID ``boundary_node_connectivity`` :class:`~iris.experimental.ugrid.mesh.Connectivity` of the :class:`Mesh`. @@ -1091,18 +1113,12 @@ def boundary_node_connectivity(self): @property def edge_coords(self): - """The *optional* UGRID ``edge`` :class:`~iris.coords.AuxCoord` coordinates - of the :class:`Mesh`. - - """ + """The *optional* UGRID ``edge`` :class:`~iris.coords.AuxCoord` coordinates of the :class:`Mesh`.""" return self._coord_manager.edge_coords @property def edge_dimension(self): - """The *optionally required* UGRID NetCDF variable name for the ``edge`` - dimension. - - """ + """The *optionally required* UGRID NetCDF variable name for the ``edge`` dimension.""" return self._metadata_manager.edge_dimension @edge_dimension.setter @@ -1115,7 +1131,9 @@ def edge_dimension(self, name): @property def edge_face_connectivity(self): - """The *optional* UGRID ``edge_face_connectivity`` + """The *optional* UGRID ``edge_face_connectivity`` :class:`~iris.experimental.ugrid.mesh.Connectivity`. + + The *optional* UGRID ``edge_face_connectivity`` :class:`~iris.experimental.ugrid.mesh.Connectivity` of the :class:`Mesh`. @@ -1124,7 +1142,9 @@ def edge_face_connectivity(self): @property def edge_node_connectivity(self): - """The UGRID ``edge_node_connectivity`` + """The UGRID ``edge_node_connectivity`` :class:`~iris.experimental.ugrid.mesh.Connectivity`. + + The UGRID ``edge_node_connectivity`` :class:`~iris.experimental.ugrid.mesh.Connectivity` of the :class:`Mesh`, which is **required** for :attr:`Mesh.topology_dimension` of ``1``, and *optionally required* for @@ -1135,18 +1155,12 @@ def edge_node_connectivity(self): @property def face_coords(self): - """The *optional* UGRID ``face`` :class:`~iris.coords.AuxCoord` coordinates - of the :class:`Mesh`. - - """ + """The *optional* UGRID ``face`` :class:`~iris.coords.AuxCoord` coordinates of the :class:`Mesh`.""" return self._coord_manager.face_coords @property def face_dimension(self): - """The *optionally required* UGRID NetCDF variable name for the ``face`` - dimension. - - """ + """The *optional* UGRID NetCDF variable name for the ``face`` dimension.""" return self._metadata_manager.face_dimension @face_dimension.setter @@ -1168,7 +1182,9 @@ def face_dimension(self, name): @property def face_edge_connectivity(self): - """The *optional* UGRID ``face_edge_connectivity`` + """The *optional* UGRID ``face_edge_connectivity``:class:`~iris.experimental.ugrid.mesh.Connectivity`. + + The *optional* UGRID ``face_edge_connectivity`` :class:`~iris.experimental.ugrid.mesh.Connectivity` of the :class:`Mesh`. @@ -1178,7 +1194,9 @@ def face_edge_connectivity(self): @property def face_face_connectivity(self): - """The *optional* UGRID ``face_face_connectivity`` + """The *optional* UGRID ``face_face_connectivity`` :class:`~iris.experimental.ugrid.mesh.Connectivity`. + + The *optional* UGRID ``face_face_connectivity`` :class:`~iris.experimental.ugrid.mesh.Connectivity` of the :class:`Mesh`. @@ -1187,7 +1205,9 @@ def face_face_connectivity(self): @property def face_node_connectivity(self): - """The UGRID ``face_node_connectivity`` + """Return ``face_node_connectivity``:class:`~iris.experimental.ugrid.mesh.Connectivity`. + + The UGRID ``face_node_connectivity`` :class:`~iris.experimental.ugrid.mesh.Connectivity` of the :class:`Mesh`, which is **required** for :attr:`Mesh.topology_dimension` of ``2``, and *optionally required* for :attr:`Mesh.topology_dimension` @@ -1198,10 +1218,7 @@ def face_node_connectivity(self): @property def node_coords(self): - """The **required** UGRID ``node`` :class:`~iris.coords.AuxCoord` coordinates - of the :class:`Mesh`. - - """ + """The **required** UGRID ``node`` :class:`~iris.coords.AuxCoord` coordinates of the :class:`Mesh`.""" return self._coord_manager.node_coords @property @@ -1283,7 +1300,9 @@ def connectivities( contains_edge=None, contains_face=None, ): - """Return all :class:`~iris.experimental.ugrid.mesh.Connectivity` + """Return all :class:`~iris.experimental.ugrid.mesh.Connectivity`. + + Return all :class:`~iris.experimental.ugrid.mesh.Connectivity` instances from the :class:`Mesh` that match the provided criteria. Criteria can be either specific properties or other objects with @@ -1371,7 +1390,9 @@ def connectivity( contains_edge=None, contains_face=None, ): - """Return a single :class:`~iris.experimental.ugrid.mesh.Connectivity` + """Return a single :class:`~iris.experimental.ugrid.mesh.Connectivity`. + + Return a single :class:`~iris.experimental.ugrid.mesh.Connectivity` from the :class:`Mesh` that matches the provided criteria. Criteria can be either specific properties or other objects with @@ -1465,7 +1486,9 @@ def coord( include_edges=None, include_faces=None, ): - """Return a single :class:`~iris.coords.AuxCoord` coordinate from the + """Return a single :class:`~iris.coords.AuxCoord` coordinate. + + Return a single :class:`~iris.coords.AuxCoord` coordinate from the :class:`Mesh` that matches the provided criteria. Criteria can be either specific properties or other objects with @@ -1548,7 +1571,9 @@ def coords( include_edges=None, include_faces=None, ): - """Return all :class:`~iris.coords.AuxCoord` coordinates from the :class:`Mesh` that + """Return all :class:`~iris.coords.AuxCoord` coordinates from the :class:`Mesh`. + + Return all :class:`~iris.coords.AuxCoord` coordinates from the :class:`Mesh` that match the provided criteria. Criteria can be either specific properties or other objects with @@ -1626,7 +1651,9 @@ def remove_connectivities( contains_edge=None, contains_face=None, ): - """Remove one or more :class:`~iris.experimental.ugrid.mesh.Connectivity` + """Remove one or more :class:`~iris.experimental.ugrid.mesh.Connectivity`. + + Remove one or more :class:`~iris.experimental.ugrid.mesh.Connectivity` from the :class:`Mesh` that match the provided criteria. Criteria can be either specific properties or other objects with @@ -1710,7 +1737,9 @@ def remove_coords( include_edges=None, include_faces=None, ): - """Remove one or more :class:`~iris.coords.AuxCoord` from the :class:`Mesh` + """Remove one or more :class:`~iris.coords.AuxCoord` from the :class:`Mesh`. + + Remove one or more :class:`~iris.coords.AuxCoord` from the :class:`Mesh` that match the provided criteria. Criteria can be either specific properties or other objects with @@ -1780,8 +1809,7 @@ def remove_coords( return self._coord_manager.remove(**kwargs) def xml_element(self, doc): - """Create the :class:`xml.dom.minidom.Element` that describes this - :class:`Mesh`. + """Create the :class:`xml.dom.minidom.Element` that describes this :class:`Mesh`. Parameters ---------- @@ -1812,7 +1840,9 @@ def xml_element(self, doc): # # return the lazy AuxCoord(...), AuxCoord(...) def to_MeshCoord(self, location, axis): - """Generate a :class:`~iris.experimental.ugrid.mesh.MeshCoord` that + """Generate a :class:`~iris.experimental.ugrid.mesh.MeshCoord`. + + Generate a :class:`~iris.experimental.ugrid.mesh.MeshCoord` that references the current :class:`Mesh`, and passing through the ``location`` and ``axis`` arguments. @@ -1839,7 +1869,9 @@ def to_MeshCoord(self, location, axis): return MeshCoord(mesh=self, location=location, axis=axis) def to_MeshCoords(self, location): - r"""Generate a tuple of + r"""Generate a tuple of :class:`~iris.experimental.ugrid.mesh.MeshCoord`\\ s. + + Generate a tuple of :class:`~iris.experimental.ugrid.mesh.MeshCoord`\\ s, each referencing the current :class:`Mesh`, one for each :attr:`AXES` value, passing through the ``location`` argument. @@ -1866,7 +1898,9 @@ def to_MeshCoords(self, location): return tuple(result) def dimension_names_reset(self, node=False, edge=False, face=False): - """Reset the name used for the NetCDF variable representing the ``node``, + """Reset the name used for the NetCDF variable. + + Reset the name used for the NetCDF variable representing the ``node``, ``edge`` and/or ``face`` dimension to ``None``. Parameters @@ -1885,7 +1919,9 @@ def dimension_names_reset(self, node=False, edge=False, face=False): return self._set_dimension_names(node, edge, face, reset=True) def dimension_names(self, node=None, edge=None, face=None): - """Assign the name to be used for the NetCDF variable representing + """Assign the name to be used for the NetCDF variable. + + Assign the name to be used for the NetCDF variable representing the ``node``, ``edge`` and ``face`` dimension. The default value of ``None`` will not be assigned to clear the @@ -1914,7 +1950,9 @@ def cf_role(self): @property def topology_dimension(self): - """The UGRID ``topology_dimension`` attribute represents the highest + """UGRID ``topology_dimension`` attribute. + + The UGRID ``topology_dimension`` attribute represents the highest dimensionality of all the geometric elements (node, edge, face) represented within the :class:`Mesh`. @@ -1923,7 +1961,8 @@ def topology_dimension(self): class _Mesh1DCoordinateManager: - """TBD: require clarity on coord_systems validation + """TBD: require clarity on coord_systems validation. + TBD: require clarity on __eq__ support TBD: rationalise self.coords() logic with other manager and Cube. @@ -2112,7 +2151,9 @@ def _add(self, coords): setattr(self, member_y, coords[1]) def add(self, node_x=None, node_y=None, edge_x=None, edge_y=None): - """Use self.remove(edge_x=True) to remove a coordinate e.g., using the + """Use self.remove(edge_x=True) to remove a coordinate. + + Use self.remove(edge_x=True) to remove a coordinate e.g., using the pattern self.add(edge_x=None) will not remove the edge_x coordinate. """ @@ -2822,8 +2863,9 @@ def copy(self, points=None, bounds=None): return new_coord def __deepcopy__(self, memo): - """Make this equivalent to "shallow" copy, returning a new MeshCoord based - on the same Mesh. + """Make this equivalent to "shallow" copy. + + Returns a new MeshCoord based on the same Mesh. Required to prevent cube copying from copying the Mesh, which would prevent "cube.copy() == cube" : see notes for :meth:`copy`. @@ -2908,7 +2950,9 @@ def summary(self, *args, **kwargs): return result def _construct_access_arrays(self): - """Build lazy points and bounds arrays, providing dynamic access via the + """Build lazy points and bounds arrays. + + Build lazy points and bounds arrays, providing dynamic access via the Mesh, according to the location and axis. Returns diff --git a/lib/iris/experimental/ugrid/save.py b/lib/iris/experimental/ugrid/save.py index 00891b3044..c78289fe26 100644 --- a/lib/iris/experimental/ugrid/save.py +++ b/lib/iris/experimental/ugrid/save.py @@ -3,8 +3,7 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Extensions to Iris' NetCDF saving to allow -:class:`~iris.experimental.ugrid.mesh.Mesh` saving in UGRID format. +"""Extension to Iris' NetCDF saving to allow :class:`~iris.experimental.ugrid.mesh.Mesh` saving in UGRID format. Eventual destination: :mod:`iris.fileformats.netcdf`. diff --git a/lib/iris/fileformats/_ff.py b/lib/iris/fileformats/_ff.py index 3edd29c410..e3749fe72d 100644 --- a/lib/iris/fileformats/_ff.py +++ b/lib/iris/fileformats/_ff.py @@ -125,10 +125,7 @@ class _WarnComboLoadingDefaulting(IrisDefaultingWarning, IrisLoadWarning): class Grid: - """An abstract class representing the default/file-level grid - definition for a FieldsFile. - - """ + """An abstract class representing the default/file-level grid definition for a FieldsFile.""" def __init__( self, @@ -178,8 +175,7 @@ def regular_y(self, subgrid): raise NotImplementedError() def vectors(self, subgrid): - """Return the X and Y coordinate vectors for the given sub-grid of - this grid. + """Return the X and Y coordinate vectors for the given sub-grid of this grid. Parameters ---------- @@ -218,8 +214,7 @@ def _x_vectors(self): return x_p, x_u def regular_x(self, subgrid): - """Return the "zeroth" value and step for the X coordinate on the - given sub-grid of this grid. + """Return the "zeroth" value & step for the X coord on the given sub-grid of this grid. Parameters ---------- @@ -238,7 +233,9 @@ def regular_x(self, subgrid): return bzx, bdx def regular_y(self, subgrid): - """Return the "zeroth" value and step for the Y coordinate on the + """Return the "zeroth" value & step for the Y coord on the given sub-grid of this grid. + + Return the "zeroth" value and step for the Y coordinate on the given sub-grid of this grid. Parameters @@ -300,7 +297,9 @@ class FFHeader: GRID_STAGGERING_CLASS = {3: NewDynamics, 6: ENDGame} def __init__(self, filename, word_depth=DEFAULT_FF_WORD_DEPTH): - """Create a FieldsFile header instance by reading the + """Create a FieldsFile header instance. + + Create a FieldsFile header instance by reading the FIXED_LENGTH_HEADER section of the FieldsFile, making the names defined in FF_HEADER available as attributes of a FFHeader instance. @@ -395,8 +394,7 @@ def _attribute_is_pointer_and_needs_addressing(self, name): return is_referenceable def shape(self, name): - """Return the dimension shape of the FieldsFile FIXED_LENGTH_HEADER - pointer attribute. + """Return the dimension shape of the FieldsFile FIXED_LENGTH_HEADER pointer attribute. Parameters ---------- @@ -438,7 +436,9 @@ class FF2PP: """A class to extract the individual PPFields from within a FieldsFile.""" def __init__(self, filename, read_data=False, word_depth=DEFAULT_FF_WORD_DEPTH): - """Create a FieldsFile to Post Process instance that returns a generator + """Create a generator of PPFields contained within the FieldsFile. + + Create a FieldsFile to Post Process instance that returns a generator of PPFields contained within the FieldsFile. Parameters diff --git a/lib/iris/fileformats/_nc_load_rules/engine.py b/lib/iris/fileformats/_nc_load_rules/engine.py index e43a1c5c4b..111e8320b6 100644 --- a/lib/iris/fileformats/_nc_load_rules/engine.py +++ b/lib/iris/fileformats/_nc_load_rules/engine.py @@ -2,7 +2,9 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""A simple mimic of the Pyke 'knowledge_engine', for interfacing to the routines +"""A simple mimic of the Pyke 'knowledge_engine'. + +A simple mimic of the Pyke 'knowledge_engine', for interfacing to the routines in 'iris.fileformats.netcdf' with minimal changes to that code. This allows us to replace the Pyke rules operation with the simpler pure-Python @@ -102,10 +104,7 @@ def get_kb(self): return self.facts def print_stats(self): - """No-op, called by - :meth:`iris.fileformats.netcdf._action_activation_stats`. - - """ + """No-op, called by :meth:`iris.fileformats.netcdf._action_activation_stats`.""" pass def add_case_specific_fact(self, fact_name, fact_arglist): diff --git a/lib/iris/fileformats/_nc_load_rules/helpers.py b/lib/iris/fileformats/_nc_load_rules/helpers.py index 894bb31af8..f656667e63 100644 --- a/lib/iris/fileformats/_nc_load_rules/helpers.py +++ b/lib/iris/fileformats/_nc_load_rules/helpers.py @@ -2,7 +2,9 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""All the pure-Python 'helper' functions which were previously included in the +"""Helper functions for NetCDF loading rules. + +All the pure-Python 'helper' functions which were previously included in the Pyke rules database 'fc_rules_cf.krb'. The 'action' routines now call these, as the rules used to do. @@ -258,22 +260,28 @@ class _WarnComboIgnoringCfLoad( def _split_cell_methods(nc_cell_methods: str) -> List[re.Match]: - """Split a CF cell_methods attribute string into a list of zero or more cell + """Split a CF cell_methods. + + Split a CF cell_methods attribute string into a list of zero or more cell methods, each of which is then parsed with a regex to return a list of match objects. - Args: - - * nc_cell_methods: The value of the cell methods attribute to be split. + Parameters + ---------- + nc_cell_methods : + The value of the cell methods attribute to be split. Returns ------- nc_cell_methods_matches: list of re.Match objects A list of re.Match objects associated with each parsed cell method + Notes + ----- Splitting is done based on words followed by colons outside of any brackets. Validation of anything other than being laid out in the expected format is left to the calling function. + """ # Find name candidates name_start_inds = [] @@ -328,18 +336,19 @@ class UnknownCellMethodWarning(iris.exceptions.IrisUnknownCellMethodWarning): def parse_cell_methods(nc_cell_methods, cf_name=None): - """Parse a CF cell_methods attribute string into a tuple of zero or - more CellMethod instances. - - Args: + """Parse a CF cell_methods attribute string into a tuple of zero or more CellMethod instances. - * nc_cell_methods (str): + Parameters + ---------- + nc_cell_methods : str The value of the cell methods attribute to be parsed. Returns ------- iterable of :class:`iris.coords.CellMethod`. + Notes + ----- Multiple coordinates, intervals and comments are supported. If a method has a non-standard name a warning will be issued, but the results are not affected. @@ -473,8 +482,11 @@ def build_cube_metadata(engine): ################################################################################ def _get_ellipsoid(cf_grid_var): - """Return a :class:`iris.coord_systems.GeogCS` using the relevant properties of + """Build a :class:`iris.coord_systems.GeogCS`. + + Return a :class:`iris.coord_systems.GeogCS` using the relevant properties of `cf_grid_var`. Returns None if no relevant properties are specified. + """ major = getattr(cf_grid_var, CF_ATTR_GRID_SEMI_MAJOR_AXIS, None) minor = getattr(cf_grid_var, CF_ATTR_GRID_SEMI_MINOR_AXIS, None) @@ -556,10 +568,7 @@ def build_rotated_coordinate_system(engine, cf_grid_var): ################################################################################ def build_transverse_mercator_coordinate_system(engine, cf_grid_var): - """Create a transverse Mercator coordinate system from the CF-netCDF - grid mapping variable. - - """ + """Create a transverse Mercator coordinate system from the CF-netCDF grid mapping variable.""" ellipsoid = _get_ellipsoid(cf_grid_var) latitude_of_projection_origin = getattr( @@ -599,10 +608,7 @@ def build_transverse_mercator_coordinate_system(engine, cf_grid_var): ################################################################################ def build_lambert_conformal_coordinate_system(engine, cf_grid_var): - """Create a Lambert conformal conic coordinate system from the CF-netCDF - grid mapping variable. - - """ + """Create a Lambert conformal conic coordinate system from the CF-netCDF grid mapping variable.""" ellipsoid = _get_ellipsoid(cf_grid_var) latitude_of_projection_origin = getattr( @@ -629,10 +635,7 @@ def build_lambert_conformal_coordinate_system(engine, cf_grid_var): ################################################################################ def build_stereographic_coordinate_system(engine, cf_grid_var): - """Create a stereographic coordinate system from the CF-netCDF - grid mapping variable. - - """ + """Create a stereographic coordinate system from the CF-netCDF grid mapping variable.""" ellipsoid = _get_ellipsoid(cf_grid_var) latitude_of_projection_origin = getattr( @@ -663,10 +666,7 @@ def build_stereographic_coordinate_system(engine, cf_grid_var): ################################################################################ def build_polar_stereographic_coordinate_system(engine, cf_grid_var): - """Create a polar stereographic coordinate system from the CF-netCDF - grid mapping variable. - - """ + """Create a polar stereographic coordinate system from the CF-netCDF grid mapping variable.""" ellipsoid = _get_ellipsoid(cf_grid_var) latitude_of_projection_origin = getattr( @@ -698,10 +698,7 @@ def build_polar_stereographic_coordinate_system(engine, cf_grid_var): ################################################################################ def build_mercator_coordinate_system(engine, cf_grid_var): - """Create a Mercator coordinate system from the CF-netCDF - grid mapping variable. - - """ + """Create a Mercator coordinate system from the CF-netCDF grid mapping variable.""" ellipsoid = _get_ellipsoid(cf_grid_var) longitude_of_projection_origin = getattr( @@ -728,10 +725,7 @@ def build_mercator_coordinate_system(engine, cf_grid_var): ################################################################################ def build_lambert_azimuthal_equal_area_coordinate_system(engine, cf_grid_var): - """Create a lambert azimuthal equal area coordinate system from the CF-netCDF - grid mapping variable. - - """ + """Create a lambert azimuthal equal area coordinate system from the CF-netCDF grid mapping variable.""" ellipsoid = _get_ellipsoid(cf_grid_var) latitude_of_projection_origin = getattr( @@ -756,10 +750,7 @@ def build_lambert_azimuthal_equal_area_coordinate_system(engine, cf_grid_var): ################################################################################ def build_albers_equal_area_coordinate_system(engine, cf_grid_var): - """Create a albers conical equal area coordinate system from the CF-netCDF - grid mapping variable. - - """ + """Create a albers conical equal area coordinate system from the CF-netCDF grid mapping variable.""" ellipsoid = _get_ellipsoid(cf_grid_var) latitude_of_projection_origin = getattr( @@ -786,10 +777,7 @@ def build_albers_equal_area_coordinate_system(engine, cf_grid_var): ################################################################################ def build_vertical_perspective_coordinate_system(engine, cf_grid_var): - """Create a vertical perspective coordinate system from the CF-netCDF - grid mapping variable. - - """ + """Create a vertical perspective coordinate system from the CF-netCDF grid mapping variables.""" ellipsoid = _get_ellipsoid(cf_grid_var) latitude_of_projection_origin = getattr( @@ -818,10 +806,7 @@ def build_vertical_perspective_coordinate_system(engine, cf_grid_var): ################################################################################ def build_geostationary_coordinate_system(engine, cf_grid_var): - """Create a geostationary coordinate system from the CF-netCDF - grid mapping variable. - - """ + """Create a geostationary coordinate system from the CF-netCDF grid mapping variable.""" ellipsoid = _get_ellipsoid(cf_grid_var) latitude_of_projection_origin = getattr( @@ -852,10 +837,7 @@ def build_geostationary_coordinate_system(engine, cf_grid_var): ################################################################################ def build_oblique_mercator_coordinate_system(engine, cf_grid_var): - """Create an oblique mercator coordinate system from the CF-netCDF - grid mapping variable. - - """ + """Create an oblique mercator coordinate system from the CF-netCDF grid mapping variable.""" ellipsoid = _get_ellipsoid(cf_grid_var) azimuth_of_central_line = getattr(cf_grid_var, CF_ATTR_GRID_AZIMUTH_CENT_LINE, None) @@ -981,10 +963,7 @@ def get_names(cf_coord_var, coord_name, attributes): ################################################################################ def get_cf_bounds_var(cf_coord_var): - """Return the CF variable representing the bounds of a coordinate - variable. - - """ + """Return the CF variable representing the bounds of a coordinate variable.""" attr_bounds = getattr(cf_coord_var, CF_ATTR_BOUNDS, None) attr_climatology = getattr(cf_coord_var, CF_ATTR_CLIMATOLOGY, None) @@ -1016,8 +995,7 @@ def get_cf_bounds_var(cf_coord_var): ################################################################################ def reorder_bounds_data(bounds_data, cf_bounds_var, cf_coord_var): - """Return a bounds_data array with the vertex dimension as the most - rapidly varying. + """Return a bounds_data array with the vertex dimension as the most rapidly varying. .. note:: @@ -1425,10 +1403,7 @@ def is_longitude(engine, cf_name): ################################################################################ def is_projection_x_coordinate(engine, cf_name): - """Determine whether the CF coordinate variable is a - projection_x_coordinate variable. - - """ + """Determine whether the CF coordinate variable is a projection_x_coordinate variable.""" cf_var = engine.cf_var.cf_group[cf_name] attr_name = getattr(cf_var, CF_ATTR_STD_NAME, None) or getattr( cf_var, CF_ATTR_LONG_NAME, None @@ -1438,10 +1413,7 @@ def is_projection_x_coordinate(engine, cf_name): ################################################################################ def is_projection_y_coordinate(engine, cf_name): - """Determine whether the CF coordinate variable is a - projection_y_coordinate variable. - - """ + """Determine whether the CF coordinate variable is a projection_y_coordinate variable.""" cf_var = engine.cf_var.cf_group[cf_name] attr_name = getattr(cf_var, CF_ATTR_STD_NAME, None) or getattr( cf_var, CF_ATTR_LONG_NAME, None @@ -1557,8 +1529,11 @@ def has_supported_mercator_parameters(engine, cf_name): ################################################################################ def has_supported_polar_stereographic_parameters(engine, cf_name): - """Determine whether the CF grid mapping variable has the supported + """Determine whether CF grid mapping variable supports Polar Stereographic. + + Determine whether the CF grid mapping variable has the supported values for the parameters of the Polar Stereographic projection. + """ is_valid = True cf_grid_var = engine.cf_var.cf_group[cf_name] diff --git a/lib/iris/fileformats/_structured_array_identification.py b/lib/iris/fileformats/_structured_array_identification.py index 05bd04036b..8dada77458 100644 --- a/lib/iris/fileformats/_structured_array_identification.py +++ b/lib/iris/fileformats/_structured_array_identification.py @@ -2,8 +2,11 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -r"""The purpose of this module is to provide utilities for the identification +r"""Identification of multi-dimensional structure in a flat sequence of homogeneous objects. + +The purpose of this module is to provide utilities for the identification of multi-dimensional structure in a flat sequence of homogeneous objects. + One application of this is to efficiently identify a higher dimensional structure from a sorted sequence of PPField instances; for an example, given a list of 12 PPFields, identification that there are 3 unique "time" values @@ -47,14 +50,13 @@ class _UnstructuredArrayException(Exception): - """Raised when an array has been incorrectly assumed to be - structured in a specific way. - - """ + """Raised when an array has been incorrectly assumed to be structured in a specific way.""" class ArrayStructure(namedtuple("ArrayStructure", ["stride", "unique_ordered_values"])): - """Represents the identified structure of an array, where stride is the + """Represent the identified structure of an array. + + Represents the identified structure of an array, where stride is the step between each unique value being seen in order in the flattened version of the array. @@ -92,7 +94,9 @@ def __new__(cls, stride, unique_ordered_values): @property def size(self): - """The ``size`` attribute is the number of the unique values in the + """Number of unique values in the original array. + + The ``size`` attribute is the number of the unique values in the original array. It is **not** the length of the original array. """ @@ -114,7 +118,9 @@ def __ne__(self, other): return not (self == other) def construct_array(self, size): - """The inverse operation of :func:`ArrayStructure.from_array`, returning + """Build 1D array. + + The inverse operation of :func:`ArrayStructure.from_array`, returning a 1D array of the given length with the appropriate repetition pattern. @@ -125,8 +131,7 @@ def construct_array(self, size): ) def nd_array_and_dims(self, original_array, target_shape, order="c"): - """Given a 1D array, and a target shape, construct an ndarray - and associated dimensions. + """Given a 1D array and a target shape, construct an ndarray and associated dimensions. Raises an _UnstructuredArrayException if no optimised shape array can be returned, in which case, simply reshaping the original_array would @@ -199,7 +204,9 @@ def nd_array_and_dims(self, original_array, target_shape, order="c"): @classmethod def from_array(cls, arr): - """Return the computed ArrayStructure for the given flat array + """Return the computed ArrayStructure for the given flat array. + + Return the computed ArrayStructure for the given flat array (if a structure exists, otherwise return None). """ @@ -284,7 +291,9 @@ def from_array(cls, arr): class GroupStructure: - """The GroupStructure class represents a collection of array structures along + """Represent a collection of array structures. + + The GroupStructure class represents a collection of array structures along with additional information such as the length of the arrays and the array order in which they are found (row-major or column-major). @@ -307,14 +316,17 @@ def __init__(self, length, component_structure, array_order="c"): @classmethod def from_component_arrays(cls, component_arrays, array_order="c"): - """Given a dictionary of component name to flattened numpy array, + """From component arrays. + + Given a dictionary of component name to flattened numpy array, return an :class:`GroupStructure` instance which is representative of the underlying array structures. - Args: - - * component_arrays - A dictionary mapping component name to the - full sized 1d (flattened) numpy array. + Parameters + ---------- + component_arrays : + A dictionary mapping component name to the full sized 1d (flattened) + numpy array. """ cmpt_structure = { @@ -329,7 +341,8 @@ def from_component_arrays(cls, component_arrays, array_order="c"): return cls(sizes[0], cmpt_structure, array_order=array_order) def _potentially_flattened_components(self): - """Return a generator of the components which could form non-trivial + """Return a generator of the components which could form non-trivial. + (i.e. ``length > 1``) array dimensions. """ @@ -342,8 +355,7 @@ def is_row_major(self): return self._array_order == "c" def possible_structures(self): - """Return a tuple containing the possible structures that this group - could have. + """Return a tuple containing the possible structures that this group could have. A structure in this case is an iterable of ``(name, ArrayStructure)`` pairs, one per dimension, of a possible @@ -443,7 +455,9 @@ def __str__(self): return "\n".join(result) def build_arrays(self, shape, elements_arrays): - """Given the target shape, and a dictionary mapping name to 1D array of + """Build Arrays. + + Given the target shape, and a dictionary mapping name to 1D array of :attr:`.length`, return a dictionary mapping element name to ``(ndarray, dims)``. diff --git a/lib/iris/fileformats/cf.py b/lib/iris/fileformats/cf.py index ec0d66f8c2..d6dab22305 100644 --- a/lib/iris/fileformats/cf.py +++ b/lib/iris/fileformats/cf.py @@ -2,7 +2,9 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Provides the capability to load netCDF files and interpret them +"""Provide capability to load netCDF files and interpret them. + +Provides the capability to load netCDF files and interpret them according to the 'NetCDF Climate and Forecast (CF) Metadata Conventions'. References @@ -132,7 +134,9 @@ def identify(self, variables, ignore=None, target=None, warn=True): pass def spans(self, cf_variable): - """Determine whether the dimensionality of this variable + """Determine dimensionality coverage. + + Determine whether the dimensionality of this variable is a subset of the specified target variable. Note that, by default scalar variables always span the @@ -243,7 +247,9 @@ def has_formula_terms(self): class CFAncillaryDataVariable(CFVariable): - """A CF-netCDF ancillary data variable is a variable that provides metadata + """CF-netCDF ancillary data variable. + + A CF-netCDF ancillary data variable is a variable that provides metadata about the individual values of another data variable. Identified by the CF-netCDF variable attribute 'ancillary_variables'. @@ -283,7 +289,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): class CFAuxiliaryCoordinateVariable(CFVariable): - """A CF-netCDF auxiliary coordinate variable is any netCDF variable that contains + """CF-netCDF auxiliary coordinate variable. + + A CF-netCDF auxiliary coordinate variable is any netCDF variable that contains coordinate data, but is not a CF-netCDF coordinate variable by definition. There is no relationship between the name of a CF-netCDF auxiliary coordinate @@ -330,7 +338,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): class CFBoundaryVariable(CFVariable): - """A CF-netCDF boundary variable is associated with a CF-netCDF variable that contains + """CF-netCDF boundary variable. + + A CF-netCDF boundary variable is associated with a CF-netCDF variable that contains coordinate data. When a data value provides information about conditions in a cell occupying a region of space/time or some other dimension, the boundary variable provides a description of cell extent. @@ -373,7 +383,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): return result def spans(self, cf_variable): - """Determine whether the dimensionality of this variable + """Determine dimensionality coverage. + + Determine whether the dimensionality of this variable is a subset of the specified target variable. Note that, by default scalar variables always span the @@ -402,7 +414,9 @@ def spans(self, cf_variable): class CFClimatologyVariable(CFVariable): - """A CF-netCDF climatology variable is associated with a CF-netCDF variable that contains + """CF-netCDF climatology variable. + + A CF-netCDF climatology variable is associated with a CF-netCDF variable that contains coordinate data. When a data value provides information about conditions in a cell occupying a region of space/time or some other dimension, the climatology variable provides a climatological description of cell extent. @@ -445,7 +459,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): return result def spans(self, cf_variable): - """Determine whether the dimensionality of this variable + """Determine dimensionality coverage. + + Determine whether the dimensionality of this variable is a subset of the specified target variable. Note that, by default scalar variables always span the @@ -474,7 +490,9 @@ def spans(self, cf_variable): class CFCoordinateVariable(CFVariable): - """A CF-netCDF coordinate variable is a one-dimensional variable with the same name + """A CF-netCDF coordinate variable. + + A CF-netCDF coordinate variable is a one-dimensional variable with the same name as its dimension, and it is defined as a numeric data type with values that are ordered monotonically. Missing values are not allowed in CF-netCDF coordinate variables. Also see [NUG] Section 2.3.1. @@ -528,7 +546,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): class _CFFormulaTermsVariable(CFVariable): - """A CF-netCDF formula terms variable corresponds to a term in a formula that + """CF-netCDF formula terms variable. + + A CF-netCDF formula terms variable corresponds to a term in a formula that allows dimensional vertical coordinate values to be computed from dimensionless vertical coordinate values and associated variables at specific grid points. @@ -596,7 +616,9 @@ def __repr__(self): class CFGridMappingVariable(CFVariable): - """A CF-netCDF grid mapping variable contains a list of specific attributes that + """CF-netCDF grid mapping variable. + + A CF-netCDF grid mapping variable contains a list of specific attributes that define a particular grid mapping. A CF-netCDF grid mapping variable must contain the attribute 'grid_mapping_name'. @@ -641,7 +663,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): class CFLabelVariable(CFVariable): - """A CF-netCDF CF label variable is any netCDF variable that contain string + """Cariable is any netCDF variable that contain string textual information, or labels. + + A CF-netCDF CF label variable is any netCDF variable that contain string textual information, or labels. Identified by the CF-netCDF variable attribute 'coordinates'. @@ -777,7 +801,9 @@ def cf_label_dimensions(self, cf_data_var): ) def spans(self, cf_variable): - """Determine whether the dimensionality of this variable + """Determine dimensionality coverage. + + Determine whether the dimensionality of this variable is a subset of the specified target variable. Note that, by default scalar variables always span the @@ -858,7 +884,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): ################################################################################ class CFGroup(MutableMapping): - """Represents a collection of 'NetCDF Climate and Forecast (CF) Metadata + """Collection of 'NetCDF CF Metadata Conventions variables and netCDF global attributes. + + Represents a collection of 'NetCDF Climate and Forecast (CF) Metadata Conventions' variables and netCDF global attributes. """ @@ -935,10 +963,7 @@ def cell_measures(self): @property def non_data_variable_names(self): - """:class:`set` of the names of the CF-netCDF variables that are not - the data pay-load. - - """ + """:class:`set` names of the CF-netCDF variables that are not the data pay-load.""" non_data_variables = ( self.ancillary_variables, self.auxiliary_coordinates, @@ -1303,10 +1328,7 @@ def __del__(self): def _getncattr(dataset, attr, default=None): - """Simple wrapper round `netCDF4.Dataset.getncattr` to make it behave - more like `getattr`. - - """ + """Wrap `netCDF4.Dataset.getncattr` to make it behave more like `getattr`.""" try: value = dataset.getncattr(attr) except AttributeError: diff --git a/lib/iris/fileformats/dot.py b/lib/iris/fileformats/dot.py index cd875b3e4a..daa3f2fd61 100644 --- a/lib/iris/fileformats/dot.py +++ b/lib/iris/fileformats/dot.py @@ -55,8 +55,8 @@ def _dot_path(): def save(cube, target): """Save a dot representation of the cube. - Args - ---- + Parameters + ---------- cube: :class:`iris.cube.Cube`. target A filename or open file handle. @@ -83,17 +83,18 @@ def save(cube, target): def save_png(source, target, launch=False): - """Produce a "dot" instance diagram by calling dot and optionally launching + """Produce a "dot" instance diagram by calling dot. + + Produce a "dot" instance diagram by calling dot and optionally launching the resulting image. - Args - ---- + Parameters + ---------- source: :class:`iris.cube.Cube`, or dot filename. - target + target : A filename or open file handle. If passing a file handle, take care to open it for binary output. - - **kwargs + **kwargs : * launch Display the image. Default is False. @@ -148,9 +149,9 @@ def save_png(source, target, launch=False): def cube_text(cube): """Return a DOT text representation a `iris.cube.Cube`. - Args - ---- - cube + Parameters + ---------- + cube : The cube for which to create DOT text. """ @@ -276,14 +277,13 @@ def cube_text(cube): def _coord_text(label, coord): - """Return a string containing the dot representation for a single coordinate - node. + """Return a string containing the dot representation for a single coordinate node. - Args - ---- - label + Parameters + ---------- + label : The dot ID of the coordinate node. - coord + coord : The coordinate to convert. """ @@ -306,14 +306,13 @@ def _coord_text(label, coord): def _coord_system_text(cs, uid): - """Return a string containing the dot representation for a single coordinate - system node. + """Return string containing dot representation for a single coordinate system node. - Args - ---- - cs + Parameters + ---------- + cs : The coordinate system to convert. - uid + uid : The uid allows/distinguishes non-identical CoordSystems of the same type. diff --git a/lib/iris/fileformats/name.py b/lib/iris/fileformats/name.py index 3d01b07dee..bc1bb690c2 100644 --- a/lib/iris/fileformats/name.py +++ b/lib/iris/fileformats/name.py @@ -6,7 +6,9 @@ def _get_NAME_loader(filename): - """Return the appropriate load function for a NAME file based + """Return a NAME load function. + + Return the appropriate load function for a NAME file based on the contents of its header. """ @@ -43,8 +45,7 @@ def _get_NAME_loader(filename): def load_cubes(filenames, callback): - """Return a generator of cubes given one or more filenames and an - optional callback. + """Return a generator of cubes given one or more filenames and an optional callback. Parameters ---------- diff --git a/lib/iris/fileformats/name_loaders.py b/lib/iris/fileformats/name_loaders.py index 545b242994..3e337383cb 100644 --- a/lib/iris/fileformats/name_loaders.py +++ b/lib/iris/fileformats/name_loaders.py @@ -98,7 +98,9 @@ def read_header(file_handle): def _read_data_arrays(file_handle, n_arrays, shape): - """Return a list of NumPy arrays containing the data extracted from + """Return a list of NumPy arrays containing the data extracted. + + Return a list of NumPy arrays containing the data extracted from the provided file object. The number and shape of the arrays must be specified. @@ -127,8 +129,11 @@ def _read_data_arrays(file_handle, n_arrays, shape): def _build_lat_lon_for_NAME_field( header, dimindex, x_or_y, coord_names=["longitude", "latitude"] ): - """Return regular latitude and longitude coordinates extracted from + """Return regular latitude and longitude coordinates. + + Return regular latitude and longitude coordinates extracted from the provided header dictionary. + """ if x_or_y == "X": start = header["X grid origin"] @@ -147,7 +152,9 @@ def _build_lat_lon_for_NAME_field( def _build_lat_lon_for_NAME_timeseries(column_headings): - """Return regular latitude and longitude coordinates extracted from + """Return regular latitude and longitude coordinates. + + Return regular latitude and longitude coordinates extracted from the provided column_headings dictionary. """ @@ -186,7 +193,9 @@ def _build_lat_lon_for_NAME_timeseries(column_headings): def _calc_integration_period(time_avgs): - """Return a list of datetime.timedelta objects determined from the provided + """Calculate averaging/integration time periods. + + Return a list of datetime.timedelta objects determined from the provided list of averaging/integration period column headings. """ @@ -387,7 +396,9 @@ def _cf_height_from_name(z_coord, lower_bound=None, upper_bound=None): def _generate_cubes(header, column_headings, coords, data_arrays, cell_methods=None): - """Yield :class:`iris.cube.Cube` instances given + """Generate NAME cubes. + + Yield :class:`iris.cube.Cube` instances given the headers, column headings, coords and data_arrays extracted from a NAME file. @@ -549,7 +560,9 @@ def _generate_cubes(header, column_headings, coords, data_arrays, cell_methods=N def _build_cell_methods(av_or_ints, coord): - """Return a list of :class:`iris.coords.CellMethod` instances + """Create cell-methods. + + Return a list of :class:`iris.coords.CellMethod` instances based on the provided list of column heading entries and the associated coordinate. If a given entry does not correspond to a cell method (e.g. "No time averaging"), a value of None is inserted. @@ -588,7 +601,9 @@ def _build_cell_methods(av_or_ints, coord): def load_NAMEIII_field(filename): - """Load a NAME III grid output file returning a + """Load NAME III cubes. + + Load a NAME III grid output file returning a generator of :class:`iris.cube.Cube` instances. Parameters diff --git a/lib/iris/fileformats/nimrod_load_rules.py b/lib/iris/fileformats/nimrod_load_rules.py index bb6d13f50a..3c4c56bc3b 100644 --- a/lib/iris/fileformats/nimrod_load_rules.py +++ b/lib/iris/fileformats/nimrod_load_rules.py @@ -45,9 +45,12 @@ def is_missing(field, value): def name(cube, field, handle_metadata_errors): """Set the cube's name from the field. + Modifies the Nimrod object title based on other meta-data in the Nimrod field and known use cases. + Adds "mean_of" or "standard_deviation_of_" to the cube name if appropriate. + """ title_from_field_code = { 12: "air_pressure", @@ -237,8 +240,7 @@ def reference_time(cube, field): def forecast_period(cube): - """Add a forecast_period coord based on existing time and - forecast_reference_time coords. + """Add forecast_period coord based on existing time and forecast_reference_time coords. Must be run after time() and reference_time() @@ -293,8 +295,7 @@ def experiment(cube, field): def proj_biaxial_ellipsoid(field, handle_metadata_errors): - """Return the correct dictionary of arguments needed to define an - iris.coord_systems.GeogCS. + """Return correct dict of arguments needed to define an iris.coord_systems.GeogCS. Based firstly on the value given by ellipsoid, then by grid if ellipsoid is missing, select the right pre-defined ellipsoid dictionary (Airy_1830 or @@ -339,7 +340,9 @@ def proj_biaxial_ellipsoid(field, handle_metadata_errors): def set_british_national_grid_defaults(field, handle_metadata_errors): - """Check for missing coord-system meta-data and set default values for + """Check for missing coord-system meta-data and set default values. + + Check for missing coord-system meta-data and set default values for the Ordnance Survey GB Transverse Mercator projection. Some Radarnet files are missing these. @@ -374,6 +377,7 @@ def set_british_national_grid_defaults(field, handle_metadata_errors): def coord_system(field, handle_metadata_errors): """Define the coordinate system for the field. + Handles Transverse Mercator, Universal Transverse Mercator and Plate Carree. Transverse Mercator projections will default to the British National Grid if any @@ -411,6 +415,7 @@ def coord_system(field, handle_metadata_errors): def horizontal_grid(cube, field, handle_metadata_errors): """Add X and Y coordinates to the cube. + Handles Transverse Mercator, Universal Transverse Mercator and Plate Carree. coordinate reference system is supplied by coord_system(field) @@ -455,7 +460,9 @@ def horizontal_grid(cube, field, handle_metadata_errors): def vertical_coord(cube, field): - """Add a vertical coord to the cube, with bounds, if appropriate. + """Add a vertical coord to the cube, with bounds. + + Add a vertical coord to the cube, with bounds, if appropriate. Handles special numbers for "at-sea-level" (8888) and "at-ground-level" (9999). @@ -695,7 +702,9 @@ def known_threshold_coord(field): def probability_coord(cube, field, handle_metadata_errors): - """Add a coord relating to probability meta-data from the header to the + """Add a coord relating to probability meta-data from the header to the cube. + + Add a coord relating to probability meta-data from the header to the cube if appropriate. Must be run after the name method. diff --git a/lib/iris/fileformats/pp.py b/lib/iris/fileformats/pp.py index 8ac49b827d..e224e26b41 100644 --- a/lib/iris/fileformats/pp.py +++ b/lib/iris/fileformats/pp.py @@ -273,7 +273,9 @@ class STASH(collections.namedtuple("STASH", "model section item")): __slots__ = () def __new__(cls, model, section, item): - """Args + """Create namedtuple STASH instance. + + Args ---- model A positive integer less than 100, or None. @@ -356,8 +358,7 @@ def __ne__(self, other): class SplittableInt: - """A class to hold integers which can easily get each decimal digit - individually. + """A class to hold integers which can easily get each decimal digit individually. >>> three_six_two = SplittableInt(362) >>> print(three_six_two) @@ -657,9 +658,10 @@ def __ne__(self, other): def _data_bytes_to_shaped_array( data_bytes, lbpack, boundary_packing, data_shape, data_type, mdi, mask=None ): - """Convert the already read binary data payload into a numpy array, unpacking - and decompressing as per the F3 specification. + """Convert binary payload into a numpy array. + Convert the already read binary data payload into a numpy array, unpacking + and decompressing as per the F3 specification. """ if lbpack.n1 in (0, 2): data = np.frombuffer(data_bytes, dtype=data_type) @@ -809,10 +811,7 @@ def _data_bytes_to_shaped_array( def _header_defn(release_number): - """Return the zero-indexed header definition for a particular release of - a PPField. - - """ + """Return zero-indexed header definition for a particular release of a PPField.""" um_header = UM_HEADERS[release_number] offset = UM_TO_PP_HEADER_OFFSET return [ @@ -822,7 +821,9 @@ def _header_defn(release_number): def _pp_attribute_names(header_defn): - """Return the allowed attributes of a PPField: + """Return the allowed attributes of a PPField. + + Return the allowed attributes of a PPField: all of the normal headers (i.e. not the _SPECIAL_HEADERS), the _SPECIAL_HEADERS with '_' prefixed, the possible extra data headers. @@ -844,7 +845,9 @@ def _pp_attribute_names(header_defn): class PPField(metaclass=ABCMeta): - """A generic class for PP fields - not specific to a particular + """Base class for PP fields. + + A generic class for PP fields - not specific to a particular header release number. A PPField instance can easily access the PP header "words" as attributes @@ -877,7 +880,9 @@ def __init__(self, header=None): self.raw_lbpack = header[self.HEADER_DICT["lbpack"][0]] def __getattr__(self, key): - """Method supports deferred attribute creation, which offers a + """Return the value of the key. + + Method supports deferred attribute creation, which offers a significant loading optimisation, particularly when not all attributes are referenced and therefore created on the instance. @@ -970,8 +975,9 @@ def __repr__(self): @property def stash(self): - """Stash property giving access to the associated STASH object, - now supporting __eq__. + """Stash property giving access to the associated STASH object. + + Now supporting __eq__. """ if ( @@ -1049,10 +1055,7 @@ def lbproc(self, value): @property def data(self): - """:class:`numpy.ndarray` representing the multidimensional data - of the pp file. - - """ + """:class:`numpy.ndarray` representing multidimensional data of the pp file.""" if is_lazy_data(self._data): # Replace with real data on the first access. self._data = as_concrete_data(self._data) @@ -1445,10 +1448,7 @@ def __ne__(self, other): class PPField2(PPField): - """A class to hold a single field from a PP file, with a - header release number of 2. - - """ + """Hold a single field from a PP file, with a header release number of 2.""" HEADER_DEFN = _header_defn(2) HEADER_DICT = dict(HEADER_DEFN) @@ -1457,7 +1457,9 @@ class PPField2(PPField): @property def t1(self): - """cftime.datetime object consisting of the lbyr, lbmon, lbdat, lbhr, + """cftime.datetime object. + + cftime.datetime object consisting of the lbyr, lbmon, lbdat, lbhr, and lbmin attributes. """ @@ -1488,7 +1490,9 @@ def t1(self, dt): @property def t2(self): - """cftime.datetime object consisting of the lbyrd, lbmond, lbdatd, + """cftime.datetime object. + + cftime.datetime object consisting of the lbyrd, lbmond, lbdatd, lbhrd, and lbmind attributes. """ @@ -1519,10 +1523,7 @@ def t2(self, dt): class PPField3(PPField): - """A class to hold a single field from a PP file, with a - header release number of 3. - - """ + """Hold a single field from a PP file, with a header release number of 3.""" HEADER_DEFN = _header_defn(3) HEADER_DICT = dict(HEADER_DEFN) @@ -1531,7 +1532,9 @@ class PPField3(PPField): @property def t1(self): - """cftime.datetime object consisting of the lbyr, lbmon, lbdat, lbhr, + """cftime.datetime object. + + cftime.datetime object consisting of the lbyr, lbmon, lbdat, lbhr, lbmin, and lbsec attributes. """ @@ -1563,7 +1566,9 @@ def t1(self, dt): @property def t2(self): - """cftime.datetime object consisting of the lbyrd, lbmond, lbdatd, + """cftime.datetime object. + + cftime.datetime object consisting of the lbyrd, lbmond, lbdatd, lbhrd, lbmind, and lbsecd attributes. """ @@ -1638,7 +1643,9 @@ def load(filename, read_data=False, little_ended=False): def _interpret_fields(fields): - """Turn the fields read with load and FF2PP._extract_field into usable + """Turn the fields read with load and FF2PP._extract_field into usable fields. + + Turn the fields read with load and FF2PP._extract_field into usable fields. One of the primary purposes of this function is to either convert "deferred bytes" into "deferred arrays" or "loaded bytes" into actual numpy arrays (via the _create_field_data) function. @@ -1706,9 +1713,12 @@ def _interpret_fields(fields): def _create_field_data(field, data_shape, land_mask_field=None): - """Modify a field's ``_data`` attribute either by: - * converting a 'deferred array bytes' tuple into a lazy array, - * converting LoadedArrayBytes into an actual numpy array. + """Modify a field's ``_data`` attribute. + + Modify a field's ``_data`` attribute either by: + + * converting a 'deferred array bytes' tuple into a lazy array, + * converting LoadedArrayBytes into an actual numpy array. If 'land_mask_field' is passed (not None), then it contains the associated landmask, which is also a field : Its data array is used as a template for @@ -1803,8 +1813,7 @@ def calc_array(mask, values): def _field_gen(filename, read_data_bytes, little_ended=False): - """Return a generator of "half-formed" PPField instances derived from - the given filename. + """Return generator of "half-formed" PPField instances derived from given filename. A field returned by the generator is only "half-formed" because its `_data` attribute represents a simple one-dimensional stream of @@ -1931,7 +1940,9 @@ def _field_gen(filename, read_data_bytes, little_ended=False): def _convert_constraints(constraints): - """Convert known constraints from Iris semantics to PP semantics + """Convert known constraints from Iris semantics to PP semantics. + + Convert known constraints from Iris semantics to PP semantics ignoring all unknown constraints. """ @@ -1940,10 +1951,7 @@ def _convert_constraints(constraints): unhandled_constraints = False def _make_func(stashobj): - """Provide unique name-space for each lambda function's stashobj - variable. - - """ + """Provide unique name-space for each lambda function's stashobj variable.""" return lambda stash: stash == stashobj for con in constraints: @@ -1974,10 +1982,7 @@ def _make_func(stashobj): unhandled_constraints = True def pp_filter(field): - """Return True if field is to be kept, - False if field does not match filter. - - """ + """Return True if field is to be kept, False if field does not match filter.""" res = True if field.stash not in _STASH_ALLOW: if pp_constraints.get("stash"): @@ -1998,11 +2003,11 @@ def pp_filter(field): def load_cubes(filenames, callback=None, constraints=None): """Load cubes from a list of pp filenames. - Args - ---- - filenames + Parameters + ---------- + filenames : list of pp filenames to load - **kwargs + **kwargs : * constraints a list of Iris constraints * callback @@ -2050,8 +2055,7 @@ def load_cubes_little_endian(filenames, callback=None, constraints=None): def load_pairs_from_fields(pp_fields): - r"""Convert an iterable of PP fields into an iterable of tuples of - (Cubes, PPField). + r"""Convert an iterable of PP fields into an iterable of tuples of (Cubes, PPField). Args ---- @@ -2182,7 +2186,9 @@ def save(cube, target, append=False, field_coords=None): def save_pairs_from_cube(cube, field_coords=None, target=None): - """Use the PP saving rules to convert a cube or + """Use the PP saving rules to convert a cube. + + Use the PP saving rules to convert a cube or iterable of cubes to an iterable of (2D cube, PP field) pairs. Args @@ -2298,14 +2304,16 @@ def save_pairs_from_cube(cube, field_coords=None, target=None): def as_fields(cube, field_coords=None, target=None): - """Use the PP saving rules (and any user rules) to convert a cube to + """Use the PP saving rules to convert a cube to an iterable of PP fields. + + Use the PP saving rules (and any user rules) to convert a cube to an iterable of PP fields. Args ---- cube A :class:`iris.cube.Cube` - **kwargs + **kwargs : * field_coords: List of 2 coords or coord names which are to be used for reducing the given cube into 2d slices, which will ultimately @@ -2332,7 +2340,7 @@ def save_fields(fields, target, append=False): An iterable of PP fields. target: A filename or open file handle. - **kwargs + **kwargs : * append: Whether to start a new file afresh or add the cube(s) to the end of the file. diff --git a/lib/iris/fileformats/pp_load_rules.py b/lib/iris/fileformats/pp_load_rules.py index 7c164edd41..01d1add197 100644 --- a/lib/iris/fileformats/pp_load_rules.py +++ b/lib/iris/fileformats/pp_load_rules.py @@ -59,8 +59,7 @@ def _convert_vertical_coords( brlev, dim=None, ): - """Encode scalar or vector vertical level values from PP headers as CM data - components. + """Encode scalar or vector vertical level values from PP headers as CM data components. Parameters ---------- @@ -340,7 +339,9 @@ def _reshape_vector_args(values_and_dims): def _collapse_degenerate_points_and_bounds(points, bounds=None, rtol=1.0e-7): - """Collapse points (and optionally bounds) in any dimensions over which all + """Collapse points (and optionally bounds) in any dimensions. + + Collapse points (and optionally bounds) in any dimensions over which all values are the same. All dimensions are tested, and if degenerate are reduced to length 1. @@ -385,8 +386,7 @@ def _collapse_degenerate_points_and_bounds(points, bounds=None, rtol=1.0e-7): def _reduce_points_and_bounds(points, lower_and_upper_bounds=None): - """Reduce the dimensionality of arrays of coordinate points (and optionally - bounds). + """Reduce the dimensionality of arrays of coordinate points (and optionally bounds). Dimensions over which all values are the same are reduced to size 1, using :func:`_collapse_degenerate_points_and_bounds`. @@ -441,7 +441,9 @@ def _reduce_points_and_bounds(points, lower_and_upper_bounds=None): def _new_coord_and_dims( is_vector_operation, name, units, points, lower_and_upper_bounds=None ): - """Make a new (coordinate, cube_dims) pair with the given points, name, units + """Make a new (coordinate, cube_dims) pair. + + Make a new (coordinate, cube_dims) pair with the given points, name, units and optional bounds. In 'vector' style operation, the data arrays must have same number of diff --git a/lib/iris/fileformats/rules.py b/lib/iris/fileformats/rules.py index 4467ae1cfa..59d0655198 100644 --- a/lib/iris/fileformats/rules.py +++ b/lib/iris/fileformats/rules.py @@ -100,7 +100,9 @@ def scalar_cell_method(cube, method, coord_name): def has_aux_factory(cube, aux_factory_class): - """Try to find an class:`~iris.aux_factory.AuxCoordFactory` instance of the + """Determine class:`~iris.aux_factory.AuxCoordFactory` availability within cube. + + Try to find an class:`~iris.aux_factory.AuxCoordFactory` instance of the specified type on the cube. """ @@ -111,7 +113,9 @@ def has_aux_factory(cube, aux_factory_class): def aux_factory(cube, aux_factory_class): - """Return the class:`~iris.aux_factory.AuxCoordFactory` instance of the + """Retrieve class:`~iris.aux_factory.AuxCoordFactory` instance from cube. + + Return the class:`~iris.aux_factory.AuxCoordFactory` instance of the specified type from a cube. """ @@ -195,7 +199,9 @@ def _regrid_to_target(src_cube, target_coords, target_cube): def _ensure_aligned(regrid_cache, src_cube, target_cube): - """Returns a version of `src_cube` suitable for use as an AuxCoord + """Ensure dimension compatible cubes are spatially aligned. + + Returns a version of `src_cube` suitable for use as an AuxCoord on `target_cube`, or None if no version can be made. """ @@ -381,8 +387,7 @@ def _load_pairs_from_fields_and_filenames( def load_pairs_from_fields(fields, converter): - """Convert an iterable of fields into an iterable of Cubes using the - provided converter. + """Convert iterable of fields into iterable of Cubes using the provided converter. Parameters ---------- diff --git a/lib/iris/fileformats/um/_fast_load.py b/lib/iris/fileformats/um/_fast_load.py index 6940bfed9c..c37d0abc32 100644 --- a/lib/iris/fileformats/um/_fast_load.py +++ b/lib/iris/fileformats/um/_fast_load.py @@ -2,7 +2,8 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Support for "fast" loading of structured UM files in iris load functions, +"""Support for "fast" loading of structured UM files in iris load functions. + i.e. :meth:`iris.load` and its associates. This provides a context manager to enable structured loading via all the iris @@ -154,8 +155,7 @@ def iter_fields_decorated_with_load_indices(fields_iter): def _convert_collation(collation): - """Converts a FieldCollation into the corresponding items of Cube - metadata. + """Converts a FieldCollation into the corresponding items of Cube metadata. Parameters ---------- @@ -542,7 +542,9 @@ def structured_um_loading(): @contextmanager def _raw_structured_loading(): - """Private context manager called by :func:`iris.load_raw` to prevent + """Prevent structured loading from concatenating its result cubes. + + Private context manager called by :func:`iris.load_raw` to prevent structured loading from concatenating its result cubes in that case. """ diff --git a/lib/iris/fileformats/um/_fast_load_structured_fields.py b/lib/iris/fileformats/um/_fast_load_structured_fields.py index 81bec94f79..17b3d4f9a0 100644 --- a/lib/iris/fileformats/um/_fast_load_structured_fields.py +++ b/lib/iris/fileformats/um/_fast_load_structured_fields.py @@ -20,7 +20,9 @@ class BasicFieldCollation: - """An object representing a group of UM fields with array structure that can + """An object representing a group of UM fields with array structure. + + An object representing a group of UM fields with array structure that can be vectorized into a single cube. For example: @@ -264,7 +266,9 @@ def _um_collation_key_function(field): def group_structured_fields( field_iterator, collation_class=BasicFieldCollation, **collation_kwargs ): - """Collect structured fields into identified groups whose fields can be + """Collect structured fields into identified groups. + + Collect structured fields into identified groups whose fields can be combined to form a single cube. Parameters diff --git a/lib/iris/fileformats/um/_ff_replacement.py b/lib/iris/fileformats/um/_ff_replacement.py index 8ceb30bb92..d8dee81b36 100644 --- a/lib/iris/fileformats/um/_ff_replacement.py +++ b/lib/iris/fileformats/um/_ff_replacement.py @@ -81,8 +81,7 @@ def load_cubes(filenames, callback, constraints=None, _loader_kwargs=None): def load_cubes_32bit_ieee(filenames, callback, constraints=None): - """Loads cubes from filenames of 32bit ieee converted UM fieldsfile-like - files. + """Loads cubes from filenames of 32bit ieee converted UM fieldsfile-like files. See Also -------- diff --git a/lib/iris/fileformats/um/_optimal_array_structuring.py b/lib/iris/fileformats/um/_optimal_array_structuring.py index 1e58a33f41..64f4e8fad2 100644 --- a/lib/iris/fileformats/um/_optimal_array_structuring.py +++ b/lib/iris/fileformats/um/_optimal_array_structuring.py @@ -9,7 +9,9 @@ def _optimal_dimensioning_structure(structure, element_priorities): - """Uses the structure options provided by the + """Determine the optimal array structure for the :class:`FieldCollation`. + + Uses the structure options provided by the :class:`~iris.fileformats._structured_array_identification.GroupStructure` to determine the optimal array structure for the :class:`FieldCollation`. diff --git a/lib/iris/iterate.py b/lib/iris/iterate.py index 1d8ae49d06..be2a436a5e 100644 --- a/lib/iris/iterate.py +++ b/lib/iris/iterate.py @@ -166,7 +166,9 @@ def izip(*cubes, **kwargs): class _ZipSlicesIterator(Iterator): - """Extension to _SlicesIterator (see cube.py) to support iteration over a + """Support iteration over a collection of cubes. + + Extension to _SlicesIterator (see cube.py) to support iteration over a collection of cubes in step. """ @@ -278,7 +280,9 @@ def __next__(self): class _CoordWrapper: - """Class for creating a coordinate wrapper that allows the use of an + """Create a coordinate wrapper. + + Class for creating a coordinate wrapper that allows the use of an alternative equality function based on metadata rather than metadata + points/bounds. diff --git a/lib/iris/plot.py b/lib/iris/plot.py index d8e9426035..7974b8fd0e 100644 --- a/lib/iris/plot.py +++ b/lib/iris/plot.py @@ -2,8 +2,7 @@ # # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. -"""Iris-specific extensions to matplotlib, mimicking the :mod:`matplotlib.pyplot` -interface. +"""Iris-specific extensions to matplotlib, mimicking the :mod:`matplotlib.pyplot` interface. See also: :ref:`matplotlib `. @@ -133,7 +132,9 @@ def _valid_bound_dim_coord(coord): def _get_plot_defn(cube, mode, ndims=2): - """Return data and plot-axis coords given a cube & a mode of either + """Return data and plot-axis coords. + + Return data and plot-axis coords given a cube & a mode of either POINT_MODE or BOUND_MODE. """ @@ -275,7 +276,9 @@ def _invert_yaxis(v_coord, axes=None): def _check_bounds_contiguity_and_mask(coord, data, atol=None, rtol=None): - """Checks that any discontiguities in the bounds of the given coordinate only + """Check discontiguities in the bounds of the given coordinate. + + Checks that any discontiguities in the bounds of the given coordinate only occur where the data is masked. Where a discontinuity occurs the grid created for plotting will not be @@ -698,7 +701,9 @@ def _get_geodesic_params(globe): def _shift_plot_sections(u_object, u, v): - """Shifts subsections of u by multiples of 360 degrees within ranges + """Shifts subsections of u by multiples of 360 degrees. + + Shifts subsections of u by multiples of 360 degrees within ranges defined by the points where the line should cross over the 0/360 degree longitude boundary. @@ -854,7 +859,9 @@ def _draw_two_1d_from_points(draw_method_name, arg_func, *args, **kwargs): def _replace_axes_with_cartopy_axes(cartopy_proj): - """Replace non-cartopy subplot/axes with a cartopy alternative + """Replace non-cartopy subplot/axes with a cartopy alternative. + + Replace non-cartopy subplot/axes with a cartopy alternative based on the provided projection. If the current axes are already an instance of :class:`cartopy.mpl.geoaxes.GeoAxes` then no action is taken. @@ -885,7 +892,9 @@ def _replace_axes_with_cartopy_axes(cartopy_proj): def _ensure_cartopy_axes_and_determine_kwargs(x_coord, y_coord, kwargs): - """Replace the current non-cartopy axes with + """Replace the current non-cartopy axes with :class:`cartopy.mpl.geoaxes.GeoAxes`. + + Replace the current non-cartopy axes with :class:`cartopy.mpl.geoaxes.GeoAxes` and return the appropriate kwargs dict based on the provided coordinates and kwargs. @@ -1475,7 +1484,9 @@ def _vector_component_args(x_points, y_points, u_data, *args, **kwargs): def barbs(u_cube, v_cube, *args, **kwargs): - """Draws a barb plot from two vector component cubes. Triangles, full-lines + """Draw a barb plot from two vector component cubes. + + Draws a barb plot from two vector component cubes. Triangles, full-lines and half-lines represent increments of 50, 10 and 5 respectively. Args: diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index 1fa2edd630..ce52fbdb6b 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -282,8 +282,7 @@ def points(cube, *args, **kwargs): def plot(*args, **kwargs): - """Draws a labelled line plot based on the given cube(s) or - coordinate(s). + """Draws a labelled line plot based on the given cube(s) or coordinate(s). See :func:`iris.plot.plot` for details of valid arguments and keyword arguments. @@ -301,8 +300,7 @@ def plot(*args, **kwargs): def scatter(x, y, *args, **kwargs): - """Draws a labelled scatter plot based on the given cubes or - coordinates. + """Draws a labelled scatter plot based on the given cubes or coordinates. See :func:`iris.plot.scatter` for details of valid arguments and keyword arguments. @@ -329,6 +327,7 @@ def fill_between(x, y1, y2, *args, **kwargs): ----- 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) @@ -346,6 +345,7 @@ def hist(x, *args, **kwargs): ----- 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/symbols.py b/lib/iris/symbols.py index 0e53588a66..4e66daa100 100644 --- a/lib/iris/symbols.py +++ b/lib/iris/symbols.py @@ -193,8 +193,11 @@ def _backslash_path(): def _wedge_fix(wedge_path): - """Fixes the problem with Path.wedge where it doesn't initialise the first, + """Fix the problem with Path.wedge. + + Fixes the problem with Path.wedge where it doesn't initialise the first, and last two vertices. + This fix should not have any side-effects once Path.wedge has been fixed, but will then be redundant and should be removed. diff --git a/lib/iris/util.py b/lib/iris/util.py index 7d87492c7f..9ae1ceb919 100644 --- a/lib/iris/util.py +++ b/lib/iris/util.py @@ -158,7 +158,9 @@ def delta(ndarray, dimension, circular=False): def describe_diff(cube_a, cube_b, output_file=None): - """Prints the differences that prevent compatibility between two cubes, as + """Print the differences that prevent compatibility between two cubes. + + Print the differences that prevent compatibility between two cubes, as defined by :meth:`iris.cube.Cube.is_compatible()`. Parameters @@ -227,7 +229,7 @@ def describe_diff(cube_a, cube_b, output_file=None): def guess_coord_axis(coord): - """Returns a "best guess" axis name of the coordinate. + """Return a "best guess" axis name of the coordinate. Heuristic categorisation of the coordinate into either label 'T', 'Z', 'Y', 'X' or None. @@ -351,7 +353,7 @@ def rolling_window(a, window=1, step=1, axis=-1): def array_equal(array1, array2, withnans=False): - """Returns whether two arrays have the same shape and elements. + """Return whether two arrays have the same shape and elements. Parameters ---------- @@ -390,7 +392,9 @@ def normalise_array(array): def approx_equal(a, b, max_absolute_error=1e-10, max_relative_error=1e-10): - """Returns whether two numbers are almost equal, allowing for the finite + """Check if two numbers are almost equal. + + Returns whether two numbers are almost equal, allowing for the finite precision of floating point numbers. .. deprecated:: 3.2.0 @@ -424,8 +428,9 @@ def approx_equal(a, b, max_absolute_error=1e-10, max_relative_error=1e-10): def between(lh, rh, lh_inclusive=True, rh_inclusive=True): - """Provides a convenient way of defining a 3 element inequality such as - ``a < number < b``. + """Provide convenient way of defining a 3 element inequality. + + Such as ``a < number < b``. Parameters ---------- @@ -630,7 +635,9 @@ def monotonic(array, strict=False, return_direction=False): def column_slices_generator(full_slice, ndims): - """Given a full slice full of tuples, return a dictionary mapping old + """Return a dictionary mapping old data dimensions to new. + + Given a full slice full of tuples, return a dictionary mapping old data dimensions to new and a generator which gives the successive slices needed to index correctly (across columns). @@ -703,7 +710,9 @@ def is_tuple_style_index(key): def _build_full_slice_given_keys(keys, ndim): - """Given the keys passed to a __getitem__ call, build an equivalent + """Build an equivalent tuple of keys which span ndims. + + Given the keys passed to a __getitem__ call, build an equivalent tuple of keys which span ndims. """ @@ -811,8 +820,7 @@ def _slice_data_with_keys(data, keys): def _wrap_function_for_method(function, docstring=None): - """Returns a wrapper function modified to be suitable for use as a - method. + """Return a wrapper function modified to be suitable for use as a method. The wrapper function renames the first argument as "self" and allows an alternative docstring, thus allowing the built-in help(...) @@ -857,7 +865,9 @@ def _wrap_function_for_method(function, docstring=None): class _MetaOrderedHashable(ABCMeta): - """A metaclass that ensures that non-abstract subclasses of _OrderedHashable + """Ensures that non-abstract subclasses are given a default __init__ method. + + A metaclass that ensures that non-abstract subclasses of _OrderedHashable without an explicit __init__ method are given a default __init__ method with the appropriate method signature. @@ -922,7 +932,9 @@ class _OrderedHashable(Hashable, metaclass=_MetaOrderedHashable): @property @abstractmethod def _names(self): - """Override this attribute to declare the names of all the attributes + """Override this attribute to declare the names of all the attributes relevant. + + Override this attribute to declare the names of all the attributes relevant to the hash/comparison semantics. """ @@ -990,7 +1002,9 @@ def create_temp_filename(suffix=""): def clip_string(the_str, clip_length=70, rider="..."): - """Returns a clipped version of the string based on the specified clip + """Return clipped version of the string based on the specified clip length. + + Return a clipped version of the string based on the specified clip length and whether or not any graceful clip points can be found. If the string to be clipped is shorter than the specified clip @@ -1025,6 +1039,7 @@ def clip_string(the_str, clip_length=70, rider="..."): ----- 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: return the_str @@ -1046,7 +1061,9 @@ def clip_string(the_str, clip_length=70, rider="..."): def format_array(arr): - """Returns the given array as a string, using the python builtin str + """Create a new axis as the leading dimension of the cube. + + Returns the given array as a string, using the python builtin str function on a piecewise basis. Useful for xml representation of arrays. @@ -1072,7 +1089,9 @@ def format_array(arr): 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 + """Create a new axis as the leading dimension of the cube. + + Create a new axis as the leading dimension of the cube, promoting a scalar coordinate if specified. Parameters @@ -1108,6 +1127,7 @@ def new_axis(src_cube, scalar_coord=None, expand_extras=()): # maybe not lazy ----- 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): @@ -1196,7 +1216,9 @@ def _handle_dimensional_metadata(cube, dm_item, cube_add_method, expand_extras): def squeeze(cube): - """Removes any dimension of length one. If it has an associated DimCoord or + """Removes any dimension of length one. + + Removes any dimension of length one. If it has an associated DimCoord or AuxCoord, this becomes a scalar coord. Parameters @@ -1234,7 +1256,9 @@ def squeeze(cube): def file_is_newer_than(result_path, source_paths): - """Return whether the 'result' file has a later modification time than all of + """Determine if the 'result' file was modified last. + + Return whether the 'result' file has a later modification time than all of the 'source' files. If a stored result depends entirely on known 'sources', it need only be @@ -1393,7 +1417,9 @@ def points_step(points): def unify_time_units(cubes): - """Performs an in-place conversion of the time units of all time coords in the + """Performs an in-place conversion of the time units. + + Performs an in-place conversion of the time units of all time coords in the cubes in a given iterable. One common epoch is defined for each calendar found in the cubes to prevent units being defined with inconsistencies between epoch and calendar. During this process, all time coordinates have @@ -1429,7 +1455,9 @@ def unify_time_units(cubes): def _is_circular(points, modulus, bounds=None): - """Determine whether the provided points or bounds are circular in nature + """Determine whether the provided points or bounds are circular. + + Determine whether the provided points or bounds are circular in nature relative to the modulus value. If the bounds are provided then these are checked for circularity rather @@ -1493,10 +1521,11 @@ def _is_circular(points, modulus, bounds=None): def promote_aux_coord_to_dim_coord(cube, name_or_coord): - r"""Promotes an AuxCoord on the cube to a DimCoord. This AuxCoord must be - associated with a single cube dimension. If the AuxCoord is associated - with a dimension that already has a DimCoord, that DimCoord gets - demoted to an AuxCoord. + r"""Promotes an auxiliary to a dimension coordinate on the cube. + + This AuxCoord must be associated with a single cube dimension. If the + AuxCoord is associated with a dimension that already has a DimCoord, that + DimCoord gets demoted to an AuxCoord. Parameters ---------- @@ -1671,7 +1700,6 @@ def demote_dim_coord_to_aux_coord(cube, name_or_coord): 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 @@ -1702,13 +1730,12 @@ def demote_dim_coord_to_aux_coord(cube, name_or_coord): @functools.wraps(np.meshgrid) def _meshgrid(*xi, **kwargs): - """@numpy v1.13, the dtype of each output n-D coordinate is the same as its + """Ensures consistent meshgrid behaviour across numpy versions. + + @numpy v1.13, the dtype of each output n-D coordinate is the same as its associated input 1D coordinate. This is not the case prior to numpy v1.13, where the output dtype is cast up to its highest resolution, regardlessly. - This convenience function ensures consistent meshgrid behaviour across - numpy versions. - Reference: https://github.com/numpy/numpy/pull/5302 """ @@ -1720,7 +1747,9 @@ def _meshgrid(*xi, **kwargs): def find_discontiguities(cube, rel_tol=1e-5, abs_tol=1e-8): - """Searches the 'x' and 'y' coord on the cube for discontiguities in the + """Identify spatial discontiguities. + + Searches the 'x' and 'y' coord on the cube for discontiguities in the bounds array, returned as a boolean array (True for all cells which are discontiguous with the cell immediately above them or to their right). @@ -1765,7 +1794,6 @@ def find_discontiguities(cube, rel_tol=1e-5, abs_tol=1e-8): This function does not maintain laziness when called; it realises data. See more at :doc:`/userguide/real_and_lazy_data`. - """ lats_and_lons = [ "latitude", @@ -1812,10 +1840,11 @@ def find_discontiguities(cube, rel_tol=1e-5, abs_tol=1e-8): def _mask_array(array, points_to_mask, in_place=False): - """Apply masking to array where points_to_mask is True/non-zero. Designed to - work with iris.analysis.maths._binary_op_common so array and points_to_mask - will be broadcastable to each other. array and points_to_mask may be numpy - or dask types (or one of each). + """Apply masking to array where points_to_mask is True/non-zero. + + Designed to work with iris.analysis.maths._binary_op_common so array + and points_to_mask will be broadcastable to each other. + array and points_to_mask may be numpy or dask types (or one of each). If array is lazy then in_place is ignored: _math_op_common will use the returned value regardless of in_place, so we do not need to implement it @@ -1865,7 +1894,9 @@ def _mask_array(array, points_to_mask, in_place=False): @_lenient_client(services=SERVICES) def mask_cube(cube, points_to_mask, in_place=False, dim=None): - """Masks any cells in the cube's data array which correspond to cells marked + """Masks any cells in the cube's data array. + + Masks any cells in the cube's data array which correspond to cells marked ``True`` (or non zero) in ``points_to_mask``. ``points_to_mask`` may be specified as a :class:`numpy.ndarray`, :class:`dask.array.Array`, :class:`iris.coords.Coord` or :class:`iris.cube.Cube`, following the same @@ -2035,10 +2066,13 @@ def is_masked(array): def _strip_metadata_from_dims(cube, dims): """Remove ancillary variables and cell measures that map to specific dimensions. - Returns a cube copy with (possibly) some cell-measures and ancillary variables removed. + Returns a cube copy with (possibly) some cell-measures and ancillary + variables removed. 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. + + Note: does nothing to (aux)-coordinates. Those would be handled explicitly + by the calling operation. """ reduced_cube = cube.copy() diff --git a/noxfile.py b/noxfile.py index 4d3bb85f98..da71144913 100644 --- a/noxfile.py +++ b/noxfile.py @@ -109,8 +109,9 @@ def cache_cartopy(session: nox.sessions.Session) -> None: def prepare_venv(session: nox.sessions.Session) -> None: - """Create and cache the nox session conda environment, and additionally - provide conda environment package details and info. + """Create and cache the nox session conda environment. + + Additionally provide conda environment package details and info. Note that, iris is installed into the environment using pip. diff --git a/pyproject.toml b/pyproject.toml index 37384a3c3e..19e3d26cdf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,12 +105,13 @@ known-first-party = ["iris"] [tool.ruff.lint.per-file-ignores] # All test scripts -"test_*.py" = [ + +"lib/iris/tests/*.py" = [ # https://docs.astral.sh/ruff/rules/undocumented-public-module/ "D100", # Missing docstring in public module + "D205", # 1 blank line required between summary line and description ] - [tool.ruff.lint.pydocstyle] convention = "numpy" diff --git a/setup.py b/setup.py index 1027085e81..004c6b2301 100644 --- a/setup.py +++ b/setup.py @@ -25,8 +25,10 @@ def run(self): def custom_command(cmd, help=""): - """Factory function to generate a custom command that adds additional - behaviour to build the CF standard names module. + """Factory function to generate a custom command. + + Custom command will add additional behaviour to build the CF + standard names module. """ From fa074429ac16456f3a01de72fff1f6744d599347 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:17:54 +0000 Subject: [PATCH 19/26] [pre-commit.ci] pre-commit autoupdate (#5699) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.1.11 → v0.1.13](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.11...v0.1.13) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ded673f008..11a5d42889 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,7 +29,7 @@ repos: - id: no-commit-to-branch - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.1.11" + rev: "v0.1.13" hooks: - id: ruff types: [file, python] From ec709b30789c853841d3cdde4c12af2fc9e0b04e Mon Sep 17 00:00:00 2001 From: Bill Little Date: Wed, 17 Jan 2024 10:45:02 +0000 Subject: [PATCH 20/26] update rtd ubuntu and mambaforge (#5702) * update rtd ubuntu and mambaforge * add whatsnew entery --- .readthedocs.yml | 4 ++-- docs/src/whatsnew/latest.rst | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index af1a8f6303..d82bd513ca 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,9 +1,9 @@ version: 2 build: - os: ubuntu-20.04 + os: "ubuntu-22.04" tools: - python: mambaforge-4.10 + python: "mambaforge-22.9" jobs: post_checkout: # The SciTools/iris repository is shallow i.e., has a .git/shallow, diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index dfc1019683..41f765bfe1 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -120,6 +120,9 @@ This document explains the changes made to Iris for this release #. `@bjlittle`_ enforced the minimum pin of ``numpy>1.22`` in accordance with the `NEP29 Drop Schedule`_. (:pull:`5668`) +#. `@bjlittle`_ updated ``ubuntu`` and ``mambaforge`` to the latest versions for ``readthedocs`` + (:pull:`5702`) + 📚 Documentation ================ From 54f9e980e7129939546b01c71e862f735e017d47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 13:55:07 +0000 Subject: [PATCH 21/26] Bump actions/cache from 3 to 4 (#5703) Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmarks_run.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmarks_run.yml b/.github/workflows/benchmarks_run.yml index 5bc2fba6ec..0d9d7f0756 100644 --- a/.github/workflows/benchmarks_run.yml +++ b/.github/workflows/benchmarks_run.yml @@ -46,7 +46,7 @@ jobs: - name: Cache environment directories id: cache-env-dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | .nox @@ -56,7 +56,7 @@ jobs: - name: Cache test data directory id: cache-test-data - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ${{ env.IRIS_TEST_DATA_PATH }} From 67bb5aee748ee154a4067be25a8276ea602ab993 Mon Sep 17 00:00:00 2001 From: tkknight <2108488+tkknight@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:46:13 +0000 Subject: [PATCH 22/26] ruff compliance for D401. (#5687) * ruff complliance for D205 (wip) * wip * wip * wip * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * various minor fixes. * fix doctest. * gallery noqa and minor fixes. * removed comments * ruff compliance for D401. * removed temp noqa's * wip * wip * fix typo. * Update lib/iris/fileformats/_ff.py Co-authored-by: Bill Little * review actions. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bill Little --- .ruff.toml | 1 - benchmarks/benchmarks/__init__.py | 8 ++-- benchmarks/benchmarks/cperf/load.py | 4 +- benchmarks/benchmarks/cube.py | 2 +- .../experimental/ugrid/regions_combine.py | 2 +- benchmarks/benchmarks/generate_data/stock.py | 8 ++-- .../benchmarks/sperf/combine_regions.py | 2 +- benchmarks/bm_runner.py | 2 +- .../general/plot_custom_file_loading.py | 4 +- .../gallery_code/meteorology/plot_COP_maps.py | 2 +- docs/gallery_tests/conftest.py | 2 +- docs/gallery_tests/test_gallery_examples.py | 2 +- lib/iris/_concatenate.py | 12 ++--- lib/iris/_data_manager.py | 4 +- lib/iris/_merge.py | 6 +-- lib/iris/_representation/cube_printout.py | 2 +- lib/iris/analysis/_interpolation.py | 2 +- lib/iris/analysis/_regrid.py | 2 +- lib/iris/analysis/cartography.py | 2 +- lib/iris/analysis/maths.py | 8 ++-- lib/iris/analysis/trajectory.py | 6 +-- lib/iris/common/_split_attribute_dicts.py | 5 +- lib/iris/common/lenient.py | 8 ++-- lib/iris/common/metadata.py | 6 +-- lib/iris/common/mixin.py | 4 +- lib/iris/coord_categorisation.py | 2 +- lib/iris/coord_systems.py | 26 +++++----- lib/iris/coords.py | 48 +++++++++---------- lib/iris/cube.py | 48 +++++++++---------- lib/iris/experimental/raster.py | 2 +- lib/iris/experimental/regrid.py | 4 +- lib/iris/experimental/representation.py | 2 +- lib/iris/experimental/stratify.py | 2 +- lib/iris/experimental/ugrid/load.py | 2 +- lib/iris/experimental/ugrid/mesh.py | 4 +- lib/iris/fileformats/_ff.py | 6 +-- .../fileformats/_nc_load_rules/actions.py | 2 +- lib/iris/fileformats/abf.py | 2 +- lib/iris/fileformats/nimrod.py | 2 +- lib/iris/fileformats/pp.py | 6 +-- lib/iris/fileformats/pp_load_rules.py | 2 +- lib/iris/fileformats/rules.py | 2 +- lib/iris/fileformats/um/_fast_load.py | 2 +- .../um/_fast_load_structured_fields.py | 2 +- lib/iris/fileformats/um/_ff_replacement.py | 4 +- lib/iris/palette.py | 2 +- lib/iris/plot.py | 8 ++-- lib/iris/quickplot.py | 2 +- lib/iris/util.py | 14 +++--- noxfile.py | 4 +- pyproject.toml | 1 + setup.py | 2 +- 52 files changed, 154 insertions(+), 155 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index 5a39e2bbf8..5d78ecdb57 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -29,7 +29,6 @@ lint.ignore = [ "D102", # Missing docstring in public method # (D-3) Temporary, before an initial review, either fix ocurrences or move to (2). "D103", # Missing docstring in public function - "D401", # First line of docstring should be in imperative mood: ... # pyupgrade (UP) # https://docs.astral.sh/ruff/rules/#pyupgrade-up diff --git a/benchmarks/benchmarks/__init__.py b/benchmarks/benchmarks/__init__.py index de03ff3fea..87a77fa5a4 100644 --- a/benchmarks/benchmarks/__init__.py +++ b/benchmarks/benchmarks/__init__.py @@ -10,7 +10,7 @@ def disable_repeat_between_setup(benchmark_object): - """Decorator for benchmarks where object persistence would be inappropriate. + """Benchmarks where object persistence would be inappropriate (decorator). E.g: * Benchmarking data realisation @@ -86,7 +86,7 @@ def addedmem_mb(self): @staticmethod def decorator(decorated_func): - """Decorates this benchmark to track growth in resident memory during execution. + """Benchmark to track growth in resident memory during execution. Intended for use on ASV ``track_`` benchmarks. Applies the :class:`TrackAddedMemoryAllocation` context manager to the benchmark @@ -107,7 +107,9 @@ def _wrapper(*args, **kwargs): def on_demand_benchmark(benchmark_object): - """Decorator. Disables these benchmark(s) unless ON_DEMAND_BENCHARKS env var is set. + """Disables these benchmark(s) unless ON_DEMAND_BENCHARKS env var is set. + + This is a decorator. For benchmarks that, for whatever reason, should not be run by default. E.g: diff --git a/benchmarks/benchmarks/cperf/load.py b/benchmarks/benchmarks/cperf/load.py index 9ace3ad56b..cafc4631c0 100644 --- a/benchmarks/benchmarks/cperf/load.py +++ b/benchmarks/benchmarks/cperf/load.py @@ -10,7 +10,7 @@ @on_demand_benchmark class SingleDiagnosticLoad(SingleDiagnosticMixin): def time_load(self, _, __, ___): - """The 'real world comparison'. + """Perform a 'real world comparison'. * UM coords are always realised (DimCoords). * LFRic coords are not realised by default (MeshCoords). @@ -26,7 +26,7 @@ def time_load(self, _, __, ___): assert coord.has_lazy_bounds() == expecting_lazy_coords def time_load_w_realised_coords(self, _, __, ___): - """A valuable extra comparison where both UM and LFRic coords are realised.""" + """Valuable extra comparison where both UM and LFRic coords are realised.""" cube = self.load() for coord_name in "longitude", "latitude": coord = cube.coord(coord_name) diff --git a/benchmarks/benchmarks/cube.py b/benchmarks/benchmarks/cube.py index fc07d55111..4548d4c28d 100644 --- a/benchmarks/benchmarks/cube.py +++ b/benchmarks/benchmarks/cube.py @@ -45,7 +45,7 @@ def setup(self): raise NotImplementedError def create(self): - """Generic cube creation. + """Create a cube (generic). cube_kwargs allow dynamic inclusion of different components; specified in subclasses. diff --git a/benchmarks/benchmarks/experimental/ugrid/regions_combine.py b/benchmarks/benchmarks/experimental/ugrid/regions_combine.py index 36feb65cbe..10711d0349 100644 --- a/benchmarks/benchmarks/experimental/ugrid/regions_combine.py +++ b/benchmarks/benchmarks/experimental/ugrid/regions_combine.py @@ -92,7 +92,7 @@ def setup_cache(self): ) def setup(self, n_cubesphere, imaginary_data=True, create_result_cube=True): - """The combine-tests "standard" setup operation. + """Combine-tests "standard" setup operation. Load the source cubes (full-mesh + region) from disk. These are specific to the cubesize parameter. diff --git a/benchmarks/benchmarks/generate_data/stock.py b/benchmarks/benchmarks/generate_data/stock.py index a04eff6701..17f3b23f92 100644 --- a/benchmarks/benchmarks/generate_data/stock.py +++ b/benchmarks/benchmarks/generate_data/stock.py @@ -49,7 +49,7 @@ def _external(func_name_, temp_file_dir, **kwargs_): def create_file__xios_2d_face_half_levels( temp_file_dir, dataset_name, n_faces=866, n_times=1 ): - """Wrapper for :meth:`iris.tests.stock.netcdf.create_file__xios_2d_face_half_levels`. + """Create file wrapper for :meth:`iris.tests.stock.netcdf.create_file__xios_2d_face_half_levels`. Have taken control of temp_file_dir @@ -67,7 +67,7 @@ def create_file__xios_2d_face_half_levels( def create_file__xios_3d_face_half_levels( temp_file_dir, dataset_name, n_faces=866, n_times=1, n_levels=38 ): - """Wrapper for :meth:`iris.tests.stock.netcdf.create_file__xios_3d_face_half_levels`. + """Create file wrapper for :meth:`iris.tests.stock.netcdf.create_file__xios_3d_face_half_levels`. Have taken control of temp_file_dir @@ -84,7 +84,7 @@ def create_file__xios_3d_face_half_levels( def sample_mesh(n_nodes=None, n_faces=None, n_edges=None, lazy_values=False): - """Wrapper for :meth:iris.tests.stock.mesh.sample_mesh`.""" + """Sample mesh wrapper for :meth:iris.tests.stock.mesh.sample_mesh`.""" def _external(*args, **kwargs): from iris.experimental.ugrid import save_mesh @@ -112,7 +112,7 @@ def _external(*args, **kwargs): def sample_meshcoord(sample_mesh_kwargs=None, location="face", axis="x"): - """Wrapper for :meth:`iris.tests.stock.mesh.sample_meshcoord`. + """Sample meshcoord wrapper for :meth:`iris.tests.stock.mesh.sample_meshcoord`. Parameters deviate from the original as cannot pass a :class:`iris.experimental.ugrid.Mesh to the separate Python instance - must diff --git a/benchmarks/benchmarks/sperf/combine_regions.py b/benchmarks/benchmarks/sperf/combine_regions.py index adc51ef6dc..7d677ed74f 100644 --- a/benchmarks/benchmarks/sperf/combine_regions.py +++ b/benchmarks/benchmarks/sperf/combine_regions.py @@ -83,7 +83,7 @@ def setup_cache(self): ) def setup(self, n_cubesphere, imaginary_data=True, create_result_cube=True): - """The combine-tests "standard" setup operation. + """Combine-tests "standard" setup operation. Load the source cubes (full-mesh + region) from disk. These are specific to the cubesize parameter. diff --git a/benchmarks/bm_runner.py b/benchmarks/bm_runner.py index 741ecb8580..10dc5f469a 100644 --- a/benchmarks/bm_runner.py +++ b/benchmarks/bm_runner.py @@ -332,7 +332,7 @@ def add_asv_arguments(self) -> None: @staticmethod @abstractmethod def func(args: argparse.Namespace): - """The function to return when the subparser is parsed. + """Return when the subparser is parsed. `func` is then called, performing the user's selected sub-command. diff --git a/docs/gallery_code/general/plot_custom_file_loading.py b/docs/gallery_code/general/plot_custom_file_loading.py index c7a560ff0f..06de887614 100644 --- a/docs/gallery_code/general/plot_custom_file_loading.py +++ b/docs/gallery_code/general/plot_custom_file_loading.py @@ -90,7 +90,7 @@ def load_NAME_III(filename): - """Loads the Met Office's NAME III grid output files. + """Load the Met Office's NAME III grid output files. Loads the Met Office's NAME III grid output files returning headers, column definitions and data arrays as 3 separate lists. @@ -180,7 +180,7 @@ def load_NAME_III(filename): def NAME_to_cube(filenames, callback): - """Returns a generator of cubes given a list of filenames and a callback.""" + """Return a generator of cubes given a list of filenames and a callback.""" for filename in filenames: header, column_headings, data_arrays = load_NAME_III(filename) diff --git a/docs/gallery_code/meteorology/plot_COP_maps.py b/docs/gallery_code/meteorology/plot_COP_maps.py index 43f25425e5..1c5e865a8f 100644 --- a/docs/gallery_code/meteorology/plot_COP_maps.py +++ b/docs/gallery_code/meteorology/plot_COP_maps.py @@ -32,7 +32,7 @@ def cop_metadata_callback(cube, field, filename): - """Function which adds an "Experiment" coordinate which comes from the filename.""" + """Add an "Experiment" coordinate which comes from the filename.""" # Extract the experiment name (such as A1B or E1) from the filename (in # this case it is just the start of the file name, before the first "."). fname = os.path.basename(filename) # filename without path. diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index ff352f5d01..564a2892a2 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -18,7 +18,7 @@ @pytest.fixture def image_setup_teardown(): - """Setup and teardown fixture. + """Perform setup and teardown fixture. Ensures all figures are closed before and after test to prevent one test polluting another if it fails with a figure unclosed. diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index 37f2858ee9..39e8fe0507 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -17,7 +17,7 @@ def gallery_examples(): - """Generator to yield all current gallery examples.""" + """Entry point for generator to yield all current gallery examples.""" for example_file in GALLERY_DIR.glob("*/plot*.py"): yield example_file.stem diff --git a/lib/iris/_concatenate.py b/lib/iris/_concatenate.py index 8be766ea85..214cfa00cc 100644 --- a/lib/iris/_concatenate.py +++ b/lib/iris/_concatenate.py @@ -151,7 +151,7 @@ def name(self): class _DerivedCoordAndDims( namedtuple("DerivedCoordAndDims", ["coord", "dims", "aux_factory"]) ): - """Container for a derived coordinate and dimnesions(s). + """Container for a derived coordinate and dimensions(s). Container for a derived coordinate, the associated AuxCoordFactory, and the associated data dimension(s) spanned over a :class:`iris.cube.Cube`. @@ -385,10 +385,7 @@ class _CubeSignature: """ def __init__(self, cube): - """Represents the cube metadata and associated coordinate metadata. - - Represents the cube metadata and associated coordinate metadata that - allows suitable cubes for concatenation to be identified. + """Represent the cube metadata and associated coordinate metadata. Parameters ---------- @@ -733,10 +730,7 @@ class _ProtoCube: """Framework for concatenating multiple source-cubes over one common dimension.""" def __init__(self, cube): - """Create a new _ProtoCube and record the cube as a source-cube. - - Create a new _ProtoCube from the given cube and record the cube - as a source-cube. + """Create a new _ProtoCube from the given cube and record the cube as a source-cube. Parameters ---------- diff --git a/lib/iris/_data_manager.py b/lib/iris/_data_manager.py index da7a19c95b..6db1d16889 100644 --- a/lib/iris/_data_manager.py +++ b/lib/iris/_data_manager.py @@ -117,7 +117,7 @@ def __ne__(self, other): return result def __repr__(self): - """Returns an string representation of the instance.""" + """Return an string representation of the instance.""" fmt = "{cls}({data!r})" result = fmt.format(data=self.core_data(), cls=type(self).__name__) @@ -269,7 +269,7 @@ def shape(self): return self.core_data().shape def copy(self, data=None): - """Returns a deep copy of this :class:`~iris._data_manager.DataManager` instance. + """Return a deep copy of this :class:`~iris._data_manager.DataManager` instance. Parameters ---------- diff --git a/lib/iris/_merge.py b/lib/iris/_merge.py index e31a4cabc7..7705dd6bea 100644 --- a/lib/iris/_merge.py +++ b/lib/iris/_merge.py @@ -1182,7 +1182,7 @@ def _report_duplicate(self, nd_indexes, group_by_nd_index): raise iris.exceptions.DuplicateDataError(msg) def merge(self, unique=True): - """Returns the list of cubes resulting from merging the registered source-cubes. + """Return the list of cubes resulting from merging the registered source-cubes. Parameters ---------- @@ -1319,7 +1319,7 @@ def register(self, cube, error_on_mismatch=False): return match def _guess_axis(self, name): - """Returns a "best guess" axis name of the candidate dimension. + """Return a "best guess" axis name of the candidate dimension. Heuristic categoration of the candidate dimension (i.e. scalar_defn index) into either label 'T', 'Z', 'Y', 'X' @@ -1564,7 +1564,7 @@ def _get_cube(self, data): return cube def _nd_index(self, position): - """Returns the n-dimensional index of thr source-cube, within the merged cube.""" + """Return the n-dimensional index of thr source-cube, within the merged cube.""" index = [] # Determine the index of the source-cube cell for each dimension. diff --git a/lib/iris/_representation/cube_printout.py b/lib/iris/_representation/cube_printout.py index 3031014faa..47c0b8b631 100644 --- a/lib/iris/_representation/cube_printout.py +++ b/lib/iris/_representation/cube_printout.py @@ -134,7 +134,7 @@ class CubePrinter: N_INDENT_EXTRA = 4 def __init__(self, cube_or_summary): - """An object that provides a printout of a cube. + """Object that provides a printout of a cube. Parameters ---------- diff --git a/lib/iris/analysis/_interpolation.py b/lib/iris/analysis/_interpolation.py index 04e1e39074..59863e3485 100644 --- a/lib/iris/analysis/_interpolation.py +++ b/lib/iris/analysis/_interpolation.py @@ -158,7 +158,7 @@ def get_xy_coords(cube, dim_coords=False): def snapshot_grid(cube): - """Helper function that returns deep copies of lateral (dimension) coordinates from a cube.""" + """Return deep copies of lateral (dimension) coordinates from a cube.""" x, y = get_xy_dim_coords(cube) return x.copy(), y.copy() diff --git a/lib/iris/analysis/_regrid.py b/lib/iris/analysis/_regrid.py index 77b3a306d8..321194d1fc 100644 --- a/lib/iris/analysis/_regrid.py +++ b/lib/iris/analysis/_regrid.py @@ -407,7 +407,7 @@ def __init__(self, src_grid_cube, target_grid_cube, weights=None): @staticmethod def _get_horizontal_coord(cube, axis): - """Gets the horizontal coordinate on the supplied cube along the specified axis. + """Get the horizontal coordinate on the supplied cube along the specified axis. Parameters ---------- diff --git a/lib/iris/analysis/cartography.py b/lib/iris/analysis/cartography.py index 1ce760db5d..58c10c1926 100644 --- a/lib/iris/analysis/cartography.py +++ b/lib/iris/analysis/cartography.py @@ -376,7 +376,7 @@ def _quadrant_area(radian_lat_bounds, radian_lon_bounds, radius_of_earth): def area_weights(cube, normalize=False): - r"""Returns an array of area weights, with the same dimensions as the cube. + r"""Return an array of area weights, with the same dimensions as the cube. This is a 2D lat/lon area weights array, repeated over the non lat/lon dimensions. diff --git a/lib/iris/analysis/maths.py b/lib/iris/analysis/maths.py index 61dc033883..216d7e3892 100644 --- a/lib/iris/analysis/maths.py +++ b/lib/iris/analysis/maths.py @@ -323,7 +323,7 @@ def _add_subtract_common( dim=None, in_place=False, ): - """Function which shares common code between addition and subtraction of cubes. + """Share common code between addition and subtraction of cubes. Parameters ---------- @@ -532,7 +532,7 @@ def divide(cube, other, dim=None, in_place=False): def exponentiate(cube, exponent, in_place=False): - """Returns the result of the given cube to the power of a scalar. + """Return the result of the given cube to the power of a scalar. Parameters ---------- @@ -821,7 +821,7 @@ def _binary_op_common( in_place=False, sanitise_metadata=True, ): - """Function which shares common code between binary operations. + """Share common code between binary operations. Parameters ---------- @@ -1172,7 +1172,7 @@ def __call__( new_name=None, **kwargs_data_func, ): - """Applies the ifunc to the cube(s). + """Apply the ifunc to the cube(s). Parameters ---------- diff --git a/lib/iris/analysis/trajectory.py b/lib/iris/analysis/trajectory.py index 61871fdc51..9adb409970 100644 --- a/lib/iris/analysis/trajectory.py +++ b/lib/iris/analysis/trajectory.py @@ -37,7 +37,7 @@ class Trajectory: """A series of given waypoints with pre-calculated sample points.""" def __init__(self, waypoints, sample_count=10): - """Defines a trajectory using a sequence of waypoints. + """Define a trajectory using a sequence of waypoints. Parameters ---------- @@ -128,7 +128,7 @@ def _get_interp_points(self): return [(k, v) for k, v in points.items()] def _src_cube_anon_dims(self, cube): - """A helper method to locate the index of anonymous dimensions. + """Locate the index of anonymous dimensions. A helper method to locate the index of anonymous dimensions on the interpolation target, ``cube``. @@ -712,7 +712,7 @@ class UnstructuredNearestNeigbourRegridder: # TODO: cache the necessary bits of the operation so reuse can actually # be more efficient. def __init__(self, src_cube, target_grid_cube): - """A nearest-neighbour regridder. + """Nearest-neighbour regridder. A nearest-neighbour regridder to perform regridding from the source grid to the target grid. diff --git a/lib/iris/common/_split_attribute_dicts.py b/lib/iris/common/_split_attribute_dicts.py index b59ad37269..17b3014fb1 100644 --- a/lib/iris/common/_split_attribute_dicts.py +++ b/lib/iris/common/_split_attribute_dicts.py @@ -66,7 +66,9 @@ def _convert_pairedkeys_dict_to_splitattrs(dic): def adjust_for_split_attribute_dictionaries(operation): - """Decorator to make a function of attribute-dictionaries work with split attributes. + """Generate attribute-dictionaries to work with split attributes. + + Decorator to make a function of attribute-dictionaries work with split attributes. The wrapped function of attribute-dictionaries is currently always one of "equals", "combine" or "difference", with signatures like : @@ -91,6 +93,7 @@ def adjust_for_split_attribute_dictionaries(operation): "Split" dictionaries are all of class :class:`~iris.cube.CubeAttrsDict`, since the only usage of 'split' attribute dictionaries is in Cubes (i.e. they are not used for cube components). + """ @wraps(operation) diff --git a/lib/iris/common/lenient.py b/lib/iris/common/lenient.py index 0180716ac6..4822d88b92 100644 --- a/lib/iris/common/lenient.py +++ b/lib/iris/common/lenient.py @@ -28,7 +28,7 @@ def _lenient_client(*dargs, services=None): - """Decorator implementing the lenient client protocol. + """Allow a client function/method to declare at runtime. Decorator that allows a client function/method to declare at runtime that it is executing and requires lenient behaviour from a prior registered @@ -129,7 +129,7 @@ def lenient_client_inner(*args, **kwargs): def _lenient_service(*dargs): - """Decorator implementing the lenient service protocol. + """Implement the lenient service protocol. Decorator that allows a function/method to declare that it supports lenient behaviour as a service. @@ -223,7 +223,7 @@ def _qualname(func): class Lenient(threading.local): def __init__(self, **kwargs): - """A container for managing the run-time lenient features and options. + """Container for managing the run-time lenient features and options. Parameters ---------- @@ -330,7 +330,7 @@ def configure_state(state): class _Lenient(threading.local): def __init__(self, *args, **kwargs): - """A container for managing the run-time lenient services and client options. + """Container for managing the run-time lenient services and client options. A container for managing the run-time lenient services and client options for pre-defined functions/methods. diff --git a/lib/iris/common/metadata.py b/lib/iris/common/metadata.py index 71d51fe6d7..92c3d34f3e 100644 --- a/lib/iris/common/metadata.py +++ b/lib/iris/common/metadata.py @@ -241,7 +241,7 @@ def __str__(self): return f"{type(self).__name__}({', '.join(field_strings)})" def _api_common(self, other, func_service, func_operation, action, lenient=None): - """Common entry-point for lenient metadata API methods. + """Perform common entry-point for lenient metadata API methods. Parameters ---------- @@ -683,7 +683,7 @@ def from_metadata(cls, other): return result def name(self, default=None, token=False): - """Returns a string name representing the identity of the metadata. + """Return a string name representing the identity of the metadata. First it tries standard name, then it tries the long name, then the NetCDF variable name, before falling-back to a default value, @@ -1561,7 +1561,7 @@ def values(self): def metadata_manager_factory(cls, **kwargs): - """Factory function for manufacturing metadata instances. + """Manufacturing metadata instances. A class instance factory function responsible for manufacturing metadata instances dynamically at runtime. diff --git a/lib/iris/common/mixin.py b/lib/iris/common/mixin.py index 762d1b1fe6..2d9605de83 100644 --- a/lib/iris/common/mixin.py +++ b/lib/iris/common/mixin.py @@ -119,7 +119,7 @@ def __setitem__(self, key, value): dict.__setitem__(self, key, value) def update(self, other, **kwargs): - """Standard ``dict.update()`` operation.""" + """Perform standard ``dict.update()`` operation.""" # Gather incoming keys keys = [] if hasattr(other, "keys"): @@ -143,7 +143,7 @@ def name(self, default=None, token=None): return self._metadata_manager.name(default=default, token=token) def rename(self, name): - """Changes the human-readable name. + """Change the human-readable name. If 'name' is a valid standard name it will assign it to :attr:`standard_name`, otherwise it will assign it to diff --git a/lib/iris/coord_categorisation.py b/lib/iris/coord_categorisation.py index 14330487b6..96407632c5 100644 --- a/lib/iris/coord_categorisation.py +++ b/lib/iris/coord_categorisation.py @@ -204,7 +204,7 @@ def add_hour(cube, coord, name="hour"): def _months_in_season(season): - """Returns a list of month numbers corresponding to each month in the given season.""" + """Return a list of month numbers corresponding to each month in the given season.""" cyclic_months = "jfmamjjasondjfmamjjasond" m0 = cyclic_months.find(season.lower()) if m0 < 0: diff --git a/lib/iris/coord_systems.py b/lib/iris/coord_systems.py index b96f6166c0..adc9895ed9 100644 --- a/lib/iris/coord_systems.py +++ b/lib/iris/coord_systems.py @@ -79,7 +79,7 @@ def __ne__(self, other): return not (self == other) def xml_element(self, doc, attrs=None): - """Default behaviour for coord systems.""" + """Perform default behaviour for coord systems.""" # attrs - optional list of (k,v) items, used for alternate output xml_element_name = type(self).__name__ @@ -496,7 +496,7 @@ def __init__( north_pole_grid_longitude=None, ellipsoid=None, ): - """Constructs a coordinate system with rotated pole, on an optional :class:`GeogCS`. + """Construct a coordinate system with rotated pole, on an optional :class:`GeogCS`. Args: @@ -604,7 +604,7 @@ def __init__( scale_factor_at_central_meridian=None, ellipsoid=None, ): - """Constructs a TransverseMercator object. + """Construct a TransverseMercator object. Args: @@ -725,7 +725,7 @@ def __init__( false_northing=None, ellipsoid=None, ): - """Constructs an Orthographic coord system. + """Construct an Orthographic coord system. Args: @@ -809,7 +809,7 @@ def __init__( false_northing=None, ellipsoid=None, ): - """Constructs a Vertical Perspective coord system. + """Construct a Vertical Perspective coord system. Args: @@ -901,7 +901,7 @@ def __init__( false_northing=None, ellipsoid=None, ): - """Constructs a Geostationary coord system. + """Construct a Geostationary coord system. Args: @@ -1005,7 +1005,7 @@ def __init__( ellipsoid=None, scale_factor_at_projection_origin=None, ): - """Constructs a Stereographic coord system. + """Construct a Stereographic coord system. Parameters ---------- @@ -1177,7 +1177,7 @@ def __init__( secant_latitudes=None, ellipsoid=None, ): - """Constructs a LambertConformal coord system. + """Construct a LambertConformal coord system. Kwargs: @@ -1283,7 +1283,7 @@ def __init__( false_easting=None, false_northing=None, ): - """Constructs a Mercator coord system. + """Construct a Mercator coord system. Kwargs: @@ -1388,7 +1388,7 @@ def __init__( false_northing=None, ellipsoid=None, ): - """Constructs a Lambert Azimuthal Equal Area coord system. + """Construct a Lambert Azimuthal Equal Area coord system. Kwargs: @@ -1469,7 +1469,7 @@ def __init__( standard_parallels=None, ellipsoid=None, ): - """Constructs a Albers Conical Equal Area coord system. + """Construct a Albers Conical Equal Area coord system. Kwargs: @@ -1574,7 +1574,7 @@ def __init__( scale_factor_at_projection_origin=None, ellipsoid=None, ): - """Constructs an ObliqueMercator object. + """Construct an ObliqueMercator object. Parameters ---------- @@ -1689,7 +1689,7 @@ def __init__( scale_factor_at_projection_origin=None, ellipsoid=None, ): - """Constructs a RotatedMercator object. + """Construct a RotatedMercator object. Parameters ---------- diff --git a/lib/iris/coords.py b/lib/iris/coords.py index caa421d11c..bf3fe1eb78 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -67,7 +67,7 @@ def __init__( units=None, attributes=None, ): - """Constructs a single dimensional metadata object. + """Construct a single dimensional metadata object. Parameters ---------- @@ -119,7 +119,7 @@ def __init__( self._bounds_dm = None # Only ever set on Coord-derived instances. def __getitem__(self, keys): - """Returns a new dimensional metadata whose values are obtained by conventional array indexing. + """Return a new dimensional metadata whose values are obtained by conventional array indexing. .. note:: @@ -156,7 +156,7 @@ def __getitem__(self, keys): return new_metadata def copy(self, values=None): - """Returns a copy of this dimensional metadata object. + """Return a copy of this dimensional metadata object. Parameters ---------- @@ -234,11 +234,11 @@ def _values(self, values): self._values_dm.data = values def _lazy_values(self): - """Returns a lazy array representing the dimensional metadata values.""" + """Return a lazy array representing the dimensional metadata values.""" return self._values_dm.lazy_data() def _core_values(self): - """The values array of this dimensional metadata which may be a NumPy array or a dask array.""" + """Value array of this dimensional metadata which may be a NumPy array or a dask array.""" result = self._values_dm.core_data() if not _lazy.is_lazy_data(result): result = result.view() @@ -246,7 +246,7 @@ def _core_values(self): return result def _has_lazy_values(self): - """Indicates whether the metadata's values array is a lazy dask array or not.""" + """Indicate whether the metadata's values array is a lazy dask array or not.""" return self._values_dm.has_lazy_data() def summary( @@ -619,7 +619,7 @@ def __hash__(self): return hash(id(self)) def __binary_operator__(self, other, mode_constant): - """Common code which is called by add, sub, mul and div. + """Perform common code which is called by add, sub, mul and div. Mode constant is one of ADD, SUB, MUL, DIV, RDIV @@ -772,7 +772,7 @@ def ndim(self): return self._values_dm.ndim def has_bounds(self): - """Indicates whether the current dimensional metadata object has a bounds array.""" + """Indicate whether the current dimensional metadata object has a bounds array.""" # Allows for code to handle unbounded dimensional metadata agnostic of # whether the metadata is a coordinate or not. return False @@ -880,7 +880,7 @@ def _xml_array_repr(data): return result def _value_type_name(self): - """A simple, readable name for the data type of the dimensional metadata values.""" + """Provide a simple name for the data type of the dimensional metadata values.""" dtype = self._core_values().dtype kind = dtype.kind if kind in "SU": @@ -905,7 +905,7 @@ def __init__( units=None, attributes=None, ): - """Constructs a single ancillary variable. + """Construct a single ancillary variable. Parameters ---------- @@ -963,7 +963,7 @@ def lazy_data(self): return super()._lazy_values() def core_data(self): - """The data array at the core of this ancillary variable. + """Return data array at the core of this ancillary variable. The data array at the core of this ancillary variable, which may be a NumPy array or a dask array. @@ -972,7 +972,7 @@ def core_data(self): return super()._core_values() def has_lazy_data(self): - """Indicates whether the ancillary variable's data array is a lazy dask array or not.""" + """Indicate whether the ancillary variable's data array is a lazy dask array or not.""" return super()._has_lazy_values() def cube_dims(self, cube): @@ -1003,7 +1003,7 @@ def __init__( attributes=None, measure=None, ): - """Constructs a single cell measure. + """Construct a single cell measure. Parameters ---------- @@ -1147,7 +1147,7 @@ def __new__( def _get_2d_coord_bound_grid(bounds): - """Creates a grid using the bounds of a 2D coordinate with 4 sided cells. + """Create a grid using the bounds of a 2D coordinate with 4 sided cells. Assumes that the four vertices of the cells are in an anti-clockwise order (bottom-left, bottom-right, top-right, top-left). @@ -1277,7 +1277,7 @@ def __hash__(self): return hash((self.point, bound)) def __eq__(self, other): - """Compares Cell equality depending on the type of the object to be compared.""" + """Compare Cell equality depending on the type of the object to be compared.""" if isinstance(other, (int, float, np.number)) or hasattr(other, "timetuple"): if self.bound is not None: return self.contains_point(other) @@ -1312,7 +1312,7 @@ def __common_cmp__(self, other, operator_method): Cell vs Cell comparison is used to define a strict order. Non-Cell vs Cell comparison is used to define Constraint matching. - """ + """ # noqa: D401 if (isinstance(other, list) and len(other) == 1) or ( isinstance(other, np.ndarray) and other.shape == (1,) ): @@ -1507,7 +1507,7 @@ def __init__( self._ignore_axis = DEFAULT_IGNORE_AXIS def copy(self, points=None, bounds=None): - """Returns a copy of this coordinate. + """Return a copy of this coordinate. points : A points array for the new coordinate. @@ -1711,11 +1711,11 @@ def lazy_bounds(self): return lazy_bounds def core_points(self): - """The points array at the core of this coord, which may be a NumPy array or a dask array.""" + """Core points array at the core of this coord, which may be a NumPy array or a dask array.""" return super()._core_values() def core_bounds(self): - """The points array at the core of this coord, which may be a NumPy array or a dask array.""" + """Core bounds. The points array at the core of this coord, which may be a NumPy array or a dask array.""" result = None if self.has_bounds(): result = self._bounds_dm.core_data() @@ -1775,7 +1775,7 @@ def convert_units(self, unit): super().convert_units(unit=unit) def cells(self): - """Returns an iterable of Cell instances for this Coord. + """Return an iterable of Cell instances for this Coord. For example:: @@ -1825,7 +1825,7 @@ def _sanity_check_bounds(self): ) def _discontiguity_in_bounds(self, rtol=1e-5, atol=1e-8): - """Checks that the bounds of the coordinate are contiguous. + """Check that the bounds of the coordinate are contiguous. rtol : float, optional Relative tolerance that is used when checking contiguity. Defaults @@ -2067,7 +2067,7 @@ def has_bounds(self): return self._bounds_dm is not None def cell(self, index): - """The point/bound cell at the given coordinate index. + """Point/bound cell at the given coordinate index. Return the single :class:`Cell` instance which results from slicing the points/bounds with the given index. @@ -2286,7 +2286,7 @@ def guess_bounds(self, bound_position=0.5): self.bounds = self._guess_bounds(bound_position) def intersect(self, other, return_indices=False): - """Returns a new coordinate from the intersection of two coordinates. + """Return a new coordinate from the intersection of two coordinates. Both coordinates must be compatible as defined by :meth:`~iris.coords.Coord.is_compatible`. @@ -2331,7 +2331,7 @@ def intersect(self, other, return_indices=False): return self[self_intersect_indices] def nearest_neighbour_index(self, point): - """Returns the index of the cell nearest to the given point. + """Return the index of the cell nearest to the given point. Only works for one-dimensional coordinates. diff --git a/lib/iris/cube.py b/lib/iris/cube.py index df0f719aca..5997eaacf5 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -66,13 +66,13 @@ def __len__(self): return len(self.cubes) def add(self, cube): - """Adds the appropriate (sub)cube to the list of cubes where it matches the constraint.""" + """Add 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: self.cubes.append(sub_cube) def merged(self, unique=False): - """Returns a new :class:`_CubeFilter` by merging the list of cubes. + """Return a new :class:`_CubeFilter` by merging the list of cubes. Parameters ---------- @@ -89,7 +89,7 @@ class _CubeFilterCollection: @staticmethod def from_cubes(cubes, constraints=None): - """Creates a new collection from an iterable of cubes, and some optional constraints.""" + """Create 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] collection = _CubeFilterCollection(pairs) @@ -101,12 +101,12 @@ def __init__(self, pairs): self.pairs = pairs def add_cube(self, cube): - """Adds the given :class:`~iris.cube.Cube` to all of the relevant constraint pairs.""" + """Add the given :class:`~iris.cube.Cube` to all of the relevant constraint pairs.""" for pair in self.pairs: pair.add(cube) def cubes(self): - """Returns all the cubes in this collection concatenated into a single :class:`CubeList`.""" + """Return all the cubes in this collection concatenated into a single :class:`CubeList`.""" result = CubeList() for pair in self.pairs: result.extend(pair.cubes) @@ -137,7 +137,7 @@ def __init__(self, *args, **kwargs): self._assert_is_cube(cube) def __str__(self): - """Runs short :meth:`Cube.summary` on every cube.""" + """Run short :meth:`Cube.summary` on every cube.""" result = [ "%s: %s" % (i, cube.summary(shorten=True)) for i, cube in enumerate(self) ] @@ -148,7 +148,7 @@ def __str__(self): return result def __repr__(self): - """Runs repr on every cube.""" + """Run repr on every cube.""" return "[%s]" % ",\n".join([repr(cube) for cube in self]) @staticmethod @@ -401,7 +401,7 @@ def merge_cube(self): return merged_cube def merge(self, unique=True): - """Returns the :class:`CubeList` resulting from merging this :class:`CubeList`. + """Return the :class:`CubeList` resulting from merging this :class:`CubeList`. Parameters ---------- @@ -1182,7 +1182,7 @@ def __init__( cell_measures_and_dims=None, ancillary_variables_and_dims=None, ): - """Creates a cube with data and optional metadata. + """Create 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. @@ -1338,7 +1338,7 @@ def attributes(self) -> CubeAttrsDict: @attributes.setter def attributes(self, attributes: Optional[Mapping]): - """An override to CfVariableMixin.attributes.setter. + """Override to CfVariableMixin.attributes.setter. An override to CfVariableMixin.attributes.setter, which ensures that Cube attributes are stored in a way which distinguishes global + local ones. @@ -1465,7 +1465,7 @@ def add_cell_method(self, cell_method): self.cell_methods += (cell_method,) def add_aux_coord(self, coord, data_dims=None): - """Adds a CF auxiliary coordinate to the cube. + """Add a CF auxiliary coordinate to the cube. Parameters ---------- @@ -1574,7 +1574,7 @@ def _add_unique_aux_coord(self, coord, data_dims): self._aux_coords_and_dims.append((coord, data_dims)) def add_aux_factory(self, aux_factory): - """Adds an auxiliary coordinate factory to the cube. + """Add an auxiliary coordinate factory to the cube. Parameters ---------- @@ -1606,7 +1606,7 @@ def coordsonly(coords_and_dims): self._aux_factories.append(aux_factory) def add_cell_measure(self, cell_measure, data_dims=None): - """Adds a CF cell measure to the cube. + """Add a CF cell measure to the cube. Parameters ---------- @@ -1639,7 +1639,7 @@ 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. + """Add a CF ancillary variable to the cube. Parameters ---------- @@ -1738,7 +1738,7 @@ 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.""" + """Remove the given auxiliary coordinate factory from the cube.""" self._aux_factories.remove(aux_factory) def _remove_coord(self, coord): @@ -1757,7 +1757,7 @@ def _remove_coord(self, coord): self.remove_aux_factory(aux_factory) def remove_coord(self, coord): - """Removes a coordinate from the cube. + """Remove a coordinate from the cube. Parameters ---------- @@ -1777,7 +1777,7 @@ def remove_coord(self, coord): factory.update(coord) def remove_cell_measure(self, cell_measure): - """Removes a cell measure from the cube. + """Remove a cell measure from the cube. Parameters ---------- @@ -1814,7 +1814,7 @@ def remove_cell_measure(self, cell_measure): ] def remove_ancillary_variable(self, ancillary_variable): - """Removes an ancillary variable from the cube. + """Remove an ancillary variable from the cube. Parameters ---------- @@ -1927,7 +1927,7 @@ def cell_measure_dims(self, cell_measure): return matches[0] def ancillary_variable_dims(self, ancillary_variable): - """Returns a tuple of the data dimensions relevant to the given AncillaryVariable. + """Return a tuple of the data dimensions relevant to the given AncillaryVariable. Parameters ---------- @@ -2777,7 +2777,7 @@ def aux_factories(self): return tuple(self._aux_factories) def summary(self, shorten=False, name_padding=35): - """String summary of the Cube. + """Summary of the Cube. String summary of the Cube with name+units, a list of dim coord names versus length and, optionally, a summary of all other components. @@ -3587,7 +3587,7 @@ 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.""" + """Return a fully valid CubeML string representation of the Cube.""" doc = Document() cube_xml_element = self._xml_element( @@ -3760,7 +3760,7 @@ def _order(array): return cube_xml_element def copy(self, data=None): - """Returns a deep copy of this cube. + """Return a deep copy of this cube. Parameters ---------- @@ -4866,9 +4866,9 @@ def keys(self): def sorted_axes(axes): - """Returns the axis names sorted alphabetically. + """Return the axis names sorted alphabetically. - Returns the axis names sorted alphabetically, with the exception that + Return the axis names sorted alphabetically, with the exception that 't', 'z', 'y', and, 'x' are sorted to the end. """ diff --git a/lib/iris/experimental/raster.py b/lib/iris/experimental/raster.py index 8d37e39df3..ba7efc68b0 100644 --- a/lib/iris/experimental/raster.py +++ b/lib/iris/experimental/raster.py @@ -107,7 +107,7 @@ def _gdal_write_array(x_min, x_step, y_max, y_step, coord_system, data, fname, f def export_geotiff(cube, fname): - """Writes cube data to raster file format as a PixelIsArea GeoTiff image. + """Write cube data to raster file format as a PixelIsArea GeoTiff image. .. deprecated:: 3.2.0 diff --git a/lib/iris/experimental/regrid.py b/lib/iris/experimental/regrid.py index dac191c64d..74b356722f 100644 --- a/lib/iris/experimental/regrid.py +++ b/lib/iris/experimental/regrid.py @@ -736,9 +736,9 @@ def __init__(self, projection=None): warn_deprecated(wmsg) def regridder(self, src_cube, target_grid): - """Creates a nearest-neighbour regridder to perform regridding. + """Create a nearest-neighbour regridder to perform regridding. - Creates a nearest-neighbour regridder to perform regridding, using + Create a nearest-neighbour regridder to perform regridding, using scipy.interpolate.griddata from unstructured source points to the target grid. The regridding calculation is performed in the given projection. diff --git a/lib/iris/experimental/representation.py b/lib/iris/experimental/representation.py index 85923a12d8..0b98c24395 100644 --- a/lib/iris/experimental/representation.py +++ b/lib/iris/experimental/representation.py @@ -288,7 +288,7 @@ def _make_content(self): return "\n".join(element for element in elements) def repr_html(self): - """The `repr` interface for Jupyter.""" + """Represent html, the `repr` interface for Jupyter.""" # Deal with the header first. header = self._make_header() diff --git a/lib/iris/experimental/stratify.py b/lib/iris/experimental/stratify.py index a6ac06a8d2..3e5fb1da9f 100644 --- a/lib/iris/experimental/stratify.py +++ b/lib/iris/experimental/stratify.py @@ -14,7 +14,7 @@ def _copy_coords_without_z_dim(src, tgt, z_dim): - """Helper function to copy across non z-dimenson coordinates between cubes. + """Copy across non z-dimenson coordinates between cubes. Parameters ---------- diff --git a/lib/iris/experimental/ugrid/load.py b/lib/iris/experimental/ugrid/load.py index 0ed1757353..b8665a499e 100644 --- a/lib/iris/experimental/ugrid/load.py +++ b/lib/iris/experimental/ugrid/load.py @@ -101,7 +101,7 @@ def context(self): def _meshes_from_cf(cf_reader): - """Common behaviour for extracting meshes from a CFReader. + """Mesh from cf, common behaviour for extracting meshes from a CFReader. Simple now, but expected to increase in complexity as Mesh sharing develops. diff --git a/lib/iris/experimental/ugrid/mesh.py b/lib/iris/experimental/ugrid/mesh.py index b12178da83..147b1fd513 100644 --- a/lib/iris/experimental/ugrid/mesh.py +++ b/lib/iris/experimental/ugrid/mesh.py @@ -119,7 +119,7 @@ def __init__( start_index=0, location_axis=0, ): - """Constructs a single connectivity. + """Construct a single connectivity. Parameters ---------- @@ -494,7 +494,7 @@ def lazy_indices(self): return super()._lazy_values() def core_indices(self): - """The indices array at the core of this connectivity. + """Return the indices array at the core of this connectivity. The indices array at the core of this connectivity, which may be a NumPy array or a Dask array. diff --git a/lib/iris/fileformats/_ff.py b/lib/iris/fileformats/_ff.py index e3749fe72d..301a45736e 100644 --- a/lib/iris/fileformats/_ff.py +++ b/lib/iris/fileformats/_ff.py @@ -804,7 +804,7 @@ def __iter__(self): def _parse_binary_stream(file_like, dtype=np.float64, count=-1): - """Replacement :func:`numpy.fromfile` due to python3 performance issues. + """Parse binary stream, replacement :func:`numpy.fromfile` due to python3 performance issues. Parameters ---------- @@ -835,7 +835,7 @@ def _parse_binary_stream(file_like, dtype=np.float64, count=-1): def load_cubes(filenames, callback, constraints=None): - """Loads cubes from a list of fields files filenames. + """Load cubes from a list of fields files filenames. Parameters ---------- @@ -859,7 +859,7 @@ def load_cubes(filenames, callback, constraints=None): def load_cubes_32bit_ieee(filenames, callback, constraints=None): - """Loads cubes from a list of 32bit ieee converted fieldsfiles filenames. + """Load cubes from a list of 32bit ieee converted fieldsfiles filenames. See Also -------- diff --git a/lib/iris/fileformats/_nc_load_rules/actions.py b/lib/iris/fileformats/_nc_load_rules/actions.py index 1532340d00..8f408716e6 100644 --- a/lib/iris/fileformats/_nc_load_rules/actions.py +++ b/lib/iris/fileformats/_nc_load_rules/actions.py @@ -103,7 +103,7 @@ def inner(engine, *args, **kwargs): @action_function def action_default(engine): - """Standard operations for every cube.""" + """Perform standard operations for every cube.""" hh.build_cube_metadata(engine) diff --git a/lib/iris/fileformats/abf.py b/lib/iris/fileformats/abf.py index 13b0d8aa8d..76f3573882 100644 --- a/lib/iris/fileformats/abf.py +++ b/lib/iris/fileformats/abf.py @@ -192,7 +192,7 @@ def to_cube(self): def load_cubes(filespecs, callback=None): - """Loads cubes from a list of ABF filenames. + """Load cubes from a list of ABF filenames. Args: diff --git a/lib/iris/fileformats/nimrod.py b/lib/iris/fileformats/nimrod.py index 778c7b3251..009535dc8f 100644 --- a/lib/iris/fileformats/nimrod.py +++ b/lib/iris/fileformats/nimrod.py @@ -290,7 +290,7 @@ def _read_data(self, infile): def load_cubes(filenames, callback=None): - """Loads cubes from a list of NIMROD filenames. + """Load cubes from a list of NIMROD filenames. Parameters ---------- diff --git a/lib/iris/fileformats/pp.py b/lib/iris/fileformats/pp.py index e224e26b41..fa95d0dab1 100644 --- a/lib/iris/fileformats/pp.py +++ b/lib/iris/fileformats/pp.py @@ -277,11 +277,11 @@ def __new__(cls, model, section, item): Args ---- - model + model : A positive integer less than 100, or None. - section + section : A non-negative integer less than 100, or None. - item + item : A positive integer less than 1000, or None. """ diff --git a/lib/iris/fileformats/pp_load_rules.py b/lib/iris/fileformats/pp_load_rules.py index 01d1add197..f93f177ba8 100644 --- a/lib/iris/fileformats/pp_load_rules.py +++ b/lib/iris/fileformats/pp_load_rules.py @@ -857,7 +857,7 @@ def _convert_scalar_pseudo_level_coords(lbuser5): def convert(f): - """Converts a PP field into the corresponding items of Cube metadata. + """Convert a PP field into the corresponding items of Cube metadata. Parameters ---------- diff --git a/lib/iris/fileformats/rules.py b/lib/iris/fileformats/rules.py index 59d0655198..bf6ae4de34 100644 --- a/lib/iris/fileformats/rules.py +++ b/lib/iris/fileformats/rules.py @@ -142,7 +142,7 @@ class _ReferenceError(Exception): def _dereference_args(factory, reference_targets, regrid_cache, cube): - """Converts all the arguments for a factory into concrete coordinates.""" + """Convert all the arguments for a factory into concrete coordinates.""" args = [] for arg in factory.args: if isinstance(arg, Reference): diff --git a/lib/iris/fileformats/um/_fast_load.py b/lib/iris/fileformats/um/_fast_load.py index c37d0abc32..12441acdcc 100644 --- a/lib/iris/fileformats/um/_fast_load.py +++ b/lib/iris/fileformats/um/_fast_load.py @@ -155,7 +155,7 @@ def iter_fields_decorated_with_load_indices(fields_iter): def _convert_collation(collation): - """Converts a FieldCollation into the corresponding items of Cube metadata. + """Convert a FieldCollation into the corresponding items of Cube metadata. Parameters ---------- diff --git a/lib/iris/fileformats/um/_fast_load_structured_fields.py b/lib/iris/fileformats/um/_fast_load_structured_fields.py index 17b3d4f9a0..6b09227491 100644 --- a/lib/iris/fileformats/um/_fast_load_structured_fields.py +++ b/lib/iris/fileformats/um/_fast_load_structured_fields.py @@ -236,7 +236,7 @@ def _calculate_structure(self): def _um_collation_key_function(field): - """Standard collation key definition for fast structured field loading. + """Collation key definition for fast structured field loading. The elements used here are the minimum sufficient to define the 'phenomenon', as described for :meth:`group_structured_fields`. diff --git a/lib/iris/fileformats/um/_ff_replacement.py b/lib/iris/fileformats/um/_ff_replacement.py index d8dee81b36..ee40bacafa 100644 --- a/lib/iris/fileformats/um/_ff_replacement.py +++ b/lib/iris/fileformats/um/_ff_replacement.py @@ -51,7 +51,7 @@ def um_to_pp(filename, read_data=False, word_depth=None): def load_cubes(filenames, callback, constraints=None, _loader_kwargs=None): - """Loads cubes from filenames of UM fieldsfile-like files. + """Load cubes from filenames of UM fieldsfile-like files. Parameters ---------- @@ -81,7 +81,7 @@ def load_cubes(filenames, callback, constraints=None, _loader_kwargs=None): def load_cubes_32bit_ieee(filenames, callback, constraints=None): - """Loads cubes from filenames of 32bit ieee converted UM fieldsfile-like files. + """Load cubes from filenames of 32bit ieee converted UM fieldsfile-like files. See Also -------- diff --git a/lib/iris/palette.py b/lib/iris/palette.py index 078d9b73ba..e180b649a8 100644 --- a/lib/iris/palette.py +++ b/lib/iris/palette.py @@ -136,7 +136,7 @@ def cmap_norm(cube): def auto_palette(func): - """Decorator wrapper function to control the default behaviour. + """Auto palette decorator wrapper function to control the default behaviour. Decorator wrapper function to control the default behaviour of the matplotlib cmap and norm keyword arguments. diff --git a/lib/iris/plot.py b/lib/iris/plot.py index 7974b8fd0e..57e338c86a 100644 --- a/lib/iris/plot.py +++ b/lib/iris/plot.py @@ -1229,7 +1229,7 @@ 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. + """Plot orography defined at cell boundaries from the given Cube. Notes ----- @@ -1267,7 +1267,7 @@ 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. + """Plot orography defined at sample points from the given Cube. Notes ----- @@ -1444,7 +1444,7 @@ def _scatter_args(u, v, data, *args, **kwargs): def _vector_component_args(x_points, y_points, u_data, *args, **kwargs): - """Callback from _draw_2d_from_points for 'quiver' and 'streamlines'. + """Vector component callback from _draw_2d_from_points for 'quiver' and 'streamlines'. Returns arguments (x, y, u, v), to be passed to the underlying matplotlib call. @@ -1681,7 +1681,7 @@ def scatter(x, y, *args, **kwargs): def fill_between(x, y1, y2, *args, **kwargs): - """Plots y1 and y2 against x, and fills the space between them. + """Plot y1 and y2 against x, and fills the space between them. Args: diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index ce52fbdb6b..1c1eaf5a56 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -49,7 +49,7 @@ def _title(cube_or_coord, with_units): def _label(cube, mode, result=None, ndims=2, coords=None, axes=None): - """Puts labels on the current plot using the given cube.""" + """Put labels on the current plot using the given cube.""" if axes is None: axes = plt.gca() diff --git a/lib/iris/util.py b/lib/iris/util.py index 9ae1ceb919..878c62e2f1 100644 --- a/lib/iris/util.py +++ b/lib/iris/util.py @@ -95,7 +95,7 @@ def broadcast_to_shape(array, shape, dim_map): def delta(ndarray, dimension, circular=False): - """Calculates the difference between values along a given dimension. + """Calculate the difference between values along a given dimension. Parameters ---------- @@ -1216,9 +1216,9 @@ def _handle_dimensional_metadata(cube, dm_item, cube_add_method, expand_extras): def squeeze(cube): - """Removes any dimension of length one. + """Remove any dimension of length one. - Removes any dimension of length one. If it has an associated DimCoord or + Remove any dimension of length one. If it has an associated DimCoord or AuxCoord, this becomes a scalar coord. Parameters @@ -1417,9 +1417,9 @@ def points_step(points): def unify_time_units(cubes): - """Performs an in-place conversion of the time units. + """Perform an in-place conversion of the time units. - Performs an in-place conversion of the time units of all time coords in the + Perform an in-place conversion of the time units of all time coords in the cubes in a given iterable. One common epoch is defined for each calendar found in the cubes to prevent units being defined with inconsistencies between epoch and calendar. During this process, all time coordinates have @@ -1521,7 +1521,7 @@ def _is_circular(points, modulus, bounds=None): def promote_aux_coord_to_dim_coord(cube, name_or_coord): - r"""Promotes an auxiliary to a dimension coordinate on the cube. + r"""Promote an auxiliary to a dimension coordinate on the cube. This AuxCoord must be associated with a single cube dimension. If the AuxCoord is associated with a dimension that already has a DimCoord, that @@ -1730,7 +1730,7 @@ def demote_dim_coord_to_aux_coord(cube, name_or_coord): @functools.wraps(np.meshgrid) def _meshgrid(*xi, **kwargs): - """Ensures consistent meshgrid behaviour across numpy versions. + """Ensure consistent meshgrid behaviour across numpy versions. @numpy v1.13, the dtype of each output n-D coordinate is the same as its associated input 1D coordinate. This is not the case prior to numpy v1.13, diff --git a/noxfile.py b/noxfile.py index da71144913..a30b6ce784 100644 --- a/noxfile.py +++ b/noxfile.py @@ -39,7 +39,7 @@ def session_lockfile(session: nox.sessions.Session) -> Path: def session_cachefile(session: nox.sessions.Session) -> Path: - """Returns the path of the session lockfile cache.""" + """Return the path of the session lockfile cache.""" lockfile = session_lockfile(session) tmp_dir = Path(session.create_tmp()) cache = tmp_dir / lockfile.name @@ -55,7 +55,7 @@ def venv_populated(session: nox.sessions.Session) -> bool: def venv_changed(session: nox.sessions.Session) -> bool: - """Returns True if the installed session is different. + """Return True if the installed session is different. Compares to that specified in the lockfile. """ diff --git a/pyproject.toml b/pyproject.toml index 19e3d26cdf..4325de0e0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -110,6 +110,7 @@ known-first-party = ["iris"] # https://docs.astral.sh/ruff/rules/undocumented-public-module/ "D100", # Missing docstring in public module "D205", # 1 blank line required between summary line and description + "D401", # 1 First line of docstring should be in imperative mood ] [tool.ruff.lint.pydocstyle] diff --git a/setup.py b/setup.py index 004c6b2301..28e7a003a9 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ def run(self): def custom_command(cmd, help=""): - """Factory function to generate a custom command. + """Create custom command with factory function. Custom command will add additional behaviour to build the CF standard names module. From fe46e05ca4e972e12a1a5aa42096130341de6d79 Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Thu, 18 Jan 2024 15:16:18 +0000 Subject: [PATCH 23/26] Re-write `pearsonr` to use `Resolve` (#5638) * Re-write pearsonr to use Resolve * add test for weight transposing case * Fix single coordinate case * use lenient coord handling * Move coordinate handling tests to separate class These do not need real and lazy versions * Make some syntax highlighters happier Co-authored-by: Martin Yeo <40734014+trexfeathers@users.noreply.github.com> * Initial review actions * Clearer comment Co-authored-by: Martin Yeo <40734014+trexfeathers@users.noreply.github.com> * assign reviewer blame * first attempt at benchmarks * directly use resolve for weight wrangling * Add note about maths broadcasting rules * use lhs/rhs instead of 1/2 for consistency * convert tests to pytest * check dask's compute is not called * revert now redundant resolve change * Improvements to pearsonr docstring. --------- Co-authored-by: Martin Yeo <40734014+trexfeathers@users.noreply.github.com> Co-authored-by: Martin Yeo --- benchmarks/benchmarks/stats.py | 38 ++++ docs/src/whatsnew/latest.rst | 3 + lib/iris/analysis/stats.py | 181 +++++++++--------- .../unit/analysis/stats/test_pearsonr.py | 171 ++++++++++++----- 4 files changed, 252 insertions(+), 141 deletions(-) create mode 100644 benchmarks/benchmarks/stats.py diff --git a/benchmarks/benchmarks/stats.py b/benchmarks/benchmarks/stats.py new file mode 100644 index 0000000000..0530431900 --- /dev/null +++ b/benchmarks/benchmarks/stats.py @@ -0,0 +1,38 @@ +# Copyright Iris contributors +# +# This file is part of Iris and is released under the BSD license. +# See LICENSE in the root of the repository for full licensing details. +"""Stats benchmark tests.""" + +import iris +from iris.analysis.stats import pearsonr +import iris.tests + + +class PearsonR: + def setup(self): + cube_temp = iris.load_cube( + iris.tests.get_data_path( + ("NetCDF", "global", "xyt", "SMALL_total_column_co2.nc") + ) + ) + + # Make data non-lazy. + cube_temp.data + + self.cube_a = cube_temp[:6] + self.cube_b = cube_temp[20:26] + self.cube_b.replace_coord(self.cube_a.coord("time")) + for name in ["latitude", "longitude"]: + self.cube_b.coord(name).guess_bounds() + self.weights = iris.analysis.cartography.area_weights(self.cube_b) + + def time_real(self): + pearsonr(self.cube_a, self.cube_b, weights=self.weights) + + def time_lazy(self): + for cube in self.cube_a, self.cube_b: + cube.data = cube.lazy_data() + + result = pearsonr(self.cube_a, self.cube_b, weights=self.weights) + result.data diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index 41f765bfe1..cc6427f9e0 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -104,6 +104,9 @@ This document explains the changes made to Iris for this release lazy data from file. This will also speed up coordinate comparison. (:pull:`5610`) +#. `@rcomer`_ and `@trexfeathers`_ (reviewer) modified + :func:`~iris.analysis.stats.pearsonr` so it preserves lazy data in all cases + and also runs a little faster. (:pull:`5638`) 🔥 Deprecations =============== diff --git a/lib/iris/analysis/stats.py b/lib/iris/analysis/stats.py index 34c37b8b11..f014dd5013 100644 --- a/lib/iris/analysis/stats.py +++ b/lib/iris/analysis/stats.py @@ -4,13 +4,16 @@ # See LICENSE in the root of the repository for full licensing details. """Statistical operations between cubes.""" +import dask.array as da import numpy as np -import numpy.ma as ma import iris -from iris.util import broadcast_to_shape +from iris.common import SERVICES, Resolve +from iris.common.lenient import _lenient_client +from iris.util import _mask_array +@_lenient_client(services=SERVICES) def pearsonr( cube_a, cube_b, @@ -23,30 +26,32 @@ def pearsonr( Parameters ---------- - cube_a, cube_b : cubes + cube_a, cube_b : :class:`iris.cube.Cube` Cubes between which the correlation will be calculated. The cubes should either be the same shape and have the same dimension coordinates - or one cube should be broadcastable to the other. + or one cube should be broadcastable to the other. Broadcasting rules + are the same as those for cube arithmetic (see :ref:`cube maths`). corr_coords : str or list of str The cube coordinate name(s) over which to calculate correlations. If no names are provided then correlation will be calculated over all common cube dimensions. weights : :class:`numpy.ndarray`, optional - Weights array of same shape as (the smaller of) cube_a and cube_b. Note - that latitude/longitude area weights can be calculated using + Weights array of same shape as (the smaller of) `cube_a` and `cube_b`. + Note that latitude/longitude area weights can be calculated using :func:`iris.analysis.cartography.area_weights`. mdtol : float, default=1.0 Tolerance of missing data. The missing data fraction is calculated - based on the number of grid cells masked in both cube_a and cube_b. If - this fraction exceed mdtol, the returned value in the corresponding - cell is masked. mdtol=0 means no missing data is tolerated while - mdtol=1 means the resulting element will be masked if and only if all - contributing elements are masked in cube_a or cube_b. Defaults to 1. + based on the number of grid cells masked in both `cube_a` and `cube_b`. + If this fraction exceed `mdtol`, the returned value in the + corresponding cell is masked. `mdtol` =0 means no missing data is + tolerated while `mdtol` =1 means the resulting element will be masked + if and only if all contributing elements are masked in `cube_a` or + `cube_b`. common_mask : bool, default=False - If True, applies a common mask to cube_a and cube_b so only cells which - are unmasked in both cubes contribute to the calculation. If False, the - variance for each cube is calculated from all available cells. Defaults - to False. + If ``True``, applies a common mask to cube_a and cube_b so only cells + which are unmasked in both cubes contribute to the calculation. If + ``False``, the variance for each cube is calculated from all available + cells. Returns ------- @@ -56,19 +61,19 @@ def pearsonr( cubes. For example providing two time/altitude/latitude/longitude cubes and - corr_coords of 'latitude' and 'longitude' will result in a + `corr_coords` of 'latitude' and 'longitude' will result in a time/altitude cube describing the latitude/longitude (i.e. pattern) correlation at each time/altitude point. Notes ----- + If either of the input cubes has lazy data, the result will have lazy data. + Reference: https://en.wikipedia.org/wiki/Pearson_correlation_coefficient - This operation is non-lazy. - """ - # Assign larger cube to cube_1 + # Assign larger cube to cube_1 for simplicity. if cube_b.ndim > cube_a.ndim: cube_1 = cube_b cube_2 = cube_a @@ -78,90 +83,88 @@ def pearsonr( smaller_shape = cube_2.shape - dim_coords_1 = [coord.name() for coord in cube_1.dim_coords] - dim_coords_2 = [coord.name() for coord in cube_2.dim_coords] - common_dim_coords = list(set(dim_coords_1) & set(dim_coords_2)) + # Get the broadcast, auto-transposed safe versions of the cube operands. + resolver = Resolve(cube_1, cube_2) + lhs_cube_resolved = resolver.lhs_cube_resolved + rhs_cube_resolved = resolver.rhs_cube_resolved + + if lhs_cube_resolved.has_lazy_data() or rhs_cube_resolved.has_lazy_data(): + al = da + array_lhs = lhs_cube_resolved.lazy_data() + array_rhs = rhs_cube_resolved.lazy_data() + else: + al = np + array_lhs = lhs_cube_resolved.data + array_rhs = rhs_cube_resolved.data + # If no coords passed then set to all common dimcoords of cubes. if corr_coords is None: - corr_coords = common_dim_coords - - def _ones_like(cube): - # Return a copy of cube with the same mask, but all data values set to 1. - # The operation is non-lazy. - # For safety we also discard any cell-measures and ancillary-variables, to - # avoid cube arithmetic possibly objecting to them, or inadvertently retaining - # them in the result where they might be inappropriate. - ones_cube = cube.copy() - ones_cube.data = np.ones_like(cube.data) - ones_cube.rename("unknown") - ones_cube.units = 1 - for cm in ones_cube.cell_measures(): - ones_cube.remove_cell_measure(cm) - for av in ones_cube.ancillary_variables(): - ones_cube.remove_ancillary_variable(av) - return ones_cube + dim_coords_1 = {coord.name() for coord in lhs_cube_resolved.dim_coords} + dim_coords_2 = {coord.name() for coord in rhs_cube_resolved.dim_coords} + corr_coords = list(dim_coords_1.intersection(dim_coords_2)) + + # Interpret coords as array dimensions. + corr_dims = set() + if isinstance(corr_coords, str): + corr_coords = [corr_coords] + for coord in corr_coords: + corr_dims.update(lhs_cube_resolved.coord_dims(coord)) + + corr_dims = tuple(corr_dims) # Match up data masks if required. if common_mask: - # Create a cube of 1's with a common mask. - if ma.is_masked(cube_2.data): - mask_cube = _ones_like(cube_2) - else: - mask_cube = 1.0 - if ma.is_masked(cube_1.data): - # Take a slice to avoid unnecessary broadcasting of cube_2. - slice_coords = [ - dim_coords_1[i] - for i in range(cube_1.ndim) - if dim_coords_1[i] not in common_dim_coords - and np.array_equal( - cube_1.data.mask.any(axis=i), cube_1.data.mask.all(axis=i) - ) - ] - cube_1_slice = next(cube_1.slices_over(slice_coords)) - mask_cube = _ones_like(cube_1_slice) * mask_cube - # Apply common mask to data. - if isinstance(mask_cube, iris.cube.Cube): - cube_1 = cube_1 * mask_cube - cube_2 = mask_cube * cube_2 - dim_coords_2 = [coord.name() for coord in cube_2.dim_coords] - - # Broadcast weights to shape of cubes if necessary. - if weights is None or cube_1.shape == smaller_shape: - weights_1 = weights - weights_2 = weights + mask_lhs = al.ma.getmaskarray(array_lhs) + if al is np: + # Reduce all invariant dimensions of mask_lhs to length 1. This avoids + # unnecessary broadcasting of array_rhs. + index = tuple( + slice(0, 1) + if np.array_equal(mask_lhs.any(axis=dim), mask_lhs.all(axis=dim)) + else slice(None) + for dim in range(mask_lhs.ndim) + ) + mask_lhs = mask_lhs[index] + + array_rhs = _mask_array(array_rhs, mask_lhs) + array_lhs = _mask_array(array_lhs, al.ma.getmaskarray(array_rhs)) + + # Broadcast weights to shape of arrays if necessary. + if weights is None: + weights_lhs = weights_rhs = None else: if weights.shape != smaller_shape: - raise ValueError( - "weights array should have dimensions {}".format(smaller_shape) - ) + msg = f"weights array should have dimensions {smaller_shape}" + raise ValueError(msg) - dims_1_common = [ - i for i in range(cube_1.ndim) if dim_coords_1[i] in common_dim_coords - ] - weights_1 = broadcast_to_shape(weights, cube_1.shape, dims_1_common) - if cube_2.shape != smaller_shape: - dims_2_common = [ - i for i in range(cube_2.ndim) if dim_coords_2[i] in common_dim_coords - ] - weights_2 = broadcast_to_shape(weights, cube_2.shape, dims_2_common) - else: - weights_2 = weights + wt_resolver = Resolve(cube_1, cube_2.copy(weights)) + weights = wt_resolver.rhs_cube_resolved.data + weights_rhs = np.broadcast_to(weights, array_rhs.shape) + weights_lhs = np.broadcast_to(weights, array_lhs.shape) # Calculate correlations. - s1 = cube_1 - cube_1.collapsed(corr_coords, iris.analysis.MEAN, weights=weights_1) - s2 = cube_2 - cube_2.collapsed(corr_coords, iris.analysis.MEAN, weights=weights_2) - - covar = (s1 * s2).collapsed( - corr_coords, iris.analysis.SUM, weights=weights_1, mdtol=mdtol + s_lhs = array_lhs - al.ma.average( + array_lhs, axis=corr_dims, weights=weights_lhs, keepdims=True + ) + s_rhs = array_rhs - al.ma.average( + array_rhs, axis=corr_dims, weights=weights_rhs, keepdims=True ) - var_1 = (s1**2).collapsed(corr_coords, iris.analysis.SUM, weights=weights_1) - var_2 = (s2**2).collapsed(corr_coords, iris.analysis.SUM, weights=weights_2) - denom = iris.analysis.maths.apply_ufunc( - np.sqrt, var_1 * var_2, new_unit=covar.units + s_prod = resolver.cube(s_lhs * s_rhs) + + # Use cube collapsed method as it takes care of coordinate collapsing and missing + # data tolerance. + covar = s_prod.collapsed( + corr_coords, iris.analysis.SUM, weights=weights_lhs, mdtol=mdtol ) + + var_lhs = iris.analysis._sum(s_lhs**2, axis=corr_dims, weights=weights_lhs) + var_rhs = iris.analysis._sum(s_rhs**2, axis=corr_dims, weights=weights_rhs) + + denom = np.sqrt(var_lhs * var_rhs) + corr_cube = covar / denom corr_cube.rename("Pearson's r") + corr_cube.units = 1 return corr_cube diff --git a/lib/iris/tests/unit/analysis/stats/test_pearsonr.py b/lib/iris/tests/unit/analysis/stats/test_pearsonr.py index 50387e1418..d46bcd21ba 100644 --- a/lib/iris/tests/unit/analysis/stats/test_pearsonr.py +++ b/lib/iris/tests/unit/analysis/stats/test_pearsonr.py @@ -8,17 +8,22 @@ # importing anything else. import iris.tests as tests # isort:skip +from unittest import mock + +import dask +import dask.array import numpy as np import numpy.ma as ma +import pytest import iris +import iris._lazy_data import iris.analysis.stats as stats from iris.exceptions import CoordinateNotFoundError -@tests.skip_data -class Test(tests.IrisTest): - def setUp(self): +class Mixin: + def setup_method(self): # 3D cubes: cube_temp = iris.load_cube( tests.get_data_path( @@ -33,21 +38,36 @@ def setUp(self): cube_temp.coord("longitude").guess_bounds() self.weights = iris.analysis.cartography.area_weights(cube_temp) - def test_perfect_corr(self): + +@tests.skip_data +class TestLazy(Mixin): + @pytest.fixture + def mocked_compute(self, monkeypatch): + m_compute = mock.Mock(wraps=dask.base.compute) + + # The three dask compute functions are all the same function but monkeypatch + # does not automatically know that. + # https://stackoverflow.com/questions/77820437 + monkeypatch.setattr(dask.base, dask.base.compute.__name__, m_compute) + monkeypatch.setattr(dask, dask.compute.__name__, m_compute) + monkeypatch.setattr(dask.array, dask.array.compute.__name__, m_compute) + + return m_compute + + def test_perfect_corr(self, mocked_compute): r = stats.pearsonr(self.cube_a, self.cube_a, ["latitude", "longitude"]) - self.assertArrayEqual(r.data, np.array([1.0] * 6)) + mocked_compute.assert_not_called() + np.testing.assert_array_equal(r.data, np.array([1.0] * 6)) - def test_perfect_corr_all_dims(self): + def test_perfect_corr_all_dims(self, mocked_compute): r = stats.pearsonr(self.cube_a, self.cube_a) - self.assertArrayEqual(r.data, np.array([1.0])) + mocked_compute.assert_not_called() + np.testing.assert_array_equal(r.data, np.array([1.0])) - def test_incompatible_cubes(self): - with self.assertRaises(ValueError): - stats.pearsonr(self.cube_a[:, 0, :], self.cube_b[0, :, :], "longitude") - - def test_compatible_cubes(self): + def test_compatible_cubes(self, mocked_compute): r = stats.pearsonr(self.cube_a, self.cube_b, ["latitude", "longitude"]) - self.assertArrayAlmostEqual( + mocked_compute.assert_not_called() + np.testing.assert_array_almost_equal( r.data, [ 0.81114936, @@ -59,13 +79,15 @@ def test_compatible_cubes(self): ], ) - def test_broadcast_cubes(self): + def test_broadcast_cubes(self, mocked_compute): r1 = stats.pearsonr( self.cube_a, self.cube_b[0, :, :], ["latitude", "longitude"] ) r2 = stats.pearsonr( self.cube_b[0, :, :], self.cube_a, ["latitude", "longitude"] ) + + mocked_compute.assert_not_called() r_by_slice = [ stats.pearsonr( self.cube_a[i, :, :], @@ -74,14 +96,16 @@ def test_broadcast_cubes(self): ).data for i in range(6) ] - self.assertArrayEqual(r1.data, np.array(r_by_slice)) - self.assertArrayEqual(r2.data, np.array(r_by_slice)) + np.testing.assert_array_equal(r1.data, np.array(r_by_slice)) + np.testing.assert_array_equal(r2.data, np.array(r_by_slice)) - def test_compatible_cubes_weighted(self): + def test_compatible_cubes_weighted(self, mocked_compute): r = stats.pearsonr( self.cube_a, self.cube_b, ["latitude", "longitude"], self.weights ) - self.assertArrayAlmostEqual( + + mocked_compute.assert_not_called() + np.testing.assert_array_almost_equal( r.data, [ 0.79105429, @@ -93,13 +117,15 @@ def test_compatible_cubes_weighted(self): ], ) - def test_broadcast_cubes_weighted(self): + def test_broadcast_cubes_weighted(self, mocked_compute): r = stats.pearsonr( self.cube_a, self.cube_b[0, :, :], ["latitude", "longitude"], weights=self.weights[0, :, :], ) + + mocked_compute.assert_not_called() r_by_slice = [ stats.pearsonr( self.cube_a[i, :, :], @@ -109,10 +135,31 @@ def test_broadcast_cubes_weighted(self): ).data for i in range(6) ] - self.assertArrayAlmostEqual(r.data, np.array(r_by_slice)) + np.testing.assert_array_almost_equal(r.data, np.array(r_by_slice)) + + def test_broadcast_transpose_cubes_weighted(self, mocked_compute): + # Reference is calculated with no transposition. + r_ref = stats.pearsonr( + self.cube_a, + self.cube_b[0, :, :], + ["latitude", "longitude"], + weights=self.weights[0, :, :], + ) + + self.cube_a.transpose() + r_test = stats.pearsonr( + self.cube_a, + self.cube_b[0, :, :], + ["latitude", "longitude"], + weights=self.weights[0, :, :], + ) + + mocked_compute.assert_not_called() + # Should get the same result, but transposed. + np.testing.assert_array_almost_equal(r_test.data, r_ref.data.T) def test_weight_error(self): - with self.assertRaises(ValueError): + with pytest.raises(ValueError): stats.pearsonr( self.cube_a, self.cube_b[0, :, :], @@ -120,54 +167,74 @@ def test_weight_error(self): weights=self.weights, ) - def test_non_existent_coord(self): - with self.assertRaises(CoordinateNotFoundError): - stats.pearsonr(self.cube_a, self.cube_b, "bad_coord") - - def test_mdtol(self): + def test_mdtol(self, mocked_compute): cube_small = self.cube_a[:, 0, 0] - cube_small_masked = cube_small.copy() - cube_small_masked.data = ma.array( - cube_small.data, mask=np.array([0, 0, 0, 1, 1, 1], dtype=bool) - ) + cube_small_masked = iris.util.mask_cube(cube_small, [0, 0, 0, 1, 1, 1]) r1 = stats.pearsonr(cube_small, cube_small_masked) r2 = stats.pearsonr(cube_small, cube_small_masked, mdtol=0.49) - self.assertArrayAlmostEqual(r1.data, np.array([0.74586593])) - self.assertMaskedArrayEqual(r2.data, ma.array([0], mask=[True])) - def test_common_mask_simple(self): + mocked_compute.assert_not_called() + np.testing.assert_array_almost_equal(r1.data, np.array([0.74586593])) + tests.assert_masked_array_equal(r2.data, ma.array([0], mask=[True])) + + def test_common_mask_simple(self, mocked_compute): cube_small = self.cube_a[:, 0, 0] - cube_small_masked = cube_small.copy() - cube_small_masked.data = ma.array( - cube_small.data, mask=np.array([0, 0, 0, 1, 1, 1], dtype=bool) - ) + cube_small_masked = iris.util.mask_cube(cube_small, [0, 0, 0, 1, 1, 1]) r = stats.pearsonr(cube_small, cube_small_masked, common_mask=True) - self.assertArrayAlmostEqual(r.data, np.array([1.0])) - def test_common_mask_broadcast(self): - cube_small = self.cube_a[:, 0, 0] + mocked_compute.assert_not_called() + np.testing.assert_array_almost_equal(r.data, np.array([1.0])) + + def test_common_mask_broadcast(self, mocked_compute): + cube_small = iris.util.mask_cube(self.cube_a[:, 0, 0], [0, 0, 0, 0, 0, 1]) + mask_2d = np.zeros((6, 2), dtype=bool) + # 2d mask varies on unshared coord: + mask_2d[0, 1] = 1 + + # Make a (6, 2) cube. cube_small_2d = self.cube_a[:, 0:2, 0] - cube_small.data = ma.array( - cube_small.data, mask=np.array([0, 0, 0, 0, 0, 1], dtype=bool) - ) - cube_small_2d.data = ma.array( - np.tile(cube_small.data[:, np.newaxis], 2), - mask=np.zeros((6, 2), dtype=bool), + # Duplicate data along unshared coord's dimension. + new_data = iris.util.broadcast_to_shape( + cube_small.core_data(), (6, 2), dim_map=[0] ) - # 2d mask varies on unshared coord: - cube_small_2d.data.mask[0, 1] = 1 + cube_small_2d.data = iris.util._mask_array(new_data, mask_2d) + r = stats.pearsonr( cube_small, cube_small_2d, weights=self.weights[:, 0, 0], common_mask=True, ) - self.assertArrayAlmostEqual(r.data, np.array([1.0, 1.0])) + + mocked_compute.assert_not_called() + np.testing.assert_array_almost_equal(r.data, np.array([1.0, 1.0])) # 2d mask does not vary on unshared coord: cube_small_2d.data.mask[0, 0] = 1 r = stats.pearsonr(cube_small, cube_small_2d, common_mask=True) - self.assertArrayAlmostEqual(r.data, np.array([1.0, 1.0])) + np.testing.assert_array_almost_equal(r.data, np.array([1.0, 1.0])) + + +class TestReal(TestLazy): + def setup_method(self): + super().setup_method() + for cube in [self.cube_a, self.cube_b]: + _ = cube.data + +class TestCoordHandling(Mixin): + def test_lenient_handling(self): + # Smoke test that mismatched var_name does not prevent operation. + self.cube_a.coord("time").var_name = "wibble" + stats.pearsonr(self.cube_a, self.cube_b) -if __name__ == "__main__": - tests.main() + def test_incompatible_cubes(self): + with pytest.raises(ValueError): + stats.pearsonr(self.cube_a[:, 0, :], self.cube_b[0, :, :], "longitude") + + def test_single_coord(self): + # Smoke test that single coord can be passed as single string. + stats.pearsonr(self.cube_a, self.cube_b, "latitude") + + def test_non_existent_coord(self): + with pytest.raises(CoordinateNotFoundError): + stats.pearsonr(self.cube_a, self.cube_b, "bad_coord") From 66893f2f16f5dfa97996a3109a126957148ab70d Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Thu, 18 Jan 2024 16:58:37 +0100 Subject: [PATCH 24/26] Make the Coord.cell method lazy (#5693) Co-authored-by: Elias <110238618+ESadek-MO@users.noreply.github.com> --- docs/src/whatsnew/latest.rst | 4 ++++ lib/iris/coords.py | 4 ++-- lib/iris/tests/unit/coords/test_Coord.py | 7 +++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index cc6427f9e0..6e6b1b5732 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -104,10 +104,14 @@ This document explains the changes made to Iris for this release lazy data from file. This will also speed up coordinate comparison. (:pull:`5610`) +#. `@bouweandela`_ changed :func:`iris.coords.Coord.cell` so it does not realize + all coordinate data and only loads a single cell instead. (:pull:`5693`) + #. `@rcomer`_ and `@trexfeathers`_ (reviewer) modified :func:`~iris.analysis.stats.pearsonr` so it preserves lazy data in all cases and also runs a little faster. (:pull:`5638`) + 🔥 Deprecations =============== diff --git a/lib/iris/coords.py b/lib/iris/coords.py index bf3fe1eb78..89c7434a15 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -2075,7 +2075,7 @@ def cell(self, index): """ index = iris.util._build_full_slice_given_keys(index, self.ndim) - point = tuple(np.array(self.points[index], ndmin=1).flatten()) + point = tuple(np.array(self.core_points()[index], ndmin=1).flatten()) if len(point) != 1: raise IndexError( "The index %s did not uniquely identify a single " @@ -2084,7 +2084,7 @@ def cell(self, index): bound = None if self.has_bounds(): - bound = tuple(np.array(self.bounds[index], ndmin=1).flatten()) + bound = tuple(np.array(self.core_bounds()[index], ndmin=1).flatten()) if self.units.is_time_reference(): point = self.units.num2date(point) diff --git a/lib/iris/tests/unit/coords/test_Coord.py b/lib/iris/tests/unit/coords/test_Coord.py index 5745c870ce..c6f740c492 100644 --- a/lib/iris/tests/unit/coords/test_Coord.py +++ b/lib/iris/tests/unit/coords/test_Coord.py @@ -240,9 +240,12 @@ def _mock_coord(self): coord = mock.Mock( spec=Coord, ndim=1, - points=np.array([mock.sentinel.time]), - bounds=np.array([[mock.sentinel.lower, mock.sentinel.upper]]), ) + coord.core_points = lambda: np.array([mock.sentinel.time]) + coord.core_bounds = lambda: np.array( + [[mock.sentinel.lower, mock.sentinel.upper]] + ) + return coord def test_time_as_object(self): From e509f145f4ee036537833e339f856abd39fe8ccd Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Fri, 19 Jan 2024 17:55:39 +0100 Subject: [PATCH 25/26] Faster trivial equality checks for coordinates and arrays (#5691) * Faster trivial equality checks * Add tests * Add whatsnew * Undo changes to cube equality --- docs/src/whatsnew/latest.rst | 2 ++ lib/iris/coords.py | 3 +++ lib/iris/tests/unit/util/test_array_equal.py | 7 +++++-- lib/iris/util.py | 2 ++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index 6e6b1b5732..831f24bfab 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -111,6 +111,8 @@ This document explains the changes made to Iris for this release :func:`~iris.analysis.stats.pearsonr` so it preserves lazy data in all cases and also runs a little faster. (:pull:`5638`) +#. `@bouweandela`_ made comparing coordinates and arrays to themselves faster. (:pull:`5691`) + 🔥 Deprecations =============== diff --git a/lib/iris/coords.py b/lib/iris/coords.py index 89c7434a15..d4d070921c 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -575,6 +575,9 @@ def __repr__(self): return self.summary(shorten=True) def __eq__(self, other): + if other is self: + return True + # Note: this method includes bounds handling code, but it only runs # within Coord type instances, as only these allow bounds to be set. diff --git a/lib/iris/tests/unit/util/test_array_equal.py b/lib/iris/tests/unit/util/test_array_equal.py index 38b9652443..f63092587c 100644 --- a/lib/iris/tests/unit/util/test_array_equal.py +++ b/lib/iris/tests/unit/util/test_array_equal.py @@ -101,12 +101,15 @@ def test_string_arrays_0d_and_scalar(self): self.assertFalse(array_equal(array_a, "foobar.")) def test_nan_equality_nan_ne_nan(self): - array = np.array([1.0, np.nan, 2.0, np.nan, 3.0]) - self.assertFalse(array_equal(array, array)) + array_a = np.array([1.0, np.nan, 2.0, np.nan, 3.0]) + array_b = array_a.copy() + self.assertFalse(array_equal(array_a, array_a)) + self.assertFalse(array_equal(array_a, array_b)) def test_nan_equality_nan_naneq_nan(self): array_a = np.array([1.0, np.nan, 2.0, np.nan, 3.0]) array_b = np.array([1.0, np.nan, 2.0, np.nan, 3.0]) + self.assertTrue(array_equal(array_a, array_a, withnans=True)) self.assertTrue(array_equal(array_a, array_b, withnans=True)) def test_nan_equality_nan_nanne_a(self): diff --git a/lib/iris/util.py b/lib/iris/util.py index 878c62e2f1..4c896dc6dd 100644 --- a/lib/iris/util.py +++ b/lib/iris/util.py @@ -373,6 +373,8 @@ def array_equal(array1, array2, withnans=False): This function maintains laziness when called; it does not realise data. See more at :doc:`/userguide/real_and_lazy_data`. """ + if withnans and (array1 is array2): + return True def normalise_array(array): if not is_lazy_data(array): From 34811cfa7a5eb321bb09d955dc2e5d7baf5175ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jan 2024 10:09:01 +0000 Subject: [PATCH 26/26] Bump scitools/workflows from 2023.12.1 to 2024.01.0 (#5710) Bumps [scitools/workflows](https://github.com/scitools/workflows) from 2023.12.1 to 2024.01.0. - [Release notes](https://github.com/scitools/workflows/releases) - [Commits](https://github.com/scitools/workflows/compare/2023.12.1...2024.01.0) --- updated-dependencies: - dependency-name: scitools/workflows dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-manifest.yml | 2 +- .github/workflows/refresh-lockfiles.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-manifest.yml b/.github/workflows/ci-manifest.yml index abe77be606..33e1fd9e09 100644 --- a/.github/workflows/ci-manifest.yml +++ b/.github/workflows/ci-manifest.yml @@ -23,4 +23,4 @@ concurrency: jobs: manifest: name: "check-manifest" - uses: scitools/workflows/.github/workflows/ci-manifest.yml@2023.12.1 + uses: scitools/workflows/.github/workflows/ci-manifest.yml@2024.01.0 diff --git a/.github/workflows/refresh-lockfiles.yml b/.github/workflows/refresh-lockfiles.yml index d1753a7b1b..0dc392979e 100644 --- a/.github/workflows/refresh-lockfiles.yml +++ b/.github/workflows/refresh-lockfiles.yml @@ -14,5 +14,5 @@ on: jobs: refresh_lockfiles: - uses: scitools/workflows/.github/workflows/refresh-lockfiles.yml@2023.12.1 + uses: scitools/workflows/.github/workflows/refresh-lockfiles.yml@2024.01.0 secrets: inherit