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 hist = sim = series(x, name) if use_dask: sim = sim.chunk({"time": -1}) if add_dims: hist = hist.expand_dims(site=[0, 1, 2, 3, 4]) sim = sim.expand_dims(site=[0, 1, 2, 3, 4]) sel = {"site": 0} else: sel = {} ref = mon_series(y, name) QDM = QuantileDeltaMapping(kind=kind, group="time.month", nquantiles=40) QDM.train(ref, hist) 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.isel(**sel), ref, rtol=0.1, atol=0.2)
def test_cannon(self, cannon_2015_dist, cannon_2015_rvs): ref, hist, sim = cannon_2015_rvs(15000, random=False) # Quantile mapping QDM = QuantileDeltaMapping(kind="*", group="time", nquantiles=50) QDM.train(ref, hist) bc_sim = QDM.adjust(sim) # Theoretical results # ref, hist, sim = cannon_2015_dist # u1 = equally_spaced_nodes(1001, None) # u = np.convolve(u1, [0.5, 0.5], mode="valid") # pu = ref.ppf(u) * sim.ppf(u) / hist.ppf(u) # pu1 = ref.ppf(u1) * sim.ppf(u1) / hist.ppf(u1) # pdf = np.diff(u1) / np.diff(pu1) # mean = np.trapz(pdf * pu, pu) # mom2 = np.trapz(pdf * pu ** 2, pu) # std = np.sqrt(mom2 - mean ** 2) np.testing.assert_almost_equal(bc_sim.mean(), 41.5, 1) np.testing.assert_almost_equal(bc_sim.std(), 16.7, 0)
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)
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( kind=kind, group="time", nquantiles=10, ) QDM.train(ref, hist) p = QDM.adjust(sim, interp="linear") q = QDM.ds.coords["quantiles"] expected = get_correction(xd.ppf(q), yd.ppf(q), kind) # Results are not so good at the endpoints np.testing.assert_array_almost_equal(QDM.ds.af.T, 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)