In [1]:
'''Compute the posterior estimates of spectral index, S1.4GHz, and P1.4GHz
as well as the posterior estimates of measured fluxes (S_i) using the Metropolis Hastings algorithm.
We assume priors: Gaussian measurments fluxes, uniform spectral index, uniform S1.4, and uniform P1.4.

Detection is defined as 5*sigma_rms. 
The detection mask can be defined to include nondetection measurements (a valid assumption for point sources).

The posterior density is then: prior x Likelihood (with priors described above).
The likelihood is an L2 on spectral index and S1.4 due to the Gaussian prior on observables.

Likelihood = exp(-1/2 * Sum (S_obs - g(alpha_i,S1.4))**2 / (Cd_i + Ct_i))

where S_obs are the measured fluxes
g(alpha_i,S1.4) gives model S_i
Cd_i is the measurement variance S_i
Ct_i is a systematic for g(...) taken to be (0.15*S_obs)**2

assuming z ~ 0.516 +- 0.002 we use the sampling of alpha and S14 to monte carlo compute the mean and variances of 
posterior S_i and P14 in lognormal as suggested by their posterior plots.

We find that the posterior distributions for:
alpha is Gaussian
S1.4 is lognormal
P1.4 is lognormal
S_i is lognormal
'''

import numpy as np
import pylab as plt
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection

def g(alpha,S14,nu):
    '''Forward equation, evaluate model at given nu array'''
    out = S14*(nu/1400e6)**alpha
    return out

def L(Sobs,alpha,S14,nu,CdCt):
    '''Likeihood for alpha and S14'''
    #only as nu_obs
    d = g(alpha,S14,nu)
    L2 = np.sum((Sobs - d)**2/CdCt)
    #L1 = np.sum(np.abs(Sobs - d)/np.sqrt(CdCt))
    return np.exp(-L2/2.)

def P(nu,z,alpha,S14):
    c = 3e8
    h0 = 0.7
    ch = 1.32151838
    q0 = 0.5
    D = ch*z*(1+z*(1-q0)/(np.sqrt(1+2*q0*z) + 1 + q0*z))
    S = S14*(nu/1400e6)
    out = 4*np.pi*S*D**2 / (1+z)**(1+alpha) * 1e26
    return out/1e24

def MHSolveSpectealIndex(nu,S,Cd,Ct,name,z,dz,nuModel=None,plot=False,plotDir=None):
    '''Assumes S in mJy'''
    if nuModel is None:
        nuModel = nu
    if plotDir is not None:
        import os
        try:
            os.makedirs(plotDir)
        except:
            pass
    N = int(1e6)
    alpha_ = np.zeros(N,dtype=np.double)
    S14_ = np.zeros(N,dtype=np.double)
    alpha_[0] = -0.8
    S14_[0] = S[0]*(1400e6/nu[0])**-0.8
    print("Working on source {}".format(name))
    mask = detectionMask[idx,:]
    CdCt = Cd + Ct
    Li = L(S,alpha_[0],S14_[0],nu,CdCt)
    print("Initial L: {}".format(Li))
    maxL = Li
    alphaMAP = alpha_[0]
    S14MAP = S14_[0]
    accepted = 0
    binning = 50
    i = 1
    while accepted < binning*binning and i < N:
        #sample priors in uniform steps
        alpha_j = np.random.uniform(low=alpha_[i-1] - 0.5,high=alpha_[i-1] + 0.5)
        S14_j = 10**(np.random.uniform(low = np.log10(S14_[i-1]/100),high=np.log10(S14_[i-1]*100)))
        Lj = L(S,alpha_j,S14_j,nu,CdCt)
        if np.random.uniform() < Lj/Li:
            alpha_[i] = alpha_j
            S14_[i] = S14_j
            Li = Lj
            accepted += 1
        else:
            alpha_[i] = alpha_[i-1]
            S14_[i] = S14_[i-1]
        if Lj > maxL:
            maxL = Lj
            alphaMAP = alpha_j
            S14MAP = S14_j
        i += 1
    if accepted == binning**2:
        print("Converged in {} steps".format(i))
        print("Acceptance: {}, rate : {}".format(accepted,float(accepted)/i))
    else:
        print("Acceptance: {}, rate : {}".format(accepted,float(accepted)/i))
    alpha_ = alpha_[:i]
    S14_ = S14_[:i]    
    #integrate out uncertainty unsing MC integration
    logS_int = np.zeros([len(alpha_),len(nuModel)],dtype=np.double)
    logP14_int = np.zeros(len(alpha_),dtype=np.double)
    i = 0 
    while i < len(alpha_):
        logS_int[i,:] = np.log(g(alpha_[i],S14_[i],nuModel))
        logP14_int[i] = np.log(P(1400e6,np.random.normal(loc=z,scale=dz),alpha_[i],S14_[i]/1e3))
        i += 1
    logS_mu = np.mean(logS_int,axis=0)
    logS_std = np.sqrt(np.mean(logS_int**2,axis=0) - logS_mu**2)
    logP14_mu = np.mean(logP14_int)
    logP14_std = np.sqrt(np.mean(logP14_int**2) - logP14_mu**2)
    S_post_mu = np.exp(logS_mu)
    S_post_up = np.exp(logS_mu + logS_std) - S_post_mu
    S_post_low = S_post_mu - np.exp(logS_mu - logS_std)
    P14_post_mu = np.exp(logP14_mu)
    P14_post_up = np.exp(logP14_mu + logP14_std) - P14_post_mu
    P14_post_low = P14_post_mu - np.exp(logP14_mu- logP14_std)
    P14 = P14_post_mu
    P14u = P14_post_up
    P14l = P14_post_low
    alpha = np.mean(alpha_)
    std_alpha = np.std(alpha_)
    mu = np.exp(np.mean(np.log(S14_)))
    S14 = mu
    S14u = np.exp(np.mean(np.log(S14_)) + np.std(np.log(S14_))) - mu
    S14l = mu - np.exp(np.mean(np.log(S14_)) - np.std(np.log(S14_)))
    if plot:
        plt.hist(alpha_,bins=binning)
        plt.xlabel(r"$\alpha$")
        plt.ylabel(r"Count")
        plt.title("alpha")
        if plotDir is not None:
            plt.savefig("{}/{}-alpha-posterior.png".format(plotDir,name),format='png')
            plt.clf()
        else:
            plt.show()
        plt.hist(S14_,bins=binning)
        plt.xlabel(r"$S_{\rm 1.4GHz}[mJy]$")
        plt.ylabel(r"Count")
        plt.title("S14")
        if plotDir is not None:
            plt.savefig("{}/{}-S14-posterior.png".format(plotDir,name),format='png')
            plt.clf()
        else:
            plt.show() 
        plt.hist(np.log10(S14_),bins=binning)
        plt.xlabel(r"$\log_{10}{S_{\rm 1.4GHz}[mJy]}$")
        plt.ylabel(r"Count")
        plt.title("log(S14)")
        if plotDir is not None:
            plt.savefig("{}/{}-logS14-posterior.png".format(plotDir,name),format='png')
            plt.clf()
        else:
            plt.show()
    print("---------")
    print("Results for source {}".format(name))
    print("Max Likelihood: {}".format(maxL))
    print("alpha: {} +- {}".format(alpha,std_alpha))
    print("MAP alpha: {}".format(alphaMAP))
    print("S14: {} + {} - {} mJy".format(S14,S14u,S14l))  
    print("MAP S14: {} mJy".format(S14MAP))
    for fi in range(len(nuModel)):
        mu = S_post_mu[fi]
        up = S_post_up[fi]
        low = S_post_low[fi]
        print("(lognormal) S{}MHz: {} + {} - {} mJy".format(int(nuModel[fi]/1e6),mu,up,low)) 
    print("(lognormal) P14: {} + {} - {} mJy".format(P14_post_mu,
                                     P14_post_up, 
                                     P14_post_low))
    #plot the Gassuan model and data
    if plot:
        plt.errorbar(nu, S, yerr=np.sqrt(CdCt), fmt='x',label='data')
        plt.errorbar(nuModel, S_post_mu, yerr=[S_post_up,S_post_low], fmt='--o',label='model')
        plt.xlabel(r"$\nu$ [Hz]")
        plt.ylabel(r"$S(\nu)$ [mJy]")
        #plt.plot(nu,S_map,label='map')
        #plt.errorbar(nu, S_model, yerr=CdCt[idx,mask], fmt='--o')
        plt.legend()
        points = []
        for j in range(len(nuModel)):
            points.append((nuModel[j],S_post_mu[j] + S_post_up[j]))
            #points.append((nuModel[j],S_post_mu[j] - S_post_low[j]))
        for j in range(len(nuModel)):
            #points.append((nuModel[j],S_post_mu[j] + S_post_up[j]))
            points.append((nuModel[-j-1],S_post_mu[-j-1] - S_post_low[-j-1]))
            
        plt.gca().add_collection(PatchCollection([Polygon(points,True)],alpha=0.4))
        plt.yscale('log')
        plt.xscale('log')
        if plotDir is not None:
            plt.savefig("{}/{}-fluxes-posterior.png".format(plotDir,name),format='png')
            plt.clf()
        else:
            plt.show()
    print("--------")
    return alpha,std_alpha,S14,S14u,S14l,S_post_mu,S_post_up,S_post_low,P14_post_mu,P14_post_up,P14_post_low
    
if __name__ == '__main__':
    names = ['C1+2','NW1','NW2','H','E','X1','X2','S']
    nu = np.array([147.667e6,322.667e6,608.046e6])
    rms = np.array([1.4e-3,120e-6,90e-6])*1e3
    beams = np.array([43.3*18.9,17.5*9.5,7.2*4.9])*np.pi/4./np.log(2.)
    print("Beams: {} (arcsec^2)".format(beams))
    pixels = np.array([5.25**2,2**2,1.25**2])
    print("px/beam: {} (pixels)".format(beams/pixels))
    print("Uncertainty per px: {} mJy".format(rms*np.sqrt(pixels/beams)))
    #measurement mask
    detectionMask = np.bitwise_not(np.array([[0,0,0],
                  [0,0,0],
                 [0,0,0],
                 [0,0,0],
                 [0,0,0],
                 [0,0,0],
                 [0,0,0],
                 [0,0,0]],dtype=np.bool))
    #measurements
    S = np.array([[  66.034     ,    7.653     ,    4.241     ],
        [ 159.14      ,   62.206     ,   45.998     ],
        [ 147.575     ,   77.056     ,   46.834     ],
        [  19.28183596,    6.89683661,    2.9826925 ],
        [  57.346     ,   22.343     ,    7.6797    ],
        [  40.672     ,    4.556     ,    0.48076422],
        [   9.45811655,    5.508     ,    4.426     ],
        [  32.342     ,   15.314     ,    9.277     ]],dtype=np.double)
    std_d = np.array([[  6.58200000e+00,   2.94200000e-01,   3.12511200e-01],
        [  7.85100000e+00,   3.86200000e-01,   1.05200000e-01],
        [  8.11100000e+00,   3.54800000e-01,   3.58600000e-01],
        [  1.40738833e+00,   2.66343558e-01,   4.32929199e-01],
        [  7.16500000e+00,   3.11300000e-01,   2.90741019e-04],
        [  7.82100000e+00,   2.09200000e-01,   8.90090959e-02],
        [  1.40738833e+00,   2.27200000e-01,   2.34200000e-01],
        [  8.07500000e+00,   2.77200000e-01,   3.67694221e-01]],dtype=np.double)
    S = np.array([[66.034,7.653,2.357 + 1.884],#c12
                  [159.140,62.206,45.998],#nw1
                 [147.575,77.056,46.834],#nw2
                 [648.7*pixels[0]/beams[0],324.8*pixels[1]/beams[1],76.31*pixels[2]/beams[2]],#h
                 [57.346,22.343,(7.619+6.07E-2)],#e
                 [40.672,4.556,12.3*pixels[2]/beams[2]],#x1
                 [318.2*pixels[0]/beams[0],5.508,4.426],#x2
                 [32.342,15.314,3.744+5.533]],dtype=np.double)#s
    std_d = np.array([[6.582,2.942E-1,np.sqrt(2.086E-1**2 + 2.327E-1**2)],#c12
                 [7.851,3.862E-1,1.052E-1],#nw1
                 [8.111,3.548E-1,3.586E-1],#nw2
                 [rms[0]*np.sqrt(937.1/beams[0]),rms[1]*np.sqrt(928./beams[1]),rms[2]*np.sqrt(925./beams[2])],#h
                 [7.165,3.113E-1,np.sqrt(1.845E-4**2 + 2.247E-4**2)],#e
                 [7.821,2.092E-1,rms[2]*np.sqrt(39.1/beams[2])],#x1
                 [rms[0]*np.sqrt(937.1/beams[0]),2.272E-1,2.342E-1],#x2
                 [8.075,2.772E-1,np.sqrt(1.900E-1**2 + 3.148E-1**2)]],dtype=np.double)#s
    Cd = std_d**2
    Ct = (S*0.15)**2
    CdCt = Cd + Ct
    #previous estimates
    #alpha0 = np.array([-2.5501,-0.8804,-0.8458, -1.4624, -0.1102, -0.8988, -0.3312, -0.7236],dtype=np.double)
    #S140 = np.array([0.4034,20.5293, 23.2775, 0.113, 13.2874, 1.1842, 3.0169, 6.2674],dtype=np.double)
    #P0 = np.array([0.4,13,15,2.1,5.7,0.9,2.3,3.7],dtype=np.double)
    
    #samples    
    m = S.shape[0]
    #posterior moments
    alpha = np.zeros(m,dtype=np.double)
    std_alpha = np.zeros(m,dtype=np.double)
    S14 = np.zeros(m,dtype=np.double)
    S14u = np.zeros(m,dtype=np.double)
    S14l = np.zeros(m,dtype=np.double)
    P14 = np.zeros(m,dtype=np.double)
    P14u = np.zeros(m,dtype=np.double)
    P14l = np.zeros(m,dtype=np.double)
    S_post_mu = np.zeros([m,3],dtype=np.double)
    S_post_up = np.zeros([m,3],dtype=np.double)
    S_post_low = np.zeros([m,3],dtype=np.double)
    idx = 0
    while idx < m:
        mask = detectionMask[idx,:]
        alpha_,std_alpha_,S14_,S14u_,S14l_, S_post_mu_,S_post_up_,S_post_low_,P14_post_mu_,P14_post_up_,P14_post_low_ = MHSolveSpectealIndex(nu[mask],S[idx,mask],
                                                                                                                                             Cd[idx,mask],Ct[idx,mask],
                                                                                                                                             names[idx],0.516,0.002,nuModel=nu,plot=True,
                                                                                                                                            plotDir=None) 
        alpha[idx] = alpha_
        std_alpha[idx] = std_alpha_
        S14[idx] = S14_
        S14u[idx] = S14u_
        S14l[idx] = S14l_
        S_post_mu[idx,:] = S_post_mu_
        S_post_up[idx,:] = S_post_up_
        S_post_low[idx,:] = S_post_low_
        P14[idx] = P14_post_mu_
        P14u[idx] = P14_post_up_
        P14l[idx] = P14_post_low_
        idx += 1
        
    i = 0
    while i < len(alpha):
        print(r"{} & ${:.2g} \pm {:.2g}$ & ${:.2g} \pm {:.2g}$ & ${:.2g} \pm {:.2g}$ & ${:.2g} \pm {:.2g}$ & ${:.2g}^{{{:.2g}}}_{{{:.2g}}}$ & ${:.2g}^{{{:.2g}}}_{{{:.2g}}}$\\".format(names[i],
                                                                                                  S[i,0],np.sqrt(CdCt[i,0]),
                                                                                                 S[i,1],np.sqrt(CdCt[i,1]),
                                                                                                 S[i,2],np.sqrt(CdCt[i,2]),
                                                                                                 alpha[i],std_alpha[i],
                                                                                                 S14[i],S14u[i],S14l[i],
                                                                                                 P14[i],P14u[i],P14l[i]))
        i += 1


Beams: [ 927.28689232  188.37621839   39.97541645] (arcsec^2)
px/beam: [ 33.64306185  47.0940546   25.58426653] (pixels)
Uncertainty per px: [ 0.24136833  0.01748631  0.01779328] mJy
Working on source C1+2
Initial L: 9.345961954855219e-245
Converged in 79776 steps
Acceptance: 2500, rate : 0.031337745687926195
---------
Results for source C1+2
Max Likelihood: 0.005908494371457167
alpha: -1.9273435186182524 +- 0.37507072470338765
MAP alpha: -1.9745340770665338
S14: 0.5527914786364434 + 0.41571841514436314 - 0.23727749079253185 mJy
MAP S14: 0.5382750708731132 mJy
(lognormal) S147MHz: 42.19649876185541 + 15.714049476622819 - 11.450036123876174 mJy
(lognormal) S322MHz: 9.354035071060595 + 1.1429322367698678 - 1.018487331918795 mJy
(lognormal) S608MHz: 2.7582204377088226 + 0.8284834663050393 - 0.637114211326204 mJy
(lognormal) P14: 0.5786707983221794 + 0.29275821835997784 - 0.19440554387178233 mJy
--------
Working on source NW1
Initial L: 0.03639598753467122
Converged in 128530 steps
Acceptance: 2500, rate : 0.019450711896055396
---------
Results for source NW1
Max Likelihood: 0.3712008177274933
alpha: -0.8779117325460012 +- 0.18868195170593835
MAP alpha: -0.8727344638393251
S14: 19.249191290300875 + 6.626122047537148 - 4.92931193298468 mJy
MAP S14: 19.951426951812888 mJy
(lognormal) S147MHz: 138.67424477641853 + 25.550039117950035 - 21.5749601378604 mJy
(lognormal) S322MHz: 69.81844120718404 + 6.629943636032053 - 6.054965463411264 mJy
(lognormal) S608MHz: 40.02992194732944 + 6.653943248968737 - 5.705543612941867 mJy
(lognormal) P14: 13.02148417001432 + 3.2455938049440025 - 2.5980356409696963 mJy
--------
Working on source NW2
Initial L: 0.9811460174097606
Converged in 132720 steps
Acceptance: 2500, rate : 0.018836648583484026
---------
Results for source NW2
Max Likelihood: 0.994767794216708
alpha: -0.8036772959617937 +- 0.16044196354220117
MAP alpha: -0.818985643166825
S14: 23.27965403095864 + 6.73302240378402 - 5.222540964768495 mJy
MAP S14: 23.453460238328425 mJy
(lognormal) S147MHz: 141.92023953359595 + 24.05262232834494 - 20.566940185012214 mJy
(lognormal) S322MHz: 75.72148461734498 + 7.48709389745639 - 6.813406448038464 mJy
(lognormal) S608MHz: 45.505269143301106 + 6.784319910542699 - 5.904087392341204 mJy
(lognormal) P14: 15.269475105526329 + 3.2650869288410114 - 2.68990243658698 mJy
--------
Working on source H
Initial L: 8.33919603937688e-09
Converged in 107659 steps
Acceptance: 2500, rate : 0.023221467782535598
---------
Results for source H
Max Likelihood: 0.999544658950585
alpha: -1.3171699208545307 +- 0.1955169953447675
MAP alpha: -1.3134082039367216
S14: 0.9621399370089945 + 0.3768054682419295 - 0.2707650275038609 mJy
MAP S14: 1.0017847942561613 mJy
(lognormal) S147MHz: 18.616950546815545 + 3.34649515114155 - 2.836601123099511 mJy
(lognormal) S322MHz: 6.649169804849519 + 0.7674519462936091 - 0.6880380959406418 mJy
(lognormal) S608MHz: 2.886065098279546 + 0.5818697655566574 - 0.4842403586149038 mJy
(lognormal) P14: 0.7813977761984569 + 0.22686862245917527 - 0.17582122870981676 mJy
--------
Working on source E
Initial L: 3.686085763760527e-21
Converged in 128825 steps
Acceptance: 2500, rate : 0.019406171162429653
---------
Results for source E
Max Likelihood: 0.6964178058303124
alpha: -1.419668073316915 +- 0.1683053403347885
MAP alpha: -1.4303067491278878
S14: 2.4103013612784183 + 0.6868904368663444 - 0.5345529314715995 mJy
MAP S14: 2.4557334995803015 mJy
(lognormal) S147MHz: 58.730867302795694 + 11.429092891896723 - 9.567287897008995 mJy
(lognormal) S322MHz: 19.36110466244512 + 2.034455981077734 - 1.841004114688058 mJy
(lognormal) S608MHz: 7.87522909931089 + 1.1256601596078406 - 0.9848839808905199 mJy
(lognormal) P14: 2.042701964421124 + 0.42396044256219145 - 0.3510917531344593 mJy
--------
Working on source X1
Initial L: 0.0
C:\Users\josh\Anaconda3\envs\compute\lib\site-packages\ipykernel_launcher.py:87: RuntimeWarning: divide by zero encountered in double_scalars
Converged in 86819 steps
Acceptance: 2500, rate : 0.02879554014674207
---------
Results for source X1
Max Likelihood: 0.530155691818247
alpha: -3.108053717197623 +- 0.24529914523349275
MAP alpha: -3.117082024829818
S14: 0.0392165791998012 + 0.017186854456080584 - 0.011949798004931466 mJy
MAP S14: 0.04075554273041413 mJy
(lognormal) S147MHz: 42.61427930720599 + 12.57538925908564 - 9.709990369661718 mJy
(lognormal) S322MHz: 3.7537101588559905 + 0.5778747385352077 - 0.5007807368366013 mJy
(lognormal) S608MHz: 0.5238182874806313 + 0.11090286748389033 - 0.09152515189973465 mJy
(lognormal) P14: 0.06709975051048614 + 0.02101326137710699 - 0.016002002038180786 mJy
--------
Working on source X2
Initial L: 0.12866953192029082
Converged in 102922 steps
Acceptance: 2500, rate : 0.024290239210275743
---------
Results for source X2
Max Likelihood: 0.8324632818886533
alpha: -0.5058801596048667 +- 0.20705310424104348
MAP alpha: -0.5260722140641654
S14: 2.716081572390427 + 0.9542865326290784 - 0.7061744195383426 mJy
MAP S14: 2.713408230216085 mJy
(lognormal) S147MHz: 8.474402804438478 + 1.955938434452321 - 1.5891531997465576 mJy
(lognormal) S322MHz: 5.706599697753342 + 0.614698956120896 - 0.5549240859010665 mJy
(lognormal) S608MHz: 4.14160192046123 + 0.6692183613611231 - 0.576125460577638 mJy
(lognormal) P14: 1.5739260920034261 + 0.3909128514454976 - 0.3131391194382247 mJy
--------
Working on source S
Initial L: 0.5024940003807835
Converged in 92221 steps
Acceptance: 2500, rate : 0.027108793008100106
---------
Results for source S
Max Likelihood: 0.9650440666817541
alpha: -0.8270578077500623 +- 0.23805352810709424
MAP alpha: -0.8612729573555803
S14: 4.501115233720177 + 1.719738591265279 - 1.2443214048963318 mJy
MAP S14: 4.455932626238705 mJy
(lognormal) S147MHz: 28.921916739293174 + 8.348468132365305 - 6.478433240127888 mJy
(lognormal) S322MHz: 15.151821601407077 + 1.855104102738684 - 1.6527505855971967 mJy
(lognormal) S608MHz: 8.971674777783155 + 1.4637172861167365 - 1.2584093992105432 mJy
(lognormal) P14: 2.9812096533838526 + 0.7805167770320858 - 0.6185681477264735 mJy
--------
C1+2 & $66 \pm 12$ & $7.7 \pm 1.2$ & $4.2 \pm 0.71$ & $-1.9 \pm 0.38$ & $0.55^{0.42}_{0.24}$ & $0.58^{0.29}_{0.19}$\\
NW1 & $1.6e+02 \pm 25$ & $62 \pm 9.3$ & $46 \pm 6.9$ & $-0.88 \pm 0.19$ & $19^{6.6}_{4.9}$ & $13^{3.2}_{2.6}$\\
NW2 & $1.5e+02 \pm 24$ & $77 \pm 12$ & $47 \pm 7$ & $-0.8 \pm 0.16$ & $23^{6.7}_{5.2}$ & $15^{3.3}_{2.7}$\\
H & $19 \pm 3.2$ & $6.9 \pm 1.1$ & $3 \pm 0.62$ & $-1.3 \pm 0.2$ & $0.96^{0.38}_{0.27}$ & $0.78^{0.23}_{0.18}$\\
E & $57 \pm 11$ & $22 \pm 3.4$ & $7.7 \pm 1.2$ & $-1.4 \pm 0.17$ & $2.4^{0.69}_{0.53}$ & $2^{0.42}_{0.35}$\\
X1 & $41 \pm 9.9$ & $4.6 \pm 0.71$ & $0.48 \pm 0.11$ & $-3.1 \pm 0.25$ & $0.039^{0.017}_{0.012}$ & $0.067^{0.021}_{0.016}$\\
X2 & $9.5 \pm 2$ & $5.5 \pm 0.86$ & $4.4 \pm 0.7$ & $-0.51 \pm 0.21$ & $2.7^{0.95}_{0.71}$ & $1.6^{0.39}_{0.31}$\\
S & $32 \pm 9.4$ & $15 \pm 2.3$ & $9.3 \pm 1.4$ & $-0.83 \pm 0.24$ & $4.5^{1.7}_{1.2}$ & $3^{0.78}_{0.62}$\\

In [2]:
from matplotlib.ticker import MaxNLocator

def plotSpectrum(nu,S,CdCt,S_post_mu,S_post_up,S_post_low, mask, ax, name):
    ax.errorbar(nu[mask], S[mask], yerr=np.sqrt(CdCt[mask]), c='black', lw=1.,fmt='--.',label='data')
    #ax.errorbar(nu, S_post_mu, yerr=[S_post_up,S_post_low], fmt='--o',label='model')
    ax.plot(nu, S_post_mu, c='orange',ls='-',label='model')
    points = []
    for j in range(len(nu)):
        points.append((nu[j],S_post_mu[j] + S_post_up[j]))
        #points.append((nuModel[j],S_post_mu[j] - S_post_low[j]))
    for j in range(len(nu)):
        #points.append((nuModel[j],S_post_mu[j] + S_post_up[j]))
        points.append((nu[-j-1],S_post_mu[-j-1] - S_post_low[-j-1]))

    ax.add_collection(PatchCollection([Polygon(points,True)],alpha=0.4))

    #ax.set_ylim([])
    ax.set_yscale('log')
    ax.set_xscale('log')
    ylims = list(ax.get_ylim())
    ylims[0] = 10**(np.floor(np.log10(np.min(S_post_mu - S_post_low))))
    ylims[1] = 10**(np.ceil(np.log10(np.max(S_post_mu+S_post_up))))
    ax.set_ybound(lower=ylims[0],upper=ylims[1])
    ax.set_ylim(ylims[0],ylims[1])
    ax.set_yticks([10**e for e in range(int(np.log10(ylims[0])),int(np.log10(ylims[1])+1))])
    ylabs = [r"$10^{{{:d}}}$".format(int(np.log10(tick))) for tick in ax.get_yticks()]
    #ylabs[0] = " "
    #ylabs[1] = " "
    #print(name,ylabs)
    ax.set_yticklabels(ylabs)
    ax.set_xbound(lower=100e6,upper=1500e6)
    ax.annotate(s=name,xy=(0.05,0.05),xycoords='axes fraction',weight='bold')
    #ax.set_xticks([])#('right')
    ax.set_xticklabels([])
    
    return ax
    
f, axs = plt.subplots(4,2,figsize=(5,7))
cols= 2
rows = 4
i=0
while i < len(alpha):
    #i = row*2 + col
    col = i%cols
    row = (i - col)//cols
    if rows == 1:
        if cols == 1:
            ax = axs
        else:
            ax = axs[col]
    else:
        ax = axs[row][col]
    #plt.figure()
    #ax = plt.subplot(111)
    mask = detectionMask[i,:]
    mask[:] = True
    plotSpectrum(np.append(nu,1400e6),np.append(S[i,:],0),np.append(CdCt[i,:],0),np.append(S_post_mu[i,:],S14[i]),
                 np.append(S_post_up[i,:],S14u[i]),np.append(S_post_low[i,:],S14l[i]),np.append(mask,False), ax,names[i])
    if col==1:
        ax.yaxis.set_label_position('right')
        ax.yaxis.tick_right()
    if row != 0:
        ax.get_yticklabels()[-1].set_visible(False)
    #ax.yaxis.set_ticks(ax.yaxis.get_ticklocs()[0:-1])
    if row == rows - 1:
        ax.xaxis.set_ticks((list(nu) + [1400e6]))
        ax.xaxis.set_ticklabels(["{:3d}".format(int(f/1e6)) for f in (list(nu) + [1400e6])])
        ax.set_xlabel(r"$\nu$ [MHz]")
    if i == 0:
        ax.legend(frameon=False,loc='upper right')
    if col == 0:
        ax.set_ylabel(r"$S(\nu)$ [mJy]")
    i += 1
#axs[-1][0].set_xlabel(r'$\nu$ [Hz]')
#axs[-1][1].set_xlabel(r'$\nu$ [Hz]')
#axs[4>>1][0].set_ylabel(r'$S(\nu)$ [mJy]')
f.subplots_adjust(hspace=0,wspace=0)
plt.savefig("spix_v2.pdf")


#plt.setp([ax.get_xticklabels() for ax in f.axes],visible=False)
#plt.setp([ax.get_yticklabels() for ax in f.axes],visible=False)
plt.show()