Skip to content

Commit

Permalink
Merge branch 'main' into numpydocs2
Browse files Browse the repository at this point in the history
* main:
  DOCS: Numpydocs1 (SciTools#5578)
  add links to scitools-classroom repo. (SciTools#5609)
  Feedstock rc branch management in do-nothing script (SciTools#5515)
  Relocated the Technical Papers documentation to Further Topics.  (SciTools#5602)
  Fix pp save of realization coordinate (SciTools#5568)
  Bump actions/checkout from 3 to 4 (SciTools#5460)
  Bump actions/github-script from 6 to 7 (SciTools#5580)
  Bump conda-incubator/setup-miniconda from 2 to 3 (SciTools#5607)
  CI: specify matplotlib-base (SciTools#5606)
  Mergeback of `FEATURE_chunk_control` branch (SciTools#5588)
  [CI Bot] environment lockfiles auto-update (SciTools#5547)
  Mergeback of "Feature _split_attrs" branch (SciTools#5152)
  add whatsnew (SciTools#5596)
  Refactor area weighted regridding, improve performance (SciTools#5543)
  Allowing exemption to axis guessing on coords (SciTools#5551)
  • Loading branch information
tkknight committed Dec 6, 2023
2 parents 515d380 + db43fde commit d22c822
Show file tree
Hide file tree
Showing 68 changed files with 9,203 additions and 2,297 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/benchmarks_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Download artifact
id: download-artifact
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow
uses: actions/github-script@v6
uses: actions/github-script@v7
with:
script: |
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
Expand Down Expand Up @@ -65,7 +65,7 @@ jobs:
if: needs.download.outputs.reports_exist == 1
steps:
- name: Checkout repo
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Download artifact
uses: actions/download-artifact@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/benchmarks_run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:

steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:

steps:
- name: "checkout"
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: "environment configure"
env:
Expand All @@ -80,7 +80,7 @@ jobs:
env_name: ${{ env.ENV_NAME }}

- name: "conda install"
uses: conda-incubator/setup-miniconda@v2
uses: conda-incubator/setup-miniconda@v3
with:
miniforge-version: latest
channels: conda-forge,defaults
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
name: "build sdist & wheel"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0

Expand Down Expand Up @@ -57,7 +57,7 @@ jobs:
env:
ENV_NAME: "ci-wheels"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0

Expand All @@ -82,7 +82,7 @@ jobs:
env_name: ${{ env.ENV_NAME }}

- name: "conda install"
uses: conda-incubator/setup-miniconda@v2
uses: conda-incubator/setup-miniconda@v3
with:
miniforge-version: latest
channels: conda-forge,defaults
Expand Down
3 changes: 1 addition & 2 deletions docs/src/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#
# All configuration values have a default; values that are commented out
# serve to show the default.

# ----------------------------------------------------------------------------

import datetime
Expand Down Expand Up @@ -195,7 +194,7 @@ def _dotv(version):
todo_include_todos = True

# api generation configuration
autodoc_member_order = "groupwise"
autodoc_member_order = "alphabetical"
autodoc_default_flags = ["show-inheritance"]

# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autodoc_typehints
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,5 @@ If you are new to using GitHub we recommend reading the

../generated/api/iris
../whatsnew/index
../techpapers/index
../copyright
../voted_issues
20 changes: 20 additions & 0 deletions docs/src/further_topics/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.. _further_topics_index:


Further Topics
===============

Extra information on specific technical issues.

.. toctree::
:maxdepth: 1

filtering_warnings
metadata
lenient_metadata
lenient_maths
um_files_loading
missing_data_handling
netcdf_io
dask_best_practices/index
ugrid/index
4 changes: 2 additions & 2 deletions docs/src/further_topics/lenient_maths.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ introduced and discussed the concept of lenient metadata; a more pragmatic and
forgiving approach to :ref:`comparing <lenient equality>`,
:ref:`combining <lenient combination>` and understanding the
:ref:`differences <lenient difference>` between your metadata
(:numref:`metadata members table`). The lenient metadata philosophy introduced
(:ref:`metadata members table`). The lenient metadata philosophy introduced
there is extended to cube maths, with the view to also preserving as much common
coordinate (:numref:`metadata classes table`) information, as well as common
coordinate (:ref:`metadata classes table`) information, as well as common
metadata, between the participating :class:`~iris.cube.Cube` operands as possible.

Let's consolidate our understanding of lenient and strict cube maths through
Expand Down
10 changes: 5 additions & 5 deletions docs/src/further_topics/lenient_metadata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ and also :ref:`conversion <metadata conversion>`.

The common metadata API is implemented through the ``metadata`` property
on each of the Iris `CF Conventions`_ class containers
(:numref:`metadata classes table`), and provides a common gateway for users to
(:ref:`metadata classes table`), and provides a common gateway for users to
easily manage and manipulate their metadata in a consistent and unified way.

This is primarily all thanks to the metadata classes (:numref:`metadata classes table`)
This is primarily all thanks to the metadata classes (:ref:`metadata classes table`)
that support the necessary state and behaviour required by the common metadata
API. Namely, it is the ``equal`` (``__eq__``), ``difference`` and ``combine``
methods that provide this rich metadata behaviour, all of which are explored
Expand Down Expand Up @@ -267,7 +267,7 @@ Now, compare our metadata,
>>> metadata.equal(latitude.metadata, lenient=True)
True

Again, lenient equality (:numref:`lenient equality table`) offers a more
Again, lenient equality (:ref:`lenient equality table`) offers a more
forgiving and practical alternative to strict behaviour.


Expand All @@ -277,7 +277,7 @@ Lenient Difference
------------------

Similar to :ref:`lenient equality`, the lenient ``difference`` method
(:numref:`lenient difference table`) considers there to be no difference between
(:ref:`lenient difference table`) considers there to be no difference between
comparing **something** with **nothing** (``None``). This working assumption is
not naively applied to all metadata members, but rather a more pragmatic approach
is adopted, as discussed later in :ref:`lenient members`.
Expand Down Expand Up @@ -334,7 +334,7 @@ Lenient Combination
-------------------

The behaviour of the lenient ``combine`` metadata class method is outlined
in :numref:`lenient combine table`, and as with :ref:`lenient equality` and
in :ref:`lenient combine table`, and as with :ref:`lenient equality` and
:ref:`lenient difference` is enabled through the ``lenient`` keyword argument.

The difference in behaviour between **lenient** and
Expand Down
67 changes: 40 additions & 27 deletions docs/src/further_topics/metadata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ give them meaning.
The **metadata** used to define an Iris `CF Conventions`_ class is composed of
individual **metadata members**, almost all of which reference specific
`CF Conventions`_ terms. The individual metadata members used to define each of
the Iris `CF Conventions`_ classes are shown in :numref:`metadata members table`.
the Iris `CF Conventions`_ classes are shown in :ref:`metadata members table`.

As :numref:`metadata members table` highlights, **specific** metadata is used to
As :ref:`metadata members table` highlights, **specific** metadata is used to
define and represent each Iris `CF Conventions`_ class. This means that metadata
alone, can be used to easily **identify**, **compare** and **differentiate**
between individual class instances.
Expand Down Expand Up @@ -91,6 +91,16 @@ actual `data attribute`_ names of the metadata members on the Iris class.
metadata members are Iris specific terms, rather than recognised `CF Conventions`_
terms.

.. note::

:class:`~iris.cube.Cube` :attr:`~iris.cube.Cube.attributes` implement the
concept of dataset-level and variable-level attributes, to enable correct
NetCDF loading and saving (see :class:`~iris.cube.CubeAttrsDict` and NetCDF
:func:`~iris.fileformats.netcdf.saver.save` for more). ``attributes`` on
the other classes do not have this distinction, but the ``attributes``
members of ALL the classes still have the same interface, and can be
compared.


Common Metadata API
===================
Expand All @@ -101,7 +111,7 @@ Common Metadata API
cube = iris.load_cube(iris.sample_data_path("A1B_north_america.nc"))

As of Iris ``3.0.0``, a unified treatment of metadata has been applied
across each Iris class (:numref:`metadata members table`) to allow users
across each Iris class (:ref:`metadata members table`) to allow users
to easily manage and manipulate their metadata in a consistent way.

This is achieved through the ``metadata`` property, which allows you to
Expand All @@ -128,10 +138,12 @@ For example, given the following :class:`~iris.cube.Cube`,
source 'Data from Met Office Unified Model 6.05'

We can easily get all of the associated metadata of the :class:`~iris.cube.Cube`
using the ``metadata`` property:
using the ``metadata`` property (note the specialised
:class:`~iris.cube.CubeAttrsDict` for the :attr:`~iris.cube.Cube.attributes`,
as mentioned earlier):

>>> cube.metadata
CubeMetadata(standard_name='air_temperature', long_name=None, var_name='air_temperature', units=Unit('K'), attributes={'Conventions': 'CF-1.5', 'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05'}, cell_methods=(CellMethod(method='mean', coord_names=('time',), intervals=('6 hour',), comments=()),))
CubeMetadata(standard_name='air_temperature', long_name=None, var_name='air_temperature', units=Unit('K'), attributes=CubeAttrsDict(globals={'Conventions': 'CF-1.5'}, locals={'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05'}), cell_methods=(CellMethod(method='mean', coord_names=('time',), intervals=('6 hour',), comments=()),))

We can also inspect the ``metadata`` of the ``longitude``
:class:`~iris.coords.DimCoord` attached to the :class:`~iris.cube.Cube` in the same way:
Expand All @@ -146,7 +158,7 @@ Or use the ``metadata`` property again, but this time on the ``forecast_period``
CoordMetadata(standard_name='forecast_period', long_name=None, var_name='forecast_period', units=Unit('hours'), attributes={}, coord_system=None, climatological=False)

Note that, the ``metadata`` property is available on each of the Iris `CF Conventions`_
class containers referenced in :numref:`metadata members table`, and thus provides
class containers referenced in :ref:`metadata members table`, and thus provides
a **common** and **consistent** approach to managing your metadata, which we'll
now explore a little more fully.

Expand All @@ -156,7 +168,7 @@ Metadata Classes

The ``metadata`` property will return an appropriate `namedtuple`_ metadata class
for each Iris `CF Conventions`_ class container. The metadata class returned by
each container class is shown in :numref:`metadata classes table` below,
each container class is shown in :ref:`metadata classes table` below,

.. _metadata classes table:
.. table:: - Iris namedtuple metadata classes
Expand All @@ -175,7 +187,7 @@ each container class is shown in :numref:`metadata classes table` below,
========================================== ========================================================

Akin to the behaviour of a `namedtuple`_, the metadata classes in
:numref:`metadata classes table` create **tuple-like** instances i.e., they provide a
:ref:`metadata classes table` create **tuple-like** instances i.e., they provide a
**snapshot** of the associated metadata member **values**, which are **not
settable**, but they **may be mutable** depending on the data-type of the member.
For example, given the following ``metadata`` of a :class:`~iris.coords.DimCoord`,
Expand Down Expand Up @@ -231,13 +243,13 @@ with a **snapshot** of the container class metadata values at that point in time

Skip ahead to :ref:`metadata assignment <metadata assignment>` for a fuller
discussion on options how to **set** and **get** metadata on the instance of
an Iris `CF Conventions`_ container class (:numref:`metadata classes table`).
an Iris `CF Conventions`_ container class (:ref:`metadata classes table`).


Metadata Class Behaviour
------------------------

As mentioned previously, the metadata classes in :numref:`metadata classes table`
As mentioned previously, the metadata classes in :ref:`metadata classes table`
inherit the behaviour of a `namedtuple`_, and so act and feel like a `namedtuple`_,
just as you might expect. For example, given the following ``metadata``,

Expand Down Expand Up @@ -314,7 +326,7 @@ Richer Metadata Behaviour
cube = iris.load_cube(iris.sample_data_path("A1B_north_america.nc"))
longitude = cube.coord("longitude")

The metadata classes from :numref:`metadata classes table` support additional
The metadata classes from :ref:`metadata classes table` support additional
behaviour above and beyond that of the standard Python `namedtuple`_, which
allows you to easily **compare**, **combine**, **convert** and understand the
**difference** between your ``metadata`` instances.
Expand All @@ -328,7 +340,7 @@ Metadata Equality
The metadata classes support both **equality** (``__eq__``) and **inequality**
(``__ne__``), but no other `rich comparison`_ operators are implemented.
This is simply because there is no obvious ordering to any collective of metadata
members, as defined in :numref:`metadata members table`.
members, as defined in :ref:`metadata members table`.

For example, given the following :class:`~iris.coords.DimCoord`,

Expand Down Expand Up @@ -443,7 +455,7 @@ be ``False``,

The reason different metadata classes cannot be compared is simply because each
metadata class contains **different** members, as shown in
:numref:`metadata members table`. However, there is an exception to the rule...
:ref:`metadata members table`. However, there is an exception to the rule...


.. _exception rule:
Expand Down Expand Up @@ -675,8 +687,8 @@ For example, consider the following :class:`~iris.common.metadata.CubeMetadata`,

.. doctest:: metadata-combine

>>> cube.metadata # doctest: +SKIP
CubeMetadata(standard_name='air_temperature', long_name=None, var_name='air_temperature', units=Unit('K'), attributes={'Conventions': 'CF-1.5', 'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05'}, cell_methods=(CellMethod(method='mean', coord_names=('time',), intervals=('6 hour',), comments=()),))
>>> cube.metadata
CubeMetadata(standard_name='air_temperature', long_name=None, var_name='air_temperature', units=Unit('K'), attributes=CubeAttrsDict(globals={'Conventions': 'CF-1.5'}, locals={'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05'}), cell_methods=(CellMethod(method='mean', coord_names=('time',), intervals=('6 hour',), comments=()),))

We can perform the **identity function** by comparing the metadata with itself,

Expand All @@ -701,7 +713,7 @@ which is replaced with a **different value**,
>>> metadata != cube.metadata
True
>>> metadata.combine(cube.metadata) # doctest: +SKIP
CubeMetadata(standard_name=None, long_name=None, var_name='air_temperature', units=Unit('K'), attributes={'STASH': STASH(model=1, section=3, item=236), 'source': 'Data from Met Office Unified Model 6.05', 'Model scenario': 'A1B', 'Conventions': 'CF-1.5'}, cell_methods=(CellMethod(method='mean', coord_names=('time',), intervals=('6 hour',), comments=()),))
CubeMetadata(standard_name=None, long_name=None, var_name='air_temperature', units=Unit('K'), attributes={'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05', 'Conventions': 'CF-1.5'}, cell_methods=(CellMethod(method='mean', coord_names=('time',), intervals=('6 hour',), comments=()),))

The ``combine`` method combines metadata by performing a **strict** comparison
between each of the associated metadata member values,
Expand All @@ -724,7 +736,7 @@ Let's reinforce this behaviour, but this time by combining metadata where the
>>> metadata != cube.metadata
True
>>> metadata.combine(cube.metadata).attributes
{'Model scenario': 'A1B'}
CubeAttrsDict(globals={}, locals={'Model scenario': 'A1B'})

The combined result for the ``attributes`` member only contains those
**common keys** with **common values**.
Expand Down Expand Up @@ -810,18 +822,19 @@ the ``from_metadata`` class method. For example, given the following

.. doctest:: metadata-convert

>>> cube.metadata # doctest: +SKIP
CubeMetadata(standard_name='air_temperature', long_name=None, var_name='air_temperature', units=Unit('K'), attributes={'Conventions': 'CF-1.5', 'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05'}, cell_methods=(CellMethod(method='mean', coord_names=('time',), intervals=('6 hour',), comments=()),))
>>> cube.metadata
CubeMetadata(standard_name='air_temperature', long_name=None, var_name='air_temperature', units=Unit('K'), attributes=CubeAttrsDict(globals={'Conventions': 'CF-1.5'}, locals={'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05'}), cell_methods=(CellMethod(method='mean', coord_names=('time',), intervals=('6 hour',), comments=()),))

We can easily convert it to a :class:`~iris.common.metadata.DimCoordMetadata` instance
using ``from_metadata``,

.. doctest:: metadata-convert

>>> DimCoordMetadata.from_metadata(cube.metadata) # doctest: +SKIP
DimCoordMetadata(standard_name='air_temperature', long_name=None, var_name='air_temperature', units=Unit('K'), attributes={'Conventions': 'CF-1.5', 'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05'}, coord_system=None, climatological=None, circular=None)
>>> newmeta = DimCoordMetadata.from_metadata(cube.metadata)
>>> print(newmeta)
DimCoordMetadata(standard_name=air_temperature, var_name=air_temperature, units=K, attributes={'Conventions': 'CF-1.5', 'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05'})

By examining :numref:`metadata members table`, we can see that the
By examining :ref:`metadata members table`, we can see that the
:class:`~iris.cube.Cube` and :class:`~iris.coords.DimCoord` container
classes share the following common metadata members,

Expand Down Expand Up @@ -849,9 +862,9 @@ class instance,

.. doctest:: metadata-convert

>>> longitude.metadata.from_metadata(cube.metadata)
DimCoordMetadata(standard_name='air_temperature', long_name=None, var_name='air_temperature', units=Unit('K'), attributes={'Conventions': 'CF-1.5', 'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05'}, coord_system=None, climatological=None, circular=None)

>>> newmeta = longitude.metadata.from_metadata(cube.metadata)
>>> print(newmeta)
DimCoordMetadata(standard_name=air_temperature, var_name=air_temperature, units=K, attributes={'Conventions': 'CF-1.5', 'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05'})

.. _metadata assignment:

Expand All @@ -867,7 +880,7 @@ Metadata Assignment
latitude = cube.coord("latitude")

The ``metadata`` property available on each Iris `CF Conventions`_ container
class (:numref:`metadata classes table`) can not only be used **to get**
class (:ref:`metadata classes table`) can not only be used **to get**
the metadata of an instance, but also **to set** the metadata on an instance.

For example, given the following :class:`~iris.common.metadata.DimCoordMetadata` of the
Expand Down Expand Up @@ -978,7 +991,7 @@ Indeed, it's also possible to assign to the ``metadata`` property with a
>>> longitude.metadata
DimCoordMetadata(standard_name='longitude', long_name=None, var_name='longitude', units=Unit('degrees'), attributes={}, coord_system=GeogCS(6371229.0), climatological=False, circular=False)
>>> longitude.metadata = cube.metadata
>>> longitude.metadata # doctest: +SKIP
>>> longitude.metadata
DimCoordMetadata(standard_name='air_temperature', long_name=None, var_name='air_temperature', units=Unit('K'), attributes={'Conventions': 'CF-1.5', 'STASH': STASH(model=1, section=3, item=236), 'Model scenario': 'A1B', 'source': 'Data from Met Office Unified Model 6.05'}, coord_system=GeogCS(6371229.0), climatological=False, circular=False)

Note that, only **common** metadata members will be assigned new associated
Expand Down
Loading

0 comments on commit d22c822

Please sign in to comment.