def calc_age_pdf(self,fehdist='casagrande'): """ NAME: calc_age_pdf PURPOSE: calculate the age PDF for a uniform SFH for a given metallicity distribution INPUT: fehdist= either: 1) a single metallicity 2) 'casagrande': local metallicity distribution following Casagrande et al. (2011) 3) a function giving OUTPUT: a function between 800 Myr and 10 Gyr giving the age distribution HISTORY: 2014-02-27 - Written in this form - Bovy (IAS) """ if isinstance(fehdist,(int,float,numpy.float32,numpy.float64)): pz= numpy.zeros(len(self._zs)) pz[numpy.argmin(numpy.fabs(self._zs-isodist.FEH2Z(fehdist,zsolar=zsolar())))]= 1. elif isinstance(fehdist,str) and fehdist.lower() == 'casagrande': pz= numpy.array([localfehdist(isodist.Z2FEH(z,zsolar=zsolar()))/z for z in self._zs]) else: pz= numpy.array([fehdist(isodist.Z2FEH(z,zsolar=zsolar()))/z for z in self._zs]) pz/= numpy.sum(pz) agezdist= self._omega/self._coarsemass pz= numpy.tile(pz,(len(self._coarselages),1)).T postage= numpy.nansum(pz*agezdist,axis=0)/numpy.nansum(pz,axis=0)/10.**self._coarselages postage= postage[self._coarselages > numpy.log10(0.8)] postage/= numpy.nanmax(postage) lages= self._coarselages[self._coarselages > numpy.log10(0.8)] postage_spline= interpolate.InterpolatedUnivariateSpline(lages, numpy.log(postage), k=3) return lambda x: dummy_page(x,copy.copy(postage_spline))
def sample_iso_MH(fehbin=[-0.6, 0.2], agebin=[0., 13.], n=1000, agebias=False, imftype='chabrier2003', isochrones='Padova'): #Load pre-computed parsec isochrone grid iso_file = open('../savs/' + isochrones + '_grid_' + imftype + '.sav') iso_grid = pickle.load(iso_file) #add rgb age bias if agebias = True if agebias == True: iso_grid[:, 6] *= agebias(10**iso_grid[:, 0]) #Perform sample cuts (logg and J-K) gridcuts = (iso_grid[:, 3] > 1.8) & (iso_grid[:, 3] < 3.0) & (iso_grid[:, 5] > 0.5) cutgrid = iso_grid[gridcuts] n_weights = cutgrid[:, 6] * (10**cutgrid[:, 0] / cutgrid[:, 1]) #make [Fe/H], age cut fehcut = (isodist.Z2FEH(cutgrid[:,1])>=fehbin[0])&(isodist.Z2FEH(cutgrid[:,1])<fehbin[1])\ &(10**cutgrid[:,0] >= agebin[0])&(10**cutgrid[:,0] < agebin[1]) # compute CDF of M_H sorter_H = numpy.argsort(cutgrid[:, 4][fehcut]) cdf_H = numpy.cumsum(n_weights[fehcut][sorter_H]) / numpy.sum( n_weights[fehcut]) #Interpolate CDF and take n samples intercdf_H = interp1d(cdf_H, cutgrid[:, 4][fehcut][sorter_H]) rand = numpy.random.uniform(size=n, low=0.0001, high=0.999999) model_MH = intercdf_H(rand) return model_MH
def loggteffcut(teff, z, upper=True): if not upper: return 1.8 else: feh = isodist.Z2FEH(z, zsolar=zsolar()) this_teff = (4760. - 4607.) / (-0.4) * feh + 4607. return 0.0018 * (teff - this_teff) + 2.5
def Gdist(tG, ZG): """The distribution of G for the local metallicity distribution REWRITE TO TAKE A Z(G) FUNCTION OBTAINED THROUGH INTERPOLATION""" try: tZ = ZG(tG) tjac = numpy.fabs(ZG.derivatives(tG)[0] / tZ / numpy.log(10.)) except ValueError: return 0. # Add Jacobian return localfehdist(isodist.Z2FEH(tZ, zsolar=0.017)) * tjac
def imf_h_jk(plotfile,Z=None,dwarf=False,log=False,h=12.,basti=False, dartmouth=False,kroupa=False): #Read isochrones if basti: zs= numpy.array([0.0001,0.0003,0.0006,0.001,0.002,0.004,0.008, 0.01,0.0198,0.03,0.04]) elif dartmouth: zs= isodist.FEH2Z(numpy.array([-2.5,-2.,-1.5,-1.,-0.5,0.,0.2,0.3,0.5])) else: zs= numpy.arange(0.0005,0.03005,0.0005) if Z is None: Zs= zs elif not basti and not dartmouth: if Z < 0.01: Zs= [Z-0.001,Z-0.0005,Z,Z+0.0005,Z+0.001] #build up statistics else: Zs= [Z-0.0005,Z,Z+0.0005] #build up statistics else: Zs= [Z] if basti: p= isodist.BastiIsochrone(Z=Zs) elif dartmouth: p= isodist.DartmouthIsochrone(feh=isodist.Z2FEH(Zs),onlyold=True) else: p= isodist.PadovaIsochrone(Z=Zs) #Get relevant data sample= [] weights= [] for logage in p.logages(): for z in Zs: thisiso= p(logage,z) if basti: mini= thisiso['M_ini'] elif dartmouth: mini= thisiso['M'] else: mini= thisiso['M_ini'] if basti: int_IMF= isodist.imf.lognormalChabrier2001(thisiso['M_ini'], int=True) dmpm= numpy.roll(int_IMF,-1)-int_IMF elif dartmouth: int_IMF= isodist.imf.lognormalChabrier2001(thisiso['M'], int=True) dmpm= numpy.roll(int_IMF,-1)-int_IMF else: if kroupa: int_IMF= isodist.imf.kroupa2003(thisiso['M_ini'],int=True) dmpm= numpy.roll(int_IMF,-1)-int_IMF else: dmpm= numpy.roll(thisiso['int_IMF'],-1)-thisiso['int_IMF'] for ii in range(1,len(mini)-1): if basti: JK= thisiso['J'][ii]-thisiso['K'][ii] else: JK= thisiso['J'][ii]-thisiso['Ks'][ii] H= thisiso['H'][ii] if JK < 0.: # or thisiso['logg'][ii] > 3.5: continue if dmpm[ii] > 0.: if basti: sample.append([thisiso['J'][ii]-thisiso['K'][ii], thisiso['H'][ii]]) else: sample.append([thisiso['J'][ii]-thisiso['Ks'][ii], thisiso['H'][ii]]) if dartmouth: if logage > numpy.log10(5.)+9.: weights.append(2.*dmpm[ii]) #Dartmouth are linearly spaced, but spacing is bigger at > 5 Gyr else: weights.append(dmpm[ii]) #Dartmouth are linearly spaced? else: weights.append(dmpm[ii]*10**(logage-7.)) #weights.append(dmpm[ii]*10**(logage-7.)*numpy.exp((10.**(logage-7.))/800.)) else: continue #no use in continuing here #Form array sample= numpy.array(sample) weights= numpy.array(weights) #Histogram if dwarf: hist, edges= numpy.histogramdd(sample,weights=weights,bins=51, range=[[0.,1.6],[2.,9.]]) else: hist, edges= numpy.histogramdd(sample,weights=weights,bins=49, range=[[0.3,1.6],[-11.,2]]) #Normalize each J-K for ii in range(len(hist[:,0])): hist[ii,:]/= numpy.nanmax(hist[ii,:])/numpy.nanmax(hist) rev= copy.copy(hist[ii,::-1]) #reverse, but in one go does not always work hist[ii,:]= rev #Plot bovy_plot.bovy_print() if log: hist= numpy.log(hist) bovy_plot.bovy_dens2d(hist.T,origin='lower',cmap='gist_yarg', xrange=[edges[0][0],edges[0][-1]], yrange=[edges[1][-1],edges[1][0]], aspect=(edges[0][-1]-edges[0][0])/float(edges[1][-1]-edges[1][0]), xlabel=r'$(J-K_s)_0\ [\mathrm{mag}]$', ylabel=r'$M_H\ [\mathrm{mag}]$', interpolation='nearest') #Add extinction arrow djk= 0.45 dh= 1.55/1.5*djk from matplotlib.patches import FancyArrowPatch ax=pyplot.gca() ax.add_patch(FancyArrowPatch((1.,-2.),(1+djk,-2+dh), arrowstyle='->',mutation_scale=20,fill=True, lw=1.25)) bovy_plot.bovy_text(1.05,-2.05,r'$\mathrm{extinction}$', rotation=-math.atan(1.5/1.55*1.3/13.)/math.pi*180., size=14.) #Add color cut bovy_plot.bovy_plot([0.5,0.5],[-20.,20.],'--',color='0.6',overplot=True) ax.add_patch(FancyArrowPatch((0.5,-6.),(0.7,-6.), arrowstyle='->',mutation_scale=20,fill=True, lw=1.25,ls='dashed',color='0.6')) bovy_plot.bovy_text(0.43,-8.,r'$\mathrm{APOGEE\ color\ cut}$',rotation=90., size=14.) #Add twin y axis ax= pyplot.gca() def my_formatter(x, pos): """distance in kpc for m=h""" xs= 10.**((h-x)/5.-2.) return r'$%.0f$' % xs def my_formatter2(x, pos): """distance in kpc for m=h""" xs= 10.**((h-x)/5.+1.) return r'$%.0f$' % xs ax2= pyplot.twinx() if dwarf: major_formatter = FuncFormatter(my_formatter2) else: major_formatter = FuncFormatter(my_formatter) ax2.yaxis.set_major_formatter(major_formatter) ystep= ax.yaxis.get_majorticklocs() ystep= ystep[1]-ystep[0] ax2.yaxis.set_minor_locator(MultipleLocator(ystep/5.)) ax2.yaxis.tick_right() ax2.yaxis.set_label_position('right') ymin, ymax= ax.yaxis.get_view_interval() ax2.yaxis.set_view_interval(ymin,ymax,ignore=True) if dwarf: ax2.set_ylabel('$\mathrm{distance\ for}\ H_0\ =\ %.1f\ [\mathrm{pc}]$' % h) else: ax2.set_ylabel('$\mathrm{distance\ for}\ H_0\ =\ %.1f\ [\mathrm{kpc}]$' % h) xstep= ax.xaxis.get_majorticklocs() xstep= xstep[1]-xstep[0] ax2.xaxis.set_minor_locator(MultipleLocator(xstep/5.)) if Z is None: bovy_plot.bovy_end_print(plotfile) else: bovy_plot.bovy_text(r'$Z\ =\ %.3f$' % Z,top_right=True,size=14.) bovy_plot.bovy_end_print(plotfile) return None
def plot_popmass(self): """ NAME: plot_popmass PURPOSE: plot the stellar-population mass for each RC star INPUT: bovy_plot.bovy_plot **kwargs OUTPUT: bovy_plot.bovy_plot output HISTORY: 2014-02-28 - Written in this form - Bovy (IAS) """ if not _BOVY_PLOT_LOADED: raise ImportError("galpy.util.bovy_plot could not be imported") fehs = numpy.linspace(-1., 0.5, 101) lages = self._coarselages plotthis = numpy.empty((len(fehs), len(lages))) for ii in range(len(fehs)): for jj in range(len(lages)): plotthis[ii, jj] = self.popmass(fehs[ii], lages[jj]) fig = pyplot.gcf() left, bottom, width, height = 0.1, 0.1, 0.8, 0.6 axBottom = pyplot.axes([left, bottom, width, height]) fig.sca(axBottom) xlimits = [fehs[0], fehs[-1]] dlages = (lages[1] - lages[0]) ylimits = [lages[0] - dlages, lages[-1] + dlages] vmin, vmax = 0., 50000. vmin2, vmax2 = 0., 25000. zlabel = r'$\mathrm{Stellar\ population\ mass\ per\ RC\ star}\,(M_\odot)$' xlabel = r'$[\mathrm{Fe/H}]\,(\mathrm{dex})$' out = bovy_plot.bovy_dens2d(plotthis.T, origin='lower', cmap='jet', xrange=xlimits, yrange=ylimits, vmin=vmin, vmax=vmax, interpolation='nearest', colorbar=True, shrink=.9, zlabel=zlabel, overplot=True) extent = xlimits + ylimits pyplot.axis(extent) bovy_plot._add_axislabels( xlabel, r'$\log_{10}\,\mathrm{Age} / 1\,\mathrm{Gyr}$') bovy_plot._add_ticks() left, bottom, width, height = 0.1, 0.68, 0.64, 0.2 axTop = pyplot.axes([left, bottom, width, height]) fig.sca(axTop) #Plot the average over SFH lages = numpy.linspace(-1., 1., 16) mtrend = numpy.zeros(len(self._zs)) exppage = 10.**self._coarselages * numpy.exp( (10.**(self._coarselages + 2.)) / 800.) #e.g., Binney (2010) exexppage = 10.**self._coarselages * numpy.exp( (10.**(self._coarselages + 2.)) / 100.) #e.g., Binney (2010) page = 10.**self._coarselages plotthis = self._coarsemass[:-1, :] / self._omega[:-1, :] mtrend = 1. / (numpy.sum(page * 1. / plotthis, axis=1) / numpy.sum(page)) expmtrend = 1. / (numpy.sum(exppage * 1. / plotthis, axis=1) / numpy.sum(exppage)) exexpmtrend = 1. / (numpy.sum(exexppage * 1. / plotthis, axis=1) / numpy.sum(exexppage)) fehs = isodist.Z2FEH(self._zs[:-1], zsolar=zsolar()) pyplot.plot(fehs, mtrend, 'k-') pyplot.plot(fehs, expmtrend, 'k--') pyplot.plot(fehs, exexpmtrend, 'k-.') pyplot.ylim(vmin2, vmax2) pyplot.xlim(xlimits[0], xlimits[1]) nullfmt = NullFormatter() # no labels thisax = pyplot.gca() thisax.xaxis.set_major_formatter(nullfmt) bovy_plot._add_ticks() return out
def __init__(self, dwarf=False, imfmodel='lognormalChabrier2001', Z=None, interpolate=False, expsfh=False, marginalizefeh=False, glon=None, dontgather=False, loggmax=None, basti=False): """ NAME: __init__ PURPOSE: initialize isomodel INPUT: Z= metallicity (if not set, use flat prior in Z over all Z; can be list) dwarf= (default: False) if True, use dwarf part imfmodel= (default: 'lognormalChabrier2001') IMF model to use (see isodist.imf code for options) interpolate= (default: False) if True, interpolate the binned representation expsfh= if True, use an exponentially-declining star-formation history marginalizefeh= if True, marginalize over the FeH distribution along line of sight glon glon - galactic longitude in rad of los for marginalizefeh dontgather= if True, don't gather surrounding Zs loggmax= if set, cut logg at this maximum basti= if True, use Basti isochrones (if False, use Padova) OUTPUT: object HISTORY: 2012-02-17 - Written - Bovy (IAS) """ #Read isochrones if basti: zs = numpy.array([ 0.0001, 0.0003, 0.0006, 0.001, 0.002, 0.004, 0.008, 0.01, 0.0198, 0.03, 0.04 ]) else: zs = numpy.arange(0.0005, 0.03005, 0.0005) if marginalizefeh: Zs = numpy.arange(0.008, 0.031, 0.001) dFeHdZ = 1. / Zs pZs = feh_l(glon, isodist.Z2FEH(Zs)) * dFeHdZ elif Z is None: Zs = zs elif isinstance(Z, float): if basti or dontgather: Zs = [Z] elif Z < 0.001 or Z > 0.0295: Zs = [Z] elif Z < 0.0015 or Z > 0.029: Zs = [Z - 0.0005, Z, Z + 0.0005] #build up statistics elif Z < 0.01: Zs = [Z - 0.001, Z - 0.0005, Z, Z + 0.0005, Z + 0.001] #build up statistics else: Zs = [Z - 0.0005, Z, Z + 0.0005] #build up statistics if basti: p = isodist.BastiIsochrone(Z=Zs) else: p = isodist.PadovaIsochrone(Z=Zs) #Get relevant data sample = [] weights = [] for logage in p.logages(): for zz in range(len(Zs)): thisiso = p(logage, Zs[zz], asrecarray=True) #Calculate int_IMF for this IMF model if not imfmodel == 'lognormalChabrier2001': #That would be the default if imfmodel == 'exponentialChabrier2001': int_IMF = isodist.imf.exponentialChabrier2001( thisiso.M_ini, int=True) elif imfmodel == 'kroupa2003': int_IMF = isodist.imf.kroupa2003(thisiso.M_ini, int=True) elif imfmodel == 'chabrier2003': int_IMF = isodist.imf.chabrier2003(thisiso.M_ini, int=True) else: raise IOError( "imfmodel option not understood (non-existing model)" ) elif basti: int_IMF = isodist.imf.lognormalChabrier2001(thisiso.M_ini, int=True) else: int_IMF = thisiso.int_IMF dN = numpy.roll(int_IMF, -1) - int_IMF for ii in range(1, len(int_IMF) - 1): if basti: JK = thisiso.J[ii] - thisiso.K[ii] else: JK = thisiso.J[ii] - thisiso.Ks[ii] H = thisiso.H[ii] if JK < 0.3 or (not loggmax is None and thisiso['logg'][ii] > loggmax): continue if dN[ii] > 0.: sample.append([JK, H]) if marginalizefeh: if H < (11. / -1.3 * (JK - 0.3)): weights.append( 0. ) #HACK TO GET RID OF UNWANTED BRIGHT POINTS elif expsfh: weights.append(pZs[zz] * dN[ii] * 10**(logage - 7.) * numpy.exp( (10.**(logage - 7.)) / 800.)) #e.g., Binney (2010) else: weights.append(pZs[zz] * dN[ii] * 10**(logage - 7.)) else: if expsfh: weights.append(dN[ii] * 10**(logage - 7.) * numpy.exp( (10.**(logage - 7.)) / 800.)) #e.g., Binney (2010) else: weights.append(dN[ii] * 10**(logage - 7.)) else: continue #no use in continuing here #Form array sample = numpy.array(sample) weights = numpy.array(weights) self._sample = sample self._weights = weights #Histogram self._jkmin, self._jkmax = 0.3, 1.6 if dwarf: self._hmin, self._hmax = 2., 9. self._nbins = 51 else: self._hmin, self._hmax = -11., 2. self._nbins = 26 #49 self._djk = (self._jkmax - self._jkmin) / float(self._nbins) self._dh = (self._hmax - self._hmin) / float(self._nbins) self._hist, self._edges = numpy.histogramdd( sample, weights=weights, bins=self._nbins, range=[[self._jkmin, self._jkmax], [self._hmin, self._hmax]]) #Save self._Zs = Zs self._interpolate = interpolate self._dwarf = dwarf self._loghist = numpy.log(self._hist) self._loghist[( self._hist == 0.)] = -numpy.finfo(numpy.dtype(numpy.float64)).max if interpolate: #Form histogram grid jks = numpy.linspace(self._jkmin + self._djk / 2., self._jkmax - self._djk / 2., self._nbins) hs = numpy.linspace(self._hmin + self._dh / 2., self._hmax - self._dh / 2., self._nbins) self._interpolatedhist = scipy.interpolate.RectBivariateSpline( jks, hs, self._hist, bbox=[self._jkmin, self._jkmax, self._hmin, self._hmax], s=0.) #raise NotImplementedError("'interpolate=True' option for isomodel not implemented yet") return None