Sampling from linear modelΒΆ

A dataset consisting of three simultaneously obtained data sets (e.g., different photometric bands or RVs determined in individual spectral orders) is constructed and a model is set up with a single slope for all series but individual means.

In [1]:
import numpy as np
import matplotlib.pylab as plt
from PyAstronomy import funcFit2 as fuf2
import scipy.optimize as sco
In [2]:
# Definition of model

class LinMod(fuf2.MBOEv):
    """ Linear model """

    def __init__(self, no):
        # no is number of measurement series
        self.no = no
        # 'parnames' specifies parameter names in the model
        parnames = ["mean%d" % (i+1) for i in range(no)]
        parnames.append("slope")

        fuf2.MBOEv.__init__(self, pars=parnames, rootName="LinMod")

    def evaluate(self, x, *args, **kwargs):
        """
        Evaluate model at 'x' here and return y = const + x*slope
        """
        r = np.zeros( (len(x), self.no) )
        for i in range(self.no):
            r[::,i] = self["slope"] * x + self["mean%d" % (i+1)]

        return r
In [3]:
# Generate mock data
np.random.seed(1718)

# Number of data points and orders
nd = 10
no = 3
# Uncertainty of individual points
s = 0.3

# Mock data and time (x) axis
d = np.zeros((nd,no))
x = np.arange(nd)

for i in range(no):
    offset = np.random.random() * 20
    d[::,i] = 0.6 * x + offset + np.random.normal(0, s, nd)

# Uncertainty
yerr = np.ones_like(d)*s
In [4]:
# Get best-fit parameters

# Instantiate model
lm = LinMod(no)
# Guess slope
lm["slope"] = 0.5
# Thaw parameters
lm.thaw(["mean%d" % (i+1) for i in range(no)])
lm.thaw(["slope"])

# Because ln inherited from MBOEv, it has a default chi-square objective function
# Find best-fit parameters
fr = sco.fmin(lm.chisqr, x0=lm.freeParamVals(), args=(x,d,yerr))
# Set model parameters to best-fit values and display
lm.setFreeParamVals(fr)
lm.parameterSummary()

# Plot best-fit model
plt.title("Data and model")
model = lm.evaluate(x)
for i in range(no):
    plt.errorbar(x, d[::,i], yerr=s, fmt='+-')
    plt.plot(x, model[::,i], 'k:')
plt.show()
Optimization terminated successfully.
         Current function value: 32.650283
         Iterations: 272
         Function evaluations: 470
-------------------- Parameter summary ---------------------
    mean1 =      2.35174, free: T, restricted: F, related: F
    mean2 =      3.68232, free: T, restricted: F, related: F
    mean3 =      5.94872, free: T, restricted: F, related: F
    slope =     0.630558, free: T, restricted: F, related: F
------------------------------------------------------------
../_images/funcFit2Doc_ex_emceesample_1_5_1.png
In [5]:
# Sample from the posterior

fuf2.sampleEMCEE2(lm, pargs=(x, d, yerr), dbfile="chain1.emcee", sampleArgs={"burn":300, "iters":1000})


ta = fuf2.TraceAnalysis2("chain1.emcee")

# Calculate mean, median, standard deviation, and
# credibility interval for the available parameters
for p in ta.availableParameters():
  hpd = ta.hpd(p, cred=0.95)
  print("Parameter %5s, mean = % g, median = % g, std = % g, 95%% HPD = % g - % g" \
        % (p, ta.mean(p), ta.median(p), ta.std(p), hpd[0], hpd[1]))

ta.plotTraceHist("slope")
ta.show()
EMCEE progress: 100% ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ETA:  0:00:00
Parameter mean1, mean =  2.38839, median =  2.39174, std =  0.132071, 95% HPD =  2.12382 -  2.62801
Parameter mean2, mean =  3.77283, median =  3.77296, std =  0.133714, 95% HPD =  3.50435 -  4.02043
Parameter mean3, mean =  5.94215, median =  5.94154, std =  0.128204, 95% HPD =  5.68971 -  6.19776
Parameter slope, mean =  0.624081, median =  0.623544, std =  0.0189487, 95% HPD =  0.588183 -  0.661993
../_images/funcFit2Doc_ex_emceesample_1_6_2.png