Exemplo n.º 1
0
def estimate_good_plot_length(xx, chrono=None, mult=100):
    """
    Estimate good length for plotting stuff
    from the time scale of the system.
    Provide sensible fall-backs (better if chrono is supplied).
    """
    if xx.ndim == 2:
        # If mult-dim, then average over dims (by ravel)....
        # But for inhomogeneous variables, it is important
        # to subtract the mean first!
        xx = xx - np.mean(xx, axis=0)
        xx = xx.ravel(order='F')

    try:
        K = mult * series.estimate_corr_length(xx)
    except ValueError:
        K = 0

    if chrono is not None:
        t = chrono
        K = int(min(max(K, t.dkObs), t.K))
        T = round2(t.tt[K], 2)  # Could return T; T>tt[-1]
        K = utils.find_1st_ind(t.tt >= T)
        if K:
            return K
        else:
            return t.K
    else:
        K = int(min(max(K, 1), len(xx)))
        T = round2(K, 2)
        return K
Exemplo n.º 2
0
    def assimilate(self, HMM, xx, yy):
        Dyn, Obs, chrono, stats = HMM.Dyn, HMM.Obs, HMM.t, self.stats

        # Compute "climatological" Kalman gain
        muC = np.mean(xx, 0)
        AC  = xx - muC
        PC  = (AC.T @ AC) / (xx.shape[0] - 1)

        # Setup scalar "time-series" covariance dynamics.
        # ONLY USED FOR DIAGNOSTICS, not to affect the Kalman gain.
        L  = series.estimate_corr_length(AC.ravel(order='F'))
        SM = fit_sigmoid(1/2, L, 0)

        # Init
        mu = muC
        stats.assess(0, mu=mu, Cov=PC)

        for k, kObs, t, dt in progbar(chrono.ticker):
            # Forecast
            mu = Dyn(mu, t-dt, dt)
            if kObs is not None:
                stats.assess(k, kObs, 'f', mu=muC, Cov=PC)

                # Analysis
                H  = Obs.linear(muC, t)
                KG  = mtools.mrdiv([email protected], H@[email protected] + Obs.noise.C.full)
                mu = muC + KG@(yy[kObs] - Obs(muC, t))

                P  = (np.eye(Dyn.M) - KG@H) @ PC
                SM = fit_sigmoid(P.trace()/PC.trace(), L, k)

            stats.assess(k, kObs, mu=mu, Cov=2*PC*SM(k))
Exemplo n.º 3
0
def estimate_good_plot_length(xx, chrono=None, mult=100):
    """Estimate the range of the xx slices for plotting.

    The length is based on the estimated time scale (wavelength)
    of the system.
    Provide sensible fall-backs (better if chrono is supplied).

    Parameters
    ----------
    xx: ndarray
        Plotted array
    chrono: `dapper.tools.chronos.Chronology`, optional
        object with property dkObS. Defaults: None
    mult: int, optional
        Number of waves for plotting. Defaults: 100

    Returns
    -------
    K: int
        length for plotting

    Example
    -------
    >>> K_lag = estimate_good_plot_length(stats.xx, chrono, mult=80) # doctest: +SKIP
    """
    if xx.ndim == 2:
        # If mult-dim, then average over dims (by ravel)....
        # But for inhomogeneous variables, it is important
        # to subtract the mean first!
        xx = xx - np.mean(xx, axis=0)
        xx = xx.ravel(order='F')

    try:
        K = mult * series.estimate_corr_length(xx)
    except ValueError:
        K = 0

    if chrono is not None:
        t = chrono
        K = int(min(max(K, t.dkObs), t.K))
        T = round2sigfig(t.tt[K], 2)  # Could return T; T>tt[-1]
        K = find_1st_ind(t.tt >= T)
        if K:
            return K
        else:
            return t.K
    else:
        K = int(min(max(K, 1), len(xx)))
        T = round2sigfig(K, 2)
        return K
Exemplo n.º 4
0
    def assimilate(self, HMM, xx, yy):
        Dyn, Obs, chrono, X0, stats = HMM.Dyn, HMM.Obs, HMM.t, HMM.X0, self.stats

        if isinstance(self.B, np.ndarray):
            # compare ndarray 1st to avoid == error for ndarray
            B = self.B.astype(float)
        elif self.B in (None, 'clim'):
            # Use climatological cov, estimated from truth
            B = np.cov(xx.T)
        elif self.B == 'eye':
            B = np.eye(HMM.Nx)
        else:
            raise ValueError("Bad input B.")
        B *= self.xB

        # ONLY USED FOR DIAGNOSTICS, not to change the Kalman gain.
        CC = 2 * np.cov(xx.T)
        L = series.estimate_corr_length(center(xx)[0].ravel(order='F'))
        P = X0.C.full
        SM = fit_sigmoid(P.trace() / CC.trace(), L, 0)

        # Init
        mu = X0.mu
        stats.assess(0, mu=mu, Cov=P)

        for k, kObs, t, dt in progbar(chrono.ticker):
            # Forecast
            mu = Dyn(mu, t - dt, dt)
            P = CC * SM(k)

            if kObs is not None:
                stats.assess(k, kObs, 'f', mu=mu, Cov=P)

                # Analysis
                H = Obs.linear(mu, t)
                KG = mrdiv(B @ H.T, H @ B @ H.T + Obs.noise.C.full)
                mu = mu + KG @ (yy[kObs] - Obs(mu, t))

                # Re-calibrate fit_sigmoid with new W0 = Pa/B
                P = (np.eye(Dyn.M) - KG @ H) @ B
                SM = fit_sigmoid(P.trace() / CC.trace(), L, k)

            stats.assess(k, kObs, mu=mu, Cov=P)