Exemple #1
0
def test_predict(seed=42):
    np.random.seed(seed)
    x = np.linspace(1, 59, 300)
    t = np.sort(np.random.uniform(10, 50, 100))
    yerr = np.random.uniform(0.1, 0.5, len(t))
    y = np.sin(t)

    kernel = terms.RealTerm(0.1, 0.5)
    for term in [(0.6, 0.7, 1.0), (0.1, 0.05, 0.5, -0.1)]:
        kernel += terms.ComplexTerm(*term)
    gp = GP(kernel)

    gp.compute(t, yerr)
    K = gp.get_matrix(include_diagonal=True)
    Ks = gp.get_matrix(x, t)
    true_mu = np.dot(Ks, np.linalg.solve(K, y))
    true_cov = gp.get_matrix(x, x) - np.dot(Ks, np.linalg.solve(K, Ks.T))

    mu, cov = gp.predict(y, x)

    _, var = gp.predict(y, x, return_var=True)
    assert np.allclose(mu, true_mu)
    assert np.allclose(cov, true_cov)
    assert np.allclose(var, np.diag(true_cov))

    mu0, cov0 = gp.predict(y, t)
    mu, cov = gp.predict(y)
    assert np.allclose(mu0, mu)
    assert np.allclose(cov0, cov)
Exemple #2
0
def test_nyquist_singularity(method, seed=4220):
    np.random.seed(seed)

    kernel = terms.ComplexTerm(1.0, np.log(1e-6), np.log(1.0))
    gp = GP(kernel, method=method)

    # Samples are very close to Nyquist with f = 1.0
    ts = np.array([0.0, 0.5, 1.0, 1.5])
    ts[1] = ts[1] + 1e-9 * np.random.randn()
    ts[2] = ts[2] + 1e-8 * np.random.randn()
    ts[3] = ts[3] + 1e-7 * np.random.randn()

    yerr = np.random.uniform(low=0.1, high=0.2, size=len(ts))
    y = np.random.randn(len(ts))

    gp.compute(ts, yerr)
    llgp = gp.log_likelihood(y)

    K = gp.get_matrix(ts)
    K[np.diag_indices_from(K)] += yerr**2.0

    ll = (-0.5 * np.dot(y, np.linalg.solve(K, y)) -
          0.5 * np.linalg.slogdet(K)[1] - 0.5 * len(y) * np.log(2.0 * np.pi))

    assert np.allclose(ll, llgp)
Exemple #3
0
def test_log_likelihood(method, seed=42):
    np.random.seed(seed)
    x = np.sort(np.random.rand(10))
    yerr = np.random.uniform(0.1, 0.5, len(x))
    y = np.sin(x)

    kernel = terms.RealTerm(0.1, 0.5)
    gp = GP(kernel, method=method)
    with pytest.raises(RuntimeError):
        gp.log_likelihood(y)

    for term in [(0.6, 0.7, 1.0)]:
        kernel += terms.ComplexTerm(*term)
        gp = GP(kernel, method=method)

        assert gp.computed is False

        with pytest.raises(ValueError):
            gp.compute(np.random.rand(len(x)), yerr)

        gp.compute(x, yerr)
        assert gp.computed is True
        assert gp.dirty is False

        ll = gp.log_likelihood(y)
        K = gp.get_matrix(include_diagonal=True)
        ll0 = -0.5 * np.dot(y, np.linalg.solve(K, y))
        ll0 -= 0.5 * np.linalg.slogdet(K)[1]
        ll0 -= 0.5 * len(x) * np.log(2*np.pi)
        assert np.allclose(ll, ll0)

    # Check that changing the parameters "un-computes" the likelihood.
    gp.set_parameter_vector(gp.get_parameter_vector())
    assert gp.dirty is True
    assert gp.computed is False

    # Check that changing the parameters changes the likelihood.
    gp.compute(x, yerr)
    ll1 = gp.log_likelihood(y)
    params = gp.get_parameter_vector()
    params[0] += 0.1
    gp.set_parameter_vector(params)
    gp.compute(x, yerr)
    ll2 = gp.log_likelihood(y)
    assert not np.allclose(ll1, ll2)

    gp[1] += 0.1
    assert gp.dirty is True
    gp.compute(x, yerr)
    ll3 = gp.log_likelihood(y)
    assert not np.allclose(ll2, ll3)
Exemple #4
0
def test_log_likelihood(seed=42):
    np.random.seed(seed)
    x = np.sort(np.random.rand(10))
    yerr = np.random.uniform(0.1, 0.5, len(x))
    y = np.sin(x)

    kernel = terms.RealTerm(0.1, 0.5)
    gp = GP(kernel)
    with pytest.raises(RuntimeError):
        gp.log_likelihood(y)

    termlist = [(0.1 + 10./j, 0.5 + 10./j) for j in range(1, 4)]
    termlist += [(1.0 + 10./j, 0.01 + 10./j, 0.5, 0.01) for j in range(1, 10)]
    termlist += [(0.6, 0.7, 1.0), (0.3, 0.05, 0.5, 0.6)]
    for term in termlist:
        if len(term) > 2:
            kernel += terms.ComplexTerm(*term)
        else:
            kernel += terms.RealTerm(*term)
        gp = GP(kernel)

        assert gp.computed is False

        with pytest.raises(ValueError):
            gp.compute(np.random.rand(len(x)), yerr)

        gp.compute(x, yerr)
        assert gp.computed is True
        assert gp.dirty is False

        ll = gp.log_likelihood(y)
        K = gp.get_matrix(include_diagonal=True)
        ll0 = -0.5 * np.dot(y, np.linalg.solve(K, y))
        ll0 -= 0.5 * np.linalg.slogdet(K)[1]
        ll0 -= 0.5 * len(x) * np.log(2*np.pi)
        assert np.allclose(ll, ll0)

    # Check that changing the parameters "un-computes" the likelihood.
    gp.set_parameter_vector(gp.get_parameter_vector())
    assert gp.dirty is True
    assert gp.computed is False

    # Check that changing the parameters changes the likelihood.
    gp.compute(x, yerr)
    ll1 = gp.log_likelihood(y)
    params = gp.get_parameter_vector()
    params[0] += 10.0
    gp.set_parameter_vector(params)
    gp.compute(x, yerr)
    ll2 = gp.log_likelihood(y)
    assert not np.allclose(ll1, ll2)

    gp[1] += 10.0
    assert gp.dirty is True
    gp.compute(x, yerr)
    ll3 = gp.log_likelihood(y)
    assert not np.allclose(ll2, ll3)

    # Test zero delta t
    ind = len(x) // 2
    x = np.concatenate((x[:ind], [x[ind]], x[ind:]))
    y = np.concatenate((y[:ind], [y[ind]], y[ind:]))
    yerr = np.concatenate((yerr[:ind], [yerr[ind]], yerr[ind:]))
    gp.compute(x, yerr)
    ll = gp.log_likelihood(y)
    K = gp.get_matrix(include_diagonal=True)
    ll0 = -0.5 * np.dot(y, np.linalg.solve(K, y))
    ll0 -= 0.5 * np.linalg.slogdet(K)[1]
    ll0 -= 0.5 * len(x) * np.log(2*np.pi)
    assert np.allclose(ll, ll0), "face"
Exemple #5
0
def test_log_likelihood(with_general, seed=42):
    np.random.seed(seed)
    x = np.sort(np.random.rand(10))
    yerr = np.random.uniform(0.1, 0.5, len(x))
    y = np.sin(x)

    if with_general:
        U = np.vander(x - np.mean(x), 4).T
        V = U * np.random.rand(4)[:, None]
        A = np.sum(U * V, axis=0) + 1e-8
    else:
        A = np.empty(0)
        U = np.empty((0, 0))
        V = np.empty((0, 0))

    # Check quiet argument with a non-positive definite kernel.
    class NPDTerm(terms.Term):
        parameter_names = ("par1", )

        def get_real_coefficients(self, params):  # NOQA
            return [params[0]], [0.1]

    gp = GP(NPDTerm(-1.0))
    with pytest.raises(celerite.solver.LinAlgError):
        gp.compute(x, 0.0)
    with pytest.raises(celerite.solver.LinAlgError):
        gp.log_likelihood(y)
    assert np.isinf(gp.log_likelihood(y, quiet=True))
    if terms.HAS_AUTOGRAD:
        assert np.isinf(gp.grad_log_likelihood(y, quiet=True)[0])

    kernel = terms.RealTerm(0.1, 0.5)
    gp = GP(kernel)
    with pytest.raises(RuntimeError):
        gp.log_likelihood(y)

    termlist = [(0.1 + 10. / j, 0.5 + 10. / j) for j in range(1, 4)]
    termlist += [(1.0 + 10. / j, 0.01 + 10. / j, 0.5, 0.01)
                 for j in range(1, 10)]
    termlist += [(0.6, 0.7, 1.0), (0.3, 0.05, 0.5, 0.6)]
    for term in termlist:
        if len(term) > 2:
            kernel += terms.ComplexTerm(*term)
        else:
            kernel += terms.RealTerm(*term)
        gp = GP(kernel)

        assert gp.computed is False

        with pytest.raises(ValueError):
            gp.compute(np.random.rand(len(x)), yerr)

        gp.compute(x, yerr, A=A, U=U, V=V)
        assert gp.computed is True
        assert gp.dirty is False

        ll = gp.log_likelihood(y)
        K = gp.get_matrix(include_diagonal=True)
        ll0 = -0.5 * np.dot(y, np.linalg.solve(K, y))
        ll0 -= 0.5 * np.linalg.slogdet(K)[1]
        ll0 -= 0.5 * len(x) * np.log(2 * np.pi)
        assert np.allclose(ll, ll0)

    # Check that changing the parameters "un-computes" the likelihood.
    gp.set_parameter_vector(gp.get_parameter_vector())
    assert gp.dirty is True
    assert gp.computed is False

    # Check that changing the parameters changes the likelihood.
    gp.compute(x, yerr, A=A, U=U, V=V)
    ll1 = gp.log_likelihood(y)
    params = gp.get_parameter_vector()
    params[0] += 10.0
    gp.set_parameter_vector(params)
    gp.compute(x, yerr, A=A, U=U, V=V)
    ll2 = gp.log_likelihood(y)
    assert not np.allclose(ll1, ll2)

    gp[1] += 10.0
    assert gp.dirty is True
    gp.compute(x, yerr, A=A, U=U, V=V)
    ll3 = gp.log_likelihood(y)
    assert not np.allclose(ll2, ll3)

    # Test zero delta t
    ind = len(x) // 2
    x = np.concatenate((x[:ind], [x[ind]], x[ind:]))
    y = np.concatenate((y[:ind], [y[ind]], y[ind:]))
    yerr = np.concatenate((yerr[:ind], [yerr[ind]], yerr[ind:]))
    gp.compute(x, yerr)
    ll = gp.log_likelihood(y)
    K = gp.get_matrix(include_diagonal=True)
    ll0 = -0.5 * np.dot(y, np.linalg.solve(K, y))
    ll0 -= 0.5 * np.linalg.slogdet(K)[1]
    ll0 -= 0.5 * len(x) * np.log(2 * np.pi)
    assert np.allclose(ll, ll0)
Exemple #6
0
def GPSpec_2Comp(wav,
                 flux,
                 flux_err,
                 shifts_in=None,
                 nsteps=2000,
                 nrange=3,
                 prefix='RR2'):
    # NB: input wavelengths should be in nm, flux continuum should be about 1
    K, N = wav.shape
    # Create 2-D array of scaled log wavelengths for fitting
    lwav = np.log(wav * 1e-9)  # in m
    lw0, lw1 = lwav.min(), lwav.max()
    x = (lwav - lw0) / (lw1 - lw0)
    # First do GP fit to individual spectra to get estimate of GP HPs
    print 'GP fit to individual spectra'
    HPs = np.zeros((K, 3))
    for i in range(K):
        xx = x[i, :].flatten()
        yy = flux[i, :].flatten()
        ee = flux_err[i, :].flatten()
        HPs[i, :] = Fit0_Jitter(xx, yy, ee, verbose=False)
    HPs = np.median(HPs, axis=0)
    print 'GP HPs:', HPs
    k = terms.Matern32Term(log_sigma=HPs[0], log_rho=HPs[1])
    k += terms.JitterTerm(log_sigma=HPs[2])
    gp1 = GP(k, mean=1.0)
    gp2 = GP(k, mean=1.0)
    # Initial (ML) estimate of parameters
    print "Starting ML fit"
    if shifts_in is None:
        shifts_in = np.zeros(2 * (K - 1))
    par_in = shifts_in / SPEED_OF_LIGHT / (lw1 - lw0)
    ML_par = np.array(Fit2(x, flux, gp1, gp2, verbose=False, par_in=par_in))
    par_ML = np.copy(ML_par)
    par_ML *= (lw1 - lw0) * SPEED_OF_LIGHT * 1e-3
    print "ML fit done"
    # MCMC
    print "Starting MCMC"
    ndim = len(ML_par)
    nwalkers = ndim * 4
    p0 = ML_par + 1e-4 * np.random.randn(nwalkers, ndim)
    sampler = emcee.EnsembleSampler(nwalkers,
                                    ndim,
                                    LP2,
                                    args=[gp1, gp2, x, flux])
    for i, result in enumerate(sampler.sample(p0, iterations=nsteps)):
        n = int((30 + 1) * float(i) / nsteps)
        print i
        sys.stdout.write("\r[{0}{1}]".format('#' * n, ' ' * (30 - n)))
    sys.stdout.write("\n")
    print("MCMC done")
    # find MAP parameters
    iMAP = np.argmax(sampler.flatlnprobability)
    MAP_par = sampler.flatchain[iMAP, :].flatten()
    # extract MCMC chains
    samples = sampler.chain
    Lprob = sampler.lnprobability
    # convert chains back to physical units: shifts in km/s
    samples_tpl = np.copy(samples)
    samples_tpl *= (lw1 - lw0) * SPEED_OF_LIGHT * 1e-3
    par_MAP = np.copy(MAP_par)
    par_MAP *= (lw1 - lw0) * SPEED_OF_LIGHT * 1e-3
    # parameter names for plots
    labels = []
    for i in range(K - 1):
        labels.append(r'$\delta v^1_{%d}$ (km/s)' % (i + 1))
    for i in range(K - 1):
        labels.append(r'$\delta v^2_{%d}$ (km/s)' % (i + 1))
    labels = np.array(labels)
    names = []
    for i in range(K - 1):
        names.append('dv1_%d (km/s)' % (i + 1))
    for i in range(K - 1):
        names.append('dv2_%d (km/s)' % (i + 1))
    names = np.array(names)
    # Plot the chains
    fig1 = plt.figure(figsize=(12, 2 * (K - 1) + 2))
    gs1 = gridspec.GridSpec(ndim + 1, 1)
    gs1.update(left=0.1, right=0.98, bottom=0.07, top=0.98, hspace=0)
    ax1 = plt.subplot(gs1[0, 0])
    plt.setp(ax1.get_xticklabels(), visible=False)
    plt.plot(Lprob.T, 'k-', alpha=0.2)
    plt.ylabel(r'$\ln P$')
    for i in range(ndim):
        print i, ndim, len(labels)
        axc = plt.subplot(gs1[i + 1, 0], sharex=ax1)
        if i < (ndim - 1):
            plt.setp(axc.get_xticklabels(), visible=False)
        plt.plot(samples_tpl[:, :, i].T, 'k-', alpha=0.2)
        plt.ylabel(labels[i])
    plt.xlim(0, nsteps)
    plt.xlabel('iteration number')
    # Discard burnout
    nburn = int(raw_input('Enter no. steps to discard as burnout: '))
    plt.axvline(nburn)
    # Evaluate and print the parameter ranges
    print '\n{:20s}: {:10s} {:10s} {:10s} - {:7s} + {:7s}'.format('Parameter', 'ML', 'MAP', \
                                                                    'Median','Error','Error')
    par50 = np.zeros(ndim)
    par84 = np.zeros(ndim)
    par16 = np.zeros(ndim)
    for i in range(ndim):
        sam = samples_tpl[:, :, i].flatten()
        b, m, f = np.percentile(sam, [16, 50, 84])
        par50[i] = m
        par16[i] = b
        par84[i] = f
        print '{:20s}: {:10.5f} {:10.5f} {:10.5f} - {:7.5f} + {:7.5f}'.format(names[i], \
                                                                                  par_ML[i], \
                                                                                  par_MAP[i], \
                                                                                  m, m-b, f-m)
    if prefix is None:
        return par_MAP, par50, par50 - par16, par84 - par50
    plt.savefig('%s_chains.png' % prefix)
    samples_flat = samples[:, nburn:, :].reshape(-1, ndim)
    samples_tpl_flat = samples_tpl[:, nburn:, :].reshape(-1, ndim)
    # Plot the parameter distributions
    fig2 = corner.corner(samples_tpl_flat, truths = par_MAP, labels = labels, show_titles = True, \
                            quantiles = [0.16, 0.84])
    plt.savefig('%s_corner.png' % prefix)
    # Plot the individual spectra with MAP fit
    xpred = np.copy(x)
    fpred, fpred_err, f1pred, f2pred = Pred2_2D(MAP_par,
                                                gp1,
                                                gp2,
                                                x,
                                                flux,
                                                flux_err,
                                                xpred=xpred)
    lwpred = (lw1 - lw0) * xpred + lw0
    wpred = np.exp(lwpred) * 1e9
    fig3 = plt.figure(figsize=(12, K + 1))
    gs3 = gridspec.GridSpec(K, 1)
    gs3.update(left=0.1, right=0.98, bottom=0.07, top=0.98, hspace=0)
    for i in range(K):
        if i == 0:
            ax1 = plt.subplot(gs3[0, 0])
        else:
            axc = plt.subplot(gs3[i, 0], sharex=ax1, sharey=ax1)
        if i < (K - 1):
            plt.setp(ax1.get_xticklabels(), visible=False)
        plt.plot(wpred[i, :], f1pred[i, :], 'C1')
        plt.plot(wpred[i, :], f2pred[i, :], 'C2')
        plt.fill_between(wpred[i,:], fpred[i,:] + 2 * fpred_err[i,:], \
                             fpred[i,:] - fpred_err[i,:], color = 'C0', alpha = 0.4, lw = 0)
        plt.plot(wpred[i, :], fpred[i, :], 'C0')
        plt.ylabel('spec. %d' % (i + 1))
        plt.errorbar(wav[i,:], flux[i,:], yerr = flux_err[i,:], \
                         fmt = ".k", ms = 3, mec = 'none', capsize = 0, alpha = 0.5, lw=0.5)

        plt.xlim(wav.min(), wav.max())
    plt.xlabel('wavelength (nm)')
    plt.savefig('%s_spectra.png' % prefix)
    # Plot the combined spectra with samples from MCMC chain
    s1 = np.append(0.0, MAP_par[:K - 1])
    x11d = (x + s1[:, None]).flatten()
    lw11d = (lw1 - lw0) * x11d + lw0
    w11d = np.exp(lw11d) * 1e9
    K1 = gp1.get_matrix(x11d)
    s2 = np.append(0.0, MAP_par[K - 1:])
    x21d = (x + s2[:, None]).flatten()
    lw21d = (lw1 - lw0) * x21d + lw0
    w21d = np.exp(lw21d) * 1e9
    K2 = gp2.get_matrix(x21d)
    y1derr = flux_err.flatten()
    Ktot = K1 + K2 + np.diag(y1derr**2)
    y1d = flux.flatten() - 1.0
    y11d = (flux - f2pred).flatten() + 1
    y21d = (flux - f1pred).flatten() + 1
    offset = 1.5 * (y11d.min() - 1)
    L = sla.cho_factor(Ktot)
    b = sla.cho_solve(L, y1d)
    fig4 = plt.figure(figsize=(12, 2 * nrange + 1))
    gs4 = gridspec.GridSpec(nrange, 1)
    gs4.update(left=0.1, right=0.98, bottom=0.07, top=0.98, hspace=0.15)
    ws = min(w11d.min(), w21d.min())
    wr = (max(w11d.max(), w21d.max()) - ws) / float(nrange)
    for i in range(nrange):
        if i == 0:
            ax1 = plt.subplot(gs4[0, 0])
        else:
            axc = plt.subplot(gs4[i, 0], sharey=ax1)
        wmin = ws + (i - 0.05) * wr
        wmax = ws + (i + 1.05) * wr
        l = (w11d >= wmin) * (w11d <= wmax)
        plt.errorbar(w11d[l], y11d[l], yerr = y1derr[l], fmt = ".k", capsize = 0, \
                         alpha = 0.5, ms = 2, mec='none')
        l = (w21d >= wmin) * (w21d <= wmax)
        plt.errorbar(w21d[l], y21d[l] + offset, yerr = y1derr[l], fmt = ".k", capsize = 0, \
                         alpha = 0.5, ms = 2, mec='none')
        wpred = np.linspace(wmin, wmax, 1000)
        lwpred = np.log(wpred * 1e-9)
        xpred = (lwpred - lw0) / (lw1 - lw0)
        isamp = np.random.randint(nsteps - nburn, size=10)
        for j in isamp:
            samp_params = samples_flat[j, :].flatten()
            s1 = samp_params[:K - 1]
            x1pred = (xpred + s1[:, None]).flatten()
            lw1pred = (lw1 - lw0) * x1pred + lw0
            w1pred = np.exp(lw1pred) * 1e9
            K1s = gp1.get_matrix(x1pred, x11d)
            s2 = samp_params[K - 1:]
            x2pred = (xpred + s2[:, None]).flatten()
            lw2pred = (lw1 - lw0) * x2pred + lw0
            w2pred = np.exp(lw2pred) * 1e9
            K2s = gp2.get_matrix(x2pred, x21d)
            Ks = K1s + K2s
            K1ss = gp1.get_matrix(x1pred)
            K2ss = gp2.get_matrix(x2pred)
            Kss = K1ss + K2ss
            mu1 = np.dot(K1s, b).reshape(x1pred.shape) + 1
            mu2 = np.dot(K2s, b).reshape(x2pred.shape) + 1
            inds1 = np.argsort(w1pred)
            plt.plot(w1pred[inds1], mu1[inds1], 'C0-', lw=0.5, alpha=0.5)
            inds2 = np.argsort(w2pred)
            plt.plot(w2pred[inds2],
                     mu2[inds2] + offset,
                     'C1-',
                     lw=0.5,
                     alpha=0.5)
        plt.xlim(wmin, wmax)
        plt.ylabel('flux')
    plt.xlabel('wavelength (nm)')
    plt.savefig('%s_combined.png' % prefix)
    return par_MAP, par50, par50 - par16, par84 - par50, [
        fig1, fig2, fig3, fig4
    ]