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'
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])
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'
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
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)