Example #1
0
def all(epos):
    if hasattr(epos, 'chain'):
        print '\nPlotting chain...'
        chain(epos)
        try:
            corners(epos)
        except NameError:
            print '  (skipping corner plot)'

        if epos.Parametric:
            parametric.oneD(epos, MCMC=True)
            parametric.twoD(epos, MCMC=True)
            if epos.Multi:
                parametric.oneD_x(epos, MCMC=True, Log=False)

        # plot sample from posterior
        if hasattr(epos, 'plotsample'):
            periodradius.panels(epos, MCMC=True)
            if epos.Multi:
                multi.multiplicity(epos, MCMC=True)
                multi.periodratio(epos, MCMC=True)
                multi.periodinner(epos, MCMC=True)

    else:
        print '\nNo chain to plot, did you run EPOS.run.mcmc()? \n'
Example #2
0
def prep_obs(epos):
    # occurrence pdf on sma from plot_input_diag?

    # cdf of obs, zoomed only
    z = epos.obs_zoom = {}
    ix = (epos.xzoom[0] <= epos.obs_xvar) & (epos.obs_xvar <= epos.xzoom[1])
    iy = (epos.yzoom[0] <= epos.obs_yvar) & (epos.obs_yvar <= epos.yzoom[1])

    if np.sum(ix & iy) == 0:
        raise ValueError('No planets in the box!')

    x = epos.obs_xvar[ix & iy]
    y = epos.obs_yvar[ix & iy]

    for key, var in zip(['x', 'y'], [x, y]):
        z[key] = np.sort(var)  # add (x0,0) and (x1,1)?
        z[key + ' cum'] = np.arange(z[key].size, dtype=float)
        z[key + ' cdf'] = z[key + ' cum'] / z[key + ' cum'][-1]

    # multis
    z['multi'] = {}
    z['multi']['bin'], z['multi']['count'] = multi.frequency(
        epos.obs_starID[ix & iy])
    z['multi']['pl cnt'] = z['multi']['bin'] * z['multi']['count']

    z['multi']['Pratio'], z['multi']['Pinner']= \
     multi.periodratio(epos.obs_starID[ix&iy], epos.obs_xvar[ix&iy])
    z['multi']['cdf'] = multi.cdf(epos.obs_starID[ix & iy])
Example #3
0
def all(epos, color='C1'):

    if hasattr(epos, 'synthetic_survey'):
        print '\nPlotting output...'

        if epos.MonteCarlo:
            periodradius.periodradius(epos, SNR=False)
            periodradius.periodradius(epos, SNR=True)
            if not epos.Parametric:
                periodradius.periodradius(epos,
                                          Model=True,
                                          SNR=False,
                                          color=color)
        else:
            # plot period-radius for non-MC
            pass

        periodradius.cdf(epos, color=color)
        periodradius.panels(epos, color=color)

        if epos.Multi:
            multi.periodradius(epos)
            multi.periodradius(epos, Nth=True)

            multi.multiplicity(epos, MC=True, color=color)
            multi.multiplicity(epos, MC=True, Planets=True, color=color)
            multi.multiplicity_cdf(epos, MC=True)
            multi.periodratio(epos, MC=True, color=color)
            if epos.Parametric and epos.spacing is not None:
                multi.periodratio(epos, MC=True, Input=True, color=color)
            multi.periodratio_cdf(epos, MC=True, color=color)
            multi.periodinner(epos, MC=True, color=color)
            if epos.Parametric and epos.spacing is not None:
                multi.periodinner(epos, MC=True, Input=True, color=color)
            multi.periodinner_cdf(epos, MC=True, color=color)
            # pdf per subgroup
            #periodradius.pdf(epos)
            #periodradius.pdf_3d(epos)

        if epos.MassRadius:
            massradius.massradius(epos, MC=True, color=color)
            massradius.massradius(epos, MC=True, Log=True, color=color)

        else:
            if epos.Parametric and epos.Multi and not epos.RV:
                multi.periodratio(epos, MC=True, N=True)
                if epos.spacing is not None:
                    multi.periodratio(epos, MC=True, N=True, Input=True)
                multi.periodinner(epos, MC=True, N=True)

    else:
        print '\nNo output to plot, did you run EPOS.run.once()? \n'
Example #4
0
def MC(epos,
       fpara,
       Store=False,
       Sample=False,
       StorePopulation=False,
       Extra=None,
       Verbose=True):
    ''' 
	Do the Monte Carlo Simulations
	Note:
	variable x/X is P
	variable y/Y is R/M
	TODO: split into multiple functions
	'''
    if Verbose: tstart = time.time()
    #if not Store: logging.debug(' '.join(['{:.3g}'.format(fpar) for fpar in fpara]))
    ''' Seed the random number generator '''
    if epos.seed is not None: np.random.seed(epos.seed)
    ''' construct 1D arrays allP, allR or allM
	dimension equal to sample size * planets_per_star
	also keeping track of:
		ID: star identifier
		I: inc
		N: Nth planet in system
		dP: period ratio
	'''
    if epos.Parametric:
        ''' parameters within bounds? '''
        try:
            epos.pdfpars.checkbounds(fpara)
        except ValueError as message:
            if Store: raise
            else:
                logging.debug(message)
                return -np.inf
        ''' Draw (inner) planet from distribution '''
        pps = epos.fitpars.getpps_fromlist(fpara)
        fpar2d = epos.fitpars.get2d_fromlist(fpara)
        npl = epos.fitpars.getmc('npl', fpara) if epos.RandomPairing else 1

        try:
            sysX, sysY = draw_from_2D_distribution(epos, pps, fpar2d, npl=npl)
        except ValueError:
            if Store: raise
            else: return -np.inf
        ''' Multi-planet systems '''
        if not epos.Multi:
            allX = sysX
            allY = sysY

        elif epos.RandomPairing:
            # set ID, nth planet in system
            isys = np.arange(sysX.size / npl)
            allID = np.repeat(isys, npl)
            order = np.lexsort((sysX, allID))  # sort by ID, then P
            assert np.all(allID[order] == allID)

            allX = sysX[order]
            allY = sysY  #[order] # random order anyway
            allN = np.tile(np.arange(npl), isys.size)  # ignores xzoom

            # isotropic or inc?
            dInc = epos.fitpars.getmc('inc', fpara)
            if dInc is not None:
                f_iso = epos.fitpars.getmc('f_iso', fpara)
                allI = np.random.rayleigh(dInc, allID.size)

            f_cor = epos.fitpars.getmc('f_cor', fpara)
            f_dP, f_inc = 1.0, 1.0  # no need to fudge these

        else:
            ''' retrieve fit parameters for multi-planets'''
            npl = epos.fitpars.getmc('npl', fpara)
            dR = epos.fitpars.getmc('dR', fpara)
            dInc = epos.fitpars.getmc('inc', fpara)
            f_iso = epos.fitpars.getmc('f_iso', fpara)
            f_cor = epos.fitpars.getmc('f_cor', fpara)

            f_dP, f_inc = 1.0, 1.0  # no need to fudge these
            ''' Parameter bounds '''
            if npl < 1:
                logging.debug('npl = {:.3g} < 1'.format(npl))
                if Store: raise ValueError('at least one planet per system')
                return -np.inf
            if (dInc <= 0) or (dR <= 0) or not (0 <= f_iso <= 1):
                if Store: raise ValueError('parameters out of bounds')
                return -np.inf
            ''' Draw multiplanet distributions '''
            allX, allY, allI, allN, allID= \
             draw_multi(epos, sysX, sysY, npl, dInc, dR, fpara, Store)
        ''' convert to observable parameters '''
        allP = allX
        if epos.RV or epos.MassRadius: allM = allY
        else: allR = allY

    else:
        pfm = epos.pfm
        ''' parameters within bounds? '''
        # move out of loop?
        try:
            epos.fitpars.checkbounds(fpara)
        except ValueError as message:
            if Store: raise
            else:
                logging.debug(message)
                return -np.inf
        ''' Fit parameters'''
        pps = epos.fitpars.getpps_fromlist(fpara)

        f_cor = epos.fitpars.getmc('f_cor', fpara)
        f_iso = epos.fitpars.getmc('f_iso', fpara)
        f_inc = epos.fitpars.getmc('f_inc', fpara)
        f_dP = epos.fitpars.getmc('f_dP', fpara)

        # need this here?
        if not (0 <= f_iso <= 1) or not (0 < pps) or not (0 <= f_cor <= 1):
            #\or not (0<=f_dP<=10) or not (0 <= f_inc < 10):
            if Store: raise ValueError('parameters out of bounds')
            return -np.inf
        ''' 
		Draw from all
		'''
        if not 'draw prob' in pfm:
            ndraw = int(round(1. * epos.nstars * pps / pfm['ns']))
            if Verbose:
                print '  {} planets in {} simulations'.format(
                    pfm['np'], pfm['ns'])
                print '  {} stars in survey, {} draws, eta={:.2g}'.format(
                    epos.nstars, ndraw, pps)

            allP = np.tile(pfm['P'], ndraw)
            allM = np.tile(pfm['M'], ndraw)
            if 'R' in pfm:
                allR = np.tile(pfm['R'], ndraw)

            if epos.Multi:
                allI = np.tile(pfm['inc'], ndraw)
                allN = np.tile(pfm['kth'], ndraw)

                # ID or system index?
                allID= np.tile(pfm['ID'], ndraw) \
                  + np.repeat(np.arange(ndraw)*pfm['ns'], pfm['np'])
        else:
            '''
			Draw from some distributions according to 'tag' parameter
			TODO: functions to calculate draw probability from tag
			'''
            #draw planetary systems from simulations
            ndraw = int(round(1. * epos.nstars * pps))
            if Verbose: print '\nDraw {} systems'.format(ndraw)
            system_index = np.random.choice(pfm['system index'],
                                            size=ndraw,
                                            p=pfm['draw prob'])

            #create a list of planets
            indexlist = [
                pfm['planet index'][pfm['ID'] == i] for i in system_index
            ]
            starIDlist = [
                np.full((pfm['ID'] == i).sum(), ID)
                for ID, i in enumerate(system_index)
            ]

            planets = np.concatenate(indexlist)
            allID = np.concatenate(starIDlist)
            allP = pfm['P'][planets]
            allM = pfm['M'][planets]
            allR = pfm['R'][planets]
            allI = pfm['inc'][planets]
            allN = pfm['kth'][planets]
            #allID= pfm['ID'][planets]

            if Verbose: print '  {} planets'.format(allP.size)

        allY = allM

        dInc = False  # Isotropic inclinations not implemented
    ''' 
	Identify transiting planets (itrans is a T/F array)
	'''
    if epos.RV:
        # RV keep all
        itrans = np.full(allP.size, True, np.bool)
    elif (not epos.Multi) or (epos.Multi and dInc == None):
        # geometric transit probability
        p_trans = epos.fgeo_prefac * allP**epos.Pindex
        itrans = p_trans >= np.random.uniform(0, 1, allP.size)
    else:
        #multi-transit probability
        itrans = istransit(epos,
                           allID,
                           allI,
                           allP,
                           f_iso,
                           f_inc,
                           Verbose=Verbose)

    # Print multi statistics
    if Verbose and epos.Multi and not epos.RV:
        print '\n  {} planets, {} transit their star'.format(
            itrans.size, itrans.sum())
        multi.frequency(allID[itrans], Verbose=True)
    '''
	remove planets according to transit probability
	'''
    MC_P = allP[itrans]
    if epos.MassRadius or epos.RV: MC_M = allM[itrans]
    else: MC_R = allR[itrans]
    if epos.Multi:
        MC_ID = allID[itrans]
        if epos.Parametric:
            MC_N = allN[itrans]  # also for PFM?
        else:
            #MC_P*= (1.+0.1*np.random.normal(size=MC_ID.size) )
            pass
    '''
	Set the observable MC_Y (R or Msin i) 
	'''
    if epos.RV:
        ''' M sin i.'''
        # Note different conventions for i in Msini (i=0 is pole-on)
        # sin(arccos(chi)) == cos(arcsin(chi)) == sqrt(1-chi^2)
        MC_Y = MC_Msini = MC_M * np.sqrt(
            1. - np.random.uniform(0, 1, MC_P.size)**2.)
    else:
        ''' Convert Mass to Radius '''
        if epos.MassRadius:
            mean, dispersion = epos.MR(MC_M)
            MC_R = mean + dispersion * np.random.normal(size=MC_M.size)
        ''' uncertainty in stellar radius? '''
        MC_Y = MC_R * (1. +
                       epos.radiusError * np.random.normal(size=MC_R.size))
    '''
	Store (transiting) planet sample for verification plot
	'''
    if Store:
        tr = epos.transit = {}
        tr['P'] = MC_P
        tr['Y'] = MC_Y
    '''
	Identify detectable planets based on SNR (idet is a T/F array)
	'''
    f_snr = interpolate.RectBivariateSpline(epos.MC_xvar, epos.MC_yvar,
                                            epos.MC_eff)
    p_snr = f_snr(MC_P, MC_Y, grid=False)
    assert p_snr.ndim == 1

    idet = p_snr >= np.random.uniform(0, 1, MC_P.size)

    # draw same random number for S/N calc, 1=correlated noise
    if epos.Multi and f_cor > 0:
        IDsys, toplanet = np.unique(MC_ID, return_inverse=True)
        idet_cor = p_snr >= np.random.uniform(0, 1, IDsys.size)[toplanet]

        cor_sys = (np.random.uniform(0, 1, IDsys.size) < f_cor)
        cor_pl = cor_sys[toplanet]
        idet = np.where(cor_pl, idet_cor, idet)
    ''' 
	Remove undetectable planets
	'''
    # arrays with detected planets
    if epos.Multi:
        det_ID = MC_ID[idet]
        if not epos.RV and epos.Parametric: det_N = MC_N[idet]
    det_P = MC_P[idet]
    det_Y = MC_Y[idet]

    #if len(alldP)>0:
    # 	if not epos.Parametric and 'all_Pratio' in sg:
    # 		det_dP= MC_dP[idet]

    if Verbose and epos.Multi:
        print '  {} transiting planets, {} detectable'.format(
            idet.size, idet.sum())
        multi.frequency(det_ID, Verbose=True)
    '''
	Probability that simulated data matches observables
	TODO:
	- store ln prob, D
	- switches for in/excluding parameters
	- likelyhood from D instead of prob?
	'''
    # bugfix
    #np.seterr(divide='raise')

    tstart = time.time()
    prob = {}
    lnp = {}

    # make sure that x=P, y=R (where?)
    ix = (epos.xzoom[0] <= det_P) & (det_P <= epos.xzoom[1])
    iy = (epos.yzoom[0] <= det_Y) & (det_Y <= epos.yzoom[1])
    if (ix & iy).sum() < 1:
        if Store: raise ValueError('no planets detectable')
        return -np.inf

    if epos.goftype == 'KS':
        prob_2samp = _prob_ks
    elif epos.goftype == 'AD':
        prob_2samp = _prob_ad
    else:
        raise ValueError('{} not a goodness-of-fit type (KS, AD)'.format(
            epos.goftype))

    if 'xvar' in epos.summarystatistic:
        prob['xvar'], lnp['xvar'] = prob_2samp(epos.obs_zoom['x'],
                                               det_P[ix & iy])
    if 'yvar' in epos.summarystatistic:
        prob['yvar'], lnp['yvar'] = prob_2samp(epos.obs_zoom['y'],
                                               det_Y[ix & iy])

    if 'N' in epos.summarystatistic:
        # chi^2: (np-nobs)/nobs**0.5 -> p: e^-0.5 x^2
        chi2 = (epos.obs_zoom['x'].size -
                np.sum(ix & iy))**2. / epos.obs_zoom['x'].size
        lnp['N'] = -0.5 * chi2
        prob['N'] = np.exp(-0.5 * chi2)

    if epos.Multi:
        ''' Multi-planet frequency, pearson chi_squared '''
        k, Nk = multi.frequency(det_ID[ix & iy])
        Nk_obs = epos.obs_zoom['multi']['count']
        ncont = max(len(Nk), len(Nk_obs))

        # pad with zeros
        obs = np.zeros((2, ncont), dtype=int)
        obs[0, :len(Nk)] = Nk
        obs[1, :len(Nk_obs)] = Nk_obs
        # remove double zero frequencies
        obs = obs[:, ~((obs[0, :] == 0) & (obs[1, :] == 0))]

        try:
            _, prob['Nk'], _, _ = chi2_contingency(obs)
        except ValueError:
            #print Nk
            #print Nk_obs
            #print obs
            raise

        with np.errstate(divide='ignore'):
            lnp['Nk'] = np.log(prob['Nk'])
        ''' Period ratio, innermost planet '''
        sim_dP, sim_Pinner = multi.periodratio(det_ID[ix & iy], det_P[ix & iy])

        if (len(sim_dP) > 0) & (len(sim_Pinner) > 0):
            prob['dP'], lnp['dP'] = prob_2samp(
                epos.obs_zoom['multi']['Pratio'], f_dP * sim_dP)
            prob['Pin'], lnp['Pin'] = prob_2samp(
                epos.obs_zoom['multi']['Pinner'], sim_Pinner)
        else:
            logging.debug('no multi-planet statistics, {}'.format(len(sim_dP)))
            prob['dP'], prob['Pin'] = 0, 0
            lnp['dP'], lnp['Pin'] = -np.inf, -np.inf

    # combine with Fischer's rule:
    lnprob = np.sum([lnp[key] for key in epos.summarystatistic])
    #dof= len(prob_keys)
    chi_fischer = -2. * lnprob

    if Verbose:
        print '\nGoodness-of-fit'
        print '  logp= {:.1f}'.format(lnprob)
        print '  - p(n={})={:.2g}'.format(np.sum(ix & iy), prob['N'])
        if 'xvar' in prob: print '  - p(x)={:.2g}'.format(prob['xvar'])
        if 'yvar' in prob: print '  - p(y)={:.2g}'.format(prob['yvar'])
        if 'Nk' in prob: print '  - p(N_k)={:.2g}'.format(prob['Nk'])
        if 'dP' in prob: print '  - p(P ratio)={:.2g}'.format(prob['dP'])
        if 'Pin' in prob: print '  - p(P inner)={:.2g}'.format(prob['Pin'])

    tgof = time.time()
    if Verbose:
        print '  observation comparison in {:.3f} sec'.format(tgof - tstart)
    ''' Store _systems_ with at least one detected planet '''
    # StorePopulation
    if Store and epos.Multi and (not epos.RV):
        # include/exclude singles w/ iso_pl?
        itransdet = np.copy(itrans)
        itransdet[itrans] = idet
        isysdet, isingle, imulti, order = storepopulation(
            allID, allP, det_ID, itransdet)

        pop = epos.population = {}
        pop['order'] = order
        pop['P'] = allP
        pop['k'] = allN
        for key, subset in zip(['system', 'single', 'multi'],
                               [isysdet, isingle, imulti]):
            pop[key] = {}
            pop[key]['Y'] = allY[subset]  # R? M?
            pop[key]['P'] = allP[subset]
            pop[key]['order'] = order[subset]
    ''' Store detectable planet population '''
    if Store:
        ss = {}
        ss['P'] = det_P  # MC_P[idet]
        ss['Y'] = det_Y
        if epos.MassRadius:
            # or if has mass and radius
            ss['M'] = MC_M[idet]
            ss['R'] = MC_R[idet]

        #if len(alldP)>0
        if epos.Multi:
            ss['ID'] = det_ID
            ss['multi'] = {}
            ss['multi']['bin'], ss['multi']['count'] = multi.frequency(
                det_ID[ix & iy])
            ss['multi']['pl cnt'] = ss['multi']['bin'] * ss['multi']['count']
            ss['multi']['Pratio'], ss['multi']['Pinner']= \
             multi.periodratio(det_ID[ix&iy], det_P[ix&iy]) # *f_dP
            ss['multi']['cdf'] = multi.cdf(det_ID[ix & iy])
            if not epos.RV and epos.Parametric:
                ss['multi']['PN'], ss['multi']['dPN'] = multi.periodratio(
                    det_ID[ix & iy], det_P[ix & iy], N=det_N[ix & iy])

        epos.prob = prob
        epos.lnprob = lnprob
        ss['P zoom'] = det_P[ix & iy]
        ss['Y zoom'] = det_Y[ix & iy]
        ss['nobs'] = ss['P zoom'].size

        # Store as an extra model
        if Sample:
            return ss
        elif Extra is not None:
            ss['name'] = Extra
            if not hasattr(epos, 'ss_extra'):
                epos.ss_extra = []
            epos.ss_extra.append(ss)
            #print 'saving extra {}'.format(Extra)
        else:
            epos.synthetic_survey = ss
    else:
        # return probability
        if np.isnan(lnprob):
            return -np.inf
        return lnprob
Example #5
0
def all(epos, color=None, imin=1e-2):
    print '\nPlotting input...'

    #add decorators for zoom T/F?
    # color into epos?

    if epos.Parametric:
        parametric.oneD(epos)
        parametric.twoD(epos)
        parametric.panels(epos)

        # plot the input distribution converted from M->Msini or M->R
        if not epos.MonteCarlo and epos.Msini:
            parametric.oneD_y(epos, Convert=True)  # no conversion for x (yet)
            parametric.twoD(epos, Convert=True)
            parametric.panels(epos, Convert=True)

    else:
        if 'R' in epos.pfm:
            model.panels_radius(epos, color=color)
        if 'M' in epos.pfm:
            model.panels_mass(epos, color=color)

        model.period(epos, color=color)

        model.multiplicity(epos, color=color)
        if hasattr(epos, 'func'):
            if epos.MassRadius:
                model.panels_mass(epos, Population=True, color=color)
            else:
                model.panels_radius(epos,
                                    Population=True,
                                    Shade=False,
                                    color=color)  #Zoom?

        if hasattr(epos, 'occurrence'):
            # model counts (debiases data)
            if 'planet' in epos.occurrence:
                model.panels_radius(epos, Occurrence=True, color=color)
                if 'R' in epos.pfm or epos.MassRadius:
                    model.period(epos, Occurrence=True, color=color)
                if epos.Zoom:
                    model.panels_radius(epos,
                                        Occurrence=True,
                                        color=color,
                                        Zoom=True)

            # planet counts (biases model)
            if 'model' in epos.occurrence:
                model.panels_radius(epos, Observation=True, color=color)
                if epos.Zoom:
                    model.panels_radius(epos,
                                        Observation=True,
                                        color=color,
                                        Zoom=True)

        if 'tag' in epos.pfm:
            model.panels_radius(epos, Tag=True)  # Zoom?
            model.period(epos, Tag=True)

        if 'inc' in epos.pfm:
            model.inclination(epos, Simple=True, color=color, imin=imin)
        if 'dP' in epos.pfm:
            model.periodratio(epos, color=color, Simple=True)
            if 'R' in epos.pfm:
                model.periodratio_size(epos, color=color)
            if 'inc' in epos.pfm:
                model.periodratio_inc(epos, color=color, imin=imin)

    if epos.Multi:
        if epos.Parametric:
            multi.periodradius(epos, MC=False)
            multi.periodradius(epos, MC=False, Nth=True)
            multi.multiplicity(epos, MC=False)
            multi.periodratio(epos, MC=False)
            multi.periodratio_cdf(epos, MC=False)
            multi.periodinner(epos, MC=False)
            multi.periodinner_cdf(epos, MC=False)
        else:
            pass

    if epos.MassRadius:
        massradius.massradius(epos, MC=False)
        massradius.massradius(epos, MC=False, Log=True)