Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

New recipe and diagnostic for Arctic-midlatitude research #3021

Merged
merged 106 commits into from
Jun 19, 2023
Merged
Show file tree
Hide file tree
Changes from 99 commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
2836bc8
calculate actors for Arctic-midlat teleconnections
egalytska Sep 9, 2022
d33012c
naming changes and recipe small improvement
Sep 12, 2022
9a7e396
minor correction
Sep 12, 2022
dc51404
correction
Sep 12, 2022
d0d32f5
corrected config file
Sep 12, 2022
1b9be14
cvdp-related things
Sep 12, 2022
0479f6b
changed the path for diagnostics
Sep 13, 2022
f13a147
remove old file
Sep 14, 2022
d5477c7
modified config user file
egalytska Jan 5, 2023
7016535
recipe to define variables for Arctic-midlatitude teleconnections, fi…
egalytska Jan 5, 2023
a693c28
delete old file
egalytska Jan 5, 2023
7d76a52
modified bash file to run esmvaltool
egalytska Jan 5, 2023
a086dbc
add python diagnostic to calculate variables and save into .nc file b…
egalytska Jan 5, 2023
451b84f
remove the old recipe, was used only for the tests
egalytska Jan 5, 2023
a500871
remove an old recipy file that was used for the tests
egalytska Jan 5, 2023
94d6e4c
added a path with cmorized HAdISST data
egalytska Jan 19, 2023
aad8e28
Merge branch 'main' into Arctic-midlat_EG
egalytska Jan 20, 2023
3384d5b
Merge branch 'main' into Arctic-midlat_EG
egalytska Feb 7, 2023
132269d
Merge branch 'main' into Arctic-midlat_EG
bsolino Feb 13, 2023
3831711
Automated code standards fixing
bsolino Feb 13, 2023
bc54e16
redundant file
egalytska Feb 15, 2023
829e3b4
redundant config-user file
egalytska Feb 15, 2023
f79b87b
updated folder name
egalytska Feb 15, 2023
8080a61
fixed issues related to the code standard in the diag script
egalytska Feb 15, 2023
8e05f49
updated folder name
egalytska Feb 15, 2023
4aaaa56
corrected path to the diag script
egalytska Feb 15, 2023
a0e7cd9
corrected typo
egalytska Feb 15, 2023
1a0ac0b
Merge branch 'main' into Arctic-midlat_EG
egalytska Feb 22, 2023
f20371a
fixing codacy missing-function-docstring (this is test)
egalytska Feb 22, 2023
3c5a17e
fixing trailing whitespace
egalytska Feb 22, 2023
f3b97d5
fixing trailing whitespace (again)
egalytska Feb 22, 2023
b8c47b5
further codacy fixes
egalytska Feb 22, 2023
2dfc60d
more codacy fixes
egalytska Feb 22, 2023
f0f5f01
more codacy fixes
egalytska Feb 22, 2023
276d643
more codacy fixes
egalytska Feb 22, 2023
fc6e222
fixed missing whitespace
egalytska Feb 23, 2023
13a5f64
Merge branch 'main' into Arctic-midlat_EG
egalytska Mar 15, 2023
553b2b5
update of the recipe according to the ESMValTool standarts
egalytska Mar 15, 2023
19f252b
Merge branch 'main' into Arctic-midlat_EG
egalytska Mar 20, 2023
6f1b79f
added .bibtex reference
egalytska Mar 20, 2023
baa2c22
added cvdp
egalytska Mar 22, 2023
d75e040
renamed the file
egalytska Mar 22, 2023
47122e1
slight improvements, no plotting function yet and no provenance yet
egalytska Mar 22, 2023
fa58394
added missing blank lines
egalytska Mar 22, 2023
e82f060
hopefully improved the diagnostics
egalytska Mar 24, 2023
e519eef
fixng minor issues
egalytska Mar 24, 2023
650b8d7
minor fixes
egalytska Mar 24, 2023
36fa992
fixes
egalytska Mar 24, 2023
fce9919
final fix?
egalytska Mar 24, 2023
930a9ee
code style improvements
egalytska Mar 24, 2023
b5594ff
added documentation
egalytska Mar 27, 2023
91dac59
deleted redundant recipe file
egalytska Mar 27, 2023
4d3b3da
changes in structure of recipe
egalytska Mar 27, 2023
6f7d9e9
fixing typos
egalytska Mar 27, 2023
dadc2b3
fixes
egalytska Mar 27, 2023
11bc620
Update esmvaltool/recipes/recipe_galytska23jgr.yml
egalytska Apr 12, 2023
135eaa3
Update esmvaltool/recipes/recipe_galytska23jgr.yml
egalytska Apr 12, 2023
ba10578
Update esmvaltool/recipes/recipe_galytska23jgr.yml
egalytska Apr 12, 2023
9e69dc6
Merge branch 'main' into Arctic-midlat_EG
egalytska Apr 12, 2023
1acdd9b
Corrected doc/sphinx/source/recipes/recipe_galytska23jgr.rst
egalytska Apr 14, 2023
6e65876
Update doc/sphinx/source/recipes/recipe_galytska23jgr.rst
egalytska Apr 14, 2023
c7873eb
Update doc/sphinx/source/recipes/recipe_galytska23jgr.rst
egalytska Apr 14, 2023
9a93763
Reference for cvdp doc/sphinx/source/recipes/recipe_galytska23jgr.rst
egalytska Apr 14, 2023
3fb80c4
returned cvdp's package diagnostic file driver.ncl to original state
egalytska Apr 14, 2023
6243a0a
edited info
egalytska Apr 14, 2023
fdc22d3
updated the info regarding the cvdp necessary changes in the header o…
egalytska Apr 14, 2023
4ad2b18
Merge branch 'main' into Arctic-midlat_EG
egalytska Apr 14, 2023
173189f
corrected docs
egalytska Apr 17, 2023
8b8c2e0
improved the diag script/ dealt with codacy issue(s)
egalytska Apr 17, 2023
6ee1c27
corrections after yamllint checks
egalytska Apr 17, 2023
7308e40
replace with the original file
egalytska Apr 17, 2023
ec41c4f
change to original driver.ncl
egalytska Apr 17, 2023
470fed3
remove redundant space
egalytska Apr 17, 2023
86e338d
added newline at the end of file
egalytska Apr 17, 2023
5bb28d0
typo fix
egalytska Apr 18, 2023
1aaf1f7
Merge remote-tracking branch 'origin/main' into Arctic-midlat_EG
egalytska May 23, 2023
6ffe28d
Update doc/sphinx/source/recipes/recipe_galytska23jgr.rst
egalytska May 23, 2023
c1a1ed2
Update doc/sphinx/source/recipes/recipe_galytska23jgr.rst
egalytska May 23, 2023
36f2fa2
Update esmvaltool/diag_scripts/cvdp/cvdp/driver.ncl
egalytska May 23, 2023
0147521
Update esmvaltool/recipes/recipe_galytska23jgr.yml
egalytska May 23, 2023
4d4a321
Update esmvaltool/recipes/recipe_galytska23jgr.yml
egalytska May 23, 2023
2a87583
corrected from daily to monthly
egalytska May 23, 2023
14db29b
Merge branch 'Arctic-midlat_EG' of https://github.com/ESMValGroup/ESM…
egalytska May 23, 2023
bbe8ed1
Update esmvaltool/diag_scripts/galytska23/select_variables_for_tigram…
egalytska May 23, 2023
8d3f71c
Update esmvaltool/diag_scripts/galytska23/select_variables_for_tigram…
egalytska May 23, 2023
f99e9c0
fixed an error: from daily to monthly
egalytska May 23, 2023
a6bb9f5
Merge branch 'Arctic-midlat_EG' of https://github.com/ESMValGroup/ESM…
egalytska May 23, 2023
84b6373
fix typo
egalytska Jun 12, 2023
fa0b676
fixed variable_cases function
egalytska Jun 12, 2023
7d455c8
improved with adding the option for plotting
egalytska Jun 15, 2023
afafed2
improved diagnostics based on the community feedback
egalytska Jun 15, 2023
bafe969
trailing space
egalytska Jun 15, 2023
8b6385f
Merge remote-tracking branch 'origin' into HEAD
egalytska Jun 15, 2023
61061d1
code style fixes
egalytska Jun 15, 2023
f2a6cb6
fix code style mistakes
egalytska Jun 15, 2023
ee14e25
fixing prospector issue
egalytska Jun 16, 2023
e0bda0d
updated figure for the docs
egalytska Jun 16, 2023
b531f80
fix typo in end_year
egalytska Jun 16, 2023
865efc5
fix typo
egalytska Jun 16, 2023
1ecd3ad
Update doc/sphinx/source/recipes/recipe_galytska23jgr.rst
egalytska Jun 16, 2023
2c407cb
Merge branch 'main' into Arctic-midlat_EG
egalytska Jun 16, 2023
93e2bb8
corrected issues with .nc files
egalytska Jun 16, 2023
619d274
code stile fixes
egalytska Jun 16, 2023
399d7cf
Delete job_DKRZ-EG.sh
egalytska Jun 16, 2023
265f040
added recipe to list of resource intensive ones
Jun 16, 2023
208b029
Update esmvaltool/diag_scripts/galytska23/select_variables_for_tigram…
egalytska Jun 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions doc/sphinx/source/recipes/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ Other
recipe_ensclus
recipe_esacci_lst
recipe_examples
recipe_galytska23jgr
recipe_multimodel_products
recipe_pv_capacity_factor
recipe_rainfarm
Expand Down
91 changes: 91 additions & 0 deletions doc/sphinx/source/recipes/recipe_galytska23jgr.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
.. _recipe_galytska23jgr:

Timeseries for Arctic-Midlatitude Teleconnections
=================================================

Overview
--------

The recipe produces the timeseries of selected variables to study Arctic-midlatitude teleconnections for further application of Causal Model Evaluation (CME) described
in Galytska et al. (2023).

The output of the recipe consists of the .nc files named after the data source (e.g. ERA5, ACCESS-CM2.nc etc.).
Each file contains the area-weighted spatial average of climatological monthly anomalies of selected variables.
The recipe also applies the CVDP package.

egalytska marked this conversation as resolved.
Show resolved Hide resolved

Available recipes and diagnostics
---------------------------------

Recipes are stored in esmvaltool/recipes/

* recipe_galytska23jgr.yml

Diagnostics are stored in esmvaltool/diag_scripts/

* galytska23/select_variables_for_tigramite.py
* cvdp/cvdp_wrapper.py

User settings in recipe
-----------------------
#. Preprocessor

* ``anomalies`` (*period: monthly*): Calculate anomalies for selected variables
* ``regrid`` (*target_grid: 1x1*): Linear regridding of all datasets to the uniform grid
* ``area_statistics`` (*operation: mean*): Calculate mean over defined regions

#. Script <select_variables_for_tigramite.py>

none

#. Script <cvdp_wrapper.py>

none

#. Script <cvdp/cvdp/driver.ncl>

* ``modular`` (*modular: True*): Run the diagnostics that is selected in ``modular_list``
* ``modular_list`` (*modular_list: psl.nam_nao*): Calculate only NAO diagnostics

Variables
---------

* zg (atmos, monthly mean, longitude latitude time)
* tas (atmos, monthly mean, longitude latitude time)
* psl (atmos, monthly mean, longitude latitude time)
* va (atmos, monthly mean, longitude latitude time)
* ta (atmos, monthly mean, longitude latitude time)
* sic/siconc (seaice, monthly mean, longitude latitude time)
* ts (atmos, monthly mean, longitude latitude time)
* pr (atmos, monthly mean, longitude latitude time)

Observations and reformat scripts
---------------------------------

* ERA5 (pr, psl, ta, tas, ts, va, zg - ERA5 data can be used via the native6 project)

* HadISST - (sic - esmvaltool/cmorizers/data/formatters/datasets/hadisst.ncl)

References
----------

* Galytska, E., Weigel, K., Handorf, D., Jaiser, R., Köhler, R. H.,
Runge, J., & Eyring, V.: Causal model evaluation of Arctic-midlatitude
teleconnections in CMIP6. Authorea Preprints.
https://doi.org/10.1002/essoar.10512569.1.


* Copernicus Climate Change Service (C3S), 2017: ERA5: Fifth generation of
ECMWF atmospheric reanalyses of the global climate, edited, Copernicus
Climate Change Service Climate Data Store (CDS).
https://cds.climate.copernicus.eu/cdsapp#!/home

egalytska marked this conversation as resolved.
Show resolved Hide resolved
* http://www.cesm.ucar.edu/working_groups/CVC/cvdp/

Example plots
-------------

.. figure:: /recipes/figures/galytska23jgr/test_fig_TAS.png
egalytska marked this conversation as resolved.
Show resolved Hide resolved
:align: center

Monthly mean temperature anomalies in the Arctic (65°–90°N) from observations and selected CMIP6 models during 1980-2021.
2 changes: 1 addition & 1 deletion esmvaltool/diag_scripts/cvdp/cvdp/driver.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -211,4 +211,4 @@
png_scale,webpage_title,compute_modes_mon,met_files/])

print("Finished: Climate Variability Diagnostics Package ("+systemfunc("date")+")")


252 changes: 252 additions & 0 deletions esmvaltool/diag_scripts/galytska23/select_variables_for_tigramite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
"""
Arctic-midlatitude teleconnections Diagnostics.

Diagnostic calculates timeseries needed for Causal Model Evaluation
of Arctic-midlatitude teleconnections.

Description:
This diagnostics calculates timeseries of the variables that represent
Arctic-midlatitude teleconenctions that are further used for the
Causal Model Evaluation of CMIP6 (Galytska et al., 2023). The output of
this diagnostics is a .nc file per data source. Optionally this diagnostics
plots the timeseries of the evolution of each selected variable. If the
user kept "plot_timeseries: True" in recipe_galytska23jgr.yml, then
"variable_to_plot:" expects the name of the variable to be plotted.
Possible options for "variable_to_plot:" are:
Arctic_temperature
Psl_Ural
Psl_Sib
Psl_Aleut
PV
heat_flux
BK_sic
Ok_sic
Author: Evgenia Galytska, IUP-UB
egalytska@iup.physik.uni-bremen.de
Project: USMILE
"""
import logging
from pathlib import Path
import iris
import numpy as np
import seaborn as sns
from matplotlib import pyplot as plt
from esmvalcore.preprocessor import (
anomalies,
area_statistics,
meridional_statistics,
zonal_statistics,
)

import esmvaltool.diag_scripts.shared.iris_helpers as ih
from esmvaltool.diag_scripts.shared import (
ProvenanceLogger,
group_metadata,
run_diagnostic,
save_data,
)
from esmvaltool.diag_scripts.shared._base import (
get_diagnostic_filename,
get_plot_filename,
)

logger = logging.getLogger(Path(__file__).stem)


def get_provenance_record(ancestor_files):
"""Create a provenance record describing the diagnostic data and plot."""
record = {
'authors': ['galytska_evgenia'],
'ancestors': ancestor_files,
'projects': ['usmile'],
'references': [
'acknow_project',
egalytska marked this conversation as resolved.
Show resolved Hide resolved
],
}
return record


def calculate_polar_vortex(dict_item):
"""Calculate polar vortex."""
var = iris.load_cube(dict_item['filename'])
var = var.collapsed('air_pressure', iris.analysis.MEAN)
# change the sign of polar vortex so the positive values
# (negative geopotential height anomalies) stand for
# the strong polar vortex, similarly to
# Kretschmer et al., 2016 and Galytska et al., 2023
var.data *= -1
var.var_name = 'PV'
return var


def calculate_arctic_tas(dict_item):
"""Read Arctic temperature data."""
var = iris.load_cube(dict_item['filename'])
var.var_name = 'Arctic_temperature'
return var


def calculate_slp(dict_item):
"""Get surface pressure."""
var = iris.load_cube(dict_item['filename'])
# calculate hPa from Pa.
var.data /= 100
return var


def finalize_bk_ice(dict_item):
"""Read sea ice data (Barents-Kara seas)."""
var = iris.load_cube(dict_item['filename'])
var.var_name = 'BK_sic'
return var


def finalize_ok_ice(dict_item):
"""Read sea ice data (Sea of Okhotsk)."""
var = iris.load_cube(dict_item['filename'])
var.var_name = 'Ok_sic'
return var


def prepare_heat_flux(dict_item):
"""Prepare variables for the heat flux calculations."""
var = iris.load_cube(dict_item['filename'])
var_avg = area_statistics(var, operator='mean')
var_mermean = meridional_statistics(var, operator='mean')
deviation = var_mermean - var_avg
return deviation


def calculate_heat_flux(list_va_ta):
"""Calculate eddy poleward heat flux."""
heat_flux = list_va_ta[0] * list_va_ta[1]
hf_anom = anomalies(heat_flux, period='monthly')
hf_anom_zm = zonal_statistics(hf_anom, operator='mean')
hf_anom_zm.var_name = 'heat_flux'
return hf_anom_zm


def variable_cases(var, item):
"""Match preprocessor name and corresponding calculations."""
if var == 'pv':
out_var = calculate_polar_vortex(item)
elif var == 'pre_tas':
out_var = calculate_arctic_tas(item)
elif var == 'pressure_ural':
out_var = calculate_slp(item)
out_var.var_name = 'Psl_Ural'
elif var == 'pressure_sib':
out_var = calculate_slp(item)
out_var.var_name = 'Psl_Sib'
elif var == 'pressure_aleut':
out_var = calculate_slp(item)
out_var.var_name = 'Psl_Aleut'
elif var == 'bk_ice':
out_var = finalize_bk_ice(item)
elif var == 'ok_ice':
out_var = finalize_ok_ice(item)
elif var == 'heat_flux':
out_var = prepare_heat_flux(item)
else:
raise NotImplementedError(f"Variable '{var}' not supported")
return out_var


def calculate_variables(input_dict):
"""Calculate all necessary variables."""
logger.debug("Variables are calculated for the following datasources:%s",
input_dict.keys())
dictionary = {}
for key, value in input_dict.items():
logger.debug("Calculating final variables for %s dataset", key)
dictionary.setdefault(key, {})
tmp_list = []
for item in value:
if item['preprocessor'] == "heat_flux":
tmp_list.append(variable_cases(item['preprocessor'], item))
else:
dictionary[key].setdefault(
variable_cases(item['preprocessor'], item).var_name,
variable_cases(item['preprocessor'], item)
)

if key != "HadISST":
# Calculate heat flux for all data sources except HadISST
heat_flux = calculate_heat_flux(tmp_list)
dictionary[key].setdefault(heat_flux.var_name, heat_flux)
return dictionary


def plotting_support(cube, key, **kwargs):
"""Help for the pretty plot."""
if cube.coords('time', dim_coords=True):
ih.unify_time_coord(cube)
iris.quickplot.plot(cube, label=key, **kwargs)
plt.legend(loc="center left", bbox_to_anchor=(1, 0.5))
plt.ylabel("Anomalies, " + str(cube.units))
plt.title(f"Time series of monthly mean {cube.var_name.upper()} anomalies")
plt.xticks(rotation=45, ha="right", rotation_mode="anchor")


def plot_timeseries(dictionary, var, cfg):
"""Timeseries plot."""
fig = plt.figure(figsize=(10, 4))
sns.set_style('whitegrid')
colors = plt.cm.viridis(np.linspace(0, 1, len(dictionary.keys())))
baseplotname = f"Timeseries_{var}_anomalies"
filename = get_plot_filename(baseplotname, cfg)
for i, key in enumerate(dictionary.keys()):
if var not in ('BK_sic', 'Ok_sic'):
if key == "HadISST":
continue
if key != 'ERA5':
plotting_support(dictionary[key][var], key,
color=colors[i])
else:
plotting_support(dictionary[key][var], key,
color='k', linewidth=2)
else:
if key == "ERA5":
continue
if key != 'HadISST':
plotting_support(dictionary[key][var], key, color=colors[i])
else:
plotting_support(dictionary[key][var], key, color='blue',
linewidth=2)
fig.savefig(filename, bbox_inches='tight')


def main(cfg):
"""Calculate and save final variables into .nc files."""
my_files_dict = group_metadata(cfg['input_data'].values(), 'dataset')
all_variables = calculate_variables(my_files_dict)
# Check is timeseries should be plotted
if cfg['plot_timeseries'] is True:
plot_timeseries(all_variables, cfg['variable_to_plot'], cfg)
for key in my_files_dict:
logger.info("Processing final calculations in dataset %s", key)
prov_record = get_provenance_record([key])
diagnostic_file = get_diagnostic_filename(key, cfg)
with ProvenanceLogger(cfg) as provenance_logger:
provenance_logger.log(diagnostic_file, prov_record)
var = all_variables[key]
if key == "ERA5":
cube_list = iris.cube.CubeList([
var['PV'], var['Arctic_temperature'], var['Psl_Ural'],
var['Psl_Sib'], var['Psl_Aleut'], var['heat_flux']])
elif key == "HadISST":
cube_list = iris.cube.CubeList([
var['BK_sic'], var['Ok_sic']])
else:
cube_list = iris.cube.CubeList([
var['PV'], var['Arctic_temperature'], var['Psl_Ural'],
var['Psl_Sib'], var['Psl_Aleut'], var['heat_flux'],
var['BK_sic'], var['Ok_sic']])
save_data(diagnostic_file, prov_record, cfg, cube_list)
logger.info("%s data is saved in .nc", key)
logger.info("Done.")


if __name__ == '__main__':
with run_diagnostic() as config:
main(config)
Loading