Skip to content

Commit f48ae8e

Browse files
Update weighted ensemble example
Use newly implemented cap to bias correction offsets.
1 parent 8a82a2f commit f48ae8e

File tree

5 files changed

+25
-12
lines changed

5 files changed

+25
-12
lines changed
9.98 KB
Loading
-3.1 KB
Loading
-87 Bytes
Loading

docs/src/examples/ensembles/weighted_ensembles.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ low flows as with GR4J.
8686

8787
![](../../assets/ensemble_model_comparison_quickplots.png)
8888

89-
Comparing the temporal cross section:
89+
Comparing the temporal cross section to get an idea of seasonality:
9090

9191
```julia
9292
ihacres_xs = temporal_cross_section(burn_dates, burn_obs, ihacres_node.outflow[burn_in:end]; title="IHACRES", yscale=:log10)
@@ -101,10 +101,11 @@ A reduction in the median error can be seen with extreme errors reduced somewhat
101101
![](../../assets/ensemble_xsection.png)
102102

103103
The median error can then be applied to modelled streamflow (on a month-day basis) as a
104-
form of bias correction.
104+
form of bias correction. Here, the correction factor is capped to -80% and +40% of predicted
105+
outflows.
105106

106107
```julia
107-
q_star = Streamfall.apply_temporal_correction(ensemble, climate, Qo[:, "410730"])
108+
q_star = Streamfall.apply_temporal_correction(ensemble, climate, Qo[:, "410730"]; low_cap=0.8, high_cap=0.4)
108109

109110
bc_ensemble_qp = quickplot(burn_obs, q_star[burn_in:end], climate; label="Bias Corrected Ensemble", log=true)
110111

@@ -116,16 +117,17 @@ bias_corrected_xs = temporal_cross_section(
116117
yscale=:log10
117118
)
118119

119-
plot(bc_ensemble_qp, bias_corrected_xs; layout=(2,1), size=(800, 800))
120+
ens_qp = plot(bc_ensemble_qp, bias_corrected_xs; layout=(2,1), size=(800, 800))
120121
```
121122

122-
While the median error has increased, its variance has reduced significantly. At the same
123-
time, performance at the 75 and 95% CI remain steady relative to the original weighted
124-
ensemble results.
123+
It can be seen here that low flows are better represented, with a commensurate decrease
124+
in median error (and its variance). At the same time, performance at the 75 and 95% CI
125+
remain steady relative to the original weighted ensemble results.
125126

126127
![](../../assets/ensemble_bias_corrected.png)
127128

128129
This ensemble approach may be improved further by:
129130

130131
- Using a rolling window to smooth ensemble predictions
131132
- Defining a custom objective function to target specific conditions
133+
- Using more advanced ensemble approaches other than the simple weighted mean approach

src/Nodes/Ensembles/WeightedEnsembleNode.jl

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import ..Analysis: TemporalCrossSection
1+
import ..Analysis: TemporalCrossSection, offsets
22

33
Base.@kwdef mutable struct WeightedEnsembleNode{N<:NetworkNode,P,A<:Real} <: EnsembleNode
44
name::String
@@ -177,20 +177,31 @@ end
177177
apply_temporal_correction(
178178
ensemble::WeightedEnsembleNode,
179179
climate::Climate,
180-
obs::Vector{T}
180+
obs::Vector{T};
181+
low_cap::Float64=1.0,
182+
high_cap::Float64=1.0
181183
) where {T<:Real}
182184
183185
Correct for model bias using median error.
186+
By default, the correction is capped to ± 100% of model prediction modified by
187+
`low_cap` and `high_cap`
184188
"""
185189
function apply_temporal_correction(
186190
ensemble::WeightedEnsembleNode,
187191
climate::Climate,
188-
obs::Vector{T}
189-
) where {T<:Real}
192+
obs::Vector{Float64};
193+
low_cap::Float64=1.0,
194+
high_cap::Float64=1.0
195+
)
196+
low_cap = clamp(low_cap, 0.0, 1.0)
197+
high_cap = clamp(high_cap, 0.0, 1.0)
198+
190199
dates = timesteps(climate)
191200
tcs = TemporalCrossSection(dates, obs, ensemble.outflow)
192201

193-
return max.(ensemble.outflow .+ Streamfall.Analysis.offsets(tcs), 0.0)
202+
x = min.(ensemble.outflow .+ offsets(tcs), ensemble.outflow .* (1.0 + high_cap))
203+
204+
return max.(x, ensemble.outflow .* (1.0 - low_cap))
194205
end
195206

196207
"""

0 commit comments

Comments
 (0)