Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into autoapi
Browse files Browse the repository at this point in the history
* upstream/main:
  Updated environment lockfiles (SciTools#6029)
  Pin matplotlib != 3.9.1 (SciTools#6065)
  add location argument to mesh.coords (SciTools#6055)
  Doctest compatibility with GeoVista v0.5. (SciTools#6064)
  Rename `Mesh` to `MeshXY` (SciTools#6056)
  Bump scitools/workflows from 2024.07.2 to 2024.07.3 (SciTools#6063)
  • Loading branch information
tkknight committed Jul 21, 2024
2 parents 71dc273 + 38e5a23 commit d371aed
Show file tree
Hide file tree
Showing 41 changed files with 741 additions and 796 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ concurrency:
jobs:
manifest:
name: "check-manifest"
uses: scitools/workflows/.github/workflows/ci-manifest.yml@2024.07.2
uses: scitools/workflows/.github/workflows/ci-manifest.yml@2024.07.3
2 changes: 1 addition & 1 deletion .github/workflows/refresh-lockfiles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ on:

jobs:
refresh_lockfiles:
uses: scitools/workflows/.github/workflows/refresh-lockfiles.yml@2024.07.2
uses: scitools/workflows/.github/workflows/refresh-lockfiles.yml@2024.07.3
secrets: inherit
2 changes: 1 addition & 1 deletion benchmarks/benchmarks/sperf/equality.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class CubeEquality(FileMixin):
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.
with attached :class:`~iris.experimental.ugrid.mesh.MeshXY`\\ es.
Uses :class:`FileMixin` as the realistic case will be comparing
:class:`~iris.cube.Cube`\\ s that have been loaded from file.
Expand Down
13 changes: 6 additions & 7 deletions benchmarks/benchmarks/unit_style/ugrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def setup(self, n_faces):
self.object = self.create()


class Mesh(UGridCommon):
class MeshXY(UGridCommon):
def setup(self, n_faces, lazy=False):
####
# Steal everything from the sample mesh for benchmarking creation of a
Expand All @@ -93,9 +93,8 @@ def setup(self, n_faces, lazy=False):
)

def get_coords_and_axes(location):
search_kwargs = {f"include_{location}s": True}
return [
(source_mesh.coord(axis=axis, **search_kwargs), axis)
(source_mesh.coord(axis=axis, location=location), axis)
for axis in ("x", "y")
]

Expand All @@ -114,7 +113,7 @@ def get_coords_and_axes(location):
self.node_x = self.object.node_coords.node_x
# Kwargs for reuse in search and remove methods.
self.connectivities_kwarg = dict(cf_role="edge_node_connectivity")
self.coords_kwarg = dict(include_faces=True)
self.coords_kwarg = dict(location="face")

# TODO: an opportunity for speeding up runtime if needed, since
# eq_object is not needed for all benchmarks. Just don't generate it
Expand All @@ -124,7 +123,7 @@ def get_coords_and_axes(location):
self.eq_object = deepcopy(self.object)

def create(self):
return ugrid.Mesh(**self.mesh_kwargs)
return ugrid.MeshXY(**self.mesh_kwargs)

def time_add_connectivities(self, n_faces):
self.object.add_connectivities(self.face_node)
Expand All @@ -149,8 +148,8 @@ def time_remove_coords(self, n_faces):


@disable_repeat_between_setup
class MeshLazy(Mesh):
"""Lazy equivalent of :class:`Mesh`."""
class MeshXYLazy(MeshXY):
"""Lazy equivalent of :class:`MeshXY`."""

def setup(self, n_faces, lazy=True):
super().setup(n_faces, lazy=lazy)
Expand Down
58 changes: 29 additions & 29 deletions docs/src/further_topics/ugrid/data_model.rst
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ The Basics
The Iris :class:`~iris.cube.Cube` has several new members:

* | :attr:`~iris.cube.Cube.mesh`
| The :class:`iris.experimental.ugrid.Mesh` that describes the
| The :class:`iris.experimental.ugrid.MeshXY` that describes the
:class:`~iris.cube.Cube`\'s horizontal geography.
* | :attr:`~iris.cube.Cube.location`
| ``node``/``edge``/``face`` - the mesh element type with which this
Expand All @@ -320,7 +320,7 @@ The Iris :class:`~iris.cube.Cube` has several new members:
indexes over the horizontal :attr:`~iris.cube.Cube.data` positions.
These members will all be ``None`` for a :class:`~iris.cube.Cube` with no
associated :class:`~iris.experimental.ugrid.Mesh`.
associated :class:`~iris.experimental.ugrid.MeshXY`.

This :class:`~iris.cube.Cube`\'s unstructured dimension has multiple attached
:class:`iris.experimental.ugrid.MeshCoord`\s (one for each axis e.g.
Expand All @@ -333,7 +333,7 @@ the :class:`~iris.cube.Cube`\'s unstructured dimension.

from iris.coords import AuxCoord, DimCoord
from iris.cube import Cube
from iris.experimental.ugrid import Connectivity, Mesh
from iris.experimental.ugrid import Connectivity, MeshXY

node_x = AuxCoord(
points=[0.0, 5.0, 0.0, 5.0, 8.0],
Expand Down Expand Up @@ -368,7 +368,7 @@ the :class:`~iris.cube.Cube`\'s unstructured dimension.
]
return [(x, "x"), (y, "y")]

my_mesh = Mesh(
my_mesh = MeshXY(
long_name="my_mesh",
topology_dimension=2,
node_coords_and_axes=[(node_x, "x"), (node_y, "y")],
Expand Down Expand Up @@ -416,41 +416,41 @@ the :class:`~iris.cube.Cube`\'s unstructured dimension.
0

>>> print(edge_cube.mesh.summary(shorten=True))
<Mesh: 'my_mesh'>
<MeshXY: 'my_mesh'>

The Detail
----------
How UGRID information is stored
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | :class:`iris.experimental.ugrid.Mesh`
* | :class:`iris.experimental.ugrid.MeshXY`
| Contains all information about the mesh.
| Includes:
* | :attr:`~iris.experimental.ugrid.Mesh.topology_dimension`
* | :attr:`~iris.experimental.ugrid.MeshXY.topology_dimension`
| The maximum dimensionality of shape (1D=edge, 2D=face) supported
by this :class:`~iris.experimental.ugrid.Mesh`. Determines which
by this :class:`~iris.experimental.ugrid.MeshXY`. Determines which
:class:`~iris.experimental.ugrid.Connectivity`\s are required/optional
(see below).
* 1-3 collections of :class:`iris.coords.AuxCoord`\s:

* | **Required**: :attr:`~iris.experimental.ugrid.Mesh.node_coords`
* | **Required**: :attr:`~iris.experimental.ugrid.MeshXY.node_coords`
| The nodes that are the basis for the mesh.
* | Optional: :attr:`~iris.experimental.ugrid.Mesh.edge_coords`,
:attr:`~iris.experimental.ugrid.Mesh.face_coords`
* | Optional: :attr:`~iris.experimental.ugrid.MeshXY.edge_coords`,
:attr:`~iris.experimental.ugrid.MeshXY.face_coords`
| For indicating the 'centres' of the edges/faces.
| **NOTE:** generating a :class:`~iris.experimental.ugrid.MeshCoord` from
a :class:`~iris.experimental.ugrid.Mesh` currently (``Jan 2022``)
a :class:`~iris.experimental.ugrid.MeshXY` currently (``Jan 2022``)
requires centre coordinates for the given ``location``; to be rectified
in future.
* 1 or more :class:`iris.experimental.ugrid.Connectivity`\s:

* | **Required for 1D (edge) elements**:
:attr:`~iris.experimental.ugrid.Mesh.edge_node_connectivity`
:attr:`~iris.experimental.ugrid.MeshXY.edge_node_connectivity`
| Define the edges by connecting nodes.
* | **Required for 2D (face) elements**:
:attr:`~iris.experimental.ugrid.Mesh.face_node_connectivity`
:attr:`~iris.experimental.ugrid.MeshXY.face_node_connectivity`
| Define the faces by connecting nodes.
* Optional: any other connectivity type. See
:attr:`iris.experimental.ugrid.mesh.Connectivity.UGRID_CF_ROLES` for the
Expand All @@ -459,7 +459,7 @@ How UGRID information is stored
.. doctest:: ugrid_summaries

>>> print(edge_cube.mesh)
Mesh : 'my_mesh'
MeshXY : 'my_mesh'
topology_dimension: 2
node
node_dimension: 'Mesh2d_node'
Expand All @@ -485,7 +485,7 @@ How UGRID information is stored
| Stores the following information:
* | :attr:`~iris.experimental.ugrid.MeshCoord.mesh`
| The :class:`~iris.experimental.ugrid.Mesh` associated with this
| The :class:`~iris.experimental.ugrid.MeshXY` associated with this
:class:`~iris.experimental.ugrid.MeshCoord`. This determines the
:attr:`~iris.cube.Cube.mesh` attribute of any :class:`~iris.cube.Cube`
this :class:`~iris.experimental.ugrid.MeshCoord` is attached to (see
Expand All @@ -503,7 +503,7 @@ How UGRID information is stored

MeshCoords
~~~~~~~~~~
Links a :class:`~iris.cube.Cube` to a :class:`~iris.experimental.ugrid.Mesh` by
Links a :class:`~iris.cube.Cube` to a :class:`~iris.experimental.ugrid.MeshXY` by
attaching to the :class:`~iris.cube.Cube`\'s unstructured dimension, in the
same way that all :class:`~iris.coords.Coord`\s attach to
:class:`~iris.cube.Cube` dimensions. This allows a single
Expand All @@ -512,30 +512,30 @@ dimensions (e.g. horizontal mesh plus vertical levels and a time series),
using the same logic for every dimension.

:class:`~iris.experimental.ugrid.MeshCoord`\s are instantiated using a given
:class:`~iris.experimental.ugrid.Mesh`, ``location``
:class:`~iris.experimental.ugrid.MeshXY`, ``location``
("node"/"edge"/"face") and ``axis``. The process interprets the
:class:`~iris.experimental.ugrid.Mesh`\'s
:attr:`~iris.experimental.ugrid.Mesh.node_coords` and if appropriate the
:attr:`~iris.experimental.ugrid.Mesh.edge_node_connectivity`/
:attr:`~iris.experimental.ugrid.Mesh.face_node_connectivity` and
:attr:`~iris.experimental.ugrid.Mesh.edge_coords`/
:attr:`~iris.experimental.ugrid.Mesh.face_coords`
:class:`~iris.experimental.ugrid.MeshXY`\'s
:attr:`~iris.experimental.ugrid.MeshXY.node_coords` and if appropriate the
:attr:`~iris.experimental.ugrid.MeshXY.edge_node_connectivity`/
:attr:`~iris.experimental.ugrid.MeshXY.face_node_connectivity` and
:attr:`~iris.experimental.ugrid.MeshXY.edge_coords`/
:attr:`~iris.experimental.ugrid.MeshXY.face_coords`
to produce a :class:`~iris.coords.Coord`
:attr:`~iris.coords.Coord.points` and :attr:`~iris.coords.Coord.bounds`
representation of all the :class:`~iris.experimental.ugrid.Mesh`\'s
representation of all the :class:`~iris.experimental.ugrid.MeshXY`\'s
nodes/edges/faces for the given axis.

The method :meth:`iris.experimental.ugrid.Mesh.to_MeshCoords` is available to
The method :meth:`iris.experimental.ugrid.MeshXY.to_MeshCoords` is available to
create a :class:`~iris.experimental.ugrid.MeshCoord` for
every axis represented by that :class:`~iris.experimental.ugrid.Mesh`,
every axis represented by that :class:`~iris.experimental.ugrid.MeshXY`,
given only the ``location`` argument

.. doctest:: ugrid_summaries

>>> for coord in edge_cube.coords(mesh_coords=True):
... print(coord)
MeshCoord : latitude / (degrees_north)
mesh: <Mesh: 'my_mesh'>
mesh: <MeshXY: 'my_mesh'>
location: 'edge'
points: [3. , 1.5, 1.5, 1.5, 0. , 0. ]
bounds: [
Expand All @@ -550,7 +550,7 @@ given only the ``location`` argument
standard_name: 'latitude'
axis: 'y'
MeshCoord : longitude / (degrees_east)
mesh: <Mesh: 'my_mesh'>
mesh: <MeshXY: 'my_mesh'>
location: 'edge'
points: [2.5, 0. , 5. , 6.5, 2.5, 6.5]
bounds: [
Expand Down
44 changes: 22 additions & 22 deletions docs/src/further_topics/ugrid/operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ subsequent example operations on this page.
>>> import numpy as np

>>> from iris.coords import AuxCoord
>>> from iris.experimental.ugrid import Connectivity, Mesh
>>> from iris.experimental.ugrid import Connectivity, MeshXY

# Going to create the following mesh
# (node indices are shown to aid understanding):
Expand Down Expand Up @@ -102,7 +102,7 @@ subsequent example operations on this page.
... indices=face_indices, cf_role="face_node_connectivity"
... )

>>> my_mesh = Mesh(
>>> my_mesh = MeshXY(
... long_name="my_mesh",
... topology_dimension=2, # Supports 2D (face) elements.
... node_coords_and_axes=[(node_x, "x"), (node_y, "y")],
Expand All @@ -112,7 +112,7 @@ subsequent example operations on this page.
... )

>>> print(my_mesh)
Mesh : 'my_mesh'
MeshXY : 'my_mesh'
topology_dimension: 2
node
node_dimension: 'Mesh2d_node'
Expand Down Expand Up @@ -143,7 +143,7 @@ Making a Cube (with a Mesh)
.. rubric:: |tagline: making a cube|

Creating a :class:`~iris.cube.Cube` is unchanged; the
:class:`~iris.experimental.ugrid.Mesh` is linked via a
:class:`~iris.experimental.ugrid.MeshXY` is linked via a
:class:`~iris.experimental.ugrid.MeshCoord` (see :ref:`ugrid MeshCoords`):

.. dropdown:: Code
Expand Down Expand Up @@ -205,7 +205,7 @@ Save
.. note:: UGRID saving support is limited to the NetCDF file format.

The Iris saving process automatically detects if the :class:`~iris.cube.Cube`
has an associated :class:`~iris.experimental.ugrid.Mesh` and automatically
has an associated :class:`~iris.experimental.ugrid.MeshXY` and automatically
saves the file in a UGRID-conformant format:

.. dropdown:: Code
Expand Down Expand Up @@ -283,7 +283,7 @@ saves the file in a UGRID-conformant format:
<BLANKLINE>

The :func:`iris.experimental.ugrid.save_mesh` function allows
:class:`~iris.experimental.ugrid.Mesh`\es to be saved to file without
:class:`~iris.experimental.ugrid.MeshXY`\es to be saved to file without
associated :class:`~iris.cube.Cube`\s:

.. dropdown:: Code
Expand Down Expand Up @@ -412,15 +412,15 @@ etcetera:
.. note::

We recommend caution if constraining on coordinates associated with a
:class:`~iris.experimental.ugrid.Mesh`. An individual coordinate value
:class:`~iris.experimental.ugrid.MeshXY`. An individual coordinate value
might not be shared by any other data points, and using a coordinate range
will demand notably higher performance given the size of the dimension
versus structured grids
(:ref:`see the data model detail <ugrid implications>`).

The :func:`iris.experimental.ugrid.load_mesh` and
:func:`~iris.experimental.ugrid.load_meshes` functions allow only
:class:`~iris.experimental.ugrid.Mesh`\es to be loaded from a file without
:class:`~iris.experimental.ugrid.MeshXY`\es to be loaded from a file without
creating any associated :class:`~iris.cube.Cube`\s:

.. dropdown:: Code
Expand All @@ -434,7 +434,7 @@ creating any associated :class:`~iris.cube.Cube`\s:
... loaded_mesh = load_mesh(cubelist_path)

>>> print(loaded_mesh)
Mesh : 'my_mesh'
MeshXY : 'my_mesh'
topology_dimension: 2
node
node_dimension: 'Mesh2d_node'
Expand Down Expand Up @@ -545,7 +545,7 @@ unrelated to spatial position**. This means that subsetted
as intended, and subsetting a :class:`~iris.experimental.ugrid.MeshCoord` is
therefore set to return an :class:`~iris.coords.AuxCoord` instead - breaking
the link between :class:`~iris.cube.Cube` and
:class:`~iris.experimental.ugrid.Mesh`:
:class:`~iris.experimental.ugrid.MeshXY`:
.. dropdown:: Code
:icon: code
Expand Down Expand Up @@ -751,7 +751,7 @@ with the
The initialisation process is computationally expensive so we use caching to
improve performance. Once a regridder has been initialised, it can be used on
any :class:`~iris.cube.Cube` which has been defined on the same
:class:`~iris.experimental.ugrid.Mesh` (or on the same **grid** in the case of
:class:`~iris.experimental.ugrid.MeshXY` (or on the same **grid** in the case of
:class:`~esmf_regrid.experimental.unstructured_scheme.GridToMeshESMFRegridder`).
Since calling a regridder is usually a lot faster than initialising, reusing
regridders can save a lot of time. We can demonstrate the reuse of the
Expand Down Expand Up @@ -819,19 +819,19 @@ Equality
.. rubric:: |tagline: equality|
:class:`~iris.experimental.ugrid.Mesh` comparison is supported, and comparing
two ':class:`~iris.experimental.ugrid.Mesh`-:class:`~iris.cube.Cube`\s' will
:class:`~iris.experimental.ugrid.MeshXY` comparison is supported, and comparing
two ':class:`~iris.experimental.ugrid.MeshXY`-:class:`~iris.cube.Cube`\s' will
include a comparison of the respective
:class:`~iris.experimental.ugrid.Mesh`\es, with no extra action needed by the
:class:`~iris.experimental.ugrid.MeshXY`\es, with no extra action needed by the
user.
.. note::
Keep an eye on memory demand when comparing large
:class:`~iris.experimental.ugrid.Mesh`\es, but note that
:class:`~iris.experimental.ugrid.Mesh`\ equality is enabled for lazy
:class:`~iris.experimental.ugrid.MeshXY`\es, but note that
:class:`~iris.experimental.ugrid.MeshXY`\ equality is enabled for lazy
processing (:doc:`/userguide/real_and_lazy_data`), so if the
:class:`~iris.experimental.ugrid.Mesh`\es being compared are lazy the
:class:`~iris.experimental.ugrid.MeshXY`\es being compared are lazy the
process will use less memory than their total size.
Combining Cubes
Expand All @@ -842,23 +842,23 @@ Combining Cubes
Merging or concatenating :class:`~iris.cube.Cube`\s (described in
:doc:`/userguide/merge_and_concat`) with two different
:class:`~iris.experimental.ugrid.Mesh`\es is not possible - a
:class:`~iris.experimental.ugrid.MeshXY`\es is not possible - a
:class:`~iris.cube.Cube` must be associated with just a single
:class:`~iris.experimental.ugrid.Mesh`, and merge/concatenate are not yet
capable of combining multiple :class:`~iris.experimental.ugrid.Mesh`\es into
:class:`~iris.experimental.ugrid.MeshXY`, and merge/concatenate are not yet
capable of combining multiple :class:`~iris.experimental.ugrid.MeshXY`\es into
one.

:class:`~iris.cube.Cube`\s that include
:class:`~iris.experimental.ugrid.MeshCoord`\s can still be merged/concatenated
on dimensions other than the :meth:`~iris.cube.Cube.mesh_dim`, since such
:class:`~iris.cube.Cube`\s will by definition share the same
:class:`~iris.experimental.ugrid.Mesh`.
:class:`~iris.experimental.ugrid.MeshXY`.

.. seealso::

You may wish to investigate
:func:`iris.experimental.ugrid.recombine_submeshes`, which can be used
for a very specific type of :class:`~iris.experimental.ugrid.Mesh`
for a very specific type of :class:`~iris.experimental.ugrid.MeshXY`
combination not detailed here.

Arithmetic
Expand Down
Loading

0 comments on commit d371aed

Please sign in to comment.