Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
27 changes: 21 additions & 6 deletions src/CSET/operators/constraints.py
Comment thread
mo-sro marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,28 @@ def generate_var_constraint(varname: str, **kwargs) -> iris.Constraint:

Returns
-------
varname_constraint: iris.Constraint
An Iris constraint for either:
- a single UM STASH code
- a single variable name
- a list of variable names (Cardington multi-input case)
Comment thread
mo-sro marked this conversation as resolved.
Outdated
"""
if re.match(r"m[0-9]{2}s[0-9]{2}i[0-9]{3}$", varname):
varname_constraint = iris.AttributeConstraint(STASH=varname)
else:
varname_constraint = iris.Constraint(name=varname)
return varname_constraint
_STASH_RE = re.compile(r"m\d{2}s\d{2}i\d{3}$")
# ---- CASE 1: list of variable names (e.g. Cardington multi-variable) ----
if isinstance(varname, (list, tuple)):
return iris.Constraint(
cube_func=lambda cube: (
cube.long_name in varname
or cube.standard_name in varname
or cube.var_name in varname
)
)

# ---- CASE 2: single UM STASH code ----
if _STASH_RE.match(varname):
return iris.AttributeConstraint(STASH=varname)

# ---- CASE 3: single variable name ----
return iris.Constraint(name=varname)
Comment thread
mo-sro marked this conversation as resolved.
Outdated


def generate_level_constraint(
Expand Down
29 changes: 29 additions & 0 deletions tests/operators/test_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

from datetime import datetime

import iris
import numpy as np
import pytest

from CSET.operators import constraints
Expand Down Expand Up @@ -279,6 +281,33 @@ def test_generate_attribute_constraint_with_value():
assert expected_attr_constraint in repr(attr_constraint)


def test_generate_var_constraint_multiple_names():
"""Test constraint works for multiple variable names."""
# Create two cubes with different names
cube1 = iris.cube.Cube(np.arange(5), long_name="temperature_long")
cube1.var_name = "var_temperature"
cube2 = iris.cube.Cube(np.arange(5), standard_name="wind_speed")
# Third cube that should NOT match
cube3 = iris.cube.Cube(np.arange(5), long_name="surface_pressure")
# Generate constraint with multiple names
constraint = constraints.generate_var_constraint(["var_temperature", "wind_speed"])
# Apply constraint
cubes = iris.cube.CubeList([cube1, cube2, cube3])
result = cubes.extract(constraint)
# Check correct cubes are selected
result_names = [c.name() for c in result]

assert cube1 in result
assert cube2 in result
assert cube3 not in result

assert "temperature_long" in result_names
assert "wind_speed" in result_names
assert "surface_pressure" not in result_names
# Should only return 2 cubes
assert len(result) == 2


def test_generate_remove_single_level_constraint():
"""Tests constraint to remove default model_level_number of zero."""
remove_level_constraint = constraints.generate_remove_single_level_constraint(
Expand Down