Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    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"
Example #4
0
    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)
Example #5
0
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
Example #6
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)