def test_quantiles(self, series, kind, name): """Train on hist: U ref: Normal Predict on hist to get ref """ ns = 10000 u = np.random.rand(ns) # Define distributions xd = uniform(loc=10, scale=1) yd = norm(loc=12, scale=1) # Generate random numbers with u so we get exact results for comparison x = xd.ppf(u) y = yd.ppf(u) # Test train hist = sim = series(x, name) ref = series(y, name) DQM = DetrendedQuantileMapping(kind=kind, group="time", nquantiles=50, interp="linear") DQM.train(ref, hist) p = DQM.adjust(sim) q = DQM.ds.quantiles ex = apply_correction(xd.ppf(q), invert(xd.mean(), kind), kind) ey = apply_correction(yd.ppf(q), invert(yd.mean(), kind), kind) expected = get_correction(ex, ey, kind) # Results are not so good at the endpoints np.testing.assert_array_almost_equal(DQM.ds.af[2:-2], expected[2:-2], 1) # Test predict # Accept discrepancies near extremes middle = (x > 1e-2) * (x < 0.99) np.testing.assert_array_almost_equal(p[middle], ref[middle], 1) # Test with simure not equal to hist ff = series(np.ones(ns) * 1.1, name) sim2 = apply_correction(sim, ff, kind) ref2 = apply_correction(ref, ff, kind) p2 = DQM.adjust(sim2) np.testing.assert_array_almost_equal(p2[middle], ref2[middle], 1) # Test with actual trend in sim trend = series( np.linspace(-0.2, 0.2, ns) + (1 if kind == MULTIPLICATIVE else 0), name) sim3 = apply_correction(sim, trend, kind) ref3 = apply_correction(ref, trend, kind) p3 = DQM.adjust(sim3) np.testing.assert_array_almost_equal(p3[middle], ref3[middle], 1)
def test_mon_U(self, mon_series, series, mon_triangular, add_dims, kind, name, use_dask): """ Train on hist: U ref: U + monthly cycle Predict on hist to get ref """ u = np.random.rand(10000) # Define distributions xd = uniform(loc=1, scale=1) yd = uniform(loc=2, scale=2) noise = uniform(loc=0, scale=1e-7) # Generate random numbers x = xd.ppf(u) y = yd.ppf(u) + noise.ppf(u) # Test train ref = mon_series(y, name) hist = sim = series(x, name) if use_dask: ref = ref.chunk({"time": -1}) hist = hist.chunk({"time": -1}) sim = sim.chunk({"time": -1}) if add_dims: ref = ref.expand_dims(site=[0, 1, 2, 3, 4]).drop_vars("site") hist = hist.expand_dims(site=[0, 1, 2, 3, 4]).drop_vars("site") sim = sim.expand_dims(site=[0, 1, 2, 3, 4]).drop_vars("site") sel = {"site": 0} else: sel = {} QDM = QuantileDeltaMapping.train(ref, hist, kind=kind, group="time.month", nquantiles=40) p = QDM.adjust(sim, interp="linear" if kind == "+" else "nearest") q = QDM.ds.coords["quantiles"] expected = get_correction(xd.ppf(q), yd.ppf(q), kind) expected = apply_correction(mon_triangular[:, np.newaxis], expected[np.newaxis, :], kind) np.testing.assert_array_almost_equal(QDM.ds.af.sel(quantiles=q, **sel), expected, 1) # Test predict np.testing.assert_allclose(p, ref.transpose(*p.dims), rtol=0.1, atol=0.2)
def test_quantiles(self, series, kind, name): """Train on x : U(1,1) y : U(1,2) """ u = np.random.rand(10000) # Define distributions xd = uniform(loc=1, scale=1) yd = uniform(loc=2, scale=4) # Generate random numbers with u so we get exact results for comparison x = xd.ppf(u) y = yd.ppf(u) # Test train hist = sim = series(x, name) ref = series(y, name) QDM = QuantileDeltaMapping.train( ref.astype("float32"), hist.astype("float32"), kind=kind, group="time", nquantiles=10, ) p = QDM.adjust(sim.astype("float32"), interp="linear") q = QDM.ds.coords["quantiles"] expected = get_correction(xd.ppf(q), yd.ppf(q), kind)[np.newaxis, :] # Results are not so good at the endpoints np.testing.assert_array_almost_equal(QDM.ds.af, expected, 1) # Test predict # Accept discrepancies near extremes middle = (u > 1e-2) * (u < 0.99) np.testing.assert_array_almost_equal(p[middle], ref[middle], 1) # Test dtype control of map_blocks assert QDM.ds.af.dtype == "float32" assert p.dtype == "float32"
def test_quantiles(self, series, kind, name): """Train on hist: U ref: Normal Predict on hist to get ref """ u = np.random.rand(10000) # Define distributions xd = uniform(loc=10, scale=1) yd = norm(loc=12, scale=1) # Generate random numbers with u so we get exact results for comparison x = xd.ppf(u) y = yd.ppf(u) # Test train hist = sim = series(x, name) ref = series(y, name) QM = EmpiricalQuantileMapping.train( ref, hist, kind=kind, group="time", nquantiles=50, ) p = QM.adjust(sim, interp="linear") q = QM.ds.coords["quantiles"] expected = get_correction(xd.ppf(q), yd.ppf(q), kind)[np.newaxis, :] # Results are not so good at the endpoints np.testing.assert_array_almost_equal(QM.ds.af[:, 2:-2], expected[:, 2:-2], 1) # Test predict # Accept discrepancies near extremes middle = (x > 1e-2) * (x < 0.99) np.testing.assert_array_almost_equal(p[middle], ref[middle], 1)
def test_interp_on_quantiles_monthly(): t = xr.cftime_range("2000-01-01", "2030-12-31", freq="D", calendar="noleap") ref = xr.DataArray( (-20 * np.cos(2 * np.pi * t.dayofyear / 365) + 2 * np.random.random_sample((t.size, )) + 273.15 + 0.1 * (t - t[0]).days / 365), # "warming" of 1K per decade, dims=("time", ), coords={"time": t}, attrs={"units": "K"}, ) sim = xr.DataArray( (-18 * np.cos(2 * np.pi * t.dayofyear / 365) + 2 * np.random.random_sample((t.size, )) + 273.15 + 0.11 * (t - t[0]).days / 365), # "warming" of 1.1K per decade dims=("time", ), coords={"time": t}, attrs={"units": "K"}, ) ref = ref.sel(time=slice(None, "2015-01-01")) hist = sim.sel(time=slice(None, "2015-01-01")) group = Grouper("time.month") quantiles = u.equally_spaced_nodes(15, eps=1e-6) ref_q = group.apply(nbu.quantile, ref, main_only=True, q=quantiles) hist_q = group.apply(nbu.quantile, hist, main_only=True, q=quantiles) af = u.get_correction(hist_q, ref_q, "+") for interp in ["nearest", "linear", "cubic"]: afi = u.interp_on_quantiles(sim, hist_q, af, group="time.month", method=interp, extrapolation="constant") assert afi.isnull().sum("time") == 0, interp
def test_mon_U(self, mon_series, series, mon_triangular, kind, name): """ Train on hist: U ref: U + monthly cycle Predict on hist to get ref """ u = np.random.rand(10000) # Define distributions xd = uniform(loc=1, scale=1) yd = uniform(loc=2, scale=2) noise = uniform(loc=0, scale=1e-7) # Generate random numbers x = xd.ppf(u) y = yd.ppf(u) + noise.ppf(u) # Test train hist = sim = series(x, name) ref = mon_series(y, name) QDM = QuantileDeltaMapping(kind=kind, group="time.month", nquantiles=40) QDM.train(ref, hist) p = QDM.adjust(sim) q = QDM.ds.coords["quantiles"] expected = get_correction(xd.ppf(q), yd.ppf(q), kind) expected = apply_correction(mon_triangular[:, np.newaxis], expected[np.newaxis, :], kind) np.testing.assert_array_almost_equal(QDM.ds.af.sel(quantiles=q), expected, 1) # Test predict np.testing.assert_array_almost_equal(p, ref, 1)