Skip to content

Commit efeb78b

Browse files
committed
Revise cloud cover example
1 parent fb69e18 commit efeb78b

File tree

1 file changed

+37
-8
lines changed

1 file changed

+37
-8
lines changed

docs/source/examples/cloud_cover.py

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
# # Correlation Time Analysis of Cloud Cover Data
33
#
44
# This example is inspired by the work of P. A. Jones {cite:p}`jones_1992_cloudcover`
5-
# on the analysis of time (and spatial) correlations in cloud cover data.
6-
# Jones observed an exponential decay of the time correlation function,
5+
# on the analysis of temporal (and spatial) correlations in cloud cover data.
6+
# Jones observed an exponential decay of the autocorrelation function,
77
# with half-life times ranging from 5 to 40 hours.
88
#
99
# Here, we analyze a time series of cloud cover data obtained from
@@ -38,7 +38,7 @@
3838
# %% [markdown]
3939
# ## Cloud Cover Data
4040
#
41-
# Cloud cover is expressed here as a fraction of the sky covered by clouds,
41+
# In this example, cloud cover is expressed as the fraction of the sky covered by clouds,
4242
# ranging from 0 (clear sky) to 1 (completely overcast).
4343

4444
# %%
@@ -98,7 +98,7 @@ def plot_histogram():
9898
plot_histogram()
9999

100100
# %% [markdown]
101-
# This histogram reflects the typical weather patterns in Belgium,
101+
# This histogram reflects the typical weather pattern in Belgium,
102102
# with plenty of cloudy days.
103103
# This is also reflected in the normalized standard deviation (NS),
104104
# as defined by Jones {cite:p}`jones_1992_cloudcover`:
@@ -121,19 +121,33 @@ def plot_histogram():
121121
#
122122
# Before applying STACIE to the data, let's first compute and plot the
123123
# autocorrelation function (ACF) directly.
124+
#
125+
# Mind the normalization: due to the zero padding in `np.correlate`,
126+
# the number of terms contributing to the ACF decreases with lag time.
127+
# Furthermore, the ACF is not normalized to 1 in this plot,
128+
# as we want to keep the amplitude information.
124129

125130

126131
# %%
132+
AMP_EXP = 0.0347 # From STACIE Lorentz B parameter, see below.
133+
TAU_EXP = 57.6 # From STACIE corrtime_exp, see below.
134+
135+
127136
def plot_acf():
128137
plt.close("acf")
129138
_, ax = plt.subplots(num="acf")
130139
delta = cover - np.mean(cover)
131140
acf = np.correlate(delta, delta, mode="same")
132141
nkeep = acf.size // 2
133142
acf = acf[nkeep:] / (len(acf) - np.arange(nkeep))
134-
acf /= acf[0]
135143
time = np.arange(240)
136144
ax.plot(time, acf[:240], "C0-")
145+
ax.plot(
146+
time,
147+
AMP_EXP * np.exp(-time / TAU_EXP),
148+
"C1--",
149+
label=r"exp(-t/\tau_\mathrm{exp})",
150+
)
137151
xticks = np.arange(0, 241, 24)
138152
ax.set_xlim(-1, 240)
139153
ax.set_xticks(xticks)
@@ -150,9 +164,14 @@ def plot_acf():
150164
# resulting in weak correlations at multiples of 24 hours.
151165
# Superimposed on these diurnal effects,
152166
# an overall exponential decay of the ACF can be observed.
153-
# However, it is difficult to fit an exponential function to the ACF due to the ripples.
154-
# Although the conventional approach of fitting an exponential decay curve provides a rough estimate,
155-
# we will use STACIE instead to perform a more robust analysis of the correlation time.
167+
# However, it is difficult to fit an exponential function to the ACF
168+
# due to (i) the ripples and (ii) non-exponential short-time effects.
169+
# Hence, fitting an exponential function can at best provide
170+
# a rough estimate of the correlation time.
171+
172+
# Below, it is shown how to use STACIE instead to perform a more robust analysis.
173+
# The exponential decay shown in the plot is derived from STACIE's output below.
174+
# It is only expected to be representative at long lag times.
156175

157176
# %% [markdown]
158177
# ## Autocorrelation Time
@@ -185,6 +204,16 @@ def plot_acf():
185204
# The exponential correlation time, which is about 60 hours,
186205
# is the longest because it captures the slowest relaxation process.
187206
# The integrated correlation time is notably shorter at about 20 hours.
207+
#
208+
# In the code below, we also derive the $B$ parameter of the Lorentz model,
209+
# which has been used to plot the exponential decay in the ACF above.
210+
211+
# %%
212+
pars = result.props["pars"]
213+
tau_exp = result.corrtime_exp
214+
amp_exp = (pars[0] - pars[1] / pars[2]) / (2 * tau_exp)
215+
print(f"TAU_EXP = {tau_exp:.4f} h")
216+
print(f"AMP_EXP = {amp_exp:.4f}")
188217

189218
# %% [markdown]
190219
# The plots below show the fitted spectrum and additional diagnostics.

0 commit comments

Comments
 (0)