Skip to content

Commit e2435c3

Browse files
committed
Ensured debiased SDM values are interpolated onto the number of expected rain days and not filtered. Added test to catch this
1 parent d498eb4 commit e2435c3

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

ibicus/debias/_scaled_distribution_mapping.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,13 @@ def _apply_on_window_relative_sdm(self, obs, cm_hist, cm_future):
338338
# Step 6
339339

340340
bc_initial = self.distribution.ppf(cdf_scaled, *fit_rainy_days_obs) * scaling
341+
bc_initial_scaled = interp_sorted_cdf_vals_on_given_length(
342+
bc_initial, expected_nr_rainy_days_cm_future
343+
)
341344
cm_future[: cm_future.size - expected_nr_rainy_days_cm_future] = 0
342-
cm_future[cm_future.size - expected_nr_rainy_days_cm_future :] = bc_initial[
343-
bc_initial.size - expected_nr_rainy_days_cm_future :
344-
]
345+
cm_future[cm_future.size - expected_nr_rainy_days_cm_future :] = (
346+
bc_initial_scaled
347+
)
345348

346349
# Step 7
347350
reverse_sorting_idx = np.argsort(argsort_cm_future)

tests/test_handling_and_trend_preservation_all_debiasers.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import unittest
1414

1515
import numpy as np
16+
import scipy.stats
1617

1718
from ibicus.debias import (
1819
ECDFM,
@@ -181,3 +182,67 @@ def test_trend_preservation_pr(self):
181182
)
182183
< 0.5
183184
)
185+
186+
def test_perfect_match_tas(self):
187+
debiasers = [
188+
QuantileMapping.from_variable("tas", running_window_mode=False),
189+
QuantileDeltaMapping.from_variable(
190+
"tas",
191+
running_window_mode=False,
192+
running_window_mode_over_years_of_cm_future=False,
193+
),
194+
CDFt.from_variable(
195+
"tas",
196+
running_window_mode=False,
197+
running_window_mode_over_years_of_cm_future=False,
198+
),
199+
ScaledDistributionMapping.from_variable("tas", running_window_mode=False),
200+
ISIMIP.from_variable("tas", running_window_mode=False),
201+
ECDFM.from_variable("tas", running_window_mode=False),
202+
]
203+
for debiaser in debiasers:
204+
n = 10000
205+
np.random.seed(1234)
206+
for mean_obs in [270]:
207+
for scale_obs in [20.0, 30.0]:
208+
for bias in [0, 2, 10]:
209+
for scale_bias in [1.0, 2.0]:
210+
obs = np.random.normal(size=n) * scale_obs + mean_obs
211+
cm_hist = (
212+
np.random.normal(size=n) * scale_obs * scale_bias
213+
+ mean_obs
214+
+ bias
215+
)
216+
217+
deb = debiaser.apply_location(obs, cm_hist, cm_hist)
218+
assert scipy.stats.kstest(obs, deb).pvalue > 0.05
219+
220+
def test_perfect_match_pr(self):
221+
debiasers = [
222+
QuantileMapping.from_variable("pr", running_window_mode=False),
223+
CDFt.from_variable(
224+
"pr",
225+
running_window_mode=False,
226+
running_window_mode_over_years_of_cm_future=False,
227+
),
228+
ScaledDistributionMapping.from_variable("pr", running_window_mode=False),
229+
ISIMIP.from_variable("pr", running_window_mode=False),
230+
ECDFM.from_variable("pr", running_window_mode=False),
231+
]
232+
233+
def generate_pr(size, prop_zeros=0.3):
234+
arr = np.zeros(size)
235+
arr[int(arr.size * prop_zeros) :] = scipy.stats.gamma(5, 1).rvs(
236+
size=arr.size - int(arr.size * prop_zeros)
237+
)
238+
np.random.shuffle(arr)
239+
return arr
240+
241+
for debiaser in debiasers:
242+
n = 10000
243+
np.random.seed(1234)
244+
for mult_bias in [1, 1.1, 1.25, 1.5, 2.0, 5.0]:
245+
obs = generate_pr(n)
246+
cm_hist = generate_pr(n) * mult_bias
247+
deb = debiaser.apply_location(obs, cm_hist, cm_hist)
248+
assert scipy.stats.kstest(obs, deb).pvalue > 0.05

0 commit comments

Comments
 (0)