def integrated(epos, MCMC=False, Planets=False): f, (ax, axb) = plt.subplots(1,2, gridspec_kw = {'width_ratios':[20, 1]}) f.subplots_adjust(wspace=0) sy= 'M' if (epos.MassRadius or epos.RV) else 'R' ax.set_title('Occurrence'+ (' (dln'+sy+' dlnP)' if MCMC else ' (Initial Guess)')) helpers.set_axes(ax, epos, Trim=True, In=epos.MassRadius) ''' color scale? ''' cmap='jet' # cool, spring vmin, vmax= -5, 0 ticks=np.linspace(vmin, vmax, (vmax-vmin)+1) levels=np.linspace(vmin, vmax, 256) ''' 2D pdf ''' pps, pdf, _, _= periodradius(epos, Init=not MCMC) pdflog= np.log10(pdf) # in % cs= ax.contourf(epos.X_in, epos.Y_in, pdflog, cmap=cmap, levels=levels) cbar= f.colorbar(cs, cax=axb, ticks=ticks) axb.set_yticklabels(100*10.**ticks) axb.tick_params(axis='y', direction='out') axb.set_title('%') ''' integrated occurrence per bin''' occbin= epos.occurrence['bin'] key = 'eta' if MCMC else 'eta0' for k, (xbin, ybin, n, inbin, occ) in enumerate( zip(occbin['x'],occbin['y in'],occbin['n'],occbin['i'], occbin[key]) ): clr= clrs[k%4] # colored dots #ax.plot(epos.obs_xvar[inbin], epos.obs_yvar[inbin], # ls='', marker='.', mew=0, ms=5.0, color=clr, zorder=1) # box ax.add_patch(patches.Rectangle( (xbin[0],ybin[0]), xbin[1]-xbin[0], ybin[1]-ybin[0], fill=False, zorder=2, ls='-', color='k') ) xnudge=1.01 ynudge=1.02 size=16 if not 'textsize' in epos.plotpars else epos.plotpars['textsize'] # 12 fit in box, 16 default ax.text(xbin[0]*xnudge,ybin[1]/ynudge,'{:.1%}'.format(occ), va='top',size=size) if MCMC: ax.text(xbin[0]*xnudge,ybin[1]/ynudge,'\n +{:.1%}\n -{:.1%}'.format( occbin['eta+'][k],occbin['eta-'][k] ), va='top',size=size) ''' overplot planets ''' if Planets: ax.plot(epos.obs_xvar, epos.obs_yvar, ls='', marker='.', mew=0, ms=5, alpha=1, color='k') fname= 'posterior' if MCMC else 'integrated' if Planets: fname+= '.planets' helpers.save(plt, epos.plotdir+'occurrence/'+fname)
def twoD(epos, PlotZoom=False, MCMC=False): # where does this go -> run.py assert epos.Parametric if not epos.Range: epos.set_ranges() # pdf pps, pdf, _, _ = periodradius(epos, Init=not MCMC) pdflog = np.log10(pdf) # in % f, (ax, axb) = plt.subplots(1, 2, gridspec_kw={'width_ratios': [20, 1]}) f.subplots_adjust(wspace=0) ax.set_title('Occurrence [%] / d ln p d ln ' + ('M' if epos.MassRadius else 'R')) helpers.set_axes(ax, epos, Trim=True, In=epos.MassRadius) ''' color scale? ''' cmap = 'jet' vmin, vmax = -5, 0 ticks = np.linspace(vmin, vmax, (vmax - vmin) + 1) levels = np.linspace(vmin, vmax) ax.contourf(epos.X_in, epos.Y_in, pdflog, cmap=cmap, levels=levels) # colorbar? norm = Normalize(vmin=vmin, vmax=vmax) cb1 = clrbar.ColorbarBase(axb, cmap=cmap, norm=norm, ticks=ticks, orientation='vertical') # horizontal axb.set_yticklabels(100 * 10.**ticks) axb.tick_params(axis='y', direction='out') fname = 'mcmc/posterior' if MCMC else 'input/parametric_initial' helpers.save(plt, epos.plotdir + fname)
def _posterior_per_bin(epos, xbins, ybins, Verbose=True): eta, gamma, area = [], [], [] pos, sigp, sign = [], [], [] for xbin, ybin in zip(xbins, ybins): area.append(np.log(xbin[1] / xbin[0]) * np.log(ybin[1] / ybin[0])) _, pdf, _, _ = periodradius(epos, Init=True, xbin=xbin, ybin=ybin) gamma.append(np.average(pdf)) eta.append(gamma[-1] * area[-1]) if Verbose: print ' x: [{:.3g},{:.3g}], y: [{:.2g},{:.2g}], area={:.2f}, eta_0={:.2g}'.format( xbin[0], xbin[-1], ybin[0], ybin[-1], area[-1], eta[-1]) ''' Posterior?''' if hasattr(epos, 'samples'): posterior = [] if epos.Parallel: pool = multiprocessing.Pool() one_arg_func = partial(_posterior, epos, xbin=xbin, ybin=ybin) posterior = pool.map(one_arg_func, epos.samples) else: for sample in epos.samples: _, pdf, _, _ = periodradius(epos, fpara=sample, xbin=xbin, ybin=ybin) posterior.append(np.average(pdf)) #pos= np.percentile(posterior, [16, 50, 84]) perc = np.percentile(posterior, [2.3, 15.9, 50., 84.1, 97.7]) pos.append(perc[2]) sigp.append(perc[3] - perc[2]) sign.append(perc[2] - perc[1]) sig2p = (perc[4] - perc[2]) sig2n = (perc[2] - perc[0]) if Verbose: print ' gamma= {:.1%} +{:.1%} -{:.1%}'.format( pos[-1], sigp[-1], sign[-1]) print ' eta= {:.1%} +{:.1%} -{:.1%}'.format( pos[-1] * area[-1], sigp[-1] * area[-1], sign[-1] * area[-1]) #print ' gamma 2sig= {:.1%} +{:.1%} -{:.1%}'.format(_pos[-1],sig2p,sig2n) return eta, gamma, area, pos, sigp, sign
def panels(epos, PlotZoom=False, MCMC=False): ''' Initial distribution, panel layout''' f, (ax, axb, axR, axP) = helpers.make_panels_clrbar(plt) # pdf pps, pdf, pdf_X, pdf_Y = periodradius(epos, Init=not MCMC) pdflog = np.log10(pdf) # in % ax.set_title('Planet Occurrence / dlnP dln' + ('M' if epos.MassRadius else 'R')) helpers.set_axes(ax, epos, Trim=True, In=epos.MassRadius) # Side panels axP.plot(epos.MC_xvar, pdf_X, marker='', ls='-', color='k') axR.plot(pdf_Y, epos.in_yvar, marker='', ls='-', color='k') #helpers.set_axis_distance(axP, epos, Trim=True) #helpers.set_axis_size(axR, epos, Trim=True, In= epos.MassRadius) axP.set_xlabel(ax.get_xlabel()) axR.set_ylabel(ax.get_ylabel()) axP.set_yscale('log') axP.set_ylim([2e-3, 5]) axP.set_yticks([0.01, 0.1, 1]) axP.set_yticklabels(['1%', '10%', '100%']) axP.yaxis.tick_right() axP.yaxis.set_ticks_position('both') axP.tick_params(axis='y', which='minor', left=False, right=False) axR.set_xscale('log') axR.set_xlim([2e-3, 5]) axR.set_xticks([0.01, 0.1, 1]) axR.set_xticklabels(['1%', '10%', '100%'], rotation=70) axR.tick_params(axis='x', which='minor', top=False, bottom=False) axP.tick_params(axis='y', which='minor', left=False, right=False) axP.tick_params(axis='y', which='major', left=False, right=True) ''' color scale? ''' cmap = 'jet' vmin, vmax = -5, 0 ticks = np.linspace(vmin, vmax, (vmax - vmin) + 1) levels = np.linspace(vmin, vmax) ax.contourf(epos.X_in, epos.Y_in, pdflog, cmap=cmap, levels=levels) # colorbar? norm = Normalize(vmin=vmin, vmax=vmax) cb1 = clrbar.ColorbarBase(axb, cmap=cmap, norm=norm, ticks=ticks, orientation='vertical') # horizontal axb.set_yticklabels(100 * 10.**ticks) axb.tick_params(axis='y', direction='out') axb.set_title('%') helpers.save(plt, epos.plotdir + 'input/panels')
def _posterior(epos, sample, xbin, ybin): _, pdf, _, _ = periodradius(epos, fpara=sample, xbin=xbin, ybin=ybin) return np.average(pdf)
def panels_mass(epos, Population=False, color='C1'): f, (ax, axM, axP) = helpers.make_panels(plt) pfm = epos.pfm eta = epos.modelpars.get('eta', Init=True) ''' Bins ''' dw = 0.5 # bin width in ln space xbins = np.exp( np.arange(np.log(pfm['P limits'][0]), np.log(pfm['P limits'][-1]) + dw, dw)) ybins = np.exp( np.arange(np.log(pfm['M limits'][0]), np.log(pfm['M limits'][-1]) + dw, dw)) ''' Posterior ''' if Population: assert hasattr(epos, 'func') fname = '.pop' # side panels marginalized over M and P limits pps, pdf, pdf_X, pdf_Y = periodradius(epos, Init=True) _, _, pdf_X, _ = periodradius(epos, Init=True, ybin=ybins) _, _, _, pdf_Y = periodradius(epos, Init=True, xbin=xbins) pps, _, _, _ = periodradius(epos, Init=True, xbin=xbins, ybin=ybins) #pdf/= np.max(pdf) #pdflog= np.log10(pdf) # in % levels = np.linspace(0, np.max(pdf)) lines = np.array([0.1, 0.5]) * np.max(pdf) ax.contourf(epos.X_in, epos.Y_in, pdf, cmap='Purples', levels=levels) #ax.contour(epos.X_in, epos.Y_in, pdf, levels=lines) # Side panels #print 'pps model= {}'.format(eta) scale = dw axP.plot(epos.MC_xvar, pdf_X * scale, marker='', ls='-', color='purple') axM.plot(pdf_Y * scale, epos.in_yvar, marker='', ls='-', color='purple') else: fname = '' ''' plot main panel''' ax.set_title(epos.name) #helpers.set_axes(ax, epos, Trim=True) ax.set_xscale('log') ax.set_yscale('log') #ax.set_xlim(epos.mod_xlim) #ax.set_ylim(epos.mod_ylim) ax.plot(pfm['P'], pfm['M'], color=color, **fmt_symbol) xlim = ax.get_xlim() ylim = ax.get_ylim() ''' Period side panel ''' #axP.yaxis.tick_right() #axP.yaxis.set_ticks_position('both') #axP.tick_params(axis='y', which='minor',left='off',right='off') axP.set_xscale('log') axP.set_xlim(xlim) #ax.set_xlabel('Semi-Major Axis [au]') axP.set_xlabel('Orbital Period [days]') axP.hist(pfm['P'], color=color, bins=xbins, weights=np.full(pfm['np'], eta / pfm['np'])) ''' Mass side panel''' #helpers.set_axis_size(axR, epos, Trim=True) #, In= epos.MassRadius) axM.set_ylabel(r'Planet Mass [M$_\bigoplus$]') axM.set_yscale('log') axM.set_ylim(ylim) axM.hist(pfm['M'], bins=ybins, orientation='horizontal', weights=np.full(pfm['np'], eta / pfm['np']), color=color) helpers.save(plt, '{}model/input.mass{}'.format(epos.plotdir, fname))
def panels_radius(epos, Population=False, Occurrence=False, Observation=False, Tag=False, color='C0', clr_obs='C3', Shade=True, Fancy=True, Zoom=False): f, (ax, axR, axP) = helpers.make_panels(plt, Fancy=Fancy) pfm = epos.pfm eta = epos.modelpars.get('eta', Init=True) title = '' if not 'R' in pfm: pfm['R'], _ = epos.MR(pfm['M']) if Tag: # function that return a simulation subset based on the tag subset = { 'Fe/H<=0': lambda tag: tag <= 0, 'Fe/H>0': lambda tag: tag > 0 } ''' Bins ''' dwR = 0.2 # bin width in ln space dwP = 0.3 if Zoom: xbins = np.exp( np.arange(np.log(epos.xzoom[0]), np.log(epos.xzoom[-1]) + dwP, dwP)) ybins = np.exp( np.arange(np.log(epos.yzoom[0]), np.log(epos.yzoom[-1]) + dwR, dwR)) else: xbins = np.exp( np.arange(np.log(epos.xtrim[0]), np.log(epos.xtrim[-1]) + dwP, dwP)) ybins = np.exp( np.arange(np.log(epos.ytrim[0]), np.log(epos.ytrim[-1]) + dwR, dwR)) ''' Plot model occurrence or observed counts''' if Observation: # plot model planets * completeness weights = eta * epos.occurrence['model']['completeness'] / pfm['ns'] else: weights = np.full(pfm['np'], eta / pfm['ns']) if 'draw prob' in pfm and not Tag: prob = pfm['draw prob'][pfm['ID']] weights *= prob * pfm['ns'] # system weights sum up to 1 #nonzero= np.where(prob>0, 1., 0.) #weights*= nonzero*(pfm['np']/nonzero.sum()) # histograms if Tag: for key, f in subset.iteritems(): toplot = f(pfm['tag']) #weights= eta*epos.occurrence['model']['completeness'] \ # *np.where(toplot,1.,0.)/f(pfm['system tag']).sum() weights = np.where(toplot, eta, 0.) / f(pfm['system tag']).sum() axP.hist(pfm['P'], bins=xbins, weights=weights, histtype='step', label=key) axR.hist(pfm['R'], bins=ybins, orientation='horizontal', weights=weights, histtype='step') else: # color have to be 1-element lists ?? axP.hist(pfm['P'], bins=xbins, weights=weights, color=[color]) axR.hist(pfm['R'], bins=ybins, orientation='horizontal', weights=weights, color=[color]) ''' Overplot observations? ''' if Population: assert hasattr(epos, 'func') fname = '.pop' + ('.zoom' if Zoom else '') title = epos.title pps, pdf, pdf_X, pdf_Y = periodradius(epos, Init=True) _, _, pdf_X, _ = periodradius(epos, Init=True, ybin=ybins) _, _, _, pdf_Y = periodradius(epos, Init=True, xbin=xbins) pps, _, _, _ = periodradius(epos, Init=True, xbin=xbins, ybin=ybins) #pdf/= np.max(pdf) #pdflog= np.log10(pdf) # in % levels = np.linspace(0, np.max(pdf)) lines = np.array([0.1, 0.5]) * np.max(pdf) if Shade: ax.contourf(epos.X_in, epos.Y_in, pdf, cmap='Purples', levels=levels) #ax.contour(epos.X_in, epos.Y_in, pdf, levels=lines) # Side panels #print 'pps model= {}'.format(eta) axP.plot(epos.MC_xvar, pdf_X * dwP, marker='', ls='-', color='purple') axR.plot(pdf_Y * dwR, epos.in_yvar, marker='', ls='-', color='purple') else: # renormalize xnorm = axP.get_ylim()[1] / max(pdf_X) ynorm = axR.get_xlim()[1] / max(pdf_Y) axP.plot(epos.MC_xvar, pdf_X * xnorm, marker='', ls='-', color=clr_obs) axR.plot(pdf_Y * ynorm, epos.in_yvar, marker='', ls='-', color=clr_obs) elif Observation: fname = '.obs' + ('.zoom' if Zoom else '') title = epos.title + ': Counts' ax.plot(epos.obs_xvar, epos.obs_yvar, ls='', marker='.', ms=5.0, color='0.5') weights = np.full(epos.obs_xvar.size, 1. / epos.nstars) axP.hist(epos.obs_xvar, bins=xbins, weights=weights, histtype='step', color='0.5') axR.hist(epos.obs_yvar, bins=ybins, weights=weights, orientation='horizontal', histtype='step', color='0.5') elif Occurrence: fname = '.occ' + ('.zoom' if Zoom else '') title = epos.title + r': Occurrence, $\eta={:.2g}$'.format(eta) ax.plot(epos.obs_xvar, epos.obs_yvar, ls='', marker='.', ms=5.0, color='0.5') cut = epos.obs_yvar > 0.45 weights = 1. / (epos.occurrence['planet']['completeness'][cut] * epos.nstars) axP.hist(epos.obs_xvar[cut], bins=xbins, weights=weights, histtype='step', color='k') axR.hist(epos.obs_yvar[cut], bins=ybins, weights=weights, orientation='horizontal', histtype='step', color='k') elif Tag: fname = '.tag' ax.set_title(epos.title + ': Tag') axP.legend(frameon=False, fontsize='small') # for k, tag in enumerate(subset): # axP.text(0.98,0.95-0.05*k,tag,ha='right',va='top',color='C1', # transform=axP.transAxes) else: fname = '' if Fancy: plt.suptitle(title, ha='center') #, x=0.05) else: ax.set_title(title) ''' plot main panel''' #helpers.set_axes(ax, epos, Trim=True) helpers.set_axes(ax, epos, Trim=True) if Tag: for key, f in subset.iteritems(): todraw = f(pfm['tag']) ax.plot(pfm['P'][todraw], pfm['R'][todraw], **fmt_symbol) elif 'draw prob' in pfm: #fmt_symbol['alpha']= 0.6*pfm['draw prob'][pfm['ID']] # alpha can't be array todraw = pfm['draw prob'][pfm['ID']] > 0 ax.plot(pfm['P'][todraw], pfm['R'][todraw], color=color, **fmt_symbol) else: ax.plot(pfm['P'], pfm['R'], color=color, **fmt_symbol) ''' Period side panel ''' #axP.yaxis.tick_right() #axP.yaxis.set_ticks_position('both') #axP.tick_params(axis='y', which='minor',left='off',right='off') helpers.set_axis_distance(axP, epos, Trim=True) ''' Mass side panel''' helpers.set_axis_size(axR, epos, Trim=True) #, In= epos.MassRadius) helpers.save(plt, '{}model/input.radius{}'.format(epos.plotdir, fname))
def mcmc(epos, nMC=500, nwalkers=100, dx=0.1, nburn=50, threads=1, npos=30, Saved=True): if not 'emcee' in sys.modules: raise ImportError('You need to install emcee') assert epos.Prep runonce = MC if epos.MonteCarlo else noMC ''' set starting parameters ''' fpara = epos.fitpars.getfit(Init=True) if not len(fpara) > 0: raise ValueError('no fit paramaters defined') ''' Load previous chain?''' ndim = len(fpara) shape = (nwalkers, nMC, ndim) # store, npy is uncompressed, savez returns as dict instead of array dir = 'chain/{}'.format(epos.name) fname = '{}/{}x{}x{}.npz'.format(dir, nwalkers, nMC, ndim) if not os.path.exists(dir): os.makedirs(dir) if os.path.isfile(fname) and Saved: print '\nLoading saved status from {}'.format(fname) npz = np.load(fname) epos.chain = npz['chain'] assert epos.chain.shape == (nwalkers, nMC, ndim) if epos.seed != npz['seed']: print '\nNOTE: Random seed changed: {} to {}'.format( npz['seed'], epos.seed) epos.seed = npz['seed'] # check if same keys (not very flexible) if 'fitkeys' in npz: for loadkey, key in zip(npz['fitkeys'], epos.fitpars.keysfit): if loadkey != key: raise ValueError('Stored key {} doesnt match {}'.format( loadkey, key)) else: ''' start the timer ''' tstart = time.time() nsims = nMC * nwalkers runtime = (epos.tMC / 3600.) * nsims # single-threaded run time print '\nPredicted runtime:' if runtime > 1: print ' {:.3f} hours for {} runs at {:.3f} sec'.format( runtime, nsims, epos.tMC) else: print ' {:.1f} minutes for {} runs at {:.3f} sec'.format( runtime * 60., nsims, epos.tMC) if threads > 1: if runtime / threads > 1: print ' {:.3f} hours at 100% scaling'.format(runtime / threads) else: print ' {:.1f} minutes at 100% scaling'.format(runtime / threads * 60.) ''' Set up a log file ''' # Note: if logging.debug is called before this, the log file is never created fdir = 'log/{}'.format(epos.name) if not os.path.exists(fdir): os.makedirs(fdir) flog = '{}/{}.log'.format(fdir, time.strftime('%Y-%m-%d_%H.%M.%S')) logging.basicConfig(filename=flog, level=logging.DEBUG, filemode='w') logging.info('MCMC with random seed {}'.format(epos.seed)) ''' Wrap function ''' lnmc = partial(runonce, epos, Verbose=False) ''' Set up the MCMC walkers ''' #p0 = [np.array(fpara)*np.random.uniform(1.-dx,1+dx,len(fpara)) # for i in range(nwalkers)] dx = np.array(epos.fitpars.getfit(attr='dx')) p0 = [ np.array(fpara) + dx * np.random.uniform(-1, 1, len(fpara)) for i in range(nwalkers) ] sampler = emcee.EnsembleSampler(nwalkers, len(fpara), lnmc, threads=threads) ''' run the chain ''' if True: # chop to pieces for progress bar? for i, result in enumerate(sampler.sample(p0, iterations=nMC)): amtDone = float(i) / nMC print '\r [{:50s}] {:5.1f}%'.format('#' * int(amtDone * 50), amtDone * 100), os.sys.stdout.flush() else: sampler.run_mcmc(p0, nMC) print '\nDone running\n' logging.info('Made it to the end') print 'Mean acceptance fraction: {0:.3f}'.format( np.mean(sampler.acceptance_fraction)) ''' Print run time''' tMC = time.time() runtime = tMC - tstart if runtime > 3600: print ' Runtime was {:.3f} hours at {:.3f} sec'.format( runtime / 3600, (tMC - tstart) / nsims) else: print ' Runtime was {:.1f} minutes at {:.3f} sec'.format( runtime / 60., (tMC - tstart) / nsims) epos.chain = sampler.chain print 'Saving status in {}'.format(fname) #np.save(fname, epos.chain) # compression slow on loading? np.savez_compressed(fname, chain=epos.chain, seed=epos.seed, keys=epos.fitpars.keysfit) ''' the posterior samples after burn-in ''' epos.samples = epos.chain[:, nburn:, :].reshape((-1, ndim)) epos.burnin = nburn fitpars = map(lambda v: (v[1], v[2] - v[1], v[1] - v[0]), zip(*np.percentile(epos.samples, [16, 50, 84], axis=0))) epos.fitpars.setfit([p[0] for p in fitpars]) ''' Generate posterior populations ''' if npos is not None: epos.plotsample = epos.samples[np.random.randint(len(epos.samples), size=npos)] # run & store print '\nMC-ing the {} samples to plot'.format(npos) epos.ss_sample = [] for fpara in epos.plotsample: epos.ss_sample.append(\ runonce(epos, fpara, Store=True, Sample=True, Verbose=False)) # parallel # return & store in structure ''' Estimate Solar System Analogs''' if epos.Parametric and epos.Multi: fMercury = [] fVenus = [] for sample in epos.samples: _, _, xpdf, _ = periodradius(epos, fpara=sample) fMercury.append(np.sum(xpdf[epos.MC_xvar > 88.]) / np.sum(xpdf)) fVenus.append(np.sum(xpdf[epos.MC_xvar > 225.]) / np.sum(xpdf)) print for name, posterior in zip(['Mercury', 'Venus'], [fMercury, fVenus]): eta = np.percentile(posterior, [16, 50, 84]) print '{} analogues < {:.1%} +{:.1%} -{:.1%}'.format( name, eta[1], eta[2] - eta[1], eta[1] - eta[0]) UL = np.percentile(posterior, [68.2, 95.4, 99.7]) for i in range(3): print ' {} sigma UL {:.1%}'.format(i + 1, UL[i]) ''' Best-fit values''' print '\nBest-fit values' for pname, fpar in zip(epos.fitpars.keysfit, fitpars): print ' {}= {:.3g} +{:.3g} -{:.3g}'.format(pname, *fpar) print '\nStarting the best-fit MC run' runonce(epos, np.array([p[0] for p in fitpars]), Store=True)
def noMC(epos, fpara, Store=False, Sample=False, StorePopulation=False, Extra=None, Verbose=True): ''' Do the Simulations without Monte Carlo ''' if Verbose: tstart = time.time() #if not Store: logging.debug(' '.join(['{:.3g}'.format(fpar) for fpar in fpara])) if epos.Multi: raise ValueError('Multi-planets need Monte Carlo (?)') if not epos.Parametric: raise ValueError('Planet Formation models need Monte Carlo (?)') ''' parameters within bounds? ''' try: epos.pdfpars.checkbounds(fpara) except ValueError as message: if Store: raise else: logging.debug(message) return -np.inf ''' Generate observable period-radius distribution, in counts''' if epos.RV: pps, pdf, pdf_X, pdf_Y = periodradius(epos, fpara=fpara, fdet=epos.MC_eff * epos.nstars) elif epos.MassRadius: raise ValueError('Generate pdf on radius grid here') else: pps, pdf, pdf_X, pdf_Y = periodradius(epos, fpara=fpara, fdet=epos.f_det * epos.nstars) ''' Probability that simulated data matches observables ''' tstart = time.time() prob = {} lnp = {} pdf_x = np.interp(epos.noMC_zoom_x, epos.MC_xvar, pdf_X) pdf_y = np.interp(epos.noMC_zoom_y, epos.MC_yvar, pdf_Y) cdf_x = np.cumsum(pdf_x) cdf_y = np.cumsum(pdf_y) cdf_x /= cdf_x[-1] cdf_y /= cdf_y[-1] ''' Wrap functions ''' func_cdf_X = partial(np.interp, xp=epos.noMC_zoom_x, fp=cdf_x, left=0, right=0) func_cdf_Y = partial(np.interp, xp=epos.noMC_zoom_y, fp=cdf_y, left=0, right=0) prob['xvar'], lnp['xvar'] = _prob_ks_func(epos.obs_zoom['x'], func_cdf_X) prob['yvar'], lnp['yvar'] = _prob_ks_func(epos.obs_zoom['y'], func_cdf_Y) #nobs= int(pdf[epos.trim_to_zoom].sum()) nobs_x = int(np.sum(pdf_x) / epos.noMC_scale_x) nobs_y = int(np.sum(pdf_y) / epos.noMC_scale_y) nobs = int(np.sqrt(nobs_x * nobs_y)) if Verbose: print 'nobs={} (x:{},y:{})'.format(nobs, nobs_x, nobs_y) # ?? chi2 = (epos.obs_zoom['x'].size - nobs)**2. / epos.obs_zoom['x'].size lnp['N'] = -0.5 * chi2 prob['N'] = np.exp(-0.5 * chi2) prob_keys = ['N', 'xvar', 'yvar'] # combine with Fischer's rule: lnprob = np.sum([lnp[key] for key in prob_keys]) #dof= len(prob_keys) chi_fischer = -2. * lnprob if Verbose: print '\nGoodness-of-fit' print ' logp= {:.1f}'.format(lnprob) print ' - p(n={})={:.2g}'.format(nobs, prob['N']) print ' - p(x)={:.2g}'.format(prob['xvar']) print ' - p(y)={:.2g}'.format(prob['yvar']) tgof = time.time() if Verbose: print ' observation comparison in {:.3f} sec'.format(tgof - tstart) ''' Store detectable planet population ''' if Store: ss = {} ss['nobs'] = nobs ss['pdf'] = pdf ss['P'] = epos.MC_xvar ss['P pdf'] = pdf_X ss['Y'] = epos.MC_yvar ss['Y pdf'] = pdf_Y ss['P zoom'] = epos.noMC_zoom_x ss['P zoom pdf'] = pdf_x # /scale? ss['P zoom cdf'] = cdf_x ss['Y zoom'] = epos.noMC_zoom_y ss['Y zoom pdf'] = pdf_y # /scale? ss['Y zoom cdf'] = cdf_y epos.prob = prob epos.lnprob = lnprob 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 oneD_x(epos, PlotZoom=False, MCMC=False, Occ=False, Log=True): if Occ: fname = 'occurrence/posterior' if MCMC else 'occurrence/input' ybin = epos.yzoom unit = r'$M_\bigoplus$' if epos.RV else r'$R_\bigoplus$' title = r'Planet Occurrence ({1:.1f}-{2:.0f} {0})'.format( unit, *epos.yzoom) else: fname = 'mcmc/posterior' if MCMC else 'input/parametric_initial' ybin = None title = r'Marginalized Distribution ({:.1f}-{:.0f} $R_\bigoplus$)'.format( *epos.ytrim) if not Log: fname += '.linear' # initial guess pps, _, pdf0_X, _ = periodradius(epos, Init=True, ybin=ybin) if MCMC: # best-fit parameters pps, _, pdf_X, _ = periodradius(epos, ybin=ybin) ''' construct the posterior parameters ''' if MCMC: plotsample = epos.samples[np.random.randint(len(epos.samples), size=100)] ''' Orbital Period ''' f, ax = plt.subplots() ax.set_title(title) ax.set_ylabel('Occurrence / {}P'.format(epos.plotpars['area'])) #ax.set_xlabel('Orbital Period [days]') #ax.set_xscale('log') #ax.set_xlim(epos.xtrim) helpers.set_axis_distance(ax, epos, Trim=True) if Log: ax.set_yscale('log') if 'occrange' in epos.plotpars: ax.set_ylim(epos.plotpars['occrange']) else: ax.set_ylim([1e-3, 1e1]) else: ax.set_ylim([0, 0.45]) if MCMC: for fpara in plotsample: _, _, xpdf, _ = periodradius(epos, fpara=fpara, ybin=ybin) ax.plot(epos.MC_xvar, xpdf, color='b', alpha=0.1) ax.plot(epos.MC_xvar, pdf0_X, marker='', ls=':', color='k', label='Starting Guess') ax.plot(epos.MC_xvar, pdf_X, marker='', ls='-', color='k', label='Best Fit') else: if 'P break' in epos.fitpars.keys2d: ax.axvline(epos.fitpars.get('P break', Init=True), ls='-', color='gray') ax.plot(epos.MC_xvar, pdf0_X, marker='', ls='-', color='k') # plot posterior excluding low detection regions (arbitrary 2000 planets assumed) if not (epos.RV or epos.MassRadius): cens = np.where(epos.f_det < 1. / 3000., 0, 1.) _, _, cens_pdf_X, _ = periodradius(epos, ybin=ybin, fdet=cens) ax.plot(epos.MC_xvar, cens_pdf_X, marker='', ls='-', color='green', label='biased') if epos.Zoom: for zoom in epos.xzoom: ax.axvline(zoom, ls='--', color='k') if Occ: occbin = epos.occurrence['yzoom'] ax.errorbar(occbin['xc'], occbin['occ'] / occbin['dlnx'], yerr=occbin['err'] / occbin['dlnx'], color='r', marker='_', ls='', capsize=3) #,capthick=2 # lognormal inner disk edge? #from scipy.stats import norm #gauss= 2.*norm(loc=1., scale=0.4).pdf(np.log10(epos.MC_xvar)) #ax.plot(epos.MC_xvar, gauss, ls='-', marker='', color='r') if not Log: if 'Pinner all' in epos.plotpars: xx = np.geomspace(20, 400) a, b, c = epos.plotpars['Pinner all'] ax.plot(xx, a * (xx / b)**c, marker='', ls='-', color='g', label='All Planets') if 'Pinner ylim' in epos.plotpars: ax.set_ylim(epos.plotpars['Pinner ylim']) if MCMC: ax.legend(loc='upper left') helpers.save(plt, epos.plotdir + fname + '_x')
def oneD_y(epos, PlotZoom=False, MCMC=False, PlotQ=False, Occ=False): if Occ: fname = 'occurrence/posterior' if MCMC else 'occurrence/input' xbin = epos.xzoom title = 'Planet occurrence ({:.2g}-{:.0f} days)'.format(*epos.xzoom) else: fname = 'mcmc/posterior' if MCMC else 'input/parametric_initial' xbin = None title = 'Marginalized Distribution ({:.2g}-{:.0f} days)'.format( *epos.xtrim) # initial guess pps, _, _, pdf0_Y = periodradius(epos, Init=True, xbin=xbin) if MCMC: # best-fit parameters pps, _, _, pdf_Y = periodradius(epos, xbin=xbin) ''' construct the posterior parameters ''' if MCMC: plotsample = epos.samples[np.random.randint(len(epos.samples), size=100)] ''' Planet Radius, Mass, or q ''' # TODO: zip into previous block f, ax = plt.subplots() ax.set_title(title) if PlotQ: ax.set_xlabel(r'Planet Mass Ratio') ax.set_ylabel('Occurrence / {}q dloga'.format(epos.plotpars['area'])) area = 2. / 3. * np.log10(epos.MC_xvar[-1] / epos.MC_xvar[0]) yscale = 1. / area elif epos.RV or epos.MassRadius: ax.set_xlabel(r'Planet Mass [M$_\bigoplus$]') ax.set_ylabel('Occurrence / {}M'.format(epos.plotpars['area'])) yscale = 1. else: ax.set_xlabel(r'Planet Radius [R$_\bigoplus$]') ax.set_ylabel('Occurrence / {}R'.format(epos.plotpars['area'])) yscale = 1. M_to_q = 1. / (epos.Mstar * cgs.Msun / cgs.Mearth) ax.set_xscale('log') ax.set_yscale('log') ax.set_xlim(np.array(epos.in_ytrim) * (M_to_q if PlotQ else 1.)) if 'occrange' in epos.plotpars: ax.set_ylim(epos.plotpars['occrange']) else: ax.set_ylim([1e-3, 1e1]) yvar = epos.in_yvar * (M_to_q if PlotQ else 1.) if MCMC: for fpara in plotsample: _, _, _, ypdf = periodradius(epos, fpara=fpara, xbin=xbin) ax.plot(yvar, ypdf * yscale, color='b', alpha=0.1) ax.plot(yvar, pdf0_Y * yscale, marker='', ls=':', color='k', label='starting guess') ax.plot(yvar, pdf_Y * yscale, marker='', ls='-', color='k', label='best-fit') else: if 'R break' in epos.fitpars.keys2d: ax.axvline(epos.fitpars.get('R break', Init=True), ls='-', color='gray') ax.plot(yvar, pdf0_Y * yscale, marker='', ls='-', color='k') # plot posterior excluding low detection regions (arbitrary 2000 planets assumed) if not (epos.RV or epos.MassRadius): cens = np.where(epos.f_det < 1. / 3000., 0, 1.) _, _, _, cens_pdf_Y = periodradius(epos, xbin=xbin, fdet=cens) ax.plot(yvar, cens_pdf_Y * yscale, marker='', ls='-', color='green', label='biased') if epos.Zoom and not epos.MassRadius: for zoom in epos.yzoom: ax.axvline(zoom, ls='--', color='k') if PlotQ and 'q Suzuki' in epos.plotpars: A, qbr, p1, p2 = epos.plotpars['q Suzuki'] ax.plot(yvar, A*(yvar/qbr)**np.where(yvar<qbr,p1,p2), color='g', \ label='Suzuki+ 2016' ) #ax.legend(loc='lower right', shadow=False, prop={'size':14}, numpoints=1) if Occ: occbin = epos.occurrence['xzoom'] ax.errorbar(occbin['yc'], occbin['occ'] / occbin['dlny'], yerr=occbin['err'] / occbin['dlny'], color='r', marker='_', ls='', capsize=3) # for y, occ, err in zip(occbin['yc'], occbin['occ']/occbin['dlny'], # occbin['err']/occbin['dlny']): # print '{:.3g} {:.3g} {:.3g}'.format(y, occ, err) #if Occ or MCMC: if MCMC: ax.legend(loc='upper right') helpers.save(plt, epos.plotdir + fname + ('_q' if PlotQ else '_y'))
def binned_metric(epos): ''' occurrence for one y bin, along x axis''' if 'yzoom' in epos.occurrence: xc = epos.occurrence['yzoom']['xc'] occ_obs = epos.occurrence['yzoom']['occ'] / epos.occurrence['yzoom'][ 'dlnx'] occ_err = epos.occurrence['yzoom']['err'] / epos.occurrence['yzoom'][ 'dlnx'] _, _, pdf_X, _ = periodradius(epos, ybin=epos.yzoom, xgrid=epos.occurrence['yzoom']['xc']) #for args in zip(xc, occ_obs, occ_err, pdf_X): #print 'xc= {:.2g}, occ={:.2g}+-{:.2g}, model= {:.2g}'.format(*args) squared_residuals = ((occ_obs - pdf_X) / occ_err)**2. zoom = (epos.xzoom[0] < xc) & (xc < epos.xzoom[-1]) rss = np.sum(squared_residuals[zoom]) nbins = zoom.sum() kfree = epos.fitpars.get_kfree() dof = nbins - kfree # kfree includes normalization parameter chi2 = rss / dof bic = EPOS.analytics.bic_rss(rss, kfree, nbins) aic = EPOS.analytics.aic_rss(rss, kfree, nbins) aic_c = EPOS.analytics.aic_c_rss(rss, kfree, nbins) print ' x: (n={}, k={})'.format(nbins, kfree) print ' chi^2= {:.1f}, reduced= {:.1f}'.format(rss, chi2) print ' bic= {:.1f}'.format(bic) print ' aic= {:.1f}, AICc= {:.1f}'.format(aic, aic_c) if 'xzoom' in epos.occurrence: yc = epos.occurrence['xzoom']['yc'] occ_obs = epos.occurrence['xzoom']['occ'] / epos.occurrence['xzoom'][ 'dlny'] occ_err = epos.occurrence['xzoom']['err'] / epos.occurrence['xzoom'][ 'dlny'] _, _, _, pdf_Y = periodradius(epos, xbin=epos.xzoom, ygrid=epos.occurrence['xzoom']['yc']) #for args in zip(yc, occ_obs, occ_err, pdf_Y): #print 'yc= {:.2g}, occ={:.2g}+-{:.2g}, model= {:.2g}'.format(*args) squared_residuals = ((occ_obs - pdf_Y) / occ_err)**2. zoom = (epos.yzoom[0] < yc) & (yc < epos.yzoom[-1]) rss = np.sum(squared_residuals[zoom]) nbins = zoom.sum() kfree = epos.fitpars.get_kfree() dof = nbins - kfree # kfree includes normalization parameter chi2 = rss / dof bic = EPOS.analytics.bic_rss(rss, kfree, nbins) aic = EPOS.analytics.aic_rss(rss, kfree, nbins) aic_c = EPOS.analytics.aic_c_rss(rss, kfree, nbins) print ' y: (n={}, k={})'.format(nbins, kfree) print ' chi^2= {:.1f}, reduced= {:.1f}'.format(rss, chi2) print ' bic= {:.1f}'.format(bic) print ' aic= {:.1f}, AICc= {:.1f}'.format(aic, aic_c)