Skip to content
Merged
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
94 changes: 91 additions & 3 deletions src/CSET/cset_workflow/meta/diagnostics/rose-meta.conf
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ title=Surface (2D) fields
description=Surface (2D) diagnostic variables for analysis.
help=Quoted variable names for surface (2D) variables. The names should follow CF naming
conventions, and will be translated appropriately. Where applicable, a STASH code in
the format "m??s??i???" maybe be used instead.
the format "m??s??i???" may be be used instead.
compulsory=true
type=python_list
sort-key=0surface1
Expand Down Expand Up @@ -264,7 +264,7 @@ title=Pressure level fields
description=Pressure level diagnosic variables for analysis.
help=Quoted variable names for pressure level variables. The names should follow CF naming
conventions, and will be translated appropriately. Where applicable, a STASH code in
the format "m??s??i???" maybe be used instead.
the format "m??s??i???" may be be used instead.
compulsory=true
type=python_list
sort-key=1pressure1
Expand Down Expand Up @@ -484,7 +484,7 @@ title=Model level fields
description=Model level diagnostic variables for analysis.
help=Quoted variable names for model level variables. The names should follow CF naming
conventions, and will be translated appropriately. Where applicable, a STASH code in
the format "m??s??i???" maybe be used instead.
the format "m??s??i???" may be be used instead.
compulsory=true
type=python_list
sort-key=2modellevel1
Expand Down Expand Up @@ -1894,3 +1894,91 @@ help=This diagnostic identifies the aviation colour state due to visibility at e
type=python_boolean
compulsory=true
sort-key=av3

###################################
# Multi-variable overlay plotting
[Diagnostics/Multi-variable]
ns=Diagnostics/Multi-variable
sort-key=sec-d1
title=Multi-variable plots

[template variables=SPATIAL_MULTI_VARIABLE]
ns=Diagnostics/Multi-variable
title=SPATIAL_MULTI_VARIABLE
description=Create spatially mapped plots for the specified surface fields.
help=This generates spatial maps of 3 variables over-plotted.
A colour-filled map of VARNAME_BASE cube is plotted for the chosen domain.
A masked colour-filled layer of VARNAME_OVERLAY cube is overlaid on top.
A contour of VARNAME_CONTOUR is then overlaid on top of both.
type=python_boolean
compulsory=true
sort-key=multi1
trigger=template variables=MULTI_BASE_FIELD: True;
template variables=MULTI_OVERLAY_FIELD: True;
template variables=MULTI_OVERLAY_MASK_CONDITION: True;
template variables=MULTI_OVERLAY_MASK_VALUE: True;
template variables=MULTI_CONTOUR_FIELD: True;
# template variables=SPATIAL_MULTI_FIELD_METHOD: True;

[template variables=MULTI_BASE_FIELD]
ns=Diagnostics/Multi-variable
title=Base variable
description=Surface (2D) diagnostic variable to form base layer in output.
help=Quoted variable names for base surface (2D) variable. The names should follow CF naming
conventions, and will be translated appropriately. Where applicable, a STASH code in
the format "m??s??i???" may be used instead.
compulsory=true
type=quoted
sort-key=multi2

[template variables=MULTI_OVERLAY_FIELD]
ns=Diagnostics/Multi-variable
title=Overlay variable (masked)
description=Masked diagnostic variable to form overlay layer in output.
help=Quoted variable names for masked variable. The names should follow CF naming
conventions, and will be translated appropriately. Where applicable, a STASH code in
the format "m??s??i???" may be be used instead.
compulsory=true
type=quoted
sort-key=multi3

[template variables=MULTI_OVERLAY_MASK_CONDITION]
ns=Diagnostics/Multi-variable
title=Overlay variable mask condition
description=Set logical condition to control overlay masking. See help for details.
help=For example, if set to "ge", only the overlay variable values
greater than or equal to overlay variable mask value will be
over-plotted.
values="ge", "gt", "eq", "lt", "le"
compulsory=true
sort-key=multi4

[template variables=MULTI_OVERLAY_MASK_VALUE]
ns=Diagnostics/Multi-variable
title=Overlay variable mask value
description=Set variable threshold value to control overlay masking. See help for details.
help=Overlay output controlled by mask condition and mask value. For example, to overplot all non-zero rainfall, set OVERLAY_FIELD="surface_microphysical_rainfall_rate"; OVERLAY_CONDITION="ge"; OVERLAY_MASK_VALUE="0.05"
compulsory=true
type=real
sort-key=multi5

[template variables=MULTI_CONTOUR_FIELD]
ns=Diagnostics/Multi-variable
title=Contour variable
description=Diagnostic variable to form contour layer in multi-variable output.
help=Quoted variable names for contour variable. The names should follow CF naming
Comment thread
jwarner8 marked this conversation as resolved.
conventions, and will be translated appropriately. Where applicable, a STASH code in
the format "m??s??i???" may be be used instead.
compulsory=true
type=quoted
sort-key=multi6

#[template variables=SPATIAL_MULTI_FIELD_METHOD]
#ns=Diagnostics/Multi-variable
#description=Select analysis method(s) for output mapped plots. Add all options required.
# Leave blank or set to "SEQ" (sequence) for plots each diagnostic output time.
# For time-collapsed outputs over each analysis period, set to "MEAN", "MAX", "MIN", "STD_DEV" etc.
#help=Quoted analysis methods. Settings should be based on available iris.analysis methods for collapsing cube dimensions.
#type=python_list
#compulsory=true
#sort-key=multi7
7 changes: 7 additions & 0 deletions src/CSET/cset_workflow/rose-suite.conf.example
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ MODERATE_RAIN_PRESENCE_SPATIAL_DIFFERENCE=False
MODERATE_RAIN_PRESENCE_SPATIAL_PLOT=False
!!MODULES_LIST=
!!MODULES_PURGE=True
!!MULTI_BASE_FIELD=""
!!MULTI_CONTOUR_FIELD=""
!!MULTI_OVERLAY_FIELD=""
!!MULTI_OVERLAY_MASK_CONDITION="ge"
!!MULTI_OVERLAY_MASK_VALUE=0.0
!!ONE_TO_ONE=False
PLACEHOLDER_OBS=False
!!PLEVEL_TRANSECT_FINISHCOORDS=
Expand Down Expand Up @@ -147,6 +152,8 @@ SPATIAL_DIFFERENCE_SURFACE_FIELD_AGGREGATION=False,False,False,False
SPATIAL_MLEVEL_FIELD=False
SPATIAL_MLEVEL_FIELD_AGGREGATION=False,False,False,False
SPATIAL_MLEVEL_FIELD_METHOD=[""]
!!SPATIAL_MULTI_FIELD_METHOD=[""]
SPATIAL_MULTI_VARIABLE=False
SPATIAL_PLEVEL_FIELD=False
SPATIAL_PLEVEL_FIELD_AGGREGATION=False,False,False,False
SPATIAL_PLEVEL_FIELD_METHOD=[""]
Expand Down
22 changes: 22 additions & 0 deletions src/CSET/loaders/spatial_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,28 @@ def load(conf: Config):
aggregation=False,
)

if conf.SPATIAL_MULTI_VARIABLE:
for model, method in itertools.product(models, conf.SPATIAL_MULTI_FIELD_METHOD):
# Multi-variable spatial plotting.
yield RawRecipe(
recipe="multi_surface_spatial_plot_sequence.yaml",
variables={
"VARNAME_BASE": conf.MULTI_BASE_FIELD,
"VARNAME_OVER": conf.MULTI_OVERLAY_FIELD,
"OVERLAY_MASK_CONDITION": conf.MULTI_OVERLAY_MASK_CONDITION,
"OVERLAY_MASK_VALUE": conf.MULTI_OVERLAY_MASK_VALUE,
"VARNAME_CONTOUR": conf.MULTI_CONTOUR_FIELD,
"MODEL_NAME": model["name"],
"METHOD": method,
"SUBAREA_TYPE": conf.SUBAREA_TYPE if conf.SELECT_SUBAREA else None,
"SUBAREA_EXTENT": conf.SUBAREA_EXTENT
if conf.SELECT_SUBAREA
else None,
},
model_ids=model["id"],
aggregation=False,
)

# Screen-level temperature probabilities
for model, condition, threshold in itertools.product(
models,
Expand Down
67 changes: 67 additions & 0 deletions src/CSET/operators/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,34 @@ def is_spatialdim(cube: iris.cube.Cube) -> bool:
return False


def is_coorddim(cube: iris.cube.Cube, coord_name) -> bool:
"""Determine whether a cube has specified dimension coordinates.

Arguments
---------
cube: iris.cube.Cube
An iris cube which will be checked to see if it contains coordinate
names that match a pre-defined list of acceptable coordinate names.

coord_name: str
A cube dimension name

Returns
-------
bool
If true, then the cube has a spatial projection and thus can be plotted
as a map.
"""
# Get a list of dimension coordinate names for the cube
coord_names = [coord.name() for coord in cube.coords(dim_coords=True)]

# Check if requested dimension is found in cube and get index
if coord_name in coord_names:
return True
else:
return False


def is_transect(cube: iris.cube.Cube) -> bool:
"""Determine whether a cube is a transect.

Expand Down Expand Up @@ -332,6 +360,45 @@ def fully_equalise_attributes(cubes: iris.cube.CubeList):
return cubes


def slice_over_maybe(cube: iris.cube.Cube, coord_name, index):
"""Test slicing over cube if exists.

Return None if not existing.

Arguments
---------
cube: iris.cube.Cube
An iris cube which will be checked to see if it can be sliced over
given coordinate.
coord_name: coord
An iris coordinate over which to slice cube.
index:
Coordinate index value to extract

Returns
-------
cube_slice: iris.cube.Cube
A slice of iris cube, if available to slice.
"""
if cube is None:
return None

# Check if coord exists as dimension coordinate
if not is_coorddim(cube, coord_name):
return cube

# Use iris to find which axis the dimension coordinate corresponds to
dim = cube.coord_dims(coord_name)[0]

# Create list of slices for each dimension
slices = [slice(None)] * cube.ndim

# Only replace the slice for the dim to be extracted
slices[dim] = index

return cube[tuple(slices)]


def is_time_aggregatable(cube: iris.cube.Cube) -> bool:
"""Determine whether a cube can be aggregated in time.

Expand Down
Loading
Loading