Skip to content

Thermosteric sea-level rise patterns #4047

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open

Conversation

mo-gregmunday
Copy link
Contributor

@mo-gregmunday mo-gregmunday commented May 20, 2025

Description

This PR calculates and evaluates patterns of thermometric sea-level rise from global thermal expansion and local sea-level changes for a range of CMIP6 models and scenarios.

Systematic calculation and evaluation of these patterns will allow for quick and easy pattern creation for future CMIP generations, and allows the patterns to be used in various sea-level rise emulation models.


Before you get started

Checklist

It is the responsibility of the author to make sure the pull request is ready to review. The icons indicate whether the item will be subject to the 🛠 Technical or 🧪 Scientific review.

New or updated recipe/diagnostic


@mo-gregmunday mo-gregmunday self-assigned this May 20, 2025
@mo-gregmunday
Copy link
Contributor Author

I know that I need a scientific and technical reviewer, I am on the hunt for both :)

@mo-gregmunday
Copy link
Contributor Author

Hey @valeriupredoi! Was wondering if you could give me a hand with some CircleCI tests failing... it's not clear whether it has anything to do with my code or not. Cheers 😊

@mo-gregmunday mo-gregmunday requested a review from ehogan June 2, 2025 09:51
@ehogan ehogan added in technical review in scientific review new recipe Use this label if you are adding a new recipe labels Jul 17, 2025
@ehogan ehogan added this to the v2.13.0 milestone Jul 17, 2025
Copy link
Contributor

@ehogan ehogan left a comment

Choose a reason for hiding this comment

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

Many thanks for your contribution @mo-gregmunday! 🥳

@@ -0,0 +1,96 @@
# (C) Crown Copyright 2022-2025, Met Office.
Copy link
Contributor

Choose a reason for hiding this comment

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

The code in this module looks very similar to what was included via #2785! Would it be possible to add a single copy of this code to esmvaltool/diag_scripts/shared and use the functions for both recipes, please? 😊

Comment on lines +5 to +6
description: Generating sterodynamic sea-level patterns from CMIP6 models.
title: Sterodynamic sea-level patterns
Copy link
Contributor

Choose a reason for hiding this comment

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

The documentation you added uses:

  • thermosteric sea-level change patterns from CMIP6 model datasets.
  • thermosteric sea-level patterns from CMIP6 models

It would be great if these were all consistent! 😊

Comment on lines +110 to +112
fig.savefig(
Path(plot_path)
/ f'detrended_{zostoga.attributes["source_id"]}.png', dpi=150)
Copy link
Contributor

Choose a reason for hiding this comment

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

Could esmvaltool.diag_scripts.shared.save_figure be used here? 😊

Copy link
Contributor

Choose a reason for hiding this comment

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

(there are other uses of this in this module!)

Comment on lines +146 to +148
idx = (yrs >= start_yr) & (yrs <= end_yr)
zostoga = zostoga[idx]
zos = zos[idx]
Copy link
Contributor

Choose a reason for hiding this comment

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

For readability, use index rather than idx 😊

Comment on lines +198 to +201
np.save(
Path(work_path)
/ f"zos_regression_{scenario}_{model}.npy", slopes)
np.save(Path(work_path) / f"zos_mask_{scenario}_{model}.npy", mask)
Copy link
Contributor

Choose a reason for hiding this comment

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

Could esmvaltool.diag_scripts.shared.save_data be used here? 😊

Copy link
Contributor

Choose a reason for hiding this comment

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

(there are other uses of this in this module!)

fig: plt.figure
figure of the evaluation
"""
# Plot the mse for each scenario
Copy link
Contributor

Choose a reason for hiding this comment

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

The next three chunks of code are very similar; would it be possible to consolidate them, please? 😊



def prepare_zostoga(
zostoga_list: iris.cube.Cube, plot_path: Path) -> list:
Copy link
Contributor

Choose a reason for hiding this comment

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

The docstring states zostoga_list is a list; which is correct?

# Calculate regression between zostoga and zos
scenarios = ["ssp245", "ssp370", "ssp585"]
slopes, masks = [], []
for i, (z_dtr, zos) in enumerate(zip(zostoga_list, zos_list)):
Copy link
Contributor

Choose a reason for hiding this comment

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

For readability, use index rather than i 😊

zos: list
list of zos scenarios
"""
# Satisfying CI linting
Copy link
Contributor

Choose a reason for hiding this comment

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

It should be possible to consolidate the code below to something like (untested):

zostoga_names = ["zostoga_picontrol", "zostoga_245", "zostoga_370", "zostoga_585"]
zostoga_cubes = []
for dataset in cfg["input_data"].values():
    if dataset["dataset"] == model:
        for zostoga_name in zostoga_names:
            if dataset["variable_group"] == zostoga_name:
                input_file = dataset["filename"]
                zostoga_cubes.append(sf.load_cube(input_file))

What do you think? 🤔

@@ -0,0 +1,531 @@
# (C) Crown Copyright 2022-2025, Met Office.
Copy link
Contributor

Choose a reason for hiding this comment

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

Are the years in this copyright statement correct? If you only worked on this code this year, the year should just be 2025.

@ehogan
Copy link
Contributor

ehogan commented Jul 17, 2025

Hey @valeriupredoi! Was wondering if you could give me a hand with some CircleCI tests failing... it's not clear whether it has anything to do with my code or not. Cheers 😊

@mo-gregmunday, run the following command in the directory containing your branch and commit the changes:

pre-commit run --files esmvaltool/diag_scripts/steric_patterns/*py

😊

@ehogan
Copy link
Contributor

ehogan commented Jul 17, 2025

To download (almost all!) the required data for this recipe, I needed to use a specific ESGF node, which I did by creating a ~/.esmvaltool/esgf-pyclient.yml configuration file containing the following:

search_connection:
  urls:
    - 'https://esg-dn1.nsc.liu.se/esg-search'

I did this both at DKRZ and at the MO 👍

@ehogan
Copy link
Contributor

ehogan commented Jul 17, 2025

Currently missing data:

2025-07-17 15:19:50,639 UTC [1831751] ERROR   Missing data for preprocessor steric_patterns/zostoga_370:
- Missing data for Dataset: zostoga, Omon, CMIP6, GISS-E2-2-G, ScenarioMIP, ssp370, r1i1p3f1, gn
2025-07-17 15:19:50,639 UTC [1831751] ERROR   Missing data for preprocessor steric_patterns/zostoga_585:
- Missing data for Dataset: zostoga, Omon, CMIP6, GISS-E2-2-G, ScenarioMIP, ssp585, r1i1p3f1, gn
2025-07-17 15:19:50,639 UTC [1831751] ERROR   Missing data for preprocessor steric_patterns/zos_370:
- Missing data for Dataset: zos, Omon, CMIP6, GISS-E2-2-G, ScenarioMIP, ssp370, r1i1p3f1, gn
2025-07-17 15:19:50,639 UTC [1831751] ERROR   Missing data for preprocessor steric_patterns/zos_585:
- Missing data for Dataset: zos, Omon, CMIP6, GISS-E2-2-G, ScenarioMIP, ssp585, r1i1p3f1, gn

@ehogan
Copy link
Contributor

ehogan commented Jul 17, 2025

I have opened #4117 for the data issue 👍

@ehogan
Copy link
Contributor

ehogan commented Jul 23, 2025

I tried again today to download data and I was able to download the data from LLNL 🥳

The recipe runs at the Met Office (using ESMValTool v2.12.0):

INFO    [2608676] Time for running the recipe was: 0:06:16.962714
INFO    [2608676] Maximum memory used (estimate): 54.6 GB
[...]
INFO    [2608676] Run was successful

However, there are no plots visible via the index.html file. This might be due to the directory structure within the plots directory.

I'm getting a failure on DKRZ:

Traceback (most recent call last):
  File "/home/b/b382148/software/ESMValTool-main/esmvaltool/diag_scripts/steric_patterns/steric_patterns.py", line 531, in <module>
    main(config)
  File "/home/b/b382148/software/ESMValTool-main/esmvaltool/diag_scripts/steric_patterns/steric_patterns.py", line 519, in main
    sf.parallelise(patterns, processes=8)(models, cfg)
  File "/home/b/b382148/software/ESMValTool-main/esmvaltool/diag_scripts/steric_patterns/sub_funcs.py", line 92, in easy_parallise
    result = pool.map_async(config_wrapper, sequence).get()
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/sw/spack-levante/miniforge3-24.11.3-0-Linux-x86_64-ftdezc/lib/python3.12/multiprocessing/pool.py", line 774, in get
    raise self._value
  File "/sw/spack-levante/miniforge3-24.11.3-0-Linux-x86_64-ftdezc/lib/python3.12/multiprocessing/pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
^^^^^^^^^^^^^^^
  File "/sw/spack-levante/miniforge3-24.11.3-0-Linux-x86_64-ftdezc/lib/python3.12/multiprocessing/pool.py", line 48, in mapstar
    return list(map(*args))
      ^^^^^^^^^^^^^^^^^
  File "/home/b/b382148/software/ESMValTool-main/esmvaltool/diag_scripts/steric_patterns/steric_patterns.py", line 489, in patterns
    slopes_arr, masks_arr = dyn_steric_regression(
  ^^^^^^^^^^^^^^^^^
  File "/home/b/b382148/software/ESMValTool-main/esmvaltool/diag_scripts/steric_patterns/steric_patterns.py", line 147, in dyn_steric_regression
    zostoga = zostoga[idx]
      ^^^^^^^^^^^^^^^^^
  File "/sw/spack-levante/miniforge3-24.11.3-0-Linux-x86_64-ftdezc/lib/python3.12/site-packages/iris/cube.py", line 3015, in __getitem__
    dimension_mapping, data = iris.util._slice_data_with_keys(cube_data, keys)
  ^^^^^^^^^^^^^^^^^
  File "/sw/spack-levante/miniforge3-24.11.3-0-Linux-x86_64-ftdezc/lib/python3.12/site-packages/iris/util.py", line 854, in _slice_data_with_keys
    data = data[this_slice]
  ^^^^^^^^^^^^^^^^^
  File "/sw/spack-levante/miniforge3-24.11.3-0-Linux-x86_64-ftdezc/lib/python3.12/site-packages/numpy/ma/core.py", line 3289, in __getitem__
    dout = self.data[indx]
  ^^^^^^^^^^^^^^^^^
IndexError: boolean index did not match indexed array along axis 0; size of axis is 3432 but size of corresponding boolean axis is 1032

@mo-gregmunday any thoughts? 🤔

Copy link
Contributor

@ehogan ehogan left a comment

Choose a reason for hiding this comment

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

One more comment!

The logs contain multiple copies of the following message:

WARNING:py.warnings:/home/b/b382148/software/ESMValTool-main/esmvaltool/diag_scripts/steric_patterns/steric_patterns.py:280: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`.
  fig = plt.figure(figsize=(12, 5), layout="constrained")

Would it be possible to implement what is suggested in this message, please? 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in scientific review in technical review new recipe Use this label if you are adding a new recipe
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Thermosteric sea-level rise patterns
2 participants