Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4da5552
added simple-track operator and tests
A-Gainford Apr 28, 2026
43f52bf
added example tracking recipe
A-Gainford Apr 30, 2026
cda1d0f
added temporary feature cbar definitons (limits to be set dynamically)
A-Gainford May 1, 2026
abdf356
added simple-track dependency to pyproject and env.yml
A-Gainford May 1, 2026
792f49a
removed unnecessary logging, added set_under option to feature plot
A-Gainford May 19, 2026
f89f789
added restriction of xy grid spacing on input cube
A-Gainford Jun 30, 2026
511dc13
changed feature colorbar properties
A-Gainford Jun 30, 2026
d821452
Update conda lockfiles
A-Gainford Jun 30, 2026
e3502fc
Update src/CSET/operators/__init__.py
A-Gainford Jun 30, 2026
5f0e0ba
Update src/CSET/operators/feature.py
A-Gainford Jun 30, 2026
ceb195e
Update .gitignore
A-Gainford Jun 30, 2026
7c2f62a
updated docstrings
A-Gainford Jun 30, 2026
89dc8c8
Update tests/operators/test_feature.py
A-Gainford Jun 30, 2026
53249e3
Update src/CSET/recipes/example_recipes/example_feature_track.yaml
A-Gainford Jun 30, 2026
cab9212
Update tests/operators/test_feature.py
A-Gainford Jun 30, 2026
edc4fb5
added custom feature colorbar to _colormaps
A-Gainford Jul 3, 2026
8632cf1
replaced deprecated cmap setting method, moved to _colormaps
A-Gainford Jul 3, 2026
32f05f1
added new line to gitignore
A-Gainford Jul 3, 2026
cab9b33
removed feature entries from _colorbar_definition.json
A-Gainford Jul 3, 2026
bf3b1f0
remove whitespace from example recipe
A-Gainford Jul 6, 2026
b57fc6b
[CI] Update conda lock files
github-actions[bot] Jul 6, 2026
f385041
Merge pull request #2250 from MetOffice/scheduled-updates-1783336276
A-Gainford Jul 6, 2026
671166e
added tests for _check_xy_coords and custom_colormap_feature_tracking
A-Gainford Jul 6, 2026
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,6 @@ dmypy.json

# NFS synchronisation files
.nfs*

# MacOS temp files
.DS_Store
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dependencies = [
"scores",
"dask",
"xarray",
"simple-track",
]

[project.urls]
Expand Down
1 change: 1 addition & 0 deletions requirements/environment.yml
Comment thread
A-Gainford marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies:
- dask-core # Dask with minimal dependencies.
- proj = 9.7.1 # Newer versions break plotting, see issue #2052.
- matplotlib-base = 3.10.9 # Newer versions break plotting, see issue #2205.
- simple-track # For feature tracking and cell stats operators

# Build dependencies
- setuptools>=64
Expand Down
3 changes: 2 additions & 1 deletion requirements/locks/py312-lock-linux-64.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Generated by conda-lock.
# platform: linux-64
# input_hash: b250a7e669442d882266a2b36dbaf02ac22a344cf68c51b4909773b01bc8ed4e
# input_hash: 18f693332aade4640da699cf921afdf4a4ddc6a3c923cf3a3b804f97de3cd919
@EXPLICIT
https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda#a9f577daf3de00bca7c3c76c0ecbd1de
https://conda.anaconda.org/conda-forge/linux-64/aom-3.14.1-pl5321h039972f_1.conda#5a78a69eb3b50f24b379e9d2a93163ae
Expand Down Expand Up @@ -283,6 +283,7 @@ https://conda.anaconda.org/conda-forge/noarch/scores-2.5.0-pyhd8ed1ab_0.conda#b8
https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda#8e194e7b992f99a5015edbd4ebd38efd
https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.2.0-pyhcf101f3_0.conda#224418e442ea786882979fbd2b36061f
https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-10.2.0-he0c3440_0.conda#cc27f4be260e32227b41d00e87d16b32
https://conda.anaconda.org/conda-forge/noarch/simple-track-2.2.1-pyhcf101f3_0.conda#9e6b5bb8d63c55901c51efcc534c7442
https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda#3339e3b65d58accf4ca4fb8748ab16b3
https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-3.1.1-pyhd8ed1ab_0.conda#46b6abe31482f6bca064b965696ae807
https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.4-pyhd8ed1ab_0.conda#9e21f087f087f805debe877d88e00a14
Expand Down
3 changes: 2 additions & 1 deletion requirements/locks/py313-lock-linux-64.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Generated by conda-lock.
# platform: linux-64
# input_hash: 9f964ad66b3ccd0df5e1897de428803405a71203d6fa546bb16f1fae4455533b
# input_hash: a4926971a72ffdc7239622d764c9e59e4be6aa95391ad6dd37f42b5bacc22cae
@EXPLICIT
https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda#a9f577daf3de00bca7c3c76c0ecbd1de
https://conda.anaconda.org/conda-forge/linux-64/aom-3.14.1-pl5321h039972f_1.conda#5a78a69eb3b50f24b379e9d2a93163ae
Expand Down Expand Up @@ -281,6 +281,7 @@ https://conda.anaconda.org/conda-forge/noarch/scores-2.5.0-pyhd8ed1ab_0.conda#b8
https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda#8e194e7b992f99a5015edbd4ebd38efd
https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.2.0-pyhcf101f3_0.conda#224418e442ea786882979fbd2b36061f
https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-10.2.0-he0c3440_0.conda#cc27f4be260e32227b41d00e87d16b32
https://conda.anaconda.org/conda-forge/noarch/simple-track-2.2.1-pyhcf101f3_0.conda#9e6b5bb8d63c55901c51efcc534c7442
https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda#3339e3b65d58accf4ca4fb8748ab16b3
https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-3.1.1-pyhd8ed1ab_0.conda#46b6abe31482f6bca064b965696ae807
https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.4-pyhd8ed1ab_0.conda#9e21f087f087f805debe877d88e00a14
Expand Down
3 changes: 2 additions & 1 deletion requirements/locks/py314-lock-linux-64.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Generated by conda-lock.
# platform: linux-64
# input_hash: ce6655aa6b01babac128d5359fbf8cc501c833139bc7a07ec3a3d72835aea244
# input_hash: 78675034effda826d4616dd32d2b3cf2f7ed14e76b8b9f35c009a784a9e21f24
@EXPLICIT
https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda#a9f577daf3de00bca7c3c76c0ecbd1de
https://conda.anaconda.org/conda-forge/linux-64/aom-3.14.1-pl5321h039972f_1.conda#5a78a69eb3b50f24b379e9d2a93163ae
Expand Down Expand Up @@ -282,6 +282,7 @@ https://conda.anaconda.org/conda-forge/noarch/scores-2.5.0-pyhd8ed1ab_0.conda#b8
https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda#8e194e7b992f99a5015edbd4ebd38efd
https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.2.0-pyhcf101f3_0.conda#224418e442ea786882979fbd2b36061f
https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-10.2.0-he0c3440_0.conda#cc27f4be260e32227b41d00e87d16b32
https://conda.anaconda.org/conda-forge/noarch/simple-track-2.2.1-pyhcf101f3_0.conda#9e6b5bb8d63c55901c51efcc534c7442
https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda#3339e3b65d58accf4ca4fb8748ab16b3
https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-3.1.1-pyhd8ed1ab_0.conda#46b6abe31482f6bca064b965696ae807
https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.4-pyhd8ed1ab_0.conda#9e21f087f087f805debe877d88e00a14
Expand Down
2 changes: 1 addition & 1 deletion requirements/locks/sources
Original file line number Diff line number Diff line change
@@ -1 +1 @@
97e468837e6c5cfff450fcad0310548b6d211f1148e4370f1e11130c3eb0de45 requirements/environment.yml
ef70f8db8d41711660879766b126d46c6b03d4e416e6ebec3598b64622a526c4 requirements/environment.yml
2 changes: 2 additions & 0 deletions src/CSET/operators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
constraints,
convection,
ensembles,
feature,
filters,
humidity,
imageprocessing,
Expand Down Expand Up @@ -61,6 +62,7 @@
"convection",
"ensembles",
"execute_recipe",
"feature",
"filters",
"humidity",
"get_operator",
Expand Down
20 changes: 20 additions & 0 deletions src/CSET/operators/_colorbar_definition.json
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,26 @@
"max": 1e-05,
"min": -1e-05
},
"precipitation_flux": {
"cmap": "cividis",
"levels": [
0,
0.125,
0.25,
0.5,
1,
2,
4,
8,
16,
32,
64,
128,
256
],
"ymax": 1.0,
"ymin": 0.0
},
"radar_reflectivity_at_1km_above_the_surface": {
"cmap": "cubehelix_r",
"max": 70.0,
Expand Down
65 changes: 65 additions & 0 deletions src/CSET/operators/_colormaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ def colorbar_map_levels(cube: iris.cube.Cube, axis: Literal["x", "y"] | None = N
cmap, levels, norm = custom_colormap_precipitation(cube, cmap, levels, norm)
cmap, levels, norm = custom_colormap_visibility_in_air(cube, cmap, levels, norm)
cmap, levels, norm = custom_colormap_celsius(cube, cmap, levels, norm)
cmap, levels, norm = custom_colormap_feature_tracking(cube, cmap, levels, norm)
return cmap, levels, norm


Expand Down Expand Up @@ -597,3 +598,67 @@ def custom_colormap_scores(cube: iris.cube.Cube):
if any("RMSE_" in name for name in varnames):
cmap = plt.get_cmap("PuRd", 51)
return cmap, levels, norm


def custom_colormap_feature_tracking(cube: iris.cube.Cube, cmap, levels, norm):
"""Return altered colormap for feature tracking.

Parameters
----------
cube: Cube
Cube of variable for which the colorbar information is desired.

Returns
-------
cmap: Matplotlib colormap.
levels: List
List of levels to use for plotting. For continuous plots the min and max
should be taken as the range.
norm: BoundaryNorm.
"""
varnames = list(filter(None, [cube.long_name, cube.standard_name, cube.var_name]))
if (
any("feature_id" in name for name in varnames)
and "difference" not in cube.long_name
and "mask" not in cube.long_name
):
# Define the levels and colors
levels = np.linspace(1, np.ma.max(cube.data), 10)
cmap = plt.get_cmap("viridis")
# Normalize the levels
norm = mcolors.BoundaryNorm(levels, cmap.N)
logging.info("change colormap for feature id variable colorbar.")
elif (
any("feature_lifetime" in name for name in varnames)
and "difference" not in cube.long_name
and "mask" not in cube.long_name
):
# Define the levels and colors
levels = np.linspace(1, np.ma.max(cube.data), 10)
cmap = plt.get_cmap("YlGnBu")
# Normalize the levels
norm = mcolors.BoundaryNorm(levels, cmap.N)
logging.info("change colormap for feature lifetime variable colorbar.")
elif (
any("feature_init" in name for name in varnames)
and "difference" not in cube.long_name
and "mask" not in cube.long_name
):
# Define the levels and colors
levels = np.array([0.5, 1])
cmap = plt.get_cmap("Blues")
# Normalize the levels
norm = mcolors.BoundaryNorm(levels, cmap.N)
logging.info("change colormap for feature init variable colorbar.")

else:
# do nothing and keep existing colorbar attributes
cmap = cmap
levels = levels
norm = norm

# Set all non-feature data to white
if any("feature" in name for name in varnames):
cmap.with_extremes(under="white")

return cmap, levels, norm
Loading