Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions docs/source/conf.py

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will need to add the sphinx-gallery package to requirements/environment.yml, under the Documentation dependencies. This will them allow the gallery to build via GitHub Actions, and will allow developers checking out this branch (and running make setup) to build the documentation.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
https://www.sphinx-doc.org/en/master/usage/configuration.html
"""

from sphinx_gallery.sorting import ExplicitOrder

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

Expand All @@ -20,6 +22,7 @@
"sphinx.ext.napoleon",
"sphinx.ext.doctest",
"sphinx.ext.extlinks",
"sphinx_gallery.gen_gallery",
]

# -- Options for HTML output -------------------------------------------------
Expand Down Expand Up @@ -61,3 +64,28 @@
# Met Office internal webserver.
r"https://wwwspice/.+",
]

# -- Sphinx gallery config ----------------------------------------------------

sphinx_gallery_conf = {
"plot_gallery": True,
"examples_dirs": "reference/cset_gallery/examples", # input scripts
"gallery_dirs": "reference/cset_gallery/generated", # output pages
"filename_pattern": r"\.py$",
"image_scrapers": ("matplotlib",),
"thumbnail_size": (800, 600),
Comment thread
ukmo-huw-lewis marked this conversation as resolved.
"capture_repr": (), # disable capture of printed / returned output
"nested_sections": False,
"subsection_order": ExplicitOrder(
[
"reference/cset_gallery/examples/spatial",
"reference/cset_gallery/examples/line",
"reference/cset_gallery/examples/custom",
]
),
}

suppress_warnings = [
"toc.not_included",
"toc.excluded",
]
3 changes: 3 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Useful links

`Source Code`_ | `Issue Tracker`_ | Releases_ | `Discussion Forum`_


For examples of CSET outputs, see :doc:`reference/cset_gallery/index`.

For information on how to use CSET, see :doc:`getting-started/index`.

For information on getting involved as a developer, see
Expand Down
4 changes: 2 additions & 2 deletions docs/source/reference/cli.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CLI Usage
=========
Command Line Usage (CLI)
========================

.. _cset-bake-command:

Expand Down
1 change: 1 addition & 0 deletions docs/source/reference/cset_gallery/examples/README.rst

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this specific file needed? All the examples themselves will be in sub categories, and the index page provides the information itself.

I wonder if the whole examples directory could be moved up a level? We might still need it to separate the source code from the generated output.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. orphan

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could be wrong on this, but I don't think this .. orphan is doing anything, given this is the comment syntax. If so it can be removed from all the files with it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I disagree, and I think I'm going to propose changes in PRs as they arrive that keep this .. orphan syntax.
Memory suggests I was trying to avoid multiple-layers of embedded links being created in LHS table of links. Only by ensuring all files were .. orphan I think did I manage to avoid 2-3 nests of same link titles being created on LHS.

2 changes: 2 additions & 0 deletions docs/source/reference/cset_gallery/examples/custom/README.rst

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently these section header files should now be called GALLERY_HEADER.rst instead of README.rst. https://sphinx-gallery.github.io/stable/configuration.html#nesting-gallery-sections

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Customising CSET outputs
========================

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments on this one apply to all of the examples.

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""
Trim edge gridcells
===================

Generate spatial map of a 2D field over selected sub-region of data with domain edges trimmed.

Spatial maps are generated using either CSET operators :py:mod:`CSET.operators.plot.spatial_pcolormesh_plot` or :py:mod:`CSET.operators.plot.spatial_contour_plot`.

General functionality is provided using :doc:`CSET recipe </usage/operator-recipes>` ``generic_surface_spatial_plot_sequence.yaml``

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm undecided on whether we want to list the operators used. On the one hand they can be looked up, on the other it is useful to explicitly say why they are being used in this example to facilitate learning.

If we do keep them I think we should formalise it a bit more. Maybe have a section for used operators with a definition list of operators used and what they do in this case? Something like:

Operators
---------

:py:mod:`CSET.operators.read.read_cubes`
    Loads the a cube of data from a file.

:py:mod:`CSET.operators.plot.spatial_contour_plot`
    Plots a spatial contour plot of the domain.

It might get a bit verbose however. Would we be better off trying to link them in the code, like matplotlib's examples do?



A) Using *cset bake* on the command line

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The A) is a bit redundant. Sphinx generates a nice listing on the side of the page for navigation, and we can also directly link to headings, so there is no need for section numbering, especially when the sections don't have any meaningful order between them.

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
----------------------------------------

While it functions fine ideally we match the heading order that other pages use. So === underlines for first level headings, --- underlines for second, and ~~~ for third level headings. (I should probably document this in some kind of style guide...)


- See :doc:`/reference/cset_gallery/generated/spatial/plot_surface_spatial` for general settings.
- Set ``SUBAREA_TYPE`` and ``SUBAREA_EXTENT`` to select trim widths, and use ``SUBAREA_NAME`` to control labelling.
- Example to generate spatial maps for selected sub-area of ``VARNAME`` for all output times:

.. code-block::

cset cookbook generic_surface_spatial_plot_sequence

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cset cookbook generic_surface_spatial_plot_sequence
cset cookbook generic_surface_spatial_plot_sequence.yml

I can't remember if the change has landed yet or not, but it is better to use the full filename (including the .yml suffix) if you can.

I might even remove the partial matching, as it causes issues when you have two recipes that share a prefix. For example spatial_plot.yml and spatial_plot_mean.yml both get selected if you query with just "spatial_plot".

cset bake -i "input_data_path" -o "my_output_path"
-r generic_surface_spatial_plot_sequence
--VARNAME="temperature_at_screen_level"
--MODEL_NAME="my_model_label"
--METHOD=""
--SUBAREA_TYPE='gridcells' --SUBAREA_EXTENT=[3, 2, 3, 1] --SUBAREA_NAME=''
[-s STYLE_FILE] [--plot-resolution PLOT_RESOLUTION] [--skip-write]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm tempted to suggest dropping these extra options. People can discover and use them on their own, but we should keep these examples as simple as we can.

That said, having an example showing using a custom style file, etc, would be a good idea.



B) Configuring the *cset_workflow*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Update workflow configuration settings via ``rose edit`` GUI or in ``rose-suite.conf`` file.
- Complete ``General setup options`` and ``Cycling and Model options`` details - see :doc:`/usage/workflow-configure`.
- Set ``SELECT_SUBAREA`` to ``True``, set ``SUBAREA_TYPE`` to ``gridcells`` and set ``SUBAREA_EXTENT``.
- Set other required configuration options on ``Diagnostics / Surface (2D) fields`` panel.

::

SELECT_SUBAREA = True
SPATIAL_SURFACE_FIELD = True
SUBAREA_TYPE = 'gridcells'
SUBAREA_EXTENT = [3, 2, 3, 1]
SUBAREA_NAME = ''
SURFACE_FIELDS = ['temperature_at_screen_level', <other_variable_of_interest>, ...]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SURFACE_FIELDS = ['temperature_at_screen_level', <other_variable_of_interest>, ...]
SURFACE_FIELDS = ['temperature_at_screen_level', ...]

The ellipsis is likely clear enough on its own as an indicator that you can provide other values.



C) Example python code
^^^^^^^^^^^^^^^^^^^^^^
"""

import CSET.operators.plot as cset_plot
import CSET.operators.read as cset_read

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tended to import the sections under their own names. For example:

from CSET.operators import read, plot

# Then use them.
cube = read.read_cube(...)

While there is the risk of something else using that name, it is always workaround able if the need arises, and I'd suggest we err on the side of simplicity where we can.


# Set path to input data
file_path = "../../../../../../tests/test_data/air_temp.nc"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relative paths like this are a bit fragile, and implicitly add the dependency that this file must be run from a checkout of the CSET workflow. Do we need to add something to CSET to easily get example data?

Both iris (iris.sample_data_path()) and cylc (cylc get-resources examples/...) do this. We could even download the data on demand to allow us to use large files if needed.

@ukmo-huw-lewis ukmo-huw-lewis Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed - as discussed, this was very much a holding line, and I wanted to use something similar to iris.sample_data_path().

However, unsure on how to achieve this in practice (i.e. set variable somewhere that points to test_data dir).

CoPilot now offering some suggestions for implementation, so can follow those.


# Read selected variable(s) of interest.
# Use read_cube parameters to control edge trim selection.
cube = cset_read.read_cubes(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you only want a single cube then read_cube() will be the operator to use. We might need some nicer example data that only has the one cube however.

file_path,
["temperature_at_screen_level"],
subarea_type="gridcells",
subarea_extent=[3, 2, 3, 1],
)[0]

# Plot single example frame using spatial_contour_plot
cset_plot.spatial_contour_plot(cube[-1])
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""
Select lat-lon subarea
======================

Generate spatial map of a 2D field over selected sub-region of data.

Spatial maps are generated using either CSET operators :py:mod:`CSET.operators.plot.spatial_pcolormesh_plot` or :py:mod:`CSET.operators.plot.spatial_contour_plot`.

General functionality is provided using :doc:`CSET recipe </usage/operator-recipes>` ``generic_surface_spatial_plot_sequence.yaml``


A) Using *cset bake* on the command line
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- See :doc:`/reference/cset_gallery/generated/spatial/plot_surface_spatial_global` for general settings.
- Set ``SUBAREA_TYPE`` and ``SUBAREA_EXTENT`` to select sub-region, and use ``SUBAREA_NAME`` to control labelling.
- Example to generate spatial maps for selected sub-area of ``VARNAME`` for all output times:

.. code-block::

cset cookbook generic_surface_spatial_plot_sequence
cset bake -i "input_data_path" -o "my_output_path"
-r generic_surface_spatial_plot_sequence
--VARNAME="temperature_at_screen_level"
--MODEL_NAME="my_model_label"
--METHOD=""
--SUBAREA_TYPE='realworld' --SUBAREA_EXTENT=[-40.0, 40.0, -20.0, 55.0] --SUBAREA_NAME='Africa'
[-s STYLE_FILE] [--plot-resolution PLOT_RESOLUTION] [--skip-write]


B) Configuring the *cset_workflow*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Update workflow configuration settings via ``rose edit`` GUI or in ``rose-suite.conf`` file.
- Complete ``General setup options`` and ``Cycling and Model options`` details - see :doc:`/usage/workflow-configure`.
- Set ``SELECT_SUBAREA`` to ``True``, choose ``SUBAREA_TYPE`` and set ``SUBAREA_EXTENT`` and ``SUBAREA_NAME``.
- Set other required configuration options on ``Diagnostics / Surface (2D) fields`` panel.

::

SELECT_SUBAREA = True
SPATIAL_SURFACE_FIELD = True
SUBAREA_TYPE = 'realworld'
SUBAREA_EXTENT = [-40.0, 40.0, -20.0, 55.0]
SUBAREA_NAME = 'Africa'
SURFACE_FIELDS = ['temperature_at_screen_level', <other_variable_of_interest>, ...]


C) Example python code
^^^^^^^^^^^^^^^^^^^^^^
"""

import CSET.operators.plot as cset_plot
import CSET.operators.read as cset_read

# Set path to input data
file_path = "../../../../../../tests/test_data/air_temperature_global.nc"

# Read selected variable(s) of interest.
# Use read_cube parameters to control subarea selection.
cube = cset_read.read_cube(
file_path,
["temperature_at_screen_level"],
subarea_type="realworld",
subarea_extent=[-40.0, 40.0, -20.0, 55.0],
)

# Plot single example frame using spatial_pcolormesh_plot
cset_plot.spatial_pcolormesh_plot(cube)
4 changes: 4 additions & 0 deletions docs/source/reference/cset_gallery/examples/line/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.. orphan

Line plots
==========
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""
Histogram plot
==============

Generate histogram of region-averaged field.

Line are generated using either CSET operators :py:mod:`CSET.operators.plot.plot_histogram_series`.

General functionality is provided using :doc:`CSET recipe </usage/operator-recipes>` ``generic_surface_histogram_series.yaml``


A) Using *cset bake* on the command line
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Access recipe file using ``cset cookbook``.
- Set required recipe inputs on command-line (or as environment variables for greater flexibility).
- Use ``SEQUENCE="realization"`` to generate one histogram for all times.
- Use ``SEQUENCE="time"`` for a histogram at each output time.
- Example to generate full domain histogram of ``VARNAME`` for all output times:

.. code-block::

cset cookbook generic_surface_histogram_series
cset bake -i "input_data_path" ["input_data_path2" "input_data_path3" "..."] -o "my_output_path"
-r generic_surface_histogram_series.yaml
--VARNAME="temperature_at_screen_level"
--MODEL_NAME="my_model_label" "my_model_label2" "my_model_label3" "..."
--SEQUENCE="realization"
--SUBAREA_TYPE='None' --SUBAREA_EXTENT='None' --SUBAREA_NAME='None'
[-s STYLE_FILE] [--plot-resolution PLOT_RESOLUTION] [--skip-write]



B) Configuring the *cset_workflow*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Update workflow configuration settings via ``rose edit`` GUI or in ``rose-suite.conf`` file.
- Complete ``General setup options`` and ``Cycling and Model options`` details - see :doc:`/usage/workflow-configure`.
- Set required configuration options on ``Diagnostics / Surface (2D) fields`` panel.
- Set ``HISTOGRAM_SURFACE_FIELD_SEQUENCE=False`` to generate one histogram for all times.
- Set ``HISTOGRAM_SURFACE_FIELD_SEQUENCE=True`` for a histogram at each output time.

::

SURFACE_FIELDS = ['temperature_at_screen_level', <other_variable_of_interest>, ...]
HISTOGRAM_SURFACE_FIELD = True
HISTOGRAM_SURFACE_FIELD_SEQUENCE = False



C) Example python code
^^^^^^^^^^^^^^^^^^^^^^
"""

import CSET.operators.plot as cset_plot
import CSET.operators.read as cset_read

# Set path to input data
file_paths = "../../../../../../tests/test_data/air_temperature_global.nc"

# Read selected variable(s) of interest
cubes = cset_read.read_cubes(file_paths, ["temperature_at_screen_level"])

# Plot domain histogram
cset_plot.plot_histogram_series(cubes, sequence_coordinate="realization")
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""
Power spectra plot
==================

Generate power spectra of region-averaged field.

Line are generated using either CSET operators :py:mod:`CSET.operators.plot.plot_line_series`.

General functionality is provided using :doc:`CSET recipe </usage/operator-recipes>` ``generic_surface_power_spectrum_series.yaml``


A) Using *cset bake* on the command line
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Access recipe file using ``cset cookbook``.
- Set required recipe inputs on command-line (or as environment variables for greater flexibility).
- Use ``SINGLE_PLOT=True`` to generate one plot for all times.
- Use ``SINGLE_PLOT=False`` for a plot at each output time.
- Example to generate full-domain power spectra of ``VARNAME`` for all output times:

.. code-block::

cset cookbook generic_surface_domain_mean_time_series
cset bake -i "input_data_path" ["input_data_path2" "input_data_path3" "..."] -o "my_output_path"
-r generic_surface_domain_mean_time_series
--VARNAME="temperature_at_screen_level"
--MODEL_NAME="my_model_label" "my_model_label2" "my_model_label3" "..."
--SINGLE_PLOT="True"
--SUBAREA_TYPE='None' --SUBAREA_EXTENT='None' --SUBAREA_NAME='None'
[-s STYLE_FILE] [--plot-resolution PLOT_RESOLUTION] [--skip-write]


B) Configuring the *cset_workflow*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Update workflow configuration settings via ``rose edit`` GUI or in ``rose-suite.conf`` file.
- Complete ``General setup options`` and ``Cycling and Model options`` details - see :doc:`/usage/workflow-configure`.
- Set required configuration options on ``Diagnostics / Surface (2D) fields`` panel.
- Set ``SPECTRUM_SURFACE_FIELD_SEQUENCE=False`` to generate spectrum for all times.
- Set ``SPECTRUM_SURFACE_FIELD_SEQUENCE=True`` for spectrum at each output time.

::

SURFACE_FIELDS = ['temperature_at_screen_level', <other_variable_of_interest>, ...]
SPECTRUM_SURFACE_FIELD = True
SPECTRUM_SURFACE_FIELD_SEQUENCE = False


C) Example python code
^^^^^^^^^^^^^^^^^^^^^^
"""

import CSET.operators.plot as cset_plot
import CSET.operators.power_spectrum as cset_spectra
import CSET.operators.read as cset_read

# Set path to input data
file_paths = "../../../../../../tests/test_data/air_temperature_global.nc"

# Read selected variable(s) of interest
cubes = cset_read.read_cubes(file_paths, ["temperature_at_screen_level"])

# Compute domain power spectrum
spectra = cset_spectra.calculate_power_spectrum(cubes)

# Plot power spectrum as line plot
cset_plot.plot_line_series(
spectra, series_coordinate="physical_wavenumber", single_plot=True
)
Loading
Loading