emcee.Originals available at: https://github.com/dfm/gp-tutorial & https://speakerdeck.com/dfm/an-astronomers-introduction-to-gaussian-processes
In [41]:
%pylab inline
# Auto imports np and plt
In [42]:
from matplotlib import rcParams
#rcParams["savefig.dpi"] = 150
import emcee # http://dan.iel.fm/emcee
import triangle # https://github.com/dfm/triangle.py
import numpy as np
import matplotlib.pyplot as plt
from astroML.plotting import hist
from astroML.stats.random import bivariate_normal
from matplotlib.patches import Ellipse
import timeit
#from IPython.display import display, Math, Latex
In [43]:
import seaborn as sns
sns.set_context("notebook", font_scale=1.5, rc={"lines.linewidth": 2.5})
cmap = sns.cubehelix_palette(light=1, as_cmap=True)
sns.palplot(sns.cubehelix_palette(light=1))
In [44]:
import pandas as pd
df = pd.read_csv('/Users/gully/Astronomy/Latex/AO_bonding_paper/data/cln_20130218_cary5000.csv')
df.set_index('wavelength', inplace=True)
mask = df.index >= 1250.0
df = df[mask]
df.tail()
Out[44]:
In [45]:
from etalon import *
np.random.seed(123456)
In [46]:
# Introduce the Real data
x = df.index.values
N = len(x)
# Define T_DSP for the model
T_DSP = T_gap_Si(x, 0.0)
n1 = sellmeier_Si(x)
# Define uncertainty
yerr = 0.0002*np.ones(N)
iid_cov = np.diag(yerr ** 2)
In [47]:
VG03 = df.VG03_pos2.values/df.VG06.values
VG02_pos2 = df.VG02_pos2.values/df.VG06.values
VG02_pos3 = df.VG02_pos3.values/df.VG06.values
VG04_pos2 = df.VG04_pos2.values/df.VG06_post.values
In [48]:
plt.errorbar(x, VG03, yerr=yerr, fmt=".k", capsize=0, label='VG03')
plt.errorbar(x, VG02_pos2, yerr=yerr, fmt=".r", capsize=0, label='VG02_pos2')
plt.errorbar(x, VG02_pos3, yerr=yerr, fmt=".b", capsize=0, label='VG02_pos3')
plt.errorbar(x, VG04_pos2, yerr=yerr, fmt=".g", capsize=0, label='VG04_pos2')
plt.xlabel('$\lambda $(nm)');
plt.ylabel('$T_{gap}$');
plt.title('Measured Si Transmission');
plt.ylim(0.9, 1.01);
plt.legend(loc='best');
In [49]:
VG03_guess, VG03_LB, VG03_UB= [4120, 0.045], [3920, 0.0], [4250, 0.5]
VG02p2_guess, VG02p2_LB, VG02p2_UB= [10, 0.01], [0, 0.0], [100, 1.0]
VG02p3_guess, VG02p3_LB, VG02p3_UB= [10, 0.01], [0, 0.0], [100, 1.0]
VG04p2_guess, VG04p2_LB, VG04p2_UB= [10, 0.01], [0, 0.0], [100, 1.0]
The off-diagonal terms are characterized by parameters $a$ and $s$.
The term $a$ controls the strength of the interaction. The term $s$ controls the range of correlation.
First we define a natural log likelihood function. You hand it a $d$, a $f$, an $a$, and an $s$ and it gives you the likelihood of the data: $\ln{p}=\ln{p(y|d,f,a,s)}$
Note: x is not passed to this function. The way Python works, x, y, and iid_cov are searched for in the local namespace, then global namespace.
In [59]:
def lnlike(d, f, lna, lns):
a, s = np.exp(lna), np.exp(lns)
off_diag_terms = a**2 * np.exp(-0.5 * (x[:, None] - x[None, :])**2 / s**2)
C = iid_cov + off_diag_terms
sgn, logdet = np.linalg.slogdet(C)
if sgn <= 0:
return -np.inf
r = VG02_pos2 - T_gap_Si_withFF_fast(x, d, f, n1)/T_DSP
return -0.5 * (np.dot(r, np.linalg.solve(C, r)) + logdet)
In [95]:
# Apply a uniform prior over some range.
# Shape params are uniform in log space
def lnprior(d, f, lna, lns):
if not (0.0 < d < 150.0 and
0.0 < f < 1.0 and
-12 < lna < -2 and
0 < lns < 10):
return -np.inf
return 0.0
In [96]:
def lnprob(p):
lp = lnprior(*p)
if not np.isfinite(lp):
return -np.inf
return lp + lnlike(*p)
In [97]:
sampler.reset()
In [106]:
ndim, nwalkers = 4, 32
a_Guess = 0.0016
s_Guess = 100.0
p0 = np.array([10.0, 0.5, np.log(a_Guess), np.log(s_Guess)]) # Decent guess
pos = [p0 + 1.0e-2*p0 * np.random.randn(ndim) for i in range(nwalkers)]
sampler = emcee.EnsembleSampler(nwalkers, ndim, lnprob)
In [107]:
# This is the burn-in
pos, lp, state = sampler.run_mcmc(pos, 200)
In [118]:
sampler.reset()
pos, lp, state = sampler.run_mcmc(pos, 3000)
chain = sampler.chain
In [119]:
fig, axes = plt.subplots(4, 1, figsize=(5, 6), sharex=True)
fig.subplots_adjust(left=0.1, bottom=0.1, right=0.96, top=0.98,
wspace=0.0, hspace=0.05)
[a.plot(np.arange(chain.shape[1]), chain[:, :, i].T, "k", alpha=0.5)
for i, a in enumerate(axes)]
[a.set_ylabel("${0}$".format(l)) for a, l in zip(axes, ["d", "f", "\ln a", "\ln s"])]
axes[-1].set_xlim(0, chain.shape[1])
axes[-1].set_xlabel("iteration");
In [120]:
samples = sampler.flatchain
samples_lin = copy(samples)
samples_lin[:, 2:] = np.exp(samples_lin[:, 2:])
In [121]:
fig = triangle.corner(samples_lin,
labels=map("${0}$".format, ["d", "f", "a", "s"]),
quantiles=[0.16, 0.84])
In [122]:
off_diag_terms = 0.0018**2 * np.exp(-0.5 * (x[:, None] - x[None, :])**2 / 12.0**2)
C = iid_cov + off_diag_terms
fit = T_gap_Si_withFF_fast(x, 4093.5, 0.04572, n1)/T_DSP
vec = np.random.multivariate_normal(fit, C)
In [125]:
for d, f, a, s in samples_lin[np.random.randint(len(samples), size=500)]:
#plt.plot(x, T_gap_Si_withFF_fast(x, d, f, n1)/T_DSP, color="r", alpha=0.03)
off_diag_terms = a**2 * np.exp(-0.5 * (x[:, None] - x[None, :])**2 / s**2)
C = iid_cov + off_diag_terms
fit = T_gap_Si_withFF_fast(x, d, f, n1)/T_DSP
vec = np.random.multivariate_normal(fit, C)
plt.plot(x, vec, color="g", alpha=0.01)
plt.errorbar(x, VG02_pos2, fmt=".k")
plt.xlabel('$\lambda$');
plt.ylabel('$T_{gap}$');
plt.title('Observed Si Transmission');
plt.ylim(0.9, 1.01);
In [115]:
d_mcmc, f_mcmc, a_mcmc, s_mcmc = map(lambda v: (v[1], v[2]-v[1], v[1]-v[0]),
zip(*np.percentile(samples_lin, [16, 50, 84],
axis=0)))
In [116]:
d_mcmc, f_mcmc, a_mcmc, s_mcmc
Out[116]:
In [ ]: