def test_mon_U(self, mon_series, series, kind, name, add_dims): """ Train on hist: U ref: U + monthly cycle Predict on hist to get ref """ n = 5000 u = np.random.rand(n) # Define distributions xd = uniform(loc=2, scale=0.1) yd = uniform(loc=4, scale=0.1) noise = uniform(loc=0, scale=1e-7) # Generate random numbers x = xd.ppf(u) y = yd.ppf(u) + noise.ppf(u) # Test train hist, ref = series(x, name), mon_series(y, name) trend = np.linspace(-0.2, 0.2, n) + int(kind == MULTIPLICATIVE) ref_t = mon_series(apply_correction(y, trend, kind), name) sim = series(apply_correction(x, trend, kind), name) if add_dims: ref = ref.expand_dims(lat=[0, 1, 2]).chunk({"lat": 1}) hist = hist.expand_dims(lat=[0, 1, 2]).chunk({"lat": 1}) sim = sim.expand_dims(lat=[0, 1, 2]).chunk({"lat": 1}) ref_t = ref_t.expand_dims(lat=[0, 1, 2]) DQM = DetrendedQuantileMapping.train(ref, hist, kind=kind, group="time.month", nquantiles=5) mqm = DQM.ds.af.mean(dim="quantiles") p = DQM.adjust(sim) if add_dims: mqm = mqm.isel(lat=0) np.testing.assert_array_almost_equal(mqm, int(kind == MULTIPLICATIVE), 1) np.testing.assert_allclose(p.transpose(..., "time"), ref_t, rtol=0.1, atol=0.5)
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=2, scale=0.1) yd = uniform(loc=4, scale=0.1) 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) QM = EmpiricalQuantileMapping(kind=kind, group="time.month", nquantiles=5) QM.train(ref, hist) p = QM.adjust(sim) mqm = QM.ds.af.mean(dim="quantiles") expected = apply_correction(mon_triangular, 2, kind) np.testing.assert_array_almost_equal(mqm, expected, 1) # Test predict np.testing.assert_array_almost_equal(p, ref, 2)
def _mon_series(values, name): """Random time series whose mean varies over a monthly cycle.""" x = series(values, name) m = mon_triangular factor = series(m[x.time.dt.month - 1], name) with xr.set_options(keep_attrs=True): return apply_correction(x, factor, x.kind)
def test_mon_U(self, mon_series, series, mon_triangular, kind, name, spatial_dims): """ Train on hist: U ref: U + monthly cycle Predict on hist to get ref """ n = 10000 u = np.random.rand(n) # Define distributions xd = uniform(loc=2, scale=0.1) yd = uniform(loc=4, scale=0.1) noise = uniform(loc=0, scale=1e-7) # Generate random numbers x = xd.ppf(u) y = yd.ppf(u) + noise.ppf(u) # Test train hist, ref = series(x, name), mon_series(y, name) trend = np.linspace(-0.2, 0.2, n) + int(kind == MULTIPLICATIVE) ref_t = mon_series(apply_correction(y, trend, kind), name) sim = series(apply_correction(x, trend, kind), name) if spatial_dims: hist = hist.expand_dims(**spatial_dims) ref = ref.expand_dims(**spatial_dims) sim = sim.expand_dims(**spatial_dims) ref_t = ref_t.expand_dims(**spatial_dims) DQM = DetrendedQuantileMapping(kind=kind, group="time.month", nquantiles=5) DQM.train(ref, hist) mqm = DQM.ds.af.mean(dim="quantiles") p = DQM.adjust(sim) if spatial_dims: mqm = mqm.isel({crd: 0 for crd in spatial_dims.keys()}) np.testing.assert_array_almost_equal(mqm, int(kind == MULTIPLICATIVE), 1) np.testing.assert_array_almost_equal(p, ref_t, 1)
def test_mon_U(self, mon_series, series, mon_triangular, kind, name): n = 10000 u = np.random.rand(n) xd = uniform(loc=2, scale=1) x = xd.ppf(u) hist = sim = series(x, name) ref = mon_series(apply_correction(x, 2, kind), name) # Test train scaling = Scaling.train(ref, hist, group="time.month", kind=kind) expected = apply_correction(mon_triangular, 2, kind) np.testing.assert_array_almost_equal(scaling.ds.af, expected) # Test predict p = scaling.adjust(sim) np.testing.assert_array_almost_equal(p, ref)
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 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_time(self, kind, name, series): n = 10000 u = np.random.rand(n) xd = uniform(loc=2, scale=1) x = xd.ppf(u) hist = sim = series(x, name) ref = series(apply_correction(x, 2, kind), name) scaling = Scaling(group="time", kind=kind) scaling.train(ref, hist) np.testing.assert_array_almost_equal(scaling.ds.af, 2) p = scaling.adjust(sim) np.testing.assert_array_almost_equal(p, ref)
def test_add_dim(self, series, mon_series): n = 10000 u = np.random.rand(n, 4) xd = uniform(loc=2, scale=1) x = xd.ppf(u) hist = sim = series(x, "tas") ref = mon_series(apply_correction(x, 2, "+"), "tas") group = Grouper("time.month", add_dims=["lon"]) scaling = Scaling.train(ref, hist, group=group, kind="+") assert "lon" not in scaling.ds p = scaling.adjust(sim) assert "lon" in p.dims np.testing.assert_array_almost_equal(p.transpose(*ref.dims), ref)
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)