diff --git a/doc/sphinx/source/recipes/figures/seaborn/displot_clt_lwcre_esacci-cloud_CESM2-WACCM.png b/doc/sphinx/source/recipes/figures/seaborn/displot_clt_lwcre_esacci-cloud_CESM2-WACCM.png new file mode 100644 index 0000000000..160b2c3213 Binary files /dev/null and b/doc/sphinx/source/recipes/figures/seaborn/displot_clt_lwcre_esacci-cloud_CESM2-WACCM.png differ diff --git a/doc/sphinx/source/recipes/figures/seaborn/displot_clt_swcre_esacci-cloud_CESM2-WACCM.png b/doc/sphinx/source/recipes/figures/seaborn/displot_clt_swcre_esacci-cloud_CESM2-WACCM.png new file mode 100644 index 0000000000..ab9ae14d20 Binary files /dev/null and b/doc/sphinx/source/recipes/figures/seaborn/displot_clt_swcre_esacci-cloud_CESM2-WACCM.png differ diff --git a/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_lwcre_CESM2-FV2.png b/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_lwcre_CESM2-FV2.png new file mode 100644 index 0000000000..d9be264ba1 Binary files /dev/null and b/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_lwcre_CESM2-FV2.png differ diff --git a/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_lwcre_esacci_cloud.png b/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_lwcre_esacci_cloud.png new file mode 100644 index 0000000000..afb427e174 Binary files /dev/null and b/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_lwcre_esacci_cloud.png differ diff --git a/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_swcre_CESM2-FV2.png b/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_swcre_CESM2-FV2.png new file mode 100644 index 0000000000..96e45bd48c Binary files /dev/null and b/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_swcre_CESM2-FV2.png differ diff --git a/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_swcre_esacci_cloud.png b/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_swcre_esacci_cloud.png new file mode 100644 index 0000000000..3adf187379 Binary files /dev/null and b/doc/sphinx/source/recipes/figures/seaborn/plot_hist_scatter_clt_swcre_esacci_cloud.png differ diff --git a/doc/sphinx/source/recipes/recipe_scatterplot.rst b/doc/sphinx/source/recipes/recipe_scatterplot.rst new file mode 100644 index 0000000000..ba3251007c --- /dev/null +++ b/doc/sphinx/source/recipes/recipe_scatterplot.rst @@ -0,0 +1,61 @@ +.. _recipes_seaborn_diag: + +Seaborn Diagnostics +=================== + +Overview +-------- + +These recipes showcase the use of the Seaborn diagnostic that provides a +high-level interface to `Seaborn `__ for ESMValTool +recipes used in the CMIP Rapid Evaluation Framework (REF). + +CMIP Rapid Evaluation Framework +--------------------------------- + +`CMIP Rapid Evaluation Framework ` + +Available recipes and diagnostics +--------------------------------- + +Recipes are stored in recipes/ref/ + +* recipe_scatterplot.yml + +Diagnostics are stored in diag_scripts/ + +* :ref:`seaborn_diag.py ` + + +Variables +--------- + +Clt, Swcre, Lwcre. + + +Observations and reformat scripts +--------------------------------- + +Arbitrary datasets are supported. + + +References +---------- + +* Waskom, M. L. (2021), seaborn: statistical data visualization, Journal of + Open Source Software, 6(60), 3021, doi:10.21105/joss.03021. + + +Example plots +------------- + +.. _fig_seaborn_1: +.. figure:: /recipes/figures/seaborn/displot_clt_lwcre_esacci-cloud_CESM2-WACCM.png + :align: center + :width: 50% + +.. _fig_seaborn_2: +.. figure:: /recipes/figures/seaborn/displot_clt_swcre_esacci-cloud_CESM2-WACCM.png + :align: center + :width: 50% + \ No newline at end of file diff --git a/esmvaltool/config-references.yml b/esmvaltool/config-references.yml index 1ece453343..523e543893 100644 --- a/esmvaltool/config-references.yml +++ b/esmvaltool/config-references.yml @@ -327,6 +327,11 @@ authors: institute: DLR, Germany orcid: github: jeremykraftdlr + pacal_aytac: + name: Pacal, Aytac + institute: DLR, Germany + orcid: https://orcid.org/0000-0002-1324-2389 + github: aytacpacal krasting_john: name: Krasting, John institute: NOAA, USA diff --git a/esmvaltool/diag_scripts/seaborn_diag.py b/esmvaltool/diag_scripts/seaborn_diag.py index aa6ca1b504..ab6f45b6ba 100644 --- a/esmvaltool/diag_scripts/seaborn_diag.py +++ b/esmvaltool/diag_scripts/seaborn_diag.py @@ -148,6 +148,7 @@ def _create_plot( plot_func_str, _get_str_from_kwargs(plot_kwargs), ) + plot_obj = plot_func(data=data_frame, **plot_kwargs) # Adjust plot appearance @@ -171,7 +172,11 @@ def _create_plot( getattr(plot_obj, func_name)(func_args) if cfg['suptitle'] is not None: logger.debug("Setting `suptitle='%s'`", cfg['suptitle']) - plt.suptitle(cfg['suptitle'], y=1.05) + if plot_func_str in ['jointplot']: + plt.suptitle(cfg['suptitle'] + .format(data_frame["shape_id"].unique()[0]), y=1.05) + else: + plt.suptitle(cfg['suptitle'], y=1.05) if cfg['legend_title'] is not None: _set_legend_title(plot_obj, cfg['legend_title']) @@ -443,6 +448,12 @@ def _set_legend_title(plot_obj, legend_title: str) -> None: legend = plot_obj.get_legend() elif hasattr(plot_obj, 'legend'): # FacetGrid, PairGrid legend = plot_obj.legend + elif isinstance(plot_obj, sns.axisgrid.JointGrid): # JointGrid + # Manually create a legend if needed in JointGrid + handles, labels = plot_obj.ax_joint.get_legend_handles_labels() + if handles and labels: + legend = plot_obj.ax_joint.legend(handles=handles, labels=labels, + title=legend_title) else: raise ValueError( f"Cannot set legend title, `{type(plot_obj).__name__}` does not " diff --git a/esmvaltool/recipes/recipe_seaborn.yml b/esmvaltool/recipes/recipe_seaborn.yml index 983efae0be..1e6967fb27 100644 --- a/esmvaltool/recipes/recipe_seaborn.yml +++ b/esmvaltool/recipes/recipe_seaborn.yml @@ -13,6 +13,9 @@ documentation: authors: - schlund_manuel + - debeire_kevin + - kraft_jeremy + - pacal_aytac maintainer: - schlund_manuel @@ -26,13 +29,10 @@ documentation: - isenes3 - usmile - preprocessors: - zonal_mean: - zonal_statistics: - operator: mean - + zonal_statistics: + operator: mean extract_ar6_regions: regrid: target_grid: 5x5 @@ -51,10 +51,215 @@ preprocessors: - Equatorial.Indic-Ocean convert_units: units: mm day-1 + + extract_regions_pr: + regrid_time: ®rid_time + calendar: standard + frequency: mon + regrid: + target_grid: 5x5 + scheme: linear + extract_shape: + shapefile: ar6 + crop: true + decomposed: true + ids: + Name: ®ions_to_regrid + - N.Europe + - West&Central-Europe + - Mediterranean + - E.Europe + - Caribbean + - E.Antarctica + convert_units: + units: mm day-1 + + extract_regions_clivi: + regrid_time: *regrid_time + regrid: + target_grid: 5x5 + scheme: linear + extract_shape: + shapefile: ar6 + crop: true + decomposed: true + ids: + Name: *regions_to_regrid + convert_units: + units: g m-2 + + extract_region_pr_jointplot: + regrid_time: *regrid_time + regrid: + target_grid: 5x5 + scheme: linear + extract_shape: + shapefile: ar6 + crop: true + decomposed: true + ids: + Name: ®ion_to_regrid + - N.Europe + convert_units: + units: mm day-1 + + extract_region_clivi_jointplot: + regrid_time: *regrid_time + regrid: + target_grid: 5x5 + scheme: linear + extract_shape: + shapefile: ar6 + crop: true + decomposed: true + ids: + Name: *region_to_regrid + convert_units: + units: g m-2 + extract_region_clt_jointplot: + regrid_time: *regrid_time + regrid: + target_grid: 5x5 + scheme: linear + extract_shape: + shapefile: ar6 + crop: true + decomposed: true + ids: + Name: *region_to_regrid diagnostics: + plot_precipitation_vs_clivi_jointplot: + description: Scatter plot and histograms of precipitation vs. clivi in grid cells for a single region. + variables: + pr: + mip: Amon + preprocessor: extract_region_pr_jointplot + exp: historical + timerange: '1991/2014' + clivi: + mip: Amon + preprocessor: extract_region_clivi_jointplot + exp: historical + timerange: '1991/2014' + additional_datasets: + - {project: CMIP6, dataset: CESM2-WACCM, grid: gn, ensemble: r1i1p1f1} + - {project: CMIP6, dataset: GFDL-ESM4, grid: gr1, ensemble: r1i1p1f1} + - {project: CMIP6, dataset: ACCESS-CM2, grid: gn, ensemble: r1i1p1f1} + - {project: native6, dataset: ERA5, type: reanaly, version: v1, tier: 3} + + scripts: + plot: + script: seaborn_diag.py + seaborn_func: jointplot + groupby_facet: dataset + seaborn_kwargs: + x: pr + y: clivi + marker: . + hue: dataset + add_aux_coords: true + reset_index: true + legend_title: Model + plot_object_methods: + set_axis_labels: + xlabel: 'Precipitation [mm/day]' + ylabel: 'Cloud Ice Water Path [g/m^2]' + suptitle: 'Simulated Precipitation vs. Cloud Ice Water Path (1991-2014) in {}' + plot_precipitation_vs_clt_jointplot: + description: Scatter plot and histograms of precipitation vs. cloud area fraction in grid cells for a single region. + variables: + pr: + mip: Amon + preprocessor: extract_region_pr_jointplot + exp: historical + timerange: '1991/2014' + clt: + mip: Amon + preprocessor: extract_region_clt_jointplot + exp: historical + timerange: '1991/2014' + additional_datasets: + - {project: CMIP6, dataset: CESM2-WACCM, grid: gn, ensemble: r1i1p1f1} + - {project: CMIP6, dataset: GFDL-ESM4, grid: gr1, ensemble: r1i1p1f1} + - {project: CMIP6, dataset: ACCESS-CM2, grid: gn, ensemble: r1i1p1f1} + - {project: native6, dataset: ERA5, type: reanaly, version: v1, tier: 3} + + scripts: + plot: + script: seaborn_diag.py + seaborn_func: jointplot + groupby_facet: dataset + seaborn_kwargs: + x: pr + y: clt + marker: . + hue: dataset + add_aux_coords: true + reset_index: true + legend_title: Model + plot_object_methods: + set_axis_labels: + xlabel: 'Precipitation [mm/day]' + ylabel: 'Cloud Area fraction [%]' + suptitle: 'Simulated Precipitation vs. Cloud Area fraction (1991-2014) in {}' + + plot_precipitation_vs_clivi: + description: Scatter plots precipitation vs. clivi in grid cells + variables: + pr: + mip: Amon + preprocessor: extract_regions_pr + project: CMIP6 + exp: historical + timerange: '1991/2014' + clivi: + mip: Amon + preprocessor: extract_regions_clivi + project: CMIP6 + exp: historical + timerange: '1991/2014' + additional_datasets: + - {dataset: CESM2-WACCM, grid: gn, ensemble: r1i1p1f1} + - {dataset: GFDL-ESM4, grid: gr1, ensemble: r1i1p1f1} + - {dataset: ACCESS-CM2, grid: gn, ensemble: r1i1p1f1} + - {dataset: ERA5, project: native6, type: reanaly, version: v1, tier: 3} + scripts: + plot: + script: seaborn_diag.py + seaborn_func: relplot + groupby_facet: dataset + seaborn_kwargs: + x: pr + y: clivi + col: shape_id + col_order: *regions_to_regrid + col_wrap: 3 + hue: dataset + marker: . + s: 5 + facet_kws: + sharey: false + sharex: false + add_aux_coords: true + dropna_kwargs: + axis: 0 + how: any + legend_title: Model + plot_object_methods: + set: + xlabel: 'Precipitation [mm/day]' + ylabel: 'Cloud Ice Water Path [g/m^2]' + set_titles: '{col_name}' + seaborn_settings: + style: ticks + rc: + axes.titlepad: 15.0 + suptitle: Simulated Precipitation vs. Cloud Ice Water Path (1991-2014) + + plot_temperature_vs_lat: description: Plot air temperature vs. latitude (pressure levels = colors). variables: diff --git a/esmvaltool/recipes/ref/recipe_scatterplot.yml b/esmvaltool/recipes/ref/recipe_scatterplot.yml new file mode 100644 index 0000000000..d1f5157f77 --- /dev/null +++ b/esmvaltool/recipes/ref/recipe_scatterplot.yml @@ -0,0 +1,131 @@ +# ESMValTool +# recipe_seaborn.yml +--- +documentation: + title: Scatter Plot of Total Cloud Cover vs. Longwave Cloud Forcing and Total Cloud Cover vs. Shortwave Cloud Forcing + + description: > + This recipe generates a scatter plots of total cloud cover (clt) vs. + longwave cloud radiative effect (lwcre) and total cloud cover (clt) vs. + shortwave cloud radiative effect (swcre) using the Seaborn diagnostic + in ESMValTool. It combines datasets and variables from CMIP6 and observational data. + + authors: + - schlund_manuel + - debeire_kevin + - kraft_jeremy + #- pacal_aytac + #- cammarano_diego + + maintainer: + - schlund_manuel + + references: + - waskom21joss + + projects: + - 4c + - esm2025 + - isenes3 + - usmile + +diagnostics: + plot_hist_scatter_clt_lwcre: + description: Scatterplot clt vs lwcre using ESACCI-CLOUD and CESM2-WACCM datasets. + variables: + clt: + mip: Amon + exp: historical + ensemble: r1i1p1 + timerange: '1982/2002' + lwcre: + mip: Amon + derive: true + force_derivation: false + exp: historical + ensemble: r1i1p1 + timerange: '1982/2002' + additional_datasets: + - {dataset: ESACCI-CLOUD, project: OBS, type: sat, version: AVHRR-AMPM-fv3.0, tier: 2} + - {dataset: CESM2-WACCM, project: CMIP6, grid: gn, ensemble: r1i1p1f1} + scripts: + plot: + script: seaborn_diag.py + seaborn_func: displot + seaborn_kwargs: + kind: hist + col: alias # Creates side-by-side plots for each dataset + x: clt + y: lwcre + bins: 50 # Adjust binning for histograms + height: 5 # Set height of each subplot + aspect: 1.2 # Set aspect ratio + stat: probability + common_norm: false + color: blue # Sets the color for the plots + cbar: True # Includes a color bar + # xlabel: 'clt [%]' + # ylabel: 'lwcre [W m-2]' + add_aux_coords: true + dropna_kwargs: + axis: 0 + how: any + plot_object_methods: + set_axis_labels: + xlabel: 'clt [%]' + ylabel: 'lwcre [W m-2]' + seaborn_settings: + style: ticks + rc: + axes.titlepad: 15.0 + suptitle: 'clt vs lwcre for ESACCI-CLOUD and CESM2-WACCM (1982-2002)' + + plot_hist_scatter_clt_swcre: + description: Scatterplot clt vs swcre using ESACCI-CLOUD and CESM2-WACCM datasets. + variables: + clt: + mip: Amon + exp: historical + ensemble: r1i1p1 + timerange: '1982/2002' + swcre: + mip: Amon + derive: true + force_derivation: false + exp: historical + ensemble: r1i1p1 + timerange: '1982/2002' + additional_datasets: + - {dataset: ESACCI-CLOUD, project: OBS, type: sat, version: AVHRR-AMPM-fv3.0, tier: 2} + - {dataset: CESM2-WACCM, project: CMIP6, grid: gn, ensemble: r1i1p1f1} + scripts: + plot: + script: seaborn_diag.py + seaborn_func: displot + seaborn_kwargs: + kind: hist + col: alias # Creates side-by-side plots for each dataset + x: clt + y: swcre + bins: 50 # Adjust binning for histograms + height: 5 # Set height of each subplot + aspect: 1.2 # Set aspect ratio + stat: probability + common_norm: false + color: blue # Sets the color for the plots + cbar: True # Includes a color bar + # xlabel: 'clt [%]' + # ylabel: 'swcre [W m-2]' + add_aux_coords: true + dropna_kwargs: + axis: 0 + how: any + plot_object_methods: + set_axis_labels: + xlabel: 'clt [%]' + ylabel: 'swcre [W m-2]' + seaborn_settings: + style: ticks + rc: + axes.titlepad: 15.0 + suptitle: 'clt vs lwcre for ESACCI-CLOUD and CESM2-WACCM (1982-2002)' \ No newline at end of file