Skip to content

Commit b129632

Browse files
committed
Add documentation for Wheeler-Kiladis diagnostic
1 parent 85cbe77 commit b129632

8 files changed

Lines changed: 177 additions & 63 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ __pycache__/
5656
# before PyInstaller builds the exe, so as to inject date/other infos into it.
5757
*.manifest
5858
*.spec
59+
5960
# Installer logs
6061
pip-log.txt
6162
pip-delete-this-directory.txt
@@ -73,6 +74,7 @@ coverage.xml
7374

7475
# Jupyter Notebook
7576
.ipynb_checkpoints
77+
7678
*.tmp
7779
*.orig
7880
/c
309 KB
Loading
323 KB
Loading
313 KB
Loading

doc/sphinx/source/recipes/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Atmosphere
6666
recipe_aod_aeronet_assess
6767
recipe_surface_trace_gas
6868
recipe_weathertyping
69+
recipe_wheeler_kiladis_diagnostic
6970

7071
Climate metrics
7172
^^^^^^^^^^^^^^^
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
.. _recipe_wheeler_kiladis_diagnostic:
2+
3+
Wheeler-Kiladis tropical wave spectra
4+
=====================================
5+
6+
Overview
7+
--------
8+
9+
This recipe computes normalized Wheeler-Kiladis wavenumber-frequency
10+
spectra for tropical precipitation and outgoing longwave radiation.
11+
12+
The diagnostic is intended to evaluate tropical wave variability,
13+
including Kelvin waves, equatorial Rossby waves, and broad intraseasonal
14+
variability such as the Madden-Julian Oscillation.
15+
16+
The recipe uses standard ESMValTool preprocessors to convert units,
17+
compute daily means, extract the tropical belt between 15S and 15N, and
18+
regrid the data to a regular latitude-longitude grid. The diagnostic then
19+
computes a cosine-latitude-weighted equatorial mean, removes leap days,
20+
removes the time mean, linear trend, and annual harmonics, optionally
21+
removes the zonal mean, computes two-dimensional Fourier spectra in time
22+
and longitude, estimates a smoothed background spectrum, and plots
23+
normalized spectra with optional shallow-water dispersion curves.
24+
25+
The diagnostic saves raw, background, and normalized Wheeler-Kiladis
26+
spectra as NetCDF files and records provenance information for both data
27+
outputs and figures.
28+
29+
Available recipes and diagnostics
30+
---------------------------------
31+
32+
Recipes are stored in ``esmvaltool/recipes/``:
33+
34+
* ``recipe_wheeler_kiladis_diagnostic.yml``
35+
36+
Diagnostics are stored in ``esmvaltool/diag_scripts/wheeler_kiladis/``:
37+
38+
* ``wheeler_kiladis.py``: ESMValTool wrapper for running the
39+
Wheeler-Kiladis diagnostic.
40+
* ``spectra.py``: utilities for preparing equatorial fields and
41+
computing wavenumber-frequency spectra.
42+
* ``plot.py``: plotting utilities for normalized Wheeler-Kiladis
43+
spectra and theoretical dispersion curves.
44+
45+
User settings in recipe
46+
-----------------------
47+
48+
#. Script ``wheeler_kiladis/wheeler_kiladis.py``
49+
50+
*Optional settings for script*
51+
52+
* ``annual_harmonics``: Number of annual harmonics removed during
53+
seasonal-cycle correction. Default: 3.
54+
55+
* ``remove_zonal_mean``: If ``True``, remove the zonal mean before
56+
the wavenumber-frequency transform. This emphasizes propagating
57+
equatorial disturbances. Default: ``True``.
58+
59+
* ``segment_length``: Length of each spectral segment in days.
60+
Default: 180.
61+
62+
* ``segment_overlap``: Overlap between consecutive spectral segments
63+
in days. Default: 90.
64+
65+
* ``sampling_frequency_per_day``: Sampling frequency of the input
66+
data in samples per day. For daily data, this should be 1.0.
67+
Default: 1.0.
68+
69+
* ``sigma_freq``: Gaussian smoothing width in the frequency direction
70+
used to estimate the background spectrum. Default: 4.0.
71+
72+
* ``sigma_wn``: Gaussian smoothing width in the zonal-wavenumber
73+
direction used to estimate the background spectrum. Default: 4.0.
74+
75+
* ``max_wavenumber``: Maximum zonal wavenumber shown in the plot.
76+
Default: 15.
77+
78+
* ``max_frequency``: Maximum frequency shown in the plot in cycles
79+
per day. Default: 0.5.
80+
81+
* ``period_ticks``: Periods in days shown as labels on the frequency
82+
axis. Default: ``[2, 3, 5, 10, 20, 30, 60, 100]``.
83+
84+
* ``equivalent_depths``: Equivalent depths in metres used to draw
85+
theoretical shallow-water dispersion curves. Default:
86+
``[8, 12, 25, 50]``.
87+
88+
* ``show_dispersion``: If ``True``, overlay theoretical Kelvin and
89+
equatorial Rossby wave dispersion curves. Default: ``True``.
90+
91+
* ``mask_zero_wavenumber``: If ``True``, mask the
92+
zonal-wavenumber-zero column in the normalized spectrum plot. This
93+
is useful when the zonal mean has been removed. Default: ``True``.
94+
95+
Variables
96+
---------
97+
98+
* pr (atmos, daily, longitude, latitude, time)
99+
* rlut (atmos, daily, longitude, latitude, time)
100+
101+
Example plots
102+
-------------
103+
104+
.. _wk_era5_pr_example:
105+
.. figure:: /recipes/figures/wheeler_kiladis/ERA5_pr_wk_normalized_example.png
106+
:align: center
107+
108+
Normalized Wheeler-Kiladis spectrum for ERA5 precipitation.
109+
110+
.. _wk_persiann_cdr_pr_example:
111+
.. figure:: /recipes/figures/wheeler_kiladis/PERSIANN-CDR_pr_wk_normalized_example.png
112+
:align: center
113+
114+
Normalized Wheeler-Kiladis spectrum for PERSIANN-CDR precipitation.
115+
116+
.. _wk_mpi_esm1_2_lr_rlut_example:
117+
.. figure:: /recipes/figures/wheeler_kiladis/MPI-ESM1-2-LR_rlut_wk_normalized_example.png
118+
:align: center
119+
120+
Normalized Wheeler-Kiladis spectrum for MPI-ESM1-2-LR outgoing
121+
longwave radiation.
122+
123+
References
124+
----------
125+
126+
* Wheeler, M. C. and Kiladis, G. N. (1999): Convectively Coupled
127+
Equatorial Waves: Analysis of Clouds and Temperature in the
128+
Wavenumber-Frequency Domain.
129+
* Kiladis, G. N. et al. (2009): Convectively Coupled Equatorial Waves.
130+
* Hannah et al. (2020): Evaluation of tropical variability using
131+
Wheeler-Kiladis-type spectra.

esmvaltool/diag_scripts/wheeler_kiladis/wheeler_kiladis.py

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,59 +31,63 @@
3131
remove_zonal_mean : bool, optional
3232
Remove the zonal mean prior to spectral analysis. This is
3333
commonly done in Wheeler-Kiladis diagnostics to emphasize
34-
propagating equatorial wave signals.
34+
propagating equatorial wave signals. Default: True.
3535
3636
segment_length : int, optional
3737
Length of each spectral segment [days]. The default value of
38-
180 days is widely used in Wheeler-Kiladis analyses and
38+
180 days is commonly used in Wheeler-Kiladis analyses and
3939
provides a balance between frequency resolution and statistical
4040
sampling.
4141
4242
segment_overlap : int, optional
43-
Overlap between consecutive segments [days]. A value of
44-
90 days corresponds to 50% overlap and increases the number
43+
Overlap between consecutive segments [days]. The default value
44+
of 90 days corresponds to 50% overlap and increases the number
4545
of spectra contributing to the ensemble average.
4646
4747
sampling_frequency_per_day : float, optional
4848
Sampling frequency of the input data [samples day^-1].
49-
Daily data correspond to a value of 1.0.
49+
The default value is 1.0, corresponding to daily data.
5050
5151
sigma_freq : float, optional
5252
Gaussian smoothing width in the frequency direction used
5353
for background-spectrum estimation. The default value of
54-
4.0 provides a smoothly varying background spectrum suitable
55-
for normalization.
54+
4.0 provides sufficient smoothing to represent the broad
55+
spectral background while retaining its large-scale structure.
5656
5757
sigma_wn : float, optional
5858
Gaussian smoothing width in the zonal-wavenumber direction
5959
used for background-spectrum estimation. The default value
60-
of 4.0 provides adequate smoothing while preserving the
61-
large-scale spectral envelope.
60+
of 4.0 provides a smoothly varying background spectrum
61+
suitable for normalization while preserving the large-scale
62+
spectral envelope.
6263
6364
max_wavenumber : int, optional
64-
Maximum zonal wavenumber shown in diagnostic plots.
65+
Maximum zonal wavenumber displayed in diagnostic plots.
66+
Default: 15.
6567
6668
max_frequency : float, optional
67-
Maximum frequency shown in diagnostic plots [cycles day^-1].
69+
Maximum frequency displayed in diagnostic plots
70+
[cycles day^-1]. Default: 0.5.
6871
6972
period_ticks : list of int, optional
70-
Period values [days] displayed on the frequency axis of the
71-
diagnostic plots.
73+
Periods [days] shown as labels on the frequency axis.
74+
Default: [2, 3, 5, 10, 20, 30, 60, 100].
7275
7376
equivalent_depths : list of float, optional
7477
Equivalent depths [m] used to draw theoretical shallow-water
75-
dispersion curves. Typical values are 8, 12, 25 and 50 m,
76-
which span the range commonly associated with convectively
77-
coupled equatorial waves.
78+
dispersion curves. The default values [8, 12, 25, 50] span
79+
the range commonly associated with convectively coupled
80+
equatorial waves.
7881
7982
show_dispersion : bool, optional
8083
If True, overlay theoretical Kelvin and equatorial Rossby
81-
wave dispersion curves on the normalized WK spectrum.
84+
wave dispersion curves on the normalized Wheeler-Kiladis
85+
spectrum. Default: True.
8286
8387
mask_zero_wavenumber : bool, optional
84-
Mask the zonal wavenumber zero column in the normalized
85-
spectrum plot. This is often useful when the zonal mean
86-
has been removed.
88+
If True, mask the zonal-wavenumber-zero column in the
89+
normalized spectrum plot. This is often useful when the
90+
zonal mean has been removed. Default: True.
8791
8892
Outputs
8993
-------
@@ -169,9 +173,9 @@ def _process_regular_dataset(cfg, attrs):
169173

170174
raw, background, normalized = compute_wk_spectra(
171175
data_anom,
172-
segment_length=cfg["segment_length"],
173-
segment_overlap=cfg["segment_overlap"],
174-
samples_per_day=cfg["sampling_frequency_per_day"],
176+
segment_length=cfg.get("segment_length", 180),
177+
segment_overlap=cfg.get("segment_overlap", 90),
178+
samples_per_day=cfg.get("sampling_frequency_per_day", 1.0),
175179
sigma_freq=cfg.get("sigma_freq", 4.0),
176180
sigma_wn=cfg.get("sigma_wn", 4.0),
177181
)
@@ -198,37 +202,36 @@ def _make_method_caption(cfg, attrs, label):
198202
"""Create a method caption describing WK settings."""
199203
dataset = attrs.get("dataset", label)
200204

201-
start_year = attrs.get(
202-
"start_year",
203-
cfg.get("start_year", "unknown"),
204-
)
205+
start_year = attrs.get("start_year")
206+
end_year = attrs.get("end_year")
205207

206-
end_year = attrs.get(
207-
"end_year",
208-
cfg.get("end_year", "unknown"),
209-
)
208+
caption = f"Wheeler-Kiladis spectrum for {dataset}. "
209+
210+
if start_year is not None and end_year is not None:
211+
caption += f"Period: {start_year}-{end_year}. "
210212

211-
caption = (
212-
f"Wheeler-Kiladis spectrum for {dataset}. "
213-
f"Period: {start_year}-{end_year}. "
213+
caption += (
214214
"Region: 15S-15N, all longitudes. "
215215
"Data are converted to daily means and equatorially averaged. "
216216
f"Anomalies are computed after removing the time mean, linear trend, "
217217
f"and the first {cfg.get('annual_harmonics', 3)} annual harmonics. "
218218
)
219219

220220
if cfg.get("remove_zonal_mean", True):
221-
caption += "The zonal mean is removed before the wavenumber-frequency transform. "
221+
caption += (
222+
"The zonal mean is removed before the "
223+
"wavenumber-frequency transform. "
224+
)
222225

223226
caption += (
224-
f"Spectra are computed using {cfg['segment_length']}-day windows "
225-
f"with {cfg['segment_overlap']}-day overlap. "
226-
f"Background normalization uses Gaussian smoothing with "
227+
f"Spectra are computed using "
228+
f"{cfg.get('segment_length', 180)}-day windows "
229+
f"with {cfg.get('segment_overlap', 90)}-day overlap. "
230+
"Background normalization uses Gaussian smoothing with "
227231
f"sigma_freq={cfg.get('sigma_freq', 4.0)} and "
228232
f"sigma_wn={cfg.get('sigma_wn', 4.0)}. "
229233
"Positive zonal wavenumber denotes eastward propagation."
230234
)
231-
232235
return caption
233236

234237

esmvaltool/recipes/recipe_wheeler_kiladis_diagnostic.yml

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,6 @@ documentation:
3232
YEARS: &years
3333
timerange: 2001/2002
3434

35-
SCRIPT_YEARS: &script_years
36-
start_year: 2001
37-
end_year: 2002
38-
39-
4035
preprocessors:
4136
wk_tropics_pr:
4237
convert_units:
@@ -74,8 +69,6 @@ preprocessors:
7469
scheme: linear
7570

7671

77-
78-
7972
diagnostics:
8073

8174
wheeler_kiladis_pr:
@@ -111,18 +104,13 @@ diagnostics:
111104
main:
112105
script: wheeler_kiladis/wheeler_kiladis.py
113106

114-
variable: pr
115-
116-
latitude_bounds: [-15., 15.]
117-
lon_resolution: 2.5
118-
119107
segment_length: 180
120108
segment_overlap: 90
121109
sampling_frequency_per_day: 1.0
122110

123111
annual_harmonics: 3
124112
remove_zonal_mean: true
125-
mask_zero_wavenumber: true
113+
mask_zero_wavenumber: false
126114

127115
sigma_freq: 4.0
128116
sigma_wn: 4.0
@@ -133,9 +121,6 @@ diagnostics:
133121
equivalent_depths: [8, 12, 25, 50]
134122
show_dispersion: true
135123

136-
normalized_vmin: 0.0
137-
normalized_vmax: 4.0
138-
139124

140125
wheeler_kiladis_rlut:
141126
title: Wheeler-Kiladis spectra of tropical outgoing longwave radiation
@@ -168,11 +153,6 @@ diagnostics:
168153
main:
169154
script: wheeler_kiladis/wheeler_kiladis.py
170155

171-
variable: rlut
172-
173-
latitude_bounds: [-15., 15.]
174-
lon_resolution: 2.5
175-
176156
segment_length: 180
177157
segment_overlap: 90
178158
sampling_frequency_per_day: 1.0
@@ -189,6 +169,3 @@ diagnostics:
189169
period_ticks: [2, 3, 5, 10, 20, 30, 60, 100]
190170
equivalent_depths: [8, 12, 25, 50]
191171
show_dispersion: true
192-
193-
normalized_vmin: 0.0
194-
normalized_vmax: 4.0

0 commit comments

Comments
 (0)