diff --git a/doc/sphinx/source/recipes/figures/bock24acp/boxplot_ssp585_south_oc.png b/doc/sphinx/source/recipes/figures/bock24acp/boxplot_ssp585_south_oc.png new file mode 100644 index 0000000000..65f242fac2 Binary files /dev/null and b/doc/sphinx/source/recipes/figures/bock24acp/boxplot_ssp585_south_oc.png differ diff --git a/doc/sphinx/source/recipes/figures/bock24acp/map_netcre.png b/doc/sphinx/source/recipes/figures/bock24acp/map_netcre.png new file mode 100644 index 0000000000..d34e1e963a Binary files /dev/null and b/doc/sphinx/source/recipes/figures/bock24acp/map_netcre.png differ diff --git a/doc/sphinx/source/recipes/figures/bock24acp/zonal_diff_clt_ssp585.png b/doc/sphinx/source/recipes/figures/bock24acp/zonal_diff_clt_ssp585.png new file mode 100644 index 0000000000..683ac90956 Binary files /dev/null and b/doc/sphinx/source/recipes/figures/bock24acp/zonal_diff_clt_ssp585.png differ diff --git a/doc/sphinx/source/recipes/index.rst b/doc/sphinx/source/recipes/index.rst index e18ada0fd7..9943989b8f 100644 --- a/doc/sphinx/source/recipes/index.rst +++ b/doc/sphinx/source/recipes/index.rst @@ -94,6 +94,7 @@ Future projections recipe_tcr recipe_tebaldi21esd recipe_climate_change_hotspot + recipe_bock24acp IPCC ^^^^ diff --git a/doc/sphinx/source/recipes/recipe_bock24acp.rst b/doc/sphinx/source/recipes/recipe_bock24acp.rst new file mode 100644 index 0000000000..dca310c136 --- /dev/null +++ b/doc/sphinx/source/recipes/recipe_bock24acp.rst @@ -0,0 +1,142 @@ +.. _recipes_bock24acp: + +Cloud properties and their projected changes in CMIP models with low to high climate sensitivity +================================================================================================ + +Overview +-------- + +The recipes recipe_bock24acp_*.yml reproduce figures (Fig. 3, 4, 6 and 7) from the publication Bock and Lauer, 2024. + + +Available recipes and diagnostics +--------------------------------- + +Recipes are stored in recipes/clouds + + * recipe_bock24acp_fig3-4_maps.yml + * recipe_bock24acp_fig6_zonal.yml + * recipe_bock24acp_fig7_boxplots.yml + +Diagnostics are stored in diag_scripts/ + + Fig. 3 and 4: + + * clouds/clouds_ecs_groups_maps.py: Geographical maps of the multi-year annual means for group means of historical CMIP simulations from all three ECS groups. + + Fig. 6: + + * clouds/clouds_ecs_groups_zonal.py: Zonally averaged group means. + + Fig. 7: + + * clouds/clouds_ecs_groups_boxplots.py: Boxplots of relative changes for all groups. + + +User settings in recipe +----------------------- + +#. Script clouds_ecs_groups_maps.py + + *Required settings (scripts)* + + reference: if true, a reference dataset is given within 'variable_group' equal 'OBS' + + *Optional settings (scripts)* + + plot_each_model: one figure for each single model + + +#. Script clouds/clouds_ecs_groups_zonal.py + + *Required settings (scripts)* + + group_by: list of 'variable_group's to have the order + plot_type: 'zonal' and 'height' plots are available + + *Optional settings (scripts)* + + filename_attach: attachment to the output files + + +#. Script clouds/clouds_ecs_groups_boxplots.py + + *Required settings (scripts)* + + exclude_datasets: list of datasets which are not used for the statistics, default is ['MultiModelMean', 'MultiModelP5', 'MultiModelP95'] + group_by: list of 'variable_group's to have the order + plot_type: 'zonal' and 'height' plots are available + + *Optional settings (scripts)* + + filename_attach: attachment to the output files + title: set title of figure + y_range: set range of the y-axes + + +Variables +--------- + +* clt (atmos, monthly, longitude latitude time) +* iwp (atmos, monthly, longitude latitude time) +* lwp (atmos, monthly, longitude latitude time) +* rlut (atmos, monthly, longitude latitude time) +* rsut (atmos, monthly, longitude latitude time) +* rlutcs (atmos, monthly, longitude latitude time) +* rsutcs (atmos, monthly, longitude latitude time) +* tas (atmos, monthly, longitude latitude time) + + +Observations and reformat scripts +--------------------------------- + +* CERES-EBAF - CERES TOA radiation fluxes (used for calculation of + cloud forcing) + + *Reformat script:* cmorizers/data/formatters/datasets/ceres_ebaf.py + + +References +---------- + +* Bock, L. and Lauer, A.: Cloud properties and their projected changes in CMIP + models with low to high climate sensitivity, Atmos. Chem. Phys., 24, 1587–1605, + https://doi.org/10.5194/acp-24-1587-2024, 2024. + + +Example plots +------------- + +.. _fig_bock24acp_1: +.. figure:: /recipes/figures/bock24acp/map_netcre.png + :align: center + + Geographical map of the multi-year annual mean net cloud radiative effect from + (a) CERES–EBAF Ed4.2 (OBS) and (b–d) group means of historical CMIP simulations + from all three ECS groups (Fig. 4). + +.. _fig_bock24acp_2: +.. figure:: /recipes/figures/bock24acp/zonal_diff_clt_ssp585.png + :align: center + + The upper panel show the zonally averaged group means of total cloud + fraction from historical simulations (solid lines) + and RCP8.5/SSP5-8.5 scenarios (dashed lines) for the three different ECS groups. + Lower panels show the corresponding relative differences of all zonally + averaged group means between the RCP8.5/SSP5-8.5 scenarios and the corresponding + historical simulations. Shading indicates the 5 % and 95 % quantiles of the single + model results (Fig. 6a). + +.. _fig_bock24acp_3: +.. figure:: /recipes/figures/bock24acp/boxplot_ssp585_south_oc.png + :align: center + + Relative change (calculated as the difference between the scenario value and the + historical value divided by the historical value) of total cloud fraction (clt), + ice water path (iwp), liquid water path (lwp), and net cloud radiative effect + (netcre) per degree of warming averaged over the Southern Ocean (30–65∘ S). In the + box plot, each box indicates the range from the first + quartile to the third quartile, the vertical line shows the median, and the + whiskers the minimum and maximum values, excluding the outliers. Outliers are + defined as being outside 1.5 times the interquartile range (Fig. 7b). + diff --git a/esmvaltool/diag_scripts/clouds/clouds_ecs_groups_boxplots.py b/esmvaltool/diag_scripts/clouds/clouds_ecs_groups_boxplots.py new file mode 100644 index 0000000000..b2f3ad8f84 --- /dev/null +++ b/esmvaltool/diag_scripts/clouds/clouds_ecs_groups_boxplots.py @@ -0,0 +1,245 @@ +"""Python diagnostic for plotting boxplots for different regions.""" +import logging +from pathlib import Path + +import iris +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import seaborn as sns + +from esmvaltool.diag_scripts.shared import ( + ProvenanceLogger, + group_metadata, + run_diagnostic, + get_diagnostic_filename, + get_plot_filename, + select_metadata, +) + +logger = logging.getLogger(Path(__file__).stem) + +VAR_NAMES = { + 'cl': 'cloud_fraction', + 'cli': 'ice_water_content', + 'clw': 'liquid_water_content', +} +PALETTE = { + 'high ECS': 'royalblue', + 'med ECS': 'green', + 'low ECS': 'orange', +} + + +def get_provenance_record(ancestor_files): + """Create a provenance record describing the diagnostic data and plot.""" + caption = ("Relative change per degree of warming averaged over the" + "chosen region.") + + record = { + 'caption': caption, + 'statistics': ['mean'], + 'domains': ['global'], + 'plot_types': ['zonal'], + 'authors': [ + 'bock_lisa', + ], + 'references': [ + 'bock24acp', + ], + 'ancestors': ancestor_files, + } + return record + + +def _get_multi_model_mean(cubes, var): + """Compute multi-model mean.""" + + logger.debug("Calculating multi-model mean") + dataset_names = [] + mmm = {} + for (dataset, cube) in cubes.items(): + dataset_names.append(dataset) + mmm['dataset'] = cube.data + mmm = np.ma.masked_invalid(list(mmm.values())) + mmm_cube = cube.copy(data=np.ma.mean(mmm, axis=0)) + attributes = { + 'dataset': 'MultiModelMean', + 'short_name': var, + 'datasets': '|'.join(dataset_names), + } + mmm_cube.attributes = attributes + return mmm_cube + + +def read_data(filename): + """Compute an example diagnostic.""" + logger.debug("Loading %s", filename) + cube = iris.load_cube(filename) + + if cube.var_name == 'cli': + cube.convert_units('g/kg') + elif cube.var_name == 'clw': + cube.convert_units('g/kg') + + cube = iris.util.squeeze(cube) + return cube + + +def compute_diff(filename1, filename2): + """Compute difference between two cubes.""" + logger.debug("Loading %s", filename1) + cube1 = iris.load_cube(filename1) + cube2 = iris.load_cube(filename2) + + if cube1.var_name == 'cli': + cube1.convert_units('g/kg') + cube2.convert_units('g/kg') + elif cube1.var_name == 'clw': + cube1.convert_units('g/kg') + cube2.convert_units('g/kg') + + cube = cube2 - cube1 + cube.metadata = cube1.metadata + return cube + + +def compute_diff_temp(input_data, group, var, dataset): + """Compute relative change per temperture change.""" + + dataset_name = dataset['dataset'] + var = dataset['short_name'] + + input_file_1 = dataset['filename'] + + var_data_2 = select_metadata(input_data, + short_name=var, + dataset=dataset_name, + variable_group=var+"_"+group[1]) + if not var_data_2: + raise ValueError( + f"No '{var}' data for '{dataset_name}' in '{group[1]}' available") + + input_file_2 = var_data_2[0]['filename'] + + tas_data_1 = select_metadata(input_data, + short_name='tas', + dataset=dataset_name, + variable_group='tas_'+group[0]) + tas_data_2 = select_metadata(input_data, + short_name='tas', + dataset=dataset_name, + variable_group='tas_'+group[1]) + if not tas_data_1: + raise ValueError( + f"No 'tas' data for '{dataset_name}' in '{group[0]}' available") + if not tas_data_2: + raise ValueError( + f"No 'tas' data for '{dataset_name}' in '{group[1]}' available") + input_file_tas_1 = tas_data_1[0]['filename'] + input_file_tas_2 = tas_data_2[0]['filename'] + + cube = read_data(input_file_1) + + cube_diff = compute_diff(input_file_1, input_file_2) + cube_tas_diff = compute_diff(input_file_tas_1, input_file_tas_2) + + cube_diff = (100. * (cube_diff / iris.analysis.maths.abs(cube)) + / cube_tas_diff) + + return cube_diff + + +def create_data_frame(input_data, cfg): + """Create data frame.""" + data_frame = pd.DataFrame(columns=['Variable', 'Group', 'Dataset', 'Data']) + + ifile = 0 + + all_vars = group_metadata(input_data, 'short_name') + groups = group_metadata(input_data, 'variable_group', sort='dataset') + + for var in all_vars: + if var != 'tas': + logger.info("Processing variable %s", var) + + if var == 'clivi': + varname = 'iwp' + else: + varname = var + + for group_names in cfg['group_by']: + logger.info("Processing group %s of variable %s", + group_names[0], var) + + for dataset in groups[var + "_" + group_names[0]]: + dataset_name = dataset['dataset'] + + if dataset_name not in cfg['exclude_datasets']: + cube_diff = compute_diff_temp(input_data, group_names, + var, dataset) + + group_name = group_names[0].split('_')[1] + " ECS" + + data_frame.loc[ifile] = [varname, group_name, + dataset_name, cube_diff.data] + ifile = ifile + 1 + + data_frame['Data'] = data_frame['Data'].astype(str).astype(float) + + return data_frame + + +def plot_boxplot(data_frame, cfg): + + sns.set_style('darkgrid') + sns.set(font_scale=2) + sns.boxplot(data=data_frame, x='Variable', y='Data', hue='Group', + palette=PALETTE) + plt.ylabel('Relative change (%/K)') + if 'y_range' in cfg: + plt.ylim(cfg.get('y_range')) + plt.title(cfg['title']) + + provenance_record = get_provenance_record( + ancestor_files=cfg['input_files']) + + # Save plot + plot_path = get_plot_filename('boxplot' + '_' + cfg['filename_attach'], + cfg) + plt.savefig(plot_path) + logger.info("Wrote %s", plot_path) + plt.close() + + with ProvenanceLogger(cfg) as provenance_logger: + provenance_logger.log(plot_path, provenance_record) + + +def main(cfg): + """Run diagnostic.""" + cfg.setdefault('exclude_datasets', ['MultiModelMean', 'MultiModelP5', + 'MultiModelP95']) + cfg.setdefault('title', 'Test') + + plt.figure(constrained_layout=True, figsize=(12, 8)) + + # Get input data + input_data = list(cfg['input_data'].values()) + + # Create data frame + data_frame = create_data_frame(input_data, cfg) + + # Create plot + plot_boxplot(data_frame, cfg) + + # Save file + basename = "boxplot_region_" + cfg['filename_attach'] + csv_path = get_diagnostic_filename(basename, cfg).replace('.nc', '.csv') + data_frame.to_csv(csv_path) + logger.info("Wrote %s", csv_path) + + +if __name__ == '__main__': + + with run_diagnostic() as config: + main(config) diff --git a/esmvaltool/diag_scripts/clouds/clouds_ecs_groups_maps.py b/esmvaltool/diag_scripts/clouds/clouds_ecs_groups_maps.py new file mode 100644 index 0000000000..b49cd51ca8 --- /dev/null +++ b/esmvaltool/diag_scripts/clouds/clouds_ecs_groups_maps.py @@ -0,0 +1,510 @@ +"""Python diagnostic for plotting geographical maps.""" +import logging +import random +from copy import deepcopy +from pathlib import Path + +import cartopy.crs as ccrs +import iris +import iris.plot as iplt +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +from iris.analysis.stats import pearsonr + +from esmvaltool.diag_scripts.shared import ( + extract_variables, + get_diagnostic_filename, + get_plot_filename, + group_metadata, + run_diagnostic, + save_data, + save_figure, +) + +logger = logging.getLogger(Path(__file__).stem) + +VAR_NAMES = { + 'clt': 'total_cloud_fraction', + 'lwp': 'liquid_water_path', + 'clivi': 'ice_water_path', + 'netcre': 'net_cre', + 'swcre': 'sw_cre', + 'lwcre': 'lw_cre', +} +PANEL = {'ECS_high': 222, 'ECS_med': 223, 'ECS_low': 224, 'OBS': 221} +PANEL_woOBS = { + 'ECS_high': 131, + 'ECS_med': 132, + 'ECS_low': 133, +} +PANEL_LABELS = { + 'ECS_high': 'b)', + 'ECS_med': 'c)', + 'ECS_low': 'd)', + 'OBS': 'a)' +} +PANEL_LABELS_woOBS = { + 'ECS_high': 'a)', + 'ECS_med': 'b)', + 'ECS_low': 'c)', +} +PANDAS_PRINT_OPTIONS = ['display.max_rows', None, 'display.max_colwidth', -1] + + +def get_provenance_record(attributes, ancestor_files): + """Create a provenance record describing the diagnostic data and plot.""" + caption = ("Climatology of {standard_name}.".format(**attributes)) + + record = { + 'caption': caption, + 'statistics': ['mean'], + 'domains': ['global'], + 'plot_types': ['map'], + 'authors': [ + 'bock_lisa', + ], + 'references': [ + 'bock24acp', + ], + 'ancestors': ancestor_files, + } + return record + + +def area_weighted_mean(cube): + logger.debug("Computing field mean") + grid_areas = iris.analysis.cartography.area_weights(cube) + mean = cube.collapsed(['longitude', 'latitude'], + iris.analysis.MEAN, + weights=grid_areas) + return mean + + +def calculate_bias(model_cube, obs_cube): + logger.debug("Computing bias") + diff = model_cube - obs_cube + bias = area_weighted_mean(diff) + bias.attributes = model_cube.attributes + return bias + + +def calculate_rmsd(model_cube, obs_cube): + logger.debug("Computing RMSD") + diff = model_cube - obs_cube + rmsd = area_weighted_mean(diff**2)**0.5 + rmsd.attributes = model_cube.attributes + return rmsd + + +def calculate_corr(model_cube, obs_cube): + logger.debug("Computing Correlation") + grid_areas = iris.analysis.cartography.area_weights(model_cube) + corr = pearsonr(model_cube, obs_cube, weights=grid_areas) + return corr + + +def compute_diagnostic(filename): + + logger.debug("Loading %s", filename) + cube = iris.load_cube(filename) + + cube = iris.util.squeeze(cube) + return cube + + +def plot_model(cube, attributes, cfg): + # Plot each model. + + levels = [10, 20, 30, 40, 50, 60, 70, 80, 90] + if attributes['short_name'] == 'clt': + levels = [10, 20, 30, 40, 50, 60, 70, 80, 90] + cmap = 'viridis' + elif attributes['short_name'] == 'clivi': + levels = [0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2] + cmap = 'viridis' + elif attributes['short_name'] == 'lwp': + levels = [0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2] + cmap = 'viridis' + elif attributes['short_name'] == 'netcre': + levels = [-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50] + cmap = 'bwr' + elif attributes['short_name'] == 'lwcre': + levels = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90] + cmap = 'Reds' + elif attributes['short_name'] == 'swcre': + levels = [-90, -80, -70, -60, -50, -40, -30, -20, -10, 0] + cmap = 'Blues_r' + else: # default + cmap = 'viridis' + plt.axes(projection=ccrs.Robinson()) + iplt.contourf(cube, levels=levels, cmap=cmap, extend='both') + plt.gca().coastlines() + colorbar = plt.colorbar(orientation='horizontal') + colorbar.set_label(cube.var_name + '/' + cube.units.origin) + if attributes['short_name'] == 'clt': + ticks = [10, 20, 30, 40, 50, 60, 70, 80, 90] + elif attributes['short_name'] == 'clivi': + ticks = [0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2] + elif attributes['short_name'] == 'lwp': + ticks = [0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2] + elif attributes['short_name'] == 'netcre': + ticks = [-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50] + elif attributes['short_name'] == 'lwcre': + ticks = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90] + elif attributes['short_name'] == 'swcre': + ticks = [-90, -80, -70, -60, -50, -40, -30, -20, -10, 0] + else: + ticks = levels + colorbar.set_ticks(ticks) + colorbar.set_ticklabels([str(tick) for tick in ticks]) + + # Appearance + dataset_name = attributes['dataset'] + exp_name = attributes['exp'] + title = f'{VAR_NAMES.get(cube.var_name, cube.var_name)} for {dataset_name}' + filename = (f'{VAR_NAMES.get(cube.var_name, cube.var_name)}_' + f'{exp_name}_{dataset_name}') + + plt.title(title) + plot_path = get_plot_filename(filename, cfg) + plt.savefig(plot_path, bbox_inches='tight', orientation='landscape') + logger.info("Wrote %s", plot_path) + plt.close() + + +def read_data(groups, cfg): + logger.debug("Read data") + cubes = iris.cube.CubeList() + cubes_out = iris.cube.CubeList() + + for group_name in groups: + logger.info("Processing variable %s", group_name) + + for attributes in groups[group_name]: + logger.info("Processing dataset %s", attributes['dataset']) + input_file = attributes['filename'] + cube = compute_diagnostic(input_file) + cube.attributes['variable_group'] = group_name + cube.attributes['dataset'] = attributes['dataset'] + + cubes.append(cube) + + if (attributes['dataset'] == 'MultiModelMean' + or group_name == 'OBS'): + cubes_out.append(cube) + else: + if cfg['plot_each_model']: + plot_model(cube, attributes, cfg) + + return cubes, cubes_out + + +def plot_diagnostic(cubes, attributes, cfg): + """Create diagnostic data and plot it.""" + + if cfg['reference']: + fig = plt.figure(figsize=(14, 9)) + title = attributes['long_name'] + fig.suptitle(title, fontsize=22) + plt.subplots_adjust(left=0.05, + bottom=0.15, + right=0.95, + top=0.90, + wspace=0.2, + hspace=0.05) + else: + fig = plt.figure(figsize=(10, 3)) + title = attributes['long_name'] + fig.suptitle(title, fontsize=16) + plt.subplots_adjust(left=0.02, + bottom=0.10, + right=0.98, + top=0.95, + wspace=0.01, + hspace=0.01) + + cmap = 'bwr' + if attributes['short_name'] == 'clt': + levels = [10, 20, 30, 40, 50, 60, 70, 80, 90] + cmap = 'viridis' + elif attributes['short_name'] == 'clivi': + levels = [0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2] + cmap = 'viridis' + elif attributes['short_name'] == 'lwp': + levels = [0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2] + cmap = 'viridis' + elif attributes['short_name'] == 'netcre': + levels = [-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50] + cmap = 'bwr' + elif attributes['short_name'] == 'lwcre': + levels = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90] + cmap = 'Reds' + elif attributes['short_name'] == 'swcre': + levels = [-90, -80, -70, -60, -50, -40, -30, -20, -10, 0] + cmap = 'Blues_r' + elif attributes['short_name'] == 'clt_diff': + levels = list(np.arange(-30, 31, 2.5)) + elif attributes['short_name'] == 'clivi_diff': + levels = list(np.arange(-0.1, 0.105, 0.01)) + elif attributes['short_name'] == 'lwp_diff': + levels = list(np.arange(-0.1, 0.105, 0.01)) + elif attributes['short_name'] in [ + 'netcre_diff', 'lwcre_diff', 'swcre_diff' + ]: + levels = list(np.arange(-30, 31, 2.5)) + else: + levels = list(np.linspace(min(cubes), max(cubes), 10)) + + for cube in cubes: + logger.info("Plotting %s %s of group %s", cube.attributes['dataset'], + attributes['short_name'], + cube.attributes['variable_group']) + mean = area_weighted_mean(cube) + + legend = cube.attributes['variable_group'] + + if cfg['reference']: + ipanel = PANEL.get(legend, None) + else: + ipanel = PANEL_woOBS.get(legend, None) + + plt.subplot(ipanel, projection=ccrs.Robinson()) + + im = iplt.contourf(cube, levels=levels, cmap=cmap, extend='both') + + plt.gca().coastlines() + + if cfg['reference']: + plt.title(legend, fontsize=18) + ipanel_label = PANEL_LABELS.get(legend, None) + plt.title(ipanel_label, fontsize=22, loc='left') + fsize = 14 + else: + plt.title(legend, fontsize=9) + ipanel_label = PANEL_LABELS_woOBS.get(legend, None) + plt.title(ipanel_label, fontsize=12, loc='left') + fsize = 8 + if attributes['short_name'] in ['clt', 'netcre']: + plt.title(f'mean = {mean.data:.1f} ', + fontsize=fsize, + loc='right') + elif attributes['short_name'] in ['clivi', 'lwp']: + plt.title(f'mean = {mean.data:.3f} ', + fontsize=fsize, + loc='right') + elif attributes['short_name'] in ['clivi_diff', 'lwp_diff']: + plt.title(f'bias = {mean.data:.3f} ', + fontsize=fsize, + loc='right') + elif attributes['short_name'] in ['clt_diff', 'netcre_diff']: + plt.title(f'bias = {mean.data:.1f} ', + fontsize=fsize, + loc='right') + else: + plt.title(f'{mean.data:.1f} ', fontsize=fsize, loc='right') + + if cfg['reference']: + cbar_ax = fig.add_axes([0.2, 0.08, 0.6, 0.03]) + colorbar = fig.colorbar(im, cax=cbar_ax, orientation='horizontal') + else: + cbar_ax = fig.add_axes([0.2, 0.18, 0.6, 0.03]) + colorbar = fig.colorbar(im, cax=cbar_ax, orientation='horizontal') + + if cube.var_name == "clivi": + colorbar.set_label('iwp / ' + cube.units.origin) + else: + colorbar.set_label(cube.var_name + ' / ' + cube.units.origin) + if attributes['short_name'] == 'clt': + ticks = [10, 20, 30, 40, 50, 60, 70, 80, 90] + elif attributes['short_name'] == 'clivi': + ticks = [0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2] + elif attributes['short_name'] == 'lwp': + ticks = [0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2] + elif attributes['short_name'] == 'netcre': + ticks = [-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50] + elif attributes['short_name'] == 'lwcre': + ticks = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90] + elif attributes['short_name'] == 'swcre': + ticks = [-90, -80, -70, -60, -50, -40, -30, -20, -10, 0] + + elif attributes['short_name'] == 'clt_diff': + ticks = list(np.arange(-30, 31, 5)) + elif attributes['short_name'] == 'clivi_diff': + ticks = [ + -0.1, -0.08, -0.06, -0.04, -0.02, 0., 0.02, 0.04, 0.06, 0.08, 0.1 + ] + elif attributes['short_name'] == 'lwp_diff': + ticks = [ + -0.1, -0.08, -0.06, -0.04, -0.02, 0., 0.02, 0.04, 0.06, 0.08, 0.1 + ] + elif attributes['short_name'] in [ + 'netcre_diff', 'lwcre_diff', 'swcre_diff' + ]: + ticks = list(np.arange(-30, 31, 5)) + else: + ticks = levels + + colorbar.set_ticks(ticks) + colorbar.set_ticklabels([str(tick) for tick in ticks]) + + # Save the data and the plot + provenance_record = get_provenance_record( + attributes, ancestor_files=cfg['input_files']) + basename = 'map_' + attributes['short_name'] + + save_data(basename, provenance_record, cfg, cubes) + save_figure(basename, provenance_record, cfg) + + +def get_dataframe(cubes, cube_obs): + + df = pd.DataFrame(columns=['Dataset', 'Group', 'Statistic', 'Value']) + idf = 0 + + for cube in cubes: + dataset = cube.attributes['dataset'] + group = cube.attributes['variable_group'] + logger.info("Computing statistics of dataset %s", dataset) + + mean = area_weighted_mean(cube) + bias = calculate_bias(cube, cube_obs) + rmsd = calculate_rmsd(cube, cube_obs) + corr = calculate_corr(cube, cube_obs) + + df.loc[idf] = [dataset, group, 'Mean', mean.data] + idf = idf + 1 + df.loc[idf] = [dataset, group, 'Bias', bias.data] + idf = idf + 1 + df.loc[idf] = [dataset, group, 'RMSD', rmsd.data] + idf = idf + 1 + df.loc[idf] = [dataset, group, 'Corr', corr.data] + idf = idf + 1 + + return df + + +def write_statistics(df, attributes, cfg): + df['Value'] = df['Value'].astype(str).astype(float) + + basename = "statistic_all_" + attributes['short_name'] + csv_path = get_diagnostic_filename(basename, cfg).replace('.nc', '.csv') + df.to_csv(csv_path) + logger.info("Wrote %s", csv_path) + + stat = df.groupby(['Statistic', 'Group'])['Value'].describe() + basename = "statistic_" + attributes['short_name'] + csv_path = get_diagnostic_filename(basename, cfg).replace('.nc', '.csv') + stat.to_csv(csv_path) + logger.info("Wrote %s", csv_path) + + +def bootstrapping(cubes, cube_obs, all_groups, attributes, cfg): + logger.info("Bootstrapping") + + for group in all_groups: + if group != 'OBS': + logger.info("Processing group %s", group) + cubes_part = {} + datasets = [] + for cube in cubes: + if cube.attributes['variable_group'] == group: + dataset = cube.attributes['dataset'] + cubes_part[dataset] = cube + datasets.append(dataset) + + nsample = 1000 + sample_stat = pd.DataFrame( + columns=['Mean', 'Bias', 'RMSD', 'Corr']) + + ncubes = len(cubes_part) + array = list(np.arange(0, ncubes)) + for iboot in range(0, nsample): + ires = random.choices(array, k=len(array)) + for i, icube in enumerate(ires): + if i == 0: + cube = cubes_part[datasets[icube]].copy() + else: + cube += cubes_part[datasets[icube]] + cube.data = cube.data / ncubes + sample_stat.loc[iboot] = [ + area_weighted_mean(cube).data, + calculate_bias(cube, cube_obs).data, + calculate_rmsd(cube, cube_obs).data, + calculate_corr(cube, cube_obs).data + ] + + sample_stat = sample_stat.astype(float) + stat = sample_stat.describe() + basename = f"bootstrapping_{attributes['short_name']}_{group}" + csv_path = (get_diagnostic_filename(basename, + cfg).replace('.nc', '.csv')) + stat.to_csv(csv_path) + logger.info("Wrote %s", csv_path) + + +def main(cfg): + """Run diagnostic.""" + cfg = deepcopy(cfg) + cfg.setdefault('plot_each_model', False) + cfg.setdefault('plot_bias', False) + + input_data = list(cfg['input_data'].values()) + + groups = group_metadata(input_data, 'variable_group', sort='dataset') + attributes = next(iter(extract_variables(cfg).values())) + all_groups = list(group_metadata(input_data, 'variable_group')) + + # Read data + cubes, cubes_out = read_data(groups, cfg) + + # Plotting climatologies + plot_diagnostic(cubes_out, attributes, cfg) + + if cfg['reference']: + # Compute bias plots + cube_obs = cubes_out.extract_cube( + iris.Constraint(cube_func=lambda cube: cube.attributes[ + 'variable_group'] == 'OBS')) + + # Bootstrapping + bootstrapping(cubes, cube_obs, all_groups, attributes, cfg) + + # Compute statistics + df = get_dataframe(cubes, cube_obs) + + # write statistics + write_statistics(df, attributes, cfg) + + # compute bias + cubes_diff = iris.cube.CubeList() + attributes['short_name'] = attributes['short_name'] + "_diff" + + if cfg['plot_bias']: + for cube in cubes_out: + if (cube.attributes['variable_group'] != 'OBS' + or cube.attributes['dataset'] != 'MultiModelMean'): + logger.info("Processing %s of group %s", + cube.attributes['dataset'], + cube.attributes['variable_group']) + bias = calculate_bias(cube, cube_obs) + rmsd = calculate_rmsd(cube, cube_obs) + corr = calculate_corr(cube, cube_obs) + cube_diff = cube - cube_obs + cube_diff.attributes = cube.attributes + cube_diff.var_name = cube.var_name + cube_diff.attributes['short_name'] = attributes[ + 'short_name'] + cubes_diff.append(cube_diff) + logger.info('%s : bias = %f, rmsd = %f, corr = %f', + cube.attributes['variable_group'], bias.data, + rmsd.data, corr.data) + + # Plotting biases + plot_diagnostic(cubes_diff, attributes, cfg) + + +if __name__ == '__main__': + + with run_diagnostic() as config: + main(config) diff --git a/esmvaltool/diag_scripts/clouds/clouds_ecs_groups_zonal.py b/esmvaltool/diag_scripts/clouds/clouds_ecs_groups_zonal.py new file mode 100644 index 0000000000..beaac2b0b1 --- /dev/null +++ b/esmvaltool/diag_scripts/clouds/clouds_ecs_groups_zonal.py @@ -0,0 +1,469 @@ +"""Python diagnostic for plotting zonal averages.""" +import logging +from copy import deepcopy +from pathlib import Path + +import iris +import iris.quickplot as qplt +import matplotlib.pyplot as plt +import numpy as np + +from esmvaltool.diag_scripts.shared import ( + group_metadata, + run_diagnostic, + save_data, + save_figure, + select_metadata, +) + +logger = logging.getLogger(Path(__file__).stem) + +VAR_NAMES = { + 'clt': 'total_cloud_fraction', + 'clivi': 'ice_water_path', + 'lwp': 'liquid_water_path', + 'swcre': 'shortwave_cloud_radiative_effect', + 'lwcre': 'longwave_cloud_radiative_effect', + 'netcre': 'net_cloud_radiative_effect', +} +LINE_LEGEND = { + 'ECS_high_hist': 'ECS_high', + 'ECS_med_hist': 'ECS_med', + 'ECS_low_hist': 'ECS_low', +} +LINE_COLOR = { + 'ECS_high_hist': 'royalblue', + 'ECS_high_scen': 'royalblue', + 'ECS_med_hist': 'green', + 'ECS_med_scen': 'green', + 'ECS_low_hist': 'orange', + 'ECS_low_scen': 'orange', + 'CMIP6': 'firebrick', + 'CMIP5': 'royalblue', + 'CMIP3': 'darkcyan', + 'OBS': 'black' +} +LINE_DASH = { + 'ECS_high_hist': 'solid', + 'ECS_high_scen': 'dashed', + 'ECS_med_hist': 'solid', + 'ECS_med_scen': 'dashed', + 'ECS_low_hist': 'solid', + 'ECS_low_scen': 'dashed', + 'CMIP6': 'solid', + 'CMIP5': 'solid', + 'CMIP3': 'solid', + 'OBS': 'solid' +} + + +def get_provenance_record(short_name, ancestor_files): + """Create a provenance record describing the diagnostic data and plot.""" + caption = (f"Zonally averaged group means of {short_name} in the upper" + "panel and the corresponding relative differences in lower" + "panel.") + + record = { + 'caption': caption, + 'statistics': ['mean'], + 'domains': ['global'], + 'plot_types': ['zonal'], + 'authors': [ + 'bock_lisa', + ], + 'references': [ + 'bock24acp', + ], + 'ancestors': ancestor_files, + } + return record + + +def _get_multi_model_mean(cubes, var): + """Compute multi-model mean.""" + + logger.debug("Calculating multi-model mean") + datasets = [] + mmm = [] + for (dataset_name, cube) in cubes.items(): + datasets.append(dataset_name) + mmm.append(cube.data) + mmm = np.ma.array(mmm) + dataset_0 = list(cubes.keys())[0] + mmm_cube = cubes[dataset_0].copy(data=np.ma.mean(mmm, axis=0)) + attributes = { + 'dataset': 'MultiModelMean', + 'short_name': var, + 'datasets': '|'.join(datasets), + } + mmm_cube.attributes = attributes + return mmm_cube + + +def _get_multi_model_quantile(cubes, var, quantile): + """Compute multi-model quantile.""" + + logger.debug("Calculating multi-model %s quantile", quantile) + datasets = [] + mmq = [] + for (dataset_name, cube) in cubes.items(): + datasets.append(dataset_name) + mmq.append(cube.data) + mmq = np.ma.array(mmq) + dataset_0 = list(cubes.keys())[0] + mmq_cube = cubes[dataset_0].copy(data=np.quantile(mmq, quantile, axis=0)) + attributes = { + 'dataset': 'MultiModel' + str(quantile), + 'short_name': var, + 'datasets': '|'.join(datasets), + } + mmq_cube.attributes = attributes + return mmq_cube + + +def compute_diagnostic(filename): + """Compute an example diagnostic.""" + logger.debug("Loading %s", filename) + cube = iris.load_cube(filename) + + if cube.var_name == 'cli': + cube.convert_units('g/kg') + elif cube.var_name == 'clw': + cube.convert_units('g/kg') + + logger.debug("Reading %s", filename) + cube = iris.util.squeeze(cube) + return cube + + +def compute_diff(filename1, filename2): + """Compute difference between two cubes.""" + logger.debug("Loading %s", filename1) + cube1 = iris.load_cube(filename1) + cube2 = iris.load_cube(filename2) + + if cube1.var_name == 'cli': + cube1.convert_units('g/kg') + cube2.convert_units('g/kg') + elif cube1.var_name == 'clw': + cube1.convert_units('g/kg') + cube2.convert_units('g/kg') + + cube = cube2 - cube1 + cube.metadata = cube1.metadata + cube = iris.util.squeeze(cube) + return cube + + +def compute_diff_temp(input_data, group, dataset, plot_type): + """Compute relative change per temperture change.""" + + dataset_name = dataset['dataset'] + var = dataset['short_name'] + + input_file_1 = dataset['filename'] + + var_data_2 = select_metadata(input_data, + short_name=var, + dataset=dataset_name, + variable_group=group[1]) + if not var_data_2: + raise ValueError( + f"No '{var}' data for '{dataset_name}' in '{group[1]}' available") + + input_file_2 = var_data_2[0]['filename'] + + if plot_type == 'zonal': + ta_data_1 = select_metadata(input_data, + short_name='tas', + dataset=dataset_name, + variable_group='tas_'+group[0]) + ta_data_2 = select_metadata(input_data, + short_name='tas', + dataset=dataset_name, + variable_group='tas_'+group[1]) + elif plot_type == 'height': + ta_data_1 = select_metadata(input_data, + short_name='ta', + dataset=dataset_name, + variable_group='ta_'+group[0]) + ta_data_2 = select_metadata(input_data, + short_name='ta', + dataset=dataset_name, + variable_group='ta_'+group[1]) + else: + raise ValueError( + f"The plot_type '{var}' is not implemented.") + + if not ta_data_1: + raise ValueError( + f"No temperature data for '{dataset_name}' " + f"in '{group[0]}' available") + if not ta_data_2: + raise ValueError( + f"No temperature data for '{dataset_name}' " + f"in '{group[1]}' available") + input_file_ta_1 = ta_data_1[0]['filename'] + input_file_ta_2 = ta_data_2[0]['filename'] + + cube = compute_diagnostic(input_file_1) + if var in ['lwp', 'clivi', 'clw', 'cli']: + cube.data[cube.data < 0.001] = np.nan + elif var in ['cl']: + cube.data[cube.data < 0.1] = np.nan + elif var in ['netcre', 'swcre', 'lwcre']: + cube.data[abs(cube.data) < 1.] = np.nan + + cube_diff = compute_diff(input_file_1, input_file_2) + cube_ta_diff = compute_diff(input_file_ta_1, input_file_ta_2) + + cube_ta_diff.data[cube_ta_diff.data < 1.] = np.nan + + cube_diff = (100. * (cube_diff / iris.analysis.maths.abs(cube)) + / cube_ta_diff) + + cube_diff.metadata = cube.metadata + + if plot_type == 'zonal': + logger.debug("Computing zonal mean") + cube_diff = cube_diff.collapsed('longitude', iris.analysis.MEAN) + elif plot_type == 'height': + logger.debug("Computing field mean") + grid_areas = iris.analysis.cartography.area_weights(cube_diff) + cube_diff = cube_diff.collapsed(['longitude', 'latitude'], + iris.analysis.MEAN, + weights=grid_areas) + else: + raise ValueError(f"Plot type {plot_type} is not implemented.") + + cube_diff.units = '%/K' + + return cube_diff + + +def plot_diagnostic(cube, legend, plot_type): + """Create diagnostic data and plot it.""" + + cube_label = legend + line_color = LINE_COLOR.get(legend, legend) + line_dash = LINE_DASH.get(legend, legend) + + plt.subplot(211) + + if plot_type == 'height': + cube.coord('air_pressure').convert_units('hPa') + y_axis = cube.coord('air_pressure') + qplt.plot(cube, y_axis, label=cube_label, color=line_color, + linestyle=line_dash) + else: + lat = cube.coord('latitude') + qplt.plot(lat, cube, label=cube_label, color=line_color, + linestyle=line_dash) + + logger.info("Plotting %s", legend) + + +def plot_diagnostic_diff(cube, legend, plot_type): + """Create diagnostic data and plot it.""" + + cube_label = LINE_LEGEND.get(legend, legend) + line_color = LINE_COLOR.get(legend, legend) + line_dash = LINE_DASH.get(legend, legend) + + plt.subplot(212) + + if cube.var_name == 'pr': + cube.units = cube.units / 'kg m-3' + cube.data = cube.core_data() / 1000. + cube.convert_units('mm day-1') + elif cube.var_name == 'cli': + cube.convert_units('g/kg') + elif cube.var_name == 'clw': + cube.convert_units('g/kg') + + if plot_type == 'height': + cube.coord('air_pressure').convert_units('hPa') + y_axis = cube.coord('air_pressure') + qplt.plot(cube, y_axis, label=cube_label, color=line_color, + linestyle=line_dash) + else: + lat = cube.coord('latitude') + qplt.plot(lat, cube, label=cube_label, color=line_color, + linestyle=line_dash) + + logger.info("Plotting %s", legend) + + +def plot_errorband(cube1, cube2, legend, plot_type): + """Create diagnostic data and plot it.""" + + line_color = LINE_COLOR.get(legend, legend) + line_dash = LINE_DASH.get(legend, legend) + + plt.subplot(211) + + if cube1.var_name == 'pr': + cube1.units = cube1.units / 'kg m-3' + cube1.data = cube1.core_data() / 1000. + cube1.convert_units('mm day-1') + cube2.units = cube2.units / 'kg m-3' + cube2.data = cube2.core_data() / 1000. + cube2.convert_units('mm day-1') + elif cube1.var_name == 'cli': + cube1.convert_units('g/kg') + cube2.convert_units('g/kg') + elif cube1.var_name == 'clw': + cube1.convert_units('g/kg') + cube2.convert_units('g/kg') + + if plot_type == 'height': + cube1.coord('air_pressure').convert_units('hPa') + cube2.coord('air_pressure').convert_units('hPa') + y_axis = cube1.coord('air_pressure').points + plt.fill_betweenx(y_axis, cube1.data, cube2.data, color=line_color, + linestyle=line_dash, alpha=.1) + else: + lat = cube1.coord('latitude').points + plt.fill_between(lat, cube1.data, cube2.data, color=line_color, + linestyle=line_dash, alpha=.1) + logger.info("Plotting %s", legend) + + +def main(cfg): + """Run diagnostic.""" + cfg = deepcopy(cfg) + cfg.setdefault('filename_attach', 'base') + + plot_type = cfg['plot_type'] + + input_data = list(cfg['input_data'].values()) + + groups = group_metadata(input_data, 'variable_group', sort='dataset') + + plt.figure(figsize=(8, 12)) + + for group_name in groups: + if ('tas_' not in group_name) and ('ta_' not in group_name): + logger.info("Processing variable %s", group_name) + + dataset_names = [] + cubes = {} + + for dataset in groups[group_name]: + + dataset_name = dataset['dataset'] + var = dataset['short_name'] + + if dataset_name not in ['MultiModelMean', 'MultiModelP5', + 'MultiModelP95']: + + logger.info("Loop dataset %s", dataset_name) + + input_file = dataset['filename'] + cube = compute_diagnostic(input_file) + logger.debug("Computing zonal mean") + if plot_type == 'zonal': + cube = cube.collapsed('longitude', iris.analysis.MEAN) + elif plot_type == 'height': + grid_areas = ( + iris.analysis.cartography.area_weights(cube)) + cube = cube.collapsed(['longitude', 'latitude'], + iris.analysis.MEAN, + weights=grid_areas) + else: + raise ValueError( + f"Plot type {plot_type} is not implemented.") + + cubes[dataset_name] = cube + + cube_mmm = _get_multi_model_mean(cubes, var) + + plot_diagnostic(cube_mmm, group_name, plot_type) + + cube_p5 = _get_multi_model_quantile(cubes, var, 0.05) + cube_p95 = _get_multi_model_quantile(cubes, var, 0.95) + + plot_errorband(cube_p5, cube_p95, group_name, plot_type) + + if plot_type == 'height': + plt.ylim(1000., 100.) + plt.yscale('log') + plt.yticks([1000., 800., 600., 400., 300., 200., 100.], + [1000, 800, 600, 400, 300, 200, 100]) + title = 'Vertical mean of ' + dataset['long_name'] + elif plot_type == 'zonal': + if dataset['long_name'] == 'Total Cloud Cover Percentage': + title = 'Zonal mean of Total Cloud Fraction' + else: + title = 'Zonal mean of ' + dataset['long_name'] + else: + title = dataset['long_name'] + + plt.title(title) + plt.legend(ncol=1) + plt.grid(True) + + for group_name in cfg['group_by']: + + logger.info("Processing group %s", group_name[0]) + + dataset_names = [] + cubes_diff = {} + + for dataset in groups[group_name[0]]: + dataset_name = dataset['dataset'] + var = dataset['short_name'] + + if dataset_name not in ['MultiModelMean', 'MultiModelP5', + 'MultiModelP95']: + logger.info("Loop dataset %s", dataset_name) + dataset_names.append(dataset_name) + + cube_diff = compute_diff_temp(input_data, group_name, dataset, + plot_type) + + cubes_diff[dataset_name] = cube_diff + + cube_mmm = _get_multi_model_mean(cubes_diff, var) + + plot_diagnostic_diff(cube_mmm, group_name[0], plot_type) + + if plot_type == 'height': + plt.xlim(0., 1.) + plt.ylim(1000., 100.) + plt.yscale('log') + plt.yticks([1000., 800., 600., 400., 300., 200., 100.], + [1000, 800, 600, 400, 300, 200, 100]) + plt.axvline(x=0, ymin=0., ymax=1., color='black', linewidth=3) + title = 'Difference of vertical mean of ' + dataset['long_name'] + elif plot_type == 'zonal': + plt.axhline(y=0, xmin=-90., xmax=90., color='black', linewidth=3) + title = 'Difference of zonal mean of ' + dataset['long_name'] + else: + title = dataset['long_name'] + + plt.title(title) + plt.legend(ncol=1) + plt.grid(True) + + provenance_record = get_provenance_record( + dataset['short_name'], ancestor_files=cfg['input_files']) + + if plot_type == 'height': + basename = ('level_diff_' + dataset['short_name'] + '_' + + cfg['filename_attach']) + else: + basename = ('zonal_diff_' + dataset['short_name'] + '_' + + cfg['filename_attach']) + + # Save the data used for the plot + save_data(basename, provenance_record, cfg, cube_mmm) + + # And save the plot + save_figure(basename, provenance_record, cfg) + + +if __name__ == '__main__': + + with run_diagnostic() as config: + main(config) diff --git a/esmvaltool/recipes/clouds/recipe_bock24acp_fig3-4_maps.yml b/esmvaltool/recipes/clouds/recipe_bock24acp_fig3-4_maps.yml new file mode 100644 index 0000000000..88076fafed --- /dev/null +++ b/esmvaltool/recipes/clouds/recipe_bock24acp_fig3-4_maps.yml @@ -0,0 +1,218 @@ +# ESMValTool +# recipe_bock24acp_fig3-4_maps.yml +# Note: The variables LWP and IWP are commented out at the moment as a different +# standard name for this variables in CMIP5 and CMIP6 gives an error. Iris +# is working on a solution for this problem. +--- +documentation: + title: Cloud properties regarding ECS (geographical maps). + + description: | + Geographical maps of cloud properties, models are grouped in + three groups regarding their ECS. + + authors: + - bock_lisa + + maintainer: + - bock_lisa + + references: + - bock24acp + + projects: + - cmug + - esm2025 + + +YEARS: &years_hist + start_year: 1985 + end_year: 2004 + +YEARS_scen: &years_scen + start_year: 2081 + end_year: 2100 + + +DATASETS_ECS_HIGH: &datasets_ecs_high + # CMIP6 + - {dataset: CanESM5, grid: gn} + - {dataset: CESM2, grid: gn, ensemble: r4i1p1f1} + - {dataset: CESM2-WACCM, grid: gn, institute: NCAR} + - {dataset: CNRM-CM6-1, ensemble: r1i1p1f2} + - {dataset: CNRM-ESM2-1, ensemble: r1i1p1f2} + - {dataset: HadGEM3-GC31-LL, grid: gn, ensemble: r1i1p1f3} + - {dataset: HadGEM3-GC31-MM, grid: gn, ensemble: r1i1p1f3} + - {dataset: IPSL-CM6A-LR} + - {dataset: KACE-1-0-G} + - {dataset: NESM3, grid: gn} + - {dataset: TaiESM1, grid: gn} + - {dataset: UKESM1-0-LL, ensemble: r1i1p1f2, grid: gn} + # CMIP5 + - {dataset: CSIRO-Mk3-6-0, ensemble: r1i1p1, project: CMIP5} + - {dataset: HadGEM2-ES, ensemble: r1i1p1, project: CMIP5} + - {dataset: IPSL-CM5A-LR, ensemble: r1i1p1, project: CMIP5} + - {dataset: IPSL-CM5A-MR, ensemble: r1i1p1, project: CMIP5} + - {dataset: MIROC-ESM, ensemble: r1i1p1, project: CMIP5} + +DATASETS_ECS_MED: &datasets_ecs_med + # CMIP6 + - {dataset: BCC-CSM2-MR, grid: gn} + - {dataset: CMCC-CM2-SR5, grid: gn} + - {dataset: CMCC-ESM2, grid: gn} + - {dataset: FGOALS-f3-L} + - {dataset: FGOALS-g3, grid: gn} + - {dataset: GISS-E2-1-H, grid: gn} + - {dataset: MPI-ESM1-2-HR, grid: gn} + - {dataset: MPI-ESM1-2-LR, grid: gn} + - {dataset: MRI-ESM2-0, grid: gn} + # CMIP5 + - {dataset: ACCESS1-0, ensemble: r1i1p1, project: CMIP5} + - {dataset: ACCESS1-3, ensemble: r1i1p1, project: CMIP5} + - {dataset: BNU-ESM, ensemble: r1i1p1, project: CMIP5} + - {dataset: CanESM2, ensemble: r1i1p1, project: CMIP5} + - {dataset: CCSM4, ensemble: r1i1p1, project: CMIP5} + - {dataset: FGOALS-g2, ensemble: r1i1p1, project: CMIP5} + - {dataset: GFDL-CM3, ensemble: r1i1p1, project: CMIP5} + - {dataset: MPI-ESM-LR, ensemble: r1i1p1, project: CMIP5} + - {dataset: MPI-ESM-MR, ensemble: r1i1p1, project: CMIP5} + +DATASETS_ECS_LOW: &datasets_ecs_low + # CMIP6 + - {dataset: CAMS-CSM1-0, grid: gn} + - {dataset: GISS-E2-1-G, grid: gn} + - {dataset: MIROC6, grid: gn} + - {dataset: MIROC-ES2L, ensemble: r1i1p1f2, grid: gn} + - {dataset: NorESM2-LM, grid: gn, institute: NCC} + - {dataset: NorESM2-MM, grid: gn, institute: NCC} + # CMIP5 + - {dataset: bcc-csm1-1, ensemble: r1i1p1, project: CMIP5} + - {dataset: bcc-csm1-1-m, ensemble: r1i1p1, project: CMIP5} + - {dataset: GFDL-ESM2G, ensemble: r1i1p1, project: CMIP5} + - {dataset: GFDL-ESM2M, ensemble: r1i1p1, project: CMIP5} + - {dataset: GISS-E2-H, ensemble: r1i1p1, project: CMIP5} + - {dataset: GISS-E2-R, ensemble: r1i1p1, project: CMIP5} + - {dataset: inmcm4, ensemble: r1i1p1, project: CMIP5} + - {dataset: IPSL-CM5B-LR, ensemble: r1i1p1, project: CMIP5} + - {dataset: MIROC5, ensemble: r1i1p1, project: CMIP5} + - {dataset: MRI-CGCM3, ensemble: r1i1p1, project: CMIP5} + - {dataset: NorESM1-M, ensemble: r1i1p1, project: CMIP5} + + +preprocessors: + + lat_lon_mmm: + custom_order: true + regrid: + target_grid: 2x2 + scheme: linear + multi_model_statistics: + span: full + statistics: [mean] + climate_statistics: + operator: mean + + lat_lon: + regrid: + target_grid: 2x2 + scheme: linear + climate_statistics: + operator: mean + + +diagnostics: + + # Figure 3abc + clt_lat_lon: &lat_lon_diag + description: comparison of geographical maps + variables: + ECS_high: &var_clt + short_name: clt + preprocessor: lat_lon_mmm + mip: Amon + project: CMIP6 + exp: historical + ensemble: r1i1p1f1 + grid: gr + <<: *years_hist + additional_datasets: *datasets_ecs_high + ECS_med: + <<: *var_clt + additional_datasets: *datasets_ecs_med + ECS_low: + <<: *var_clt + additional_datasets: *datasets_ecs_low + scripts: + lat_lon: + script: clouds/clouds_ecs_groups_maps.py + group_by: variable_group + plot_each_model: false + reference: false + + + # Figure 3def + # lwp_lat_lon: + # <<: *lat_lon_diag + # variables: + # ECS_high: + # <<: *var_clt + # short_name: lwp + # derive: true + # additional_datasets: *datasets_ecs_high + # ECS_med: + # <<: *var_clt + # short_name: lwp + # derive: true + # additional_datasets: *datasets_ecs_med + # ECS_low: + # <<: *var_clt + # short_name: lwp + # derive: true + # additional_datasets: *datasets_ecs_low + + + # Figure 3ghi + # iwp_lat_lon: + # <<: *lat_lon_diag + # variables: + # ECS_high: + # <<: *var_clt + # short_name: clivi + # additional_datasets: *datasets_ecs_high + # ECS_med: + # <<: *var_clt + # short_name: clivi + # additional_datasets: *datasets_ecs_med + # ECS_low: + # <<: *var_clt + # short_name: clivi + # additional_datasets: *datasets_ecs_low + + + # Figure 4 + netcre_lat_lon: &lat_lon_cre + description: comparison of geographical maps + variables: + ECS_high: &var_cre + <<: *var_clt + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_high + ECS_med: + <<: *var_cre + additional_datasets: *datasets_ecs_med + ECS_low: + <<: *var_cre + additional_datasets: *datasets_ecs_low + OBS: + <<: *var_cre + preprocessor: lat_lon + additional_datasets: + - {dataset: CERES-EBAF, project: OBS, type: sat, version: Ed4.2, + tier: 2, start_year: 2001, end_year: 2022} + scripts: + lat_lon: + script: clouds/clouds_ecs_groups_maps.py + group_by: variable_group + plot_each_model: false + reference: true diff --git a/esmvaltool/recipes/clouds/recipe_bock24acp_fig6_zonal.yml b/esmvaltool/recipes/clouds/recipe_bock24acp_fig6_zonal.yml new file mode 100644 index 0000000000..05a765baa0 --- /dev/null +++ b/esmvaltool/recipes/clouds/recipe_bock24acp_fig6_zonal.yml @@ -0,0 +1,579 @@ +# ESMValTool +# recipe_bock24acp_fig6_zonal.yml +--- +documentation: + title: Cloud properties regarding ECS (zonal plots). + + description: | + Zonal plots of cloud properties and their projected changes, + models are grouped in three groups regarding their ECS. + + authors: + - bock_lisa + + maintainer: + - lauer_axel + + references: + - bock24acp + + project: + - cmug + - esm2025 + + +YEARS_hist: &years_hist + start_year: 1985 + end_year: 2004 + +YEARS_scen: &years_scen + start_year: 2081 + end_year: 2100 + + +DATASETS_ECS_HIGH: &datasets_ecs_high + # CMIP6 + - {dataset: CanESM5, grid: gn} + - {dataset: CESM2, grid: gn, ensemble: r4i1p1f1} + - {dataset: CESM2-WACCM, grid: gn, institute: NCAR} + - {dataset: CNRM-CM6-1, ensemble: r1i1p1f2} + - {dataset: CNRM-ESM2-1, ensemble: r1i1p1f2} + - {dataset: HadGEM3-GC31-LL, grid: gn, ensemble: r1i1p1f3} + - {dataset: HadGEM3-GC31-MM, grid: gn, ensemble: r1i1p1f3} + - {dataset: IPSL-CM6A-LR} + - {dataset: KACE-1-0-G} + - {dataset: NESM3, grid: gn} + - {dataset: TaiESM1, grid: gn} + - {dataset: UKESM1-0-LL, ensemble: r1i1p1f2, grid: gn} + # CMIP5 + - {dataset: CSIRO-Mk3-6-0, ensemble: r1i1p1, project: CMIP5} + - {dataset: HadGEM2-ES, ensemble: r1i1p1, project: CMIP5} + - {dataset: IPSL-CM5A-LR, ensemble: r1i1p1, project: CMIP5} + - {dataset: IPSL-CM5A-MR, ensemble: r1i1p1, project: CMIP5} + - {dataset: MIROC-ESM, ensemble: r1i1p1, project: CMIP5} + +DATASETS_ECS_HIGH_scenario: &datasets_ecs_high_scenario + # CMIP6 + - {dataset: CanESM5, grid: gn, exp: ssp585} + - {dataset: CESM2, grid: gn, ensemble: r4i1p1f1, exp: ssp585} + - {dataset: CESM2-WACCM, grid: gn, institute: NCAR, exp: ssp585} + - {dataset: CNRM-CM6-1, ensemble: r1i1p1f2, exp: ssp585} + - {dataset: CNRM-ESM2-1, ensemble: r1i1p1f2, exp: ssp585} + - {dataset: HadGEM3-GC31-LL, grid: gn, ensemble: r1i1p1f3, exp: ssp585} + - {dataset: HadGEM3-GC31-MM, grid: gn, ensemble: r1i1p1f3, exp: ssp585} + - {dataset: IPSL-CM6A-LR, exp: ssp585} + - {dataset: KACE-1-0-G, exp: ssp585} + - {dataset: NESM3, grid: gn, exp: ssp585} + - {dataset: TaiESM1, grid: gn, exp: ssp585} + - {dataset: UKESM1-0-LL, ensemble: r1i1p1f2, grid: gn, exp: ssp585} + # CMIP5 + - {dataset: CSIRO-Mk3-6-0, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: HadGEM2-ES, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: IPSL-CM5A-LR, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: IPSL-CM5A-MR, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: MIROC-ESM, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + +DATASETS_ECS_MED: &datasets_ecs_med + # CMIP6 + - {dataset: BCC-CSM2-MR, grid: gn} + - {dataset: CMCC-CM2-SR5, grid: gn} + - {dataset: CMCC-ESM2, grid: gn} + - {dataset: FGOALS-f3-L} + - {dataset: FGOALS-g3, grid: gn} + - {dataset: GISS-E2-1-H, grid: gn} + - {dataset: MPI-ESM1-2-HR, grid: gn} + - {dataset: MPI-ESM1-2-LR, grid: gn} + - {dataset: MRI-ESM2-0, grid: gn} + # CMIP5 + - {dataset: ACCESS1-0, ensemble: r1i1p1, project: CMIP5} + - {dataset: ACCESS1-3, ensemble: r1i1p1, project: CMIP5} + - {dataset: BNU-ESM, ensemble: r1i1p1, project: CMIP5} + - {dataset: CanESM2, ensemble: r1i1p1, project: CMIP5} + - {dataset: CCSM4, ensemble: r1i1p1, project: CMIP5} + - {dataset: FGOALS-g2, ensemble: r1i1p1, project: CMIP5} + - {dataset: GFDL-CM3, ensemble: r1i1p1, project: CMIP5} + - {dataset: MPI-ESM-LR, ensemble: r1i1p1, project: CMIP5} + - {dataset: MPI-ESM-MR, ensemble: r1i1p1, project: CMIP5} + +DATASETS_ECS_MED_scenario: &datasets_ecs_med_scenario + # CMIP6 + - {dataset: BCC-CSM2-MR, grid: gn, exp: ssp585} + - {dataset: CMCC-CM2-SR5, grid: gn, exp: ssp585} + - {dataset: CMCC-ESM2, grid: gn, exp: ssp585} + - {dataset: FGOALS-f3-L, exp: ssp585} + - {dataset: FGOALS-g3, grid: gn, exp: ssp585} + - {dataset: GISS-E2-1-H, grid: gn, ensemble: r1i1p1f2, exp: ssp585} + - {dataset: MPI-ESM1-2-HR, grid: gn, exp: ssp585} + - {dataset: MPI-ESM1-2-LR, grid: gn, exp: ssp585} + - {dataset: MRI-ESM2-0, grid: gn, exp: ssp585} + # CMIP5 + - {dataset: ACCESS1-0, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: ACCESS1-3, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: BNU-ESM, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: CanESM2, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: CCSM4, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: FGOALS-g2, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: GFDL-CM3, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: MPI-ESM-LR, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: MPI-ESM-MR, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + +DATASETS_ECS_LOW: &datasets_ecs_low + # CMIP6 + - {dataset: CAMS-CSM1-0, grid: gn} + - {dataset: GISS-E2-1-G, grid: gn} + - {dataset: MIROC6, grid: gn} + - {dataset: MIROC-ES2L, ensemble: r1i1p1f2, grid: gn} + - {dataset: NorESM2-LM, grid: gn, institute: NCC} + - {dataset: NorESM2-MM, grid: gn, institute: NCC} + # CMIP5 + - {dataset: bcc-csm1-1, ensemble: r1i1p1, project: CMIP5} + - {dataset: bcc-csm1-1-m, ensemble: r1i1p1, project: CMIP5} + - {dataset: GFDL-ESM2G, ensemble: r1i1p1, project: CMIP5} + - {dataset: GFDL-ESM2M, ensemble: r1i1p1, project: CMIP5} + - {dataset: GISS-E2-H, ensemble: r1i1p1, project: CMIP5} + - {dataset: GISS-E2-R, ensemble: r1i1p1, project: CMIP5} + - {dataset: inmcm4, ensemble: r1i1p1, project: CMIP5} + - {dataset: IPSL-CM5B-LR, ensemble: r1i1p1, project: CMIP5} + - {dataset: MIROC5, ensemble: r1i1p1, project: CMIP5} + - {dataset: MRI-CGCM3, ensemble: r1i1p1, project: CMIP5} + - {dataset: NorESM1-M, ensemble: r1i1p1, project: CMIP5} + +DATASETS_ECS_LOW_scenario: &datasets_ecs_low_scenario + # CMIP6 + - {dataset: CAMS-CSM1-0, grid: gn, exp: ssp585, end_year: 2099} + - {dataset: GISS-E2-1-G, grid: gn, ensemble: r1i1p1f2, exp: ssp585} + - {dataset: MIROC6, grid: gn, exp: ssp585} + - {dataset: MIROC-ES2L, ensemble: r1i1p1f2, grid: gn, exp: ssp585} + - {dataset: NorESM2-LM, grid: gn, institute: NCC, exp: ssp585} + - {dataset: NorESM2-MM, grid: gn, institute: NCC, exp: ssp585} + # CMIP5 + - {dataset: bcc-csm1-1, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: bcc-csm1-1-m, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: GFDL-ESM2G, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: GFDL-ESM2M, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: GISS-E2-H, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: GISS-E2-R, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: inmcm4, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: IPSL-CM5B-LR, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: MIROC5, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: MRI-CGCM3, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: NorESM1-M, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + + +preprocessors: + + zonal_mmm: + custom_order: true + regrid: + target_grid: 2x2 + scheme: linear + zonal_statistics: + operator: mean + multi_model_statistics: + span: full + statistics: [mean, p5, p95] + climate_statistics: + operator: mean + + zonal: + regrid: + target_grid: 2x2 + scheme: linear + climate_statistics: + operator: mean + + +diagnostics: + + # Figure 6a + clt_zonal: &zonal_diag + description: comparison of zonal mean + variables: + ECS_high_hist: &var_clt + short_name: clt + preprocessor: zonal + mip: Amon + project: CMIP6 + exp: historical + ensemble: r1i1p1f1 + grid: gr + <<: *years_hist + additional_datasets: *datasets_ecs_high + ECS_med_hist: + <<: *var_clt + additional_datasets: *datasets_ecs_med + ECS_low_hist: + <<: *var_clt + additional_datasets: *datasets_ecs_low + ECS_high_scen: + <<: *var_clt + <<: *years_scen + additional_datasets: *datasets_ecs_high_scenario + ECS_med_scen: + <<: *var_clt + <<: *years_scen + additional_datasets: *datasets_ecs_med_scenario + ECS_low_scen: + <<: *var_clt + <<: *years_scen + additional_datasets: *datasets_ecs_low_scenario + tas_ECS_high_hist: &var_tas + <<: *var_clt + short_name: tas + tas_ECS_med_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_med + tas_ECS_low_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_low + tas_ECS_high_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + tas_ECS_med_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_med_scenario + tas_ECS_low_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_low_scenario + scripts: + zonal_diff: + script: clouds/clouds_ecs_groups_zonal.py + group_by: [['ECS_low_hist', 'ECS_low_scen'], + ['ECS_med_hist', 'ECS_med_scen'], + ['ECS_high_hist', 'ECS_high_scen']] + plot_type: zonal + filename_attach: 'ssp585' + + + # Figure 6b + lwp_zonal: + <<: *zonal_diag + variables: + ECS_high_hist: + <<: *var_clt + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_high + ECS_med_hist: + <<: *var_clt + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med + ECS_low_hist: + <<: *var_clt + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low + ECS_high_scen: + <<: *var_clt + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_high_scenario + ECS_med_scen: + <<: *var_clt + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med_scenario + ECS_low_scen: + <<: *var_clt + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low_scenario + tas_ECS_high_hist: + <<: *var_tas + tas_ECS_med_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_med + tas_ECS_low_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_low + tas_ECS_high_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + tas_ECS_med_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_med_scenario + tas_ECS_low_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_low_scenario + + + # Figure 6c + iwp_zonal: + <<: *zonal_diag + variables: + ECS_high_hist: + <<: *var_clt + short_name: clivi + additional_datasets: *datasets_ecs_high + ECS_med_hist: + <<: *var_clt + short_name: clivi + additional_datasets: *datasets_ecs_med + ECS_low_hist: + <<: *var_clt + short_name: clivi + additional_datasets: *datasets_ecs_low + ECS_high_scen: + <<: *var_clt + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_high_scenario + ECS_med_scen: + <<: *var_clt + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_med_scenario + ECS_low_scen: + <<: *var_clt + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_low_scenario + tas_ECS_high_hist: + <<: *var_tas + tas_ECS_med_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_med + tas_ECS_low_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_low + tas_ECS_high_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + tas_ECS_med_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_med_scenario + tas_ECS_low_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_low_scenario + + + # Figure 6d + netcre_zonal: + <<: *zonal_diag + variables: + ECS_high_hist: + <<: *var_clt + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_high + ECS_med_hist: + <<: *var_clt + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med + ECS_low_hist: + <<: *var_clt + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low + ECS_high_scen: + <<: *var_clt + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_high_scenario + ECS_med_scen: + <<: *var_clt + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med_scenario + ECS_low_scen: + <<: *var_clt + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low_scenario + tas_ECS_high_hist: + <<: *var_tas + tas_ECS_med_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_med + tas_ECS_low_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_low + tas_ECS_high_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + tas_ECS_med_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_med_scenario + tas_ECS_low_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_low_scenario + OBS: + <<: *var_clt + short_name: netcre + derive: true + preprocessor: zonal + additional_datasets: + - {dataset: CERES-EBAF, project: OBS, type: sat, version: Ed4.2, + tier: 2, start_year: 2001, end_year: 2022} + + + # Figure 6e + swcre_zonal: + <<: *zonal_diag + variables: + ECS_high_hist: + <<: *var_clt + short_name: swcre + derive: true + additional_datasets: *datasets_ecs_high + ECS_med_hist: + <<: *var_clt + short_name: swcre + derive: true + additional_datasets: *datasets_ecs_med + ECS_low_hist: + <<: *var_clt + short_name: swcre + derive: true + additional_datasets: *datasets_ecs_low + ECS_high_scen: + <<: *var_clt + <<: *years_scen + short_name: swcre + derive: true + additional_datasets: *datasets_ecs_high_scenario + ECS_med_scen: + <<: *var_clt + <<: *years_scen + short_name: swcre + derive: true + additional_datasets: *datasets_ecs_med_scenario + ECS_low_scen: + <<: *var_clt + <<: *years_scen + short_name: swcre + derive: true + additional_datasets: *datasets_ecs_low_scenario + tas_ECS_high_hist: + <<: *var_tas + tas_ECS_med_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_med + tas_ECS_low_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_low + tas_ECS_high_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + tas_ECS_med_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_med_scenario + tas_ECS_low_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_low_scenario + OBS: + <<: *var_clt + short_name: swcre + derive: true + preprocessor: zonal + additional_datasets: + - {dataset: CERES-EBAF, project: OBS, type: sat, version: Ed4.2, + tier: 2, start_year: 2001, end_year: 2022} + + + # Figure 6f + lwcre_zonal: + <<: *zonal_diag + variables: + ECS_high_hist: + <<: *var_clt + short_name: lwcre + derive: true + additional_datasets: *datasets_ecs_high + ECS_med_hist: + <<: *var_clt + short_name: lwcre + derive: true + additional_datasets: *datasets_ecs_med + ECS_low_hist: + <<: *var_clt + short_name: lwcre + derive: true + additional_datasets: *datasets_ecs_low + ECS_high_scen: + <<: *var_clt + <<: *years_scen + short_name: lwcre + derive: true + additional_datasets: *datasets_ecs_high_scenario + ECS_med_scen: + <<: *var_clt + <<: *years_scen + short_name: lwcre + derive: true + additional_datasets: *datasets_ecs_med_scenario + ECS_low_scen: + <<: *var_clt + <<: *years_scen + short_name: lwcre + derive: true + additional_datasets: *datasets_ecs_low_scenario + tas_ECS_high_hist: + <<: *var_tas + tas_ECS_med_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_med + tas_ECS_low_hist: + <<: *var_tas + additional_datasets: *datasets_ecs_low + tas_ECS_high_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + tas_ECS_med_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_med_scenario + tas_ECS_low_scen: + <<: *var_tas + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_low_scenario + OBS: + <<: *var_clt + short_name: lwcre + derive: true + preprocessor: zonal + additional_datasets: + - {dataset: CERES-EBAF, project: OBS, type: sat, version: Ed4.2, + tier: 2, start_year: 2001, end_year: 2022} diff --git a/esmvaltool/recipes/clouds/recipe_bock24acp_fig7_boxplots.yml b/esmvaltool/recipes/clouds/recipe_bock24acp_fig7_boxplots.yml new file mode 100644 index 0000000000..e4fb30c7e3 --- /dev/null +++ b/esmvaltool/recipes/clouds/recipe_bock24acp_fig7_boxplots.yml @@ -0,0 +1,1003 @@ +# ESMValTool +# recipe_bock24acp_fig7_boxplots.yml +--- +documentation: + title: Cloud properties regarding ECS (boxplots). + + description: | + Bockplots fo projected changes of cloud properties + for different regions. + + authors: + - bock_lisa + + maintainer: + - bock_lisa + + references: + - bock24acp + + project: + - cmug + - esm2025 + + +YEARS_hist: &years_hist + start_year: 1985 + end_year: 2004 + +YEARS_scen: &years_scen + start_year: 2081 + end_year: 2100 + +VARIABLE_SETTINGS: &var_settings + short_name: clt + mip: Amon + project: CMIP6 + exp: historical + ensemble: r1i1p1f1 + grid: gr + <<: *years_hist + +BOXPLOT_SETTINGS: &boxplot_settings + script: clouds/clouds_ecs_groups_boxplots.py + group_by: [['ECS_low_hist', 'ECS_low_scen'], + ['ECS_med_hist', 'ECS_med_scen'], + ['ECS_high_hist', 'ECS_high_scen']] + y_range: [-25., 22.] + + +DATASETS_ECS_HIGH: &datasets_ecs_high + # CMIP6 + - {dataset: CanESM5, grid: gn} + # - {dataset: CESM2, grid: gn, ensemble: r4i1p1f1} + # - {dataset: CESM2-WACCM, grid: gn, institute: NCAR} + - {dataset: CNRM-CM6-1, ensemble: r1i1p1f2} + - {dataset: CNRM-ESM2-1, ensemble: r1i1p1f2} + - {dataset: HadGEM3-GC31-LL, grid: gn, ensemble: r1i1p1f3} + - {dataset: HadGEM3-GC31-MM, grid: gn, ensemble: r1i1p1f3} + - {dataset: IPSL-CM6A-LR} + - {dataset: KACE-1-0-G} + - {dataset: NESM3, grid: gn} + - {dataset: TaiESM1, grid: gn} + - {dataset: UKESM1-0-LL, ensemble: r1i1p1f2, grid: gn} + # CMIP5 + - {dataset: CSIRO-Mk3-6-0, ensemble: r1i1p1, project: CMIP5} + - {dataset: HadGEM2-ES, ensemble: r1i1p1, project: CMIP5} + - {dataset: IPSL-CM5A-LR, ensemble: r1i1p1, project: CMIP5} + - {dataset: IPSL-CM5A-MR, ensemble: r1i1p1, project: CMIP5} + - {dataset: MIROC-ESM, ensemble: r1i1p1, project: CMIP5} + +DATASETS_ECS_HIGH_scenario: &datasets_ecs_high_scenario + # CMIP6 + - {dataset: CanESM5, grid: gn, exp: ssp585} + # - {dataset: CESM2, grid: gn, ensemble: r4i1p1f1, exp: ssp585} + # - {dataset: CESM2-WACCM, grid: gn, institute: NCAR, exp: ssp585} + - {dataset: CNRM-CM6-1, ensemble: r1i1p1f2, exp: ssp585} + - {dataset: CNRM-ESM2-1, ensemble: r1i1p1f2, exp: ssp585} + - {dataset: HadGEM3-GC31-LL, grid: gn, ensemble: r1i1p1f3, exp: ssp585} + - {dataset: HadGEM3-GC31-MM, grid: gn, ensemble: r1i1p1f3, exp: ssp585} + - {dataset: IPSL-CM6A-LR, exp: ssp585} + - {dataset: KACE-1-0-G, exp: ssp585} + - {dataset: NESM3, grid: gn, exp: ssp585} + - {dataset: TaiESM1, grid: gn, exp: ssp585} + - {dataset: UKESM1-0-LL, ensemble: r1i1p1f2, grid: gn, exp: ssp585} + # CMIP5 + - {dataset: CSIRO-Mk3-6-0, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: HadGEM2-ES, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: IPSL-CM5A-LR, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: IPSL-CM5A-MR, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: MIROC-ESM, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + +DATASETS_ECS_MED: &datasets_ecs_med + # CMIP6 + - {dataset: BCC-CSM2-MR, grid: gn} + - {dataset: CMCC-CM2-SR5, grid: gn} + - {dataset: CMCC-ESM2, grid: gn} + - {dataset: FGOALS-f3-L} + - {dataset: FGOALS-g3, grid: gn} + - {dataset: GISS-E2-1-H, grid: gn} + - {dataset: MPI-ESM1-2-HR, grid: gn} + - {dataset: MPI-ESM1-2-LR, grid: gn} + - {dataset: MRI-ESM2-0, grid: gn} + # CMIP5 + - {dataset: ACCESS1-0, ensemble: r1i1p1, project: CMIP5} + - {dataset: ACCESS1-3, ensemble: r1i1p1, project: CMIP5} + - {dataset: BNU-ESM, ensemble: r1i1p1, project: CMIP5} + - {dataset: CanESM2, ensemble: r1i1p1, project: CMIP5} + - {dataset: CCSM4, ensemble: r1i1p1, project: CMIP5} + - {dataset: FGOALS-g2, ensemble: r1i1p1, project: CMIP5} + - {dataset: GFDL-CM3, ensemble: r1i1p1, project: CMIP5} + - {dataset: MPI-ESM-LR, ensemble: r1i1p1, project: CMIP5} + - {dataset: MPI-ESM-MR, ensemble: r1i1p1, project: CMIP5} + +DATASETS_ECS_MED_scenario: &datasets_ecs_med_scenario + # CMIP6 + - {dataset: BCC-CSM2-MR, grid: gn, exp: ssp585} + - {dataset: CMCC-CM2-SR5, grid: gn, exp: ssp585} + - {dataset: CMCC-ESM2, grid: gn, exp: ssp585} + - {dataset: FGOALS-f3-L, exp: ssp585} + - {dataset: FGOALS-g3, grid: gn, exp: ssp585} + - {dataset: GISS-E2-1-H, grid: gn, ensemble: r1i1p1f2, exp: ssp585} + - {dataset: MPI-ESM1-2-HR, grid: gn, exp: ssp585} + - {dataset: MPI-ESM1-2-LR, grid: gn, exp: ssp585} + - {dataset: MRI-ESM2-0, grid: gn, exp: ssp585} + # CMIP5 + - {dataset: ACCESS1-0, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: ACCESS1-3, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: BNU-ESM, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: CanESM2, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: CCSM4, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: FGOALS-g2, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: GFDL-CM3, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: MPI-ESM-LR, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: MPI-ESM-MR, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + +DATASETS_ECS_LOW: &datasets_ecs_low + # CMIP6 + - {dataset: CAMS-CSM1-0, grid: gn} + - {dataset: GISS-E2-1-G, grid: gn} + - {dataset: MIROC6, grid: gn} + - {dataset: MIROC-ES2L, ensemble: r1i1p1f2, grid: gn} + - {dataset: NorESM2-LM, grid: gn, institute: NCC} + - {dataset: NorESM2-MM, grid: gn, institute: NCC} + # CMIP5 + - {dataset: bcc-csm1-1, ensemble: r1i1p1, project: CMIP5} + - {dataset: bcc-csm1-1-m, ensemble: r1i1p1, project: CMIP5} + - {dataset: GFDL-ESM2G, ensemble: r1i1p1, project: CMIP5} + - {dataset: GFDL-ESM2M, ensemble: r1i1p1, project: CMIP5} + - {dataset: GISS-E2-H, ensemble: r1i1p1, project: CMIP5} + - {dataset: GISS-E2-R, ensemble: r1i1p1, project: CMIP5} + - {dataset: inmcm4, ensemble: r1i1p1, project: CMIP5} + - {dataset: IPSL-CM5B-LR, ensemble: r1i1p1, project: CMIP5} + - {dataset: MIROC5, ensemble: r1i1p1, project: CMIP5} + - {dataset: MRI-CGCM3, ensemble: r1i1p1, project: CMIP5} + - {dataset: NorESM1-M, ensemble: r1i1p1, project: CMIP5} + +DATASETS_ECS_LOW_scenario: &datasets_ecs_low_scenario + # CMIP6 + - {dataset: CAMS-CSM1-0, grid: gn, exp: ssp585, end_year: 2099} + - {dataset: GISS-E2-1-G, grid: gn, ensemble: r1i1p1f2, exp: ssp585} + - {dataset: MIROC6, grid: gn, exp: ssp585} + - {dataset: MIROC-ES2L, ensemble: r1i1p1f2, grid: gn, exp: ssp585} + - {dataset: NorESM2-LM, grid: gn, institute: NCC, exp: ssp585} + - {dataset: NorESM2-MM, grid: gn, institute: NCC, exp: ssp585} + # CMIP5 + - {dataset: bcc-csm1-1, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: bcc-csm1-1-m, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: GFDL-ESM2G, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: GFDL-ESM2M, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: GISS-E2-H, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: GISS-E2-R, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: inmcm4, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: IPSL-CM5B-LR, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: MIROC5, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: MRI-CGCM3, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + - {dataset: NorESM1-M, ensemble: r1i1p1, project: CMIP5, exp: rcp85} + + +preprocessors: + + tropical_ocean: + custom_order: true + extract_region: + start_latitude: -30. + end_latitude: 30. + start_longitude: 0. + end_longitude: 360. + mask_landsea: &mask_land + mask_out: land + area_statistics: &area_mean + operator: mean + climate_statistics: &clim_mean + operator: mean + + southern_ocean: + custom_order: true + extract_region: + start_latitude: -65. + end_latitude: -30. + start_longitude: 0. + end_longitude: 360. + mask_landsea: *mask_land + area_statistics: *area_mean + climate_statistics: *clim_mean + + pacific_itcz: + custom_order: true + extract_region: + start_latitude: 0. + end_latitude: 12. + start_longitude: 135. + end_longitude: 275. + mask_landsea: *mask_land + area_statistics: *area_mean + climate_statistics: *clim_mean + + stratocumulus: + custom_order: true + extract_shape: + shapefile: shapefiles/sc_regions.shp + crop: true + decomposed: false + ids: + sc: + - SEP + - NEP + - SEA + mask_landsea: *mask_land + area_statistics: *area_mean + climate_statistics: *clim_mean + + arctic: + custom_order: true + extract_region: + start_latitude: 70. + end_latitude: 90. + start_longitude: 0. + end_longitude: 360. + mask_landsea: *mask_land + area_statistics: *area_mean + climate_statistics: *clim_mean + + +diagnostics: + + diag_tropical_ocean: + description: compare field means + variables: + clt_ECS_high_hist: &var_clt_1 + <<: *var_settings + preprocessor: tropical_ocean + additional_datasets: *datasets_ecs_high + clt_ECS_med_hist: + <<: *var_clt_1 + additional_datasets: *datasets_ecs_med + clt_ECS_low_hist: + <<: *var_clt_1 + additional_datasets: *datasets_ecs_low + clt_ECS_high_scen: + <<: *var_clt_1 + <<: *years_scen + additional_datasets: *datasets_ecs_high_scenario + clt_ECS_med_scen: + <<: *var_clt_1 + <<: *years_scen + additional_datasets: *datasets_ecs_med_scenario + clt_ECS_low_scen: + <<: *var_clt_1 + <<: *years_scen + additional_datasets: *datasets_ecs_low_scenario + clivi_ECS_high_hist: + <<: *var_clt_1 + short_name: clivi + additional_datasets: *datasets_ecs_high + clivi_ECS_med_hist: + <<: *var_clt_1 + short_name: clivi + additional_datasets: *datasets_ecs_med + clivi_ECS_low_hist: + <<: *var_clt_1 + short_name: clivi + additional_datasets: *datasets_ecs_low + clivi_ECS_high_scen: + <<: *var_clt_1 + <<: *years_scen + short_name: clivi + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + clivi_ECS_med_scen: + <<: *var_clt_1 + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_med_scenario + clivi_ECS_low_scen: + <<: *var_clt_1 + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_low_scenario + lwp_ECS_high_hist: + <<: *var_clt_1 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_high + lwp_ECS_med_hist: + <<: *var_clt_1 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med + lwp_ECS_low_hist: + <<: *var_clt_1 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low + lwp_ECS_high_scen: + <<: *var_clt_1 + <<: *years_scen + short_name: lwp + derive: true + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + lwp_ECS_med_scen: + <<: *var_clt_1 + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med_scenario + lwp_ECS_low_scen: + <<: *var_clt_1 + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low_scenario + netcre_ECS_high_hist: + <<: *var_clt_1 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_high + netcre_ECS_med_hist: + <<: *var_clt_1 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med + netcre_ECS_low_hist: + <<: *var_clt_1 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low + netcre_ECS_high_scen: + <<: *var_clt_1 + <<: *years_scen + short_name: netcre + derive: true + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + netcre_ECS_med_scen: + <<: *var_clt_1 + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med_scenario + netcre_ECS_low_scen: + <<: *var_clt_1 + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low_scenario + tas_ECS_high_hist: &var_tas_1 + <<: *var_clt_1 + short_name: tas + tas_ECS_med_hist: + <<: *var_tas_1 + additional_datasets: *datasets_ecs_med + tas_ECS_low_hist: + <<: *var_tas_1 + additional_datasets: *datasets_ecs_low + tas_ECS_high_scen: + <<: *var_tas_1 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + tas_ECS_med_scen: + <<: *var_tas_1 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_med_scenario + tas_ECS_low_scen: + <<: *var_tas_1 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_low_scenario + scripts: + barplot: + <<: *boxplot_settings + filename_attach: 'ssp585_tropoc' + title: 'Tropical Ocean' + + + diag_southern_ocean: + description: compare field means + variables: + clt_ECS_high_hist: &var_clt_2 + <<: *var_settings + preprocessor: southern_ocean + additional_datasets: *datasets_ecs_high + clt_ECS_med_hist: + <<: *var_clt_2 + additional_datasets: *datasets_ecs_med + clt_ECS_low_hist: + <<: *var_clt_2 + additional_datasets: *datasets_ecs_low + clt_ECS_high_scen: + <<: *var_clt_2 + <<: *years_scen + additional_datasets: *datasets_ecs_high_scenario + clt_ECS_med_scen: + <<: *var_clt_2 + <<: *years_scen + additional_datasets: *datasets_ecs_med_scenario + clt_ECS_low_scen: + <<: *var_clt_2 + <<: *years_scen + additional_datasets: *datasets_ecs_low_scenario + clivi_ECS_high_hist: + <<: *var_clt_2 + short_name: clivi + additional_datasets: *datasets_ecs_high + clivi_ECS_med_hist: + <<: *var_clt_2 + short_name: clivi + additional_datasets: *datasets_ecs_med + clivi_ECS_low_hist: + <<: *var_clt_2 + short_name: clivi + additional_datasets: *datasets_ecs_low + clivi_ECS_high_scen: + <<: *var_clt_2 + <<: *years_scen + short_name: clivi + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + clivi_ECS_med_scen: + <<: *var_clt_2 + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_med_scenario + clivi_ECS_low_scen: + <<: *var_clt_2 + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_low_scenario + lwp_ECS_high_hist: + <<: *var_clt_2 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_high + lwp_ECS_med_hist: + <<: *var_clt_2 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med + lwp_ECS_low_hist: + <<: *var_clt_2 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low + lwp_ECS_high_scen: + <<: *var_clt_2 + <<: *years_scen + short_name: lwp + derive: true + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + lwp_ECS_med_scen: + <<: *var_clt_2 + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med_scenario + lwp_ECS_low_scen: + <<: *var_clt_2 + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low_scenario + netcre_ECS_high_hist: + <<: *var_clt_2 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_high + netcre_ECS_med_hist: + <<: *var_clt_2 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med + netcre_ECS_low_hist: + <<: *var_clt_2 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low + netcre_ECS_high_scen: + <<: *var_clt_2 + <<: *years_scen + short_name: netcre + derive: true + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + netcre_ECS_med_scen: + <<: *var_clt_2 + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med_scenario + netcre_ECS_low_scen: + <<: *var_clt_2 + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low_scenario + tas_ECS_high_hist: &var_tas_2 + <<: *var_clt_2 + short_name: tas + tas_ECS_med_hist: + <<: *var_tas_2 + additional_datasets: *datasets_ecs_med + tas_ECS_low_hist: + <<: *var_tas_2 + additional_datasets: *datasets_ecs_low + tas_ECS_high_scen: + <<: *var_tas_2 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + tas_ECS_med_scen: + <<: *var_tas_2 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_med_scenario + tas_ECS_low_scen: + <<: *var_tas_2 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_low_scenario + scripts: + barplot: + <<: *boxplot_settings + filename_attach: 'ssp585_south_oc' + title: 'Southern Ocean' + + + diag_pacific_itcz: + description: compare field means + variables: + clt_ECS_high_hist: &var_clt_3 + <<: *var_settings + preprocessor: pacific_itcz + additional_datasets: *datasets_ecs_high + clt_ECS_med_hist: + <<: *var_clt_3 + additional_datasets: *datasets_ecs_med + clt_ECS_low_hist: + <<: *var_clt_3 + additional_datasets: *datasets_ecs_low + clt_ECS_high_scen: + <<: *var_clt_3 + <<: *years_scen + additional_datasets: *datasets_ecs_high_scenario + clt_ECS_med_scen: + <<: *var_clt_3 + <<: *years_scen + additional_datasets: *datasets_ecs_med_scenario + clt_ECS_low_scen: + <<: *var_clt_3 + <<: *years_scen + additional_datasets: *datasets_ecs_low_scenario + clivi_ECS_high_hist: + <<: *var_clt_3 + short_name: clivi + additional_datasets: *datasets_ecs_high + clivi_ECS_med_hist: + <<: *var_clt_3 + short_name: clivi + additional_datasets: *datasets_ecs_med + clivi_ECS_low_hist: + <<: *var_clt_3 + short_name: clivi + additional_datasets: *datasets_ecs_low + clivi_ECS_high_scen: + <<: *var_clt_3 + <<: *years_scen + short_name: clivi + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + clivi_ECS_med_scen: + <<: *var_clt_3 + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_med_scenario + clivi_ECS_low_scen: + <<: *var_clt_3 + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_low_scenario + lwp_ECS_high_hist: + <<: *var_clt_3 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_high + lwp_ECS_med_hist: + <<: *var_clt_3 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med + lwp_ECS_low_hist: + <<: *var_clt_3 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low + lwp_ECS_high_scen: + <<: *var_clt_3 + <<: *years_scen + short_name: lwp + derive: true + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + lwp_ECS_med_scen: + <<: *var_clt_3 + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med_scenario + lwp_ECS_low_scen: + <<: *var_clt_3 + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low_scenario + netcre_ECS_high_hist: + <<: *var_clt_3 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_high + netcre_ECS_med_hist: + <<: *var_clt_3 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med + netcre_ECS_low_hist: + <<: *var_clt_3 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low + netcre_ECS_high_scen: + <<: *var_clt_3 + <<: *years_scen + short_name: netcre + derive: true + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + netcre_ECS_med_scen: + <<: *var_clt_3 + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med_scenario + netcre_ECS_low_scen: + <<: *var_clt_3 + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low_scenario + tas_ECS_high_hist: &var_tas_3 + <<: *var_clt_3 + short_name: tas + tas_ECS_med_hist: + <<: *var_tas_3 + additional_datasets: *datasets_ecs_med + tas_ECS_low_hist: + <<: *var_tas_3 + additional_datasets: *datasets_ecs_low + tas_ECS_high_scen: + <<: *var_tas_3 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + tas_ECS_med_scen: + <<: *var_tas_3 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_med_scenario + tas_ECS_low_scen: + <<: *var_tas_3 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_low_scenario + scripts: + barplot: + <<: *boxplot_settings + filename_attach: 'ssp585_paitcz' + title: 'Pacific ITCZ' + + + diag_stratocumulus: + description: compare field means + variables: + clt_ECS_high_hist: &var_clt_str + <<: *var_settings + preprocessor: stratocumulus + additional_datasets: *datasets_ecs_high + clt_ECS_med_hist: + <<: *var_clt_str + additional_datasets: *datasets_ecs_med + clt_ECS_low_hist: + <<: *var_clt_str + additional_datasets: *datasets_ecs_low + clt_ECS_high_scen: + <<: *var_clt_str + <<: *years_scen + additional_datasets: *datasets_ecs_high_scenario + clt_ECS_med_scen: + <<: *var_clt_str + <<: *years_scen + additional_datasets: *datasets_ecs_med_scenario + clt_ECS_low_scen: + <<: *var_clt_str + <<: *years_scen + additional_datasets: *datasets_ecs_low_scenario + clivi_ECS_high_hist: + <<: *var_clt_str + short_name: clivi + additional_datasets: *datasets_ecs_high + clivi_ECS_med_hist: + <<: *var_clt_str + short_name: clivi + additional_datasets: *datasets_ecs_med + clivi_ECS_low_hist: + <<: *var_clt_str + short_name: clivi + additional_datasets: *datasets_ecs_low + clivi_ECS_high_scen: + <<: *var_clt_str + <<: *years_scen + short_name: clivi + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + clivi_ECS_med_scen: + <<: *var_clt_str + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_med_scenario + clivi_ECS_low_scen: + <<: *var_clt_str + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_low_scenario + lwp_ECS_high_hist: + <<: *var_clt_str + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_high + lwp_ECS_med_hist: + <<: *var_clt_str + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med + lwp_ECS_low_hist: + <<: *var_clt_str + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low + lwp_ECS_high_scen: + <<: *var_clt_str + <<: *years_scen + short_name: lwp + derive: true + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + lwp_ECS_med_scen: + <<: *var_clt_str + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med_scenario + lwp_ECS_low_scen: + <<: *var_clt_str + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low_scenario + netcre_ECS_high_hist: + <<: *var_clt_str + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_high + netcre_ECS_med_hist: + <<: *var_clt_str + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med + netcre_ECS_low_hist: + <<: *var_clt_str + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low + netcre_ECS_high_scen: + <<: *var_clt_str + <<: *years_scen + short_name: netcre + derive: true + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + netcre_ECS_med_scen: + <<: *var_clt_str + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med_scenario + netcre_ECS_low_scen: + <<: *var_clt_str + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low_scenario + tas_ECS_high_hist: &var_tas_str + <<: *var_clt_str + short_name: tas + tas_ECS_med_hist: + <<: *var_tas_str + additional_datasets: *datasets_ecs_med + tas_ECS_low_hist: + <<: *var_tas_str + additional_datasets: *datasets_ecs_low + tas_ECS_high_scen: + <<: *var_tas_str + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + tas_ECS_med_scen: + <<: *var_tas_str + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_med_scenario + tas_ECS_low_scen: + <<: *var_tas_str + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_low_scenario + scripts: + barplot: + <<: *boxplot_settings + filename_attach: 'ssp585_stratocumulus' + title: 'Stratocumulus region' + + + diag_arctic: + description: compare field means + variables: + clt_ECS_high_hist: &var_clt_5 + <<: *var_settings + preprocessor: arctic + additional_datasets: *datasets_ecs_high + clt_ECS_med_hist: + <<: *var_clt_5 + additional_datasets: *datasets_ecs_med + clt_ECS_low_hist: + <<: *var_clt_5 + additional_datasets: *datasets_ecs_low + clt_ECS_high_scen: + <<: *var_clt_5 + <<: *years_scen + additional_datasets: *datasets_ecs_high_scenario + clt_ECS_med_scen: + <<: *var_clt_5 + <<: *years_scen + additional_datasets: *datasets_ecs_med_scenario + clt_ECS_low_scen: + <<: *var_clt_5 + <<: *years_scen + additional_datasets: *datasets_ecs_low_scenario + clivi_ECS_high_hist: + <<: *var_clt_5 + short_name: clivi + additional_datasets: *datasets_ecs_high + clivi_ECS_med_hist: + <<: *var_clt_5 + short_name: clivi + additional_datasets: *datasets_ecs_med + clivi_ECS_low_hist: + <<: *var_clt_5 + short_name: clivi + additional_datasets: *datasets_ecs_low + clivi_ECS_high_scen: + <<: *var_clt_5 + <<: *years_scen + short_name: clivi + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + clivi_ECS_med_scen: + <<: *var_clt_5 + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_med_scenario + clivi_ECS_low_scen: + <<: *var_clt_5 + <<: *years_scen + short_name: clivi + additional_datasets: *datasets_ecs_low_scenario + lwp_ECS_high_hist: + <<: *var_clt_5 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_high + lwp_ECS_med_hist: + <<: *var_clt_5 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med + lwp_ECS_low_hist: + <<: *var_clt_5 + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low + lwp_ECS_high_scen: + <<: *var_clt_5 + <<: *years_scen + short_name: lwp + derive: true + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + lwp_ECS_med_scen: + <<: *var_clt_5 + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_med_scenario + lwp_ECS_low_scen: + <<: *var_clt_5 + <<: *years_scen + short_name: lwp + derive: true + additional_datasets: *datasets_ecs_low_scenario + netcre_ECS_high_hist: + <<: *var_clt_5 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_high + netcre_ECS_med_hist: + <<: *var_clt_5 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med + netcre_ECS_low_hist: + <<: *var_clt_5 + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low + netcre_ECS_high_scen: + <<: *var_clt_5 + <<: *years_scen + short_name: netcre + derive: true + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + netcre_ECS_med_scen: + <<: *var_clt_5 + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_med_scenario + netcre_ECS_low_scen: + <<: *var_clt_5 + <<: *years_scen + short_name: netcre + derive: true + additional_datasets: *datasets_ecs_low_scenario + tas_ECS_high_hist: &var_tas_5 + <<: *var_clt_5 + short_name: tas + tas_ECS_med_hist: + <<: *var_tas_5 + additional_datasets: *datasets_ecs_med + tas_ECS_low_hist: + <<: *var_tas_5 + additional_datasets: *datasets_ecs_low + tas_ECS_high_scen: + <<: *var_tas_5 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_high_scenario + tas_ECS_med_scen: + <<: *var_tas_5 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_med_scenario + tas_ECS_low_scen: + <<: *var_tas_5 + <<: *years_scen + exp: ssp585 + additional_datasets: *datasets_ecs_low_scenario + scripts: + barplot: + <<: *boxplot_settings + filename_attach: 'ssp585_pol' + title: 'Arctic' diff --git a/esmvaltool/references/bock24acp.bibtex b/esmvaltool/references/bock24acp.bibtex new file mode 100644 index 0000000000..6915a5855c --- /dev/null +++ b/esmvaltool/references/bock24acp.bibtex @@ -0,0 +1,12 @@ +@article{https://doi.org/10.5194/acp-24-1587-2024, +author = {Bock, L. and Lauer, A.}, +title = {Cloud properties and their projected changes in CMIP models with low to high climate sensitivity}, +journal = {Atmospheric Chemistry and Physics}, +volume = {24}, +number = {3}, +pages = {1587--1605}, +doi = {10.5194/acp-24-1587-2024}, +url = {https://doi.org/10.5194/acp-24-1587-2024 +year = {2024} +} +