diff --git a/esmvaltool/diag_scripts/enso_metrics/climatology_diagnostic1.py b/esmvaltool/diag_scripts/enso_metrics/climatology_diagnostic1.py index 440a8d9d1e..7e591177a3 100755 --- a/esmvaltool/diag_scripts/enso_metrics/climatology_diagnostic1.py +++ b/esmvaltool/diag_scripts/enso_metrics/climatology_diagnostic1.py @@ -47,7 +47,7 @@ def plot_level1(input_data, cfg, provenance): cube, ) - if dataset["project"] == "CMIP6": + if dataset["project"].startswith("CMIP"): qplt.plot(cube, label=dataset["dataset"]) model_data = cube.data else: @@ -201,15 +201,16 @@ def main(cfg): ) # for each select obs and iterate others, obs last for grp, var_attr in variable_groups.items(): - logger.info("%s : %d, %s", grp, len(var_attr), pformat(var_attr)) + datasets = [attr["dataset"] for attr in var_attr] + logger.info("%s : %d, %s", grp, len(var_attr), datasets) pairs = [var_attr[-1]] # obs to list - prov = provenance_record(grp, list(cfg["input_data"].keys())) + prov = provenance_record(grp, [attr["filename"] for attr in var_attr]) for metadata in var_attr: logger.info("iterate though datasets\n %s", pformat(metadata)) - if metadata["project"] == "CMIP6": + if metadata["project"].startswith("CMIP"): pairs.append(metadata) fig, filename, rmse = plot_level1(pairs, cfg, prov) - + logger.info("metric %s", rmse) save_figure( "_".join(filename), prov, diff --git a/esmvaltool/diag_scripts/enso_metrics/climatology_diagnosticlevel2.py b/esmvaltool/diag_scripts/enso_metrics/climatology_diagnosticlevel2.py index 083379ab0b..af7e7564fd 100755 --- a/esmvaltool/diag_scripts/enso_metrics/climatology_diagnosticlevel2.py +++ b/esmvaltool/diag_scripts/enso_metrics/climatology_diagnosticlevel2.py @@ -26,6 +26,7 @@ def plotmaps_level2(input_data, grp): """Create map plots for pair of input data.""" fig = plt.figure(figsize=(18, 6)) proj = ccrs.Orthographic(central_longitude=210.0) + cubes = [] for plt_pos, dataset in enumerate(input_data, start=121): logger.info( "dataset: %s - %s", @@ -34,6 +35,9 @@ def plotmaps_level2(input_data, grp): ) cube, cbar_label = load_seacycle_stdev(dataset) + # return cubes to save + cubes.append(cube) + ax1 = plt.subplot(plt_pos, projection=proj) ax1.add_feature(cfeature.LAND, facecolor="gray") ax1.coastlines() @@ -61,7 +65,7 @@ def plotmaps_level2(input_data, grp): cbar = fig.colorbar(cf1, cax=cax, orientation="horizontal", extend="both") cbar.set_label(cbar_label) - return fig + return fig, cubes def load_seacycle_stdev(dataset): @@ -153,9 +157,10 @@ def main(cfg): # create pairs, add obs first to list pairs = [var_attr[-1]] logger.info("iterate though datasets\n %s", pformat(metadata)) - if metadata["project"] == "CMIP6": + if metadata["project"].startswith("CMIP"): pairs.append(metadata) - fig = plotmaps_level2(pairs, grp) + fig, data_cubes = plotmaps_level2(pairs, grp) + save_plotdata(data_cubes, grp, pairs, cfg) filename = "_".join( [ metadata["dataset"], diff --git a/esmvaltool/diag_scripts/enso_metrics/climatology_diagnosticlevel3.py b/esmvaltool/diag_scripts/enso_metrics/climatology_diagnosticlevel3.py index 8e359b1e2a..50777a55f1 100755 --- a/esmvaltool/diag_scripts/enso_metrics/climatology_diagnosticlevel3.py +++ b/esmvaltool/diag_scripts/enso_metrics/climatology_diagnosticlevel3.py @@ -48,6 +48,7 @@ def plotmaps_level3(input_data, itcz=False): "ts": np.arange(20, 31, 1), "tauu": np.arange(-80, 90, 10), } + cubes = [] for plt_pos, dataset in enumerate(input_data, start=121): logger.info( "dataset: %s - %s", @@ -56,6 +57,8 @@ def plotmaps_level3(input_data, itcz=False): ) cube, cbar_label, x_label = load_seacycle_stat(dataset, itcz) + # return cubes to save + cubes.append(cube) ax1 = plt.subplot(plt_pos) cf1 = iplt.contourf( cube, @@ -78,7 +81,7 @@ def plotmaps_level3(input_data, itcz=False): cbar = fig.colorbar(cf1, cax=cax, orientation="horizontal", extend="both") cbar.set_label(cbar_label) - return fig + return fig, cubes def load_seacycle_stat(dataset, itcz=False): @@ -176,7 +179,7 @@ def save_plotdata(plotdata, group, pairs, cfg): datafile = [ pairs[i]["dataset"], pairs[i]["short_name"], - pairs[i]["preprocessor"], + group, ] save_data("_".join(datafile), data_prov, cfg, cube) @@ -193,16 +196,17 @@ def main(cfg): ) # for each select obs and iterate others, obs last for grp, var_attr in variable_groups.items(): - logger.info("%s : %d, %s", grp, len(var_attr), pformat(var_attr)) + datasets = [attr["dataset"] for attr in var_attr] + logger.info("%s : %d, %s", grp, len(var_attr), datasets) if grp in ["pr_seacycle", "sst_seacycle", "tauu_seacycle"]: for metadata in var_attr: # create pairs, add obs first to list pairs = [var_attr[-1]] logger.info("iterate though datasets\n %s", pformat(metadata)) - if metadata["project"] == "CMIP6": + if metadata["project"].startswith("CMIP"): pairs.append(metadata) - fig = plotmaps_level3(pairs, itcz=False) - # save_plotdata(data_cubes, grp, pairs, cfg) + fig, data_cubes = plotmaps_level3(pairs, itcz=False) + save_plotdata(data_cubes, grp, pairs, cfg) filename = "_".join( [ metadata["dataset"], @@ -224,7 +228,8 @@ def main(cfg): if grp == "pr_seacycle": # replace pr with doubleITCZ grp_itcz = "doubleITCZ_seacycle" - fig = plotmaps_level3(pairs, itcz=True) + fig, data_cubes = plotmaps_level3(pairs, itcz=True) + save_plotdata(data_cubes, grp_itcz, pairs, cfg) filename = "_".join( [ metadata["dataset"], diff --git a/esmvaltool/diag_scripts/enso_metrics/enso_diag1metrics.py b/esmvaltool/diag_scripts/enso_metrics/enso_diag1metrics.py index 5b639461af..5f24758273 100755 --- a/esmvaltool/diag_scripts/enso_metrics/enso_diag1metrics.py +++ b/esmvaltool/diag_scripts/enso_metrics/enso_diag1metrics.py @@ -22,6 +22,7 @@ get_diagnostic_filename, group_metadata, run_diagnostic, + save_data, save_figure, select_metadata, ) @@ -135,8 +136,9 @@ def sst_regressed(n34_cube): # Select the data for the current year and append it to n34_selected year_enso = iris.Constraint( - time=lambda cell, enso_epoch=enso_epoch: cell.point.year - in enso_epoch, + time=lambda cell, enso_epoch=enso_epoch: ( + cell.point.year in enso_epoch + ), ) cube_2 = n34_cube.extract(year_enso) n34_selected.append(cube_2.data.data) @@ -234,7 +236,7 @@ def compute_enso_metrics(input_pair, dt_ls, var_group, metric): "ENSO lifecycle", dt_ls, ) - + # save - require months data_to_save.append(data_to_cube(obs, months, metric)) data_to_save.append(data_to_cube(model, months, metric)) @@ -275,8 +277,6 @@ def compute_enso_metrics(input_pair, dt_ls, var_group, metric): "ENSO seasonality", dt_ls, ) - data_to_save.append(data_to_cube(data_values[0], None, metric)) - data_to_save.append(data_to_cube(data_values[1], None, metric)) elif metric == "13asymmetry": model_skew = skew(input_pair[1][var_group[0]].data, axis=0) @@ -291,8 +291,6 @@ def compute_enso_metrics(input_pair, dt_ls, var_group, metric): "ENSO skewness", dt_ls, ) - data_to_save.append(data_to_cube(obs_skew, None, metric)) - data_to_save.append(data_to_cube(model_skew, None, metric)) elif metric == "14duration": model = sst_regressed(input_pair[1][var_group[0]]) @@ -313,15 +311,14 @@ def compute_enso_metrics(input_pair, dt_ls, var_group, metric): "ENSO duration", dt_ls, ) - data_to_save.append(data_to_cube(data_values[0], None, metric)) - data_to_save.append(data_to_cube(data_values[1], None, metric)) + elif metric == "15diversity": for datas in input_pair: # obs 0, mod 1 events = enso_events(datas[var_group[0]]) results_lon = diversity(datas[var_group[1]], events) results_lon["enso"] = results_lon["nino"] + results_lon["nina"] data_values.append(iqr(results_lon["enso"])) - # compute(obs, mod) + val = compute(data_values[0], data_values[1]) fig = plot_level1( data_values, @@ -330,6 +327,8 @@ def compute_enso_metrics(input_pair, dt_ls, var_group, metric): "ENSO diversity", dt_ls, ) + + if metric not in ["09pattern", "10lifecycle"]: data_to_save.append(data_to_cube(data_values[0], None, metric)) data_to_save.append(data_to_cube(data_values[1], None, metric)) @@ -458,10 +457,27 @@ def group_obs_models(obs, models, metric, var_preproc, cfg): figure=output[1], dpi=300, ) + + # save data_cubes output[2] + save_plotdata(output[2], metric, [obs, attributes], cfg) + # clear value,fig output = None +def save_plotdata(plotdata, metric, pairs, cfg): + """Save both obs and model plotted data.""" + for i, cube in enumerate(plotdata): + files = [attr["filename"] for attr in pairs[i]] + data_prov = get_provenance_record(metric, files) + datafile = [ + pairs[i][0]["dataset"], + pairs[i][0]["short_name"], + metric, + ] + save_data("_".join(datafile), data_prov, cfg, cube) + + def get_provenance_record(metric, ancestor_files): """Create a provenance record describing the diagnostic data and plot.""" caption = { @@ -549,11 +565,21 @@ def main(cfg): variable_group=var_prep, project="OBS6", ) + obs += select_metadata( + input_data, + variable_group=var_prep, + project="obs4MIPs", + ) models += select_metadata( input_data, variable_group=var_prep, project="CMIP6", ) + models += select_metadata( + input_data, + variable_group=var_prep, + project="CMIP7", + ) group_obs_models(obs, models, metric, var_preproc, cfg) diff --git a/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/ampseasskew_1113.py b/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/ampseasskew_1113.py index b177d7ce01..b259f87f0a 100755 --- a/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/ampseasskew_1113.py +++ b/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/ampseasskew_1113.py @@ -347,10 +347,48 @@ def compute_enso_metrics(input_pair, dt_ls, var_group, metric): return fig2, fig3 -def get_provenance_record(caption, ancestor_files): +def get_provenance_record(metric_level, ancestor_files): """Create a provenance record describing the diagnostic data and plot.""" + captions = { + "11amplitude_2": ( + "Zonal structure of the standard deviation of SSTA in the " + "equatorial Pacific (averaged between 5°S and 5°N)" + ), + "11amplitude_3": ( + "Spatial structure of the standard deviation of SSTA in the " + "equatorial Pacific" + ), + "12seasonality_2": ( + "Seasonality level 2: Mean annual structure of the standard " + "deviation of SSTA in the central equatorial Pacific (Niño 3.4 " + "region average), illustrating the seasonal variability." + ), + "12seasonality_3": ( + "Seasonality level 3: Spatio-mean annual structure of the " + "standard deviation of SSTA in the equatorial Pacific " + "(averaged between 5°S and 5°N)." + ), + "12seasonality_4": ( + "Seasonality level 4: Zonal structure of the standard deviation " + "of SSTA in the equatorial Pacific (averaged between 5°S and 5°N)" + " during winter (red curves) and spring (blue curves)." + ), + "12seasonality_5": ( + "Seasonality level 5: Spatial structure of the standard deviation" + " of SSTA in the equatorial Pacific during winter (NDJ) " + "and spring (MAM)." + ), + "13asymmetry_2": ( + "Zonal structure of the skewness of SSTA in the equatorial " + "Pacific (averaged between 5°S and 5°N)." + ), + "13asymmetry_3": ( + "Spatial structure of the skewness of SSTA in the equatorial " + "Pacific." + ), + } record = { - "caption": caption, + "caption": captions.get(metric_level), "statistics": ["anomaly"], "domains": ["eq"], "plot_types": ["line"], @@ -398,11 +436,21 @@ def main(cfg): variable_group=var_prep, project="OBS6", ) + obs += select_metadata( + input_data, + variable_group=var_prep, + project="obs4MIPs", + ) models += select_metadata( input_data, variable_group=var_prep, project="CMIP6", ) + models += select_metadata( + input_data, + variable_group=var_prep, + project="CMIP7", + ) # log msg = f"{metric} : observation datasets {len(obs)}, models {pformat(models)}" @@ -448,7 +496,7 @@ def main(cfg): dt_files = obs_files + [ds["filename"] for ds in models] for i, fig in enumerate(figs): prov_record = get_provenance_record( - f"ENSO metrics {metric} level {i + 2}", + f"{metric}_{i + 2}", dt_files, ) diff --git a/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/durdiver_1415.py b/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/durdiver_1415.py index 0715f8c9f1..b976c22afa 100755 --- a/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/durdiver_1415.py +++ b/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/durdiver_1415.py @@ -74,8 +74,9 @@ def enso_composite(n34): cube_data = {} for enso_epoch in years_of_interest: year_enso = iris.Constraint( - time=lambda cell, enso_epoch=enso_epoch: cell.point.year - in enso_epoch, + time=lambda cell, enso_epoch=enso_epoch: ( + cell.point.year in enso_epoch + ), ) cube_2 = n34.extract(year_enso) # extract rolling 6 yr = enso_epoch[2] @@ -247,10 +248,23 @@ def format_longitude(x, _pos): return f"{int(x)}°E" -def get_provenance_record(caption, ancestor_files): +def get_provenance_record(metric, ancestor_files): """Create a provenance record describing the diagnostic data and plot.""" + captions = { + "14duration": ( + "Distributions of durations of ENSO events " + "The black and blue boxplots show respectively the reference and " + "the model, the left and right panels show respectively La Niña " + "distributions and the El Niño distributions " + ), + "15diversity": ( + "Distributions of the zonal location of the maximum SSTA during " + "La Niña events (top left), El Niño events (top right) " + " and all ENSO events (bottom)." + ), + } record = { - "caption": caption, + "caption": captions.get(metric), "statistics": ["anomaly"], "domains": ["eq"], "plot_types": ["line"], @@ -292,11 +306,21 @@ def main(cfg): variable_group=var_prep, project="OBS6", ) + obs += select_metadata( + input_data, + variable_group=var_prep, + project="obs4MIPs", + ) models += select_metadata( input_data, variable_group=var_prep, project="CMIP6", ) + models += select_metadata( + input_data, + variable_group=var_prep, + project="CMIP7", + ) msg = ( f"{metric} : observation datasets {len(obs)}, models {len(models)}" @@ -341,7 +365,7 @@ def main(cfg): dt_files = obs_files + [ds["filename"] for ds in models] prov_record = get_provenance_record( - f"ENSO metrics {metric} dive down", + metric, dt_files, ) diff --git a/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/lifecycle_10.py b/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/lifecycle_10.py index 59581049de..7d039d3171 100755 --- a/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/lifecycle_10.py +++ b/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/lifecycle_10.py @@ -43,8 +43,9 @@ def sst_regressed_2d(event_years, n34_area, n34_dec): for yr in event_years: enso_epoch = [yr - 2, yr - 1, yr, yr + 1, yr + 2, yr + 3] year_enso = iris.Constraint( - time=lambda cell, enso_epoch=enso_epoch: cell.point.year - in enso_epoch, + time=lambda cell, enso_epoch=enso_epoch: ( + cell.point.year in enso_epoch + ), ) n34_area_selected.append(n34_area.extract(year_enso).data) @@ -150,8 +151,9 @@ def enso_composite_plot(model_n34, line): for yr in years: enso_epoch = [yr - 2, yr - 1, yr, yr + 1, yr + 2, yr + 3] year_enso = iris.Constraint( - time=lambda cell, enso_epoch=enso_epoch: cell.point.year - in enso_epoch, + time=lambda cell, enso_epoch=enso_epoch: ( + cell.point.year in enso_epoch + ), ) cube_2 = model_n34.extract(year_enso) # extract rolling 6yr cube_data.append(cube_2.data.data) @@ -167,8 +169,9 @@ def sst_2d(event_years, n34_area): for yr in event_years: enso_epoch = [yr - 2, yr - 1, yr, yr + 1, yr + 2, yr + 3] year_enso = iris.Constraint( - time=lambda cell, enso_epoch=enso_epoch: cell.point.year - in enso_epoch, + time=lambda cell, enso_epoch=enso_epoch: ( + cell.point.year in enso_epoch + ), ) n34_area_selected.append(n34_area.extract(year_enso).data) @@ -348,10 +351,27 @@ def format_longitude(x, _pos): return f"{int(x)}°E" -def get_provenance_record(caption, ancestor_files): +def get_provenance_record(metric_level, ancestor_files): """Create a provenance record describing the diagnostic data and plot.""" + captions = { + "10lifecycle_2": ( + "Spatial-temporal structure of sea surface temperature anomalies " + "(SSTA) associated with ENSO in the equatorial Pacific " + "(5°S-5°N average)" + ), + "10lifecycle_3": ( + "Temporal lifecycle of sea surface temperature anomalies " + "(SSTA) during La Niña and El Niño in the central equatorial " + "Pacific (Niño3.4 averaged)" + ), + "10lifecycle_4": ( + "Spatial-temporal structure of sea surface temperature anomalies " + "(SSTA) during La Niña and El Niño in the equatorial Pacific " + "(5°S-5°N average)" + ), + } record = { - "caption": caption, + "caption": captions.get(metric_level), "statistics": ["anomaly"], "domains": ["eq"], "plot_types": ["line"], @@ -392,11 +412,21 @@ def main(cfg): variable_group=var_prep, project="OBS6", ) + obs += select_metadata( + input_data, + variable_group=var_prep, + project="obs4MIPs", + ) models += select_metadata( input_data, variable_group=var_prep, project="CMIP6", ) + models += select_metadata( + input_data, + variable_group=var_prep, + project="CMIP7", + ) # log msg = ( @@ -443,7 +473,7 @@ def main(cfg): for i, fig in enumerate(figs): prov_record = get_provenance_record( - f"ENSO metrics {metric} level {i + 2}", + f"{metric}_{i + 2}", dt_files, ) diff --git a/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/pattern_9.py b/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/pattern_9.py index 4d6b4d1173..c6c4cbc79c 100755 --- a/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/pattern_9.py +++ b/esmvaltool/diag_scripts/enso_metrics/enso_divedowns/pattern_9.py @@ -292,10 +292,21 @@ def compute_enso_metrics(input_pair, dt_ls, var_group, metric): return fig2, fig3, fig4 -def get_provenance_record(caption, ancestor_files): +def get_provenance_record(metric_level, ancestor_files): """Create a provenance record describing the diagnostic data and plot.""" + captions = { + "09pattern_2": ( + "Sea surface temperature anomalies (SSTA) associated with ENSO in the equatorial Pacific" + ), + "09pattern_3": ( + "Sea surface temperature anomalies (SSTA) during La Niña and El Niño in the equatorial Pacific" + ), + "09pattern_4": ( + "Composite SSTA patterns for El Niño and La Niña in the equatorial Pacific" + ), + } record = { - "caption": caption, + "caption": captions.get(metric_level), "statistics": ["anomaly"], "domains": ["eq"], "plot_types": ["line"], @@ -334,11 +345,21 @@ def main(cfg): variable_group=var_prep, project="OBS6", ) + obs += select_metadata( + input_data, + variable_group=var_prep, + project="obs4MIPs", + ) models += select_metadata( input_data, variable_group=var_prep, project="CMIP6", ) + models += select_metadata( + input_data, + variable_group=var_prep, + project="CMIP7", + ) msg = f"{metric} : observation datasets {len(obs)}, models {pformat(models)}" logger.info(msg) @@ -383,7 +404,7 @@ def main(cfg): dt_files = obs_files + [ds["filename"] for ds in models] for i, fig in enumerate(figs): prov_record = get_provenance_record( - f"ENSO metrics {metric} level {i + 2}", + f"{metric}_{i + 2}", dt_files, ) diff --git a/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_metrics.py b/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_metrics.py index fd65f1b892..8b29b4b077 100755 --- a/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_metrics.py +++ b/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_metrics.py @@ -416,11 +416,21 @@ def main(cfg): variable_group=var_prep, project="OBS6", ) + obs += select_metadata( + input_data, + variable_group=var_prep, + project="obs4MIPs", + ) models += select_metadata( input_data, variable_group=var_prep, project="CMIP6", ) + models += select_metadata( + input_data, + variable_group=var_prep, + project="CMIP7", + ) # log msg = ( diff --git a/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_metrics_lvl4.py b/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_metrics_lvl4.py index 2d6b1509d9..5346975ed6 100755 --- a/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_metrics_lvl4.py +++ b/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_metrics_lvl4.py @@ -320,11 +320,21 @@ def main(cfg): variable_group=var_prep, project="OBS6", ) + obs += select_metadata( + input_data, + variable_group=var_prep, + project="obs4MIPs", + ) models += select_metadata( input_data, variable_group=var_prep, project="CMIP6", ) + models += select_metadata( + input_data, + variable_group=var_prep, + project="CMIP7", + ) # log msg = ( diff --git a/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_nhf_lvl3_4.py b/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_nhf_lvl3_4.py index 4a6601d2ab..e48be90c39 100755 --- a/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_nhf_lvl3_4.py +++ b/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_nhf_lvl3_4.py @@ -332,7 +332,9 @@ def main(cfg): obs += select_metadata(input_data, project="OBS") obs += select_metadata(input_data, project="OBS6") + obs += select_metadata(input_data, project="obs4MIPs") models += select_metadata(input_data, project="CMIP6") + models += select_metadata(input_data, project="CMIP7") # log msg = f"{metric} : observation datasets {len(obs)}, models {len(models)}" diff --git a/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_nhf_metric.py b/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_nhf_metric.py index 402b4518e8..0f87b96b12 100755 --- a/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_nhf_metric.py +++ b/esmvaltool/diag_scripts/enso_metrics/feedback/feedback_nhf_metric.py @@ -275,7 +275,9 @@ def main(cfg): obs += select_metadata(input_data, project="OBS") obs += select_metadata(input_data, project="OBS6") + obs += select_metadata(input_data, project="obs4MIPs") models += select_metadata(input_data, project="CMIP6") + models += select_metadata(input_data, project="CMIP7") # log msg = f"{metric} : observation datasets {len(obs)}, models {len(models)}" diff --git a/esmvaltool/diag_scripts/enso_metrics/teleconnections_metrics.py b/esmvaltool/diag_scripts/enso_metrics/teleconnections_metrics.py index 6413391c2a..618ed6d452 100755 --- a/esmvaltool/diag_scripts/enso_metrics/teleconnections_metrics.py +++ b/esmvaltool/diag_scripts/enso_metrics/teleconnections_metrics.py @@ -335,11 +335,21 @@ def main(cfg): variable_group=var_prep, project="OBS6", ) + obs += select_metadata( + input_data, + variable_group=var_prep, + project="obs4MIPs", + ) models += select_metadata( input_data, variable_group=var_prep, project="CMIP6", ) + models += select_metadata( + input_data, + variable_group=var_prep, + project="CMIP7", + ) # log msg = ( diff --git a/esmvaltool/recipes/ref/recipe_enso_basicclimatology.yml b/esmvaltool/recipes/ref/recipe_enso_basicclimatology_CMIP7.yml similarity index 50% rename from esmvaltool/recipes/ref/recipe_enso_basicclimatology.yml rename to esmvaltool/recipes/ref/recipe_enso_basicclimatology_CMIP7.yml index 1a523b051a..9a006f3299 100644 --- a/esmvaltool/recipes/ref/recipe_enso_basicclimatology.yml +++ b/esmvaltool/recipes/ref/recipe_enso_basicclimatology_CMIP7.yml @@ -13,15 +13,23 @@ documentation: datasets: ## one CMIP6 model for REF ## - - {dataset: ACCESS-CM2, project: CMIP6, exp: historical, ensemble: r1i1p1f1, grid: gn, start_year: 1850, end_year: 2014} - + # - {dataset: ACCESS-CM2, project: CMIP6, exp: historical, ensemble: r1i1p1f1, grid: gn, start_year: 1850, end_year: 2014} + - dataset: DUMMY-MODEL + project: CMIP7 + exp: historical + ensemble: r1i1p1f1 + grid: g999 + activity: CMIP + institute: CCCma + frequency: mon + region: glb preprocessors: base_bias: &base_bias custom_order: true - # mask_landsea: - # mask_out: land + mask_landsea: + mask_out: land climate_statistics: operator: mean period: full @@ -34,6 +42,17 @@ preprocessors: start_latitude: -15. end_latitude: 15. + base_bias_sea: &base_bias_sea + custom_order: true + climate_statistics: + operator: mean + period: full + regrid: + target_grid: 1x1 + scheme: linear + extract_region: + <<: *double + ITCZ_bias: <<: *base_bias convert_units: @@ -50,6 +69,12 @@ preprocessors: end_latitude: 5. meridional_statistics: operator: mean + eq_bias_sea: + <<: *base_bias_sea + extract_region: + <<: *eq_region + meridional_statistics: + operator: mean base_cycle: &base_cycle <<: *base_bias @@ -66,22 +91,25 @@ preprocessors: <<: *base_cycle extract_region: <<: *eq_region - - map_bias_level2: &map_bias - custom_order: true - # mask_landsea: - # mask_out: land + eq_sea_cycle_tos: + <<: *base_bias_sea climate_statistics: operator: mean - period: full - regrid: - target_grid: 1x1 - scheme: linear + period: monthly + extract_region: + <<: *eq_region + + map_bias_level2: &map_bias + <<: *base_bias extract_region: &ext start_longitude: 150. end_longitude: 270. start_latitude: -15. end_latitude: 15. + map_bias_level2_sea: + <<: *base_bias_sea + extract_region: + <<: *ext map_sea_cyclel2: <<: *map_bias @@ -97,83 +125,103 @@ diagnostics: pr_double: short_name: pr preprocessor: ITCZ_bias - mip: Amon + mip: atmos + frequency: mon + branding_suffix: tavg-u-hxy-u additional_datasets: - - {dataset: "GPCP-V2.3", project: obs4MIPs, tier: 1, start_year: 1979, end_year: 2017} + - {dataset: "GPCP-V3.3", project: obs4MIPs, tier: 1, start_year: 1983, end_year: 2021} eq_pr_bias: short_name: pr preprocessor: eq_bias - mip: Amon + mip: atmos + frequency: mon + branding_suffix: tavg-u-hxy-u additional_datasets: - - {dataset: "GPCP-V2.3", project: obs4MIPs, tier: 1, start_year: 1979, end_year: 2017} + - {dataset: "GPCP-V3.3", project: obs4MIPs, tier: 1, start_year: 1983, end_year: 2021} eq_sst_bias: short_name: tos - preprocessor: eq_bias - mip: Omon + preprocessor: eq_bias_sea + mip: ocean + branding_suffix: tavg-u-hxy-sea additional_datasets: - - {dataset: TROPFLUX, version: v1, project: OBS6, type: reanaly, tier: 2, start_year: 1979, end_year: 2018} + - {dataset: TROPFLUX, version: v2, project: OBS6, type: reanaly, tier: 2, mip: Omon, start_year: 1979, end_year: 2021} eq_tauu_bias: short_name: tauu preprocessor: eq_bias - mip: Amon + mip: atmos + branding_suffix: tavg-u-hxy-u additional_datasets: - - {dataset: TROPFLUX, version: v1, project: OBS6, type: reanaly, tier: 2, mip: Amon, start_year: 1979, end_year: 2018} + - {dataset: TROPFLUX, version: v2, project: OBS6, type: reanaly, tier: 2, mip: Amon, start_year: 1979, end_year: 2021} pr_double_seacycle: short_name: pr preprocessor: ITCZ_sea_cycle - mip: Amon + mip: atmos + frequency: mon + branding_suffix: tavg-u-hxy-u additional_datasets: - - {dataset: "GPCP-V2.3", project: obs4MIPs, tier: 1, start_year: 1979, end_year: 2017} + - {dataset: "GPCP-V3.3", project: obs4MIPs, tier: 1, start_year: 1983, end_year: 2021} eq_pr_seacycle: short_name: pr preprocessor: eq_sea_cycle - mip: Amon + mip: atmos + frequency: mon + branding_suffix: tavg-u-hxy-u additional_datasets: - - {dataset: "GPCP-V2.3", project: obs4MIPs, tier: 1, start_year: 1979, end_year: 2017} + - {dataset: "GPCP-V3.3", project: obs4MIPs, tier: 1, start_year: 1983, end_year: 2021} eq_sst_seacycle: short_name: tos - preprocessor: eq_sea_cycle - mip: Omon + preprocessor: eq_sea_cycle_tos + mip: ocean + branding_suffix: tavg-u-hxy-sea additional_datasets: - - {dataset: TROPFLUX, version: v1, project: OBS6, type: reanaly, tier: 2, mip: Omon} + - {dataset: TROPFLUX, version: v2, project: OBS6, type: reanaly, tier: 2, mip: Omon, start_year: 1979, end_year: 2021} eq_tauu_seacycle: short_name: tauu preprocessor: eq_sea_cycle - mip: Amon + mip: atmos + branding_suffix: tavg-u-hxy-u additional_datasets: - - {dataset: TROPFLUX, version: v1, project: OBS6, type: reanaly, tier: 2, mip: Amon, start_year: 1979, end_year: 2018} + - {dataset: TROPFLUX, version: v2, project: OBS6, type: reanaly, tier: 2, mip: Amon, start_year: 1979, end_year: 2021} scripts: plot_script: script: enso_metrics/climatology_diagnostic1.py - diagnostic_level2: + diagnostic_divedowns: description: run preprocessors on variables for background climatology diagnostic level 2 variables: pr_bias: short_name: pr preprocessor: map_bias_level2 - mip: Amon + mip: atmos + frequency: mon + branding_suffix: tavg-u-hxy-u additional_datasets: - - {dataset: "GPCP-V2.3", project: obs4MIPs, tier: 1, start_year: 1979, end_year: 2017} + - {dataset: "GPCP-V3.3", project: obs4MIPs, tier: 1, start_year: 1983, end_year: 2021} pr_seacycle: short_name: pr preprocessor: map_sea_cyclel2 - mip: Amon + mip: atmos + frequency: mon + branding_suffix: tavg-u-hxy-u additional_datasets: - - {dataset: "GPCP-V2.3", project: obs4MIPs, tier: 1, start_year: 1979, end_year: 2017} + - {dataset: "GPCP-V3.3", project: obs4MIPs, tier: 1, start_year: 1983, end_year: 2021} sst_bias: short_name: tos - preprocessor: map_bias_level2 - mip: Omon + preprocessor: map_bias_level2_sea + mip: ocean + branding_suffix: tavg-u-hxy-sea additional_datasets: - - {dataset: TROPFLUX, version: v1, project: OBS6, type: reanaly, tier: 2, mip: Omon} + - {dataset: TROPFLUX, version: v2, project: OBS6, type: reanaly, tier: 2, mip: Omon, start_year: 1979, end_year: 2021} tauu_bias: short_name: tauu preprocessor: map_bias_level2 - mip: Amon + mip: atmos + branding_suffix: tavg-u-hxy-u additional_datasets: - - {dataset: TROPFLUX, version: v1, project: OBS6, type: reanaly, tier: 2, mip: Amon, start_year: 1979, end_year: 2018} + - {dataset: TROPFLUX, version: v2, project: OBS6, type: reanaly, tier: 2, mip: Amon, start_year: 1979, end_year: 2021} scripts: - plot_script: + plotlevel2_script: script: enso_metrics/climatology_diagnosticlevel2.py + plotlevel3_script: + script: enso_metrics/climatology_diagnosticlevel3.py diff --git a/esmvaltool/recipes/ref/recipe_enso_characteristics.yml b/esmvaltool/recipes/ref/recipe_enso_characteristics.yml deleted file mode 100644 index 46ce5deac9..0000000000 --- a/esmvaltool/recipes/ref/recipe_enso_characteristics.yml +++ /dev/null @@ -1,127 +0,0 @@ -# ESMValTool ENSO characteristics -# ---- -documentation: - description: ENSO CLIVAR metrics by Yann Planton - basic ENSO characteristics for use in REF - title: Reproducing basic ENSO characteristics metrics - authors: - - chun_felicity - - beucher_romain - - sullivan_arnold - - planton_yann - maintainer: - - chun_felicity - -datasets: - ## one CMIP6 model for REF ## - - {dataset: ACCESS-CM2, project: CMIP6, exp: historical, ensemble: r1i1p1f1, grid: gn, start_year: 1850, end_year: 2014} - - # observations - use one - # - {dataset: NOAA-ERSSTv5, version: v5, project: OBS6, type: reanaly, tier: 2, mip: Omon} - - {dataset: TROPFLUX, version: v1, project: OBS6, type: reanaly, tier: 2, mip: Omon} - -preprocessors: - ssta_enso: &base_enso # pattern, lifecycle w/o month, duration, diversity - custom_order: true - convert_units: - units: degC - regrid: - target_grid: 1x1 - scheme: linear - extract_region: &nino34 - start_longitude: 190. - end_longitude: 240. - start_latitude: -5. - end_latitude: 5. - rolling_window_statistics: - coordinate: time - operator: mean - window_length: 5 - anomalies: - period: monthly - - ssta_ninoarea: # lifecycle duration - <<: *base_enso - area_statistics: - operator: mean - - ssta_dec_area: # pattern diversity - <<: *base_enso - area_statistics: - operator: mean - extract_month: - month: 12 - - ssta_meridional: # diversity, lifecycle duration - <<: *base_enso - extract_region: &eqp - start_longitude: 150. - end_longitude: 270. - start_latitude: -5. - end_latitude: 5. - meridional_statistics: - operator: mean - - ssta_pattern2: # pattern - <<: *base_enso - extract_region: - <<: *eqp - extract_month: - month: 12 - meridional_statistics: - operator: mean - - enso_amplitude: - <<: *base_enso - area_statistics: - operator: mean - climate_statistics: - operator: std_dev - period: full - - enso_seas_asym: - custom_order: true - extract_region: - <<: *nino34 - convert_units: - units: degC - anomalies: - period: monthly - area_statistics: - operator: mean - - -diagnostics: - diagnostic_metrics: - description: run preprocessors on variables for ENSO metrics - variables: - tos_seas_asym: # seasonality and asymmetry - short_name: tos - mip: Omon - preprocessor: enso_seas_asym - - tos_amp: # amplitude - short_name: tos - mip: Omon - preprocessor: enso_amplitude - - tos_patdiv1: # pattern diversity pt1 - short_name: tos - mip: Omon - preprocessor: ssta_dec_area - tos_lifdur1: # lifecycle duration pt1 - short_name: tos - mip: Omon - preprocessor: ssta_ninoarea - tos_lifdurdiv2: # pt2 diversity lifecycle duration - short_name: tos - mip: Omon - preprocessor: ssta_meridional - tos_pat2: # pt2 pattern - short_name: tos - mip: Omon - preprocessor: ssta_pattern2 - - scripts: - plot_script: - script: enso_metrics/enso_diag1metrics.py diff --git a/esmvaltool/recipes/ref/recipe_enso_characteristics_CMIP7.yml b/esmvaltool/recipes/ref/recipe_enso_characteristics_CMIP7.yml new file mode 100644 index 0000000000..7b1395b7d1 --- /dev/null +++ b/esmvaltool/recipes/ref/recipe_enso_characteristics_CMIP7.yml @@ -0,0 +1,252 @@ +# ESMValTool ENSO characteristics +# +--- +documentation: + description: ENSO CLIVAR metrics by Yann Planton - basic ENSO characteristics for use in REF + title: Reproducing basic ENSO characteristics metrics + authors: + - chun_felicity + - beucher_romain + - sullivan_arnold + - planton_yann + maintainer: + - chun_felicity + +datasets: + ## one CMIP6 model for REF ## + # - {dataset: ACCESS-CM2, project: CMIP6, exp: historical, ensemble: r1i1p1f1, grid: gn, start_year: 1850, end_year: 2014} + - dataset: DUMMY-MODEL #mock CMIP7 data + project: CMIP7 + exp: historical + ensemble: r1i1p1f1 + grid: g999 + activity: CMIP + institute: CCCma + mip: ocean + branding_suffix: tavg-u-hxy-sea + frequency: mon + region: glb + + # observations - use one + # - {dataset: NOAA-ERSSTv5, version: v5, project: OBS6, type: reanaly, tier: 2, mip: Omon, start_year: 1979, end_year: 2021} + - {dataset: TROPFLUX, version: v2, project: OBS6, type: reanaly, tier: 2, mip: Omon, start_year: 1979, end_year: 2021} + +preprocessors: + ssta_enso: &base_enso # pattern, lifecycle w/o month, duration, diversity + custom_order: true + # mask_landsea: + # mask_out: land + convert_units: + units: degC + regrid: + target_grid: 1x1 + scheme: linear + extract_region: &nino34 + start_longitude: 190. + end_longitude: 240. + start_latitude: -5. + end_latitude: 5. + rolling_window_statistics: + coordinate: time + operator: mean + window_length: 5 + anomalies: + period: monthly + + ssta_ninoarea: # lifecycle duration + <<: *base_enso + area_statistics: + operator: mean + + ssta_dec_area: # pattern diversity + <<: *base_enso + area_statistics: + operator: mean + extract_month: + month: 12 + + ssta_meridional: # diversity, lifecycle duration + <<: *base_enso + extract_region: &eqp + start_longitude: 150. + end_longitude: 270. + start_latitude: -5. + end_latitude: 5. + meridional_statistics: + operator: mean + + ssta_pattern2: # pattern + <<: *base_enso + extract_region: + <<: *eqp + extract_month: + month: 12 + meridional_statistics: + operator: mean + + enso_amplitude: + <<: *base_enso + area_statistics: + operator: mean + climate_statistics: + operator: std_dev + period: full + + enso_seas_asym: + custom_order: true + extract_region: + <<: *nino34 + convert_units: + units: degC + anomalies: + period: monthly + area_statistics: + operator: mean + + ssta_pattern_map: # pattern level 2,4 + <<: *base_enso + extract_region: + start_longitude: 150. + end_longitude: 270. + start_latitude: -15. + end_latitude: 15. + extract_month: + month: 12 + + + ssta_seasamp: &seas_amp # seas4 w meri + custom_order: true + convert_units: + units: degC + regrid: + target_grid: 1x1 + scheme: linear + extract_region: + start_longitude: 150. + end_longitude: 280. + start_latitude: -5. + end_latitude: 5. + anomalies: + period: monthly + + enso_amp3: + <<: *seas_amp + extract_region: &latext + start_longitude: 120. + end_longitude: 280. + start_latitude: -15. + end_latitude: 15. + climate_statistics: + operator: std_dev + period: full + + enso_seas_2: + <<: *seas_amp + extract_region: + start_longitude: 190. + end_longitude: 240. + start_latitude: -5. + end_latitude: 5. + area_statistics: + operator: mean + climate_statistics: + operator: std_dev + period: monthly + + enso_seas_3: + <<: *seas_amp + extract_region: + start_longitude: 130. + end_longitude: 280. + start_latitude: -5. + end_latitude: 5. + meridional_statistics: + operator: mean + climate_statistics: + operator: std_dev + period: monthly + + enso_seas_4: + <<: *seas_amp + meridional_statistics: + operator: mean + + enso_asymmetry: + <<: *seas_amp + extract_region: # extract again for lvl2 (5 lats) + <<: *latext + end_longitude: 290. + + +diagnostics: + diagnostic_metrics: + description: run preprocessors on variables for ENSO metrics + variables: + tos_seas_asym: # seasonality and asymmetry + short_name: tos + preprocessor: enso_seas_asym + + tos_amp: # amplitude + short_name: tos + preprocessor: enso_amplitude + + tos_patdiv1: # pattern diversity pt1 + short_name: tos + preprocessor: ssta_dec_area + tos_lifdur1: # lifecycle duration pt1 + short_name: tos + preprocessor: ssta_ninoarea + tos_lifdurdiv2: # pt2 diversity lifecycle duration + short_name: tos + preprocessor: ssta_meridional + tos_pat2: # pt2 pattern + short_name: tos + preprocessor: ssta_pattern2 + + tos_pat_map: # pattern 2,4 map + short_name: tos + mip: Omon + preprocessor: ssta_pattern_map + + scripts: + metrics_script: + script: enso_metrics/enso_diag1metrics.py + + + pattern_script: + script: enso_metrics/enso_divedowns/pattern_9.py + + lifecycle_script: + script: enso_metrics/enso_divedowns/lifecycle_10.py + + durationdiversity_script: + script: enso_metrics/enso_divedowns/durdiver_1415.py + + diagnostic_seas_skew_amp: + description: Assymetry, amplitude, seasonality divedowns + variables: + tos_seas_area: # seasonality + short_name: tos + mip: Omon + preprocessor: enso_seas_2 + tos_seas_meri: # seasonality + short_name: tos + mip: Omon + preprocessor: enso_seas_3 + tos_seas_split: # seasonality + short_name: tos + mip: Omon + preprocessor: enso_seas_4 + + tos_amp: # amplitude + short_name: tos + mip: Omon + preprocessor: enso_amp3 # amp2 tos_seas_split + tos_asym: + short_name: tos + mip: Omon + preprocessor: enso_asymmetry + + scripts: + seas_asym_amp_script: + script: enso_metrics/enso_divedowns/ampseasskew_1113.py