def random_gal(galreal,Nrand,Nmin=10): """ Prefered random galaxy generator. For a given galaxy with a given magnitude (and other properties), it calculates the redshift sensitivity function from galaxies in a magnitude band around the selected one (i.e., including slightly brighter and fainter galaxies), and places Nrand new galaxies at a random redshift given by a smoothed version of the observed sensitivity function. For extremely bright or faint galaxies (rare) the sensitivity function is calculated from at least Nmin (=50) galaxies (i.e. the magnitude band is increased).""" from astro.sampledist import RanDist from astro.fit import InterpCubicSpline from scipy.ndimage import gaussian_filter as gf Ckms = 299792.458 Nmin = int(Nmin) #minimum number of galaxys for the fit zmin = np.min(galreal.ZGAL) zmax = np.max(galreal.ZGAL) + 0.1 DZ = 0.01 #delta z for the histogram for getting the spline in z smooth_scale = 10. #smoothing scale for the histogram (in number #of bins, so depends on DZ) galreal.sort(order='MAG') #np.recarray.sort() galrand = galreal.repeat(Nrand) delta_mag = 0.5 # half of the magnitude bandwidth to generate the z histogram bins = np.append(np.linspace(0,zmin,20),np.arange(zmin+DZ, zmax, DZ)) for i in xrange(len(galreal)): if i < Nmin: vals,bins = np.histogram(galreal.ZGAL[:Nmin], bins) vals = gf(vals.astype(float),smooth_scale) # smooth the histogram spl = InterpCubicSpline(0.5*(bins[:-1] + bins[1:]), vals.astype(float)) else: delta_mag2=delta_mag while True: cond = (galreal.MAG > 0) & (galreal.MAG < 90) cond = cond & (galreal.MAG<=galreal.MAG[i]+delta_mag2)&(galreal.MAG>galreal.MAG[i]-delta_mag2) if np.sum(cond)>=Nmin: break else: delta_mag2+=0.1 vals,bins = np.histogram(galreal.ZGAL[cond], bins) vals = gf(vals.astype(float),smooth_scale) # smooth the histogram spl = InterpCubicSpline(0.5*(bins[:-1] + bins[1:]), vals.astype(float)) rvals = np.linspace(0, zmax, 1e4) rand_z = RanDist(rvals, spl(rvals)) zrand = rand_z.random(Nrand) integer_random2 = np.random.randint(0,len(galreal),Nrand) #for RA,DEC RArand = galreal.RA[integer_random2] DECrand = galreal.DEC[integer_random2] galrand.ZGAL[i*Nrand:(i+1)*Nrand] = zrand galrand.RA[i*Nrand:(i+1)*Nrand] = RArand galrand.DEC[i*Nrand:(i+1)*Nrand] = DECrand return galrand
def random_gal(galreal,Nrand,Nmin=20): """ Prefered random galaxy generator. For a given galaxy with a given magnitude (and other properties), it calculates the redshift sensitivity function from galaxies in a magnitude band around the selected one (i.e., including slightly brighter and fainter galaxies), and places Nrand new galaxies at a random redshift given by a smoothed version of the observed sensitivity function. For extremely bright or faint galaxies (rare) the sensitivity function is calculated from at least Nmin (=50) galaxies (i.e. the magnitude band is increased).""" from astro.sampledist import RanDist from astro.fit import InterpCubicSpline from scipy.ndimage import gaussian_filter as gf Ckms = 299792.458 Nmin = int(Nmin) #minimum number of galaxys for the fit zmin = np.min(galreal.ZGAL) zmax = np.max(galreal.ZGAL) + 0.1 DZ = 0.01 #delta z for the histogram for getting the spline in z smooth_scale = 10. #smoothing scale for the histogram (in number #of bins, so depends on DZ) galreal.sort(order='MAG') #np.recarray.sort() galrand = galreal.repeat(Nrand) delta_mag = 0.5 # half of the magnitude bandwidth to generate the z histogram bins = np.append(np.linspace(0,zmin,20),np.arange(zmin+DZ, zmax, DZ)) for i in xrange(len(galreal)): if i < Nmin: vals,bins = np.histogram(galreal.ZGAL[:Nmin], bins) vals = gf(vals.astype(float),smooth_scale) # smooth the histogram spl = InterpCubicSpline(0.5*(bins[:-1] + bins[1:]), vals.astype(float)) else: delta_mag2=delta_mag while True: cond = (galreal.MAG > 0) & (galreal.MAG < 90) cond = cond & (galreal.MAG<=galreal.MAG[i]+delta_mag2)&(galreal.MAG>galreal.MAG[i]-delta_mag2) if np.sum(cond)>=Nmin: break else: delta_mag2+=0.1 vals,bins = np.histogram(galreal.ZGAL[cond], bins) vals = gf(vals.astype(float),smooth_scale) # smooth the histogram spl = InterpCubicSpline(0.5*(bins[:-1] + bins[1:]), vals.astype(float)) rvals = np.linspace(0, zmax, 1e4) rand_z = RanDist(rvals, spl(rvals)) zrand = rand_z.random(Nrand) galrand.ZGAL[i*Nrand:(i+1)*Nrand] = zrand return galrand
def random_abs(absreal, Nrand, wa, er, sl=3, R=20000, ion='HI'): """From a real absorber catalog it creates a random catalog. For a given real absorber with (z_obs,logN_obs,b_obs) it places it at a new z_rand, defined by where the line could have been observed. Input parameters: --- absreal: numpy rec array with the absorber catalog. Nrand: number of random lines per real one generated (integer). wa: numpy array of wavelenght covered by the spectrum. er: numpy array of error in the normalized flux of the spectrum for a given wavelenght. sl: significance level for the detection of the absorption line. From the error we calculate the Wmin = sl * wa * er / (1+z) / R, where z = wa/w0 - 1 (w0 is the rest frame wavelenght of the transition) and R is the resolution of the spectrograp. We then smooth Wmin with a boxcar (sharp edges). For the given absorber we transform (logN_obs,b_obs) to a W_obs assuming linear part of the curve-of-growth. We then compute the redshifts where W_obs could have been observed according to the given Wmin, and place Nrand new absorbers with the same properties as the given one accordingly. """ from astro.sampledist import RanDist from scipy.ndimage import gaussian_filter as gf absreal.sort(order='LOGN') #np.recarray.sort() sorted by column density Nrand = int(Nrand) absrand = absreal.repeat(Nrand) Ckms = 299792.458 if ion == 'HI': w0 = 1215.67 # HI w0 in angstroms z = wa / w0 - 1. # spectrum in z coordinates er = np.where(er == 0, 1e10, er) er = np.where(np.isnan(er), 1e10, er) Wmin = 3 * sl * w0 * er / R #3*sl*wa*er / (1. + z) / R Wmin = gf(Wmin.astype(float), 10) # smoothed version for i in xrange(len(absreal)): Wr = logN_b_to_Wr(absreal.LOGN[i], absreal.B[i], ion='HI') zgood = (Wr > Wmin) & (z > 0) rand_z = RanDist(z, zgood * 1.) zrand = rand_z.random(Nrand) absrand.ZABS[i * Nrand:(i + 1) * Nrand] = zrand return absrand
def random_abs(absreal,Nrand,wa,er,sl=3,R=20000,ion='HI'): """From a real absorber catalog it creates a random catalog. For a given real absorber with (z_obs,logN_obs,b_obs) it places it at a new z_rand, defined by where the line could have been observed. Input parameters: --- absreal: numpy rec array with the absorber catalog. Nrand: number of random lines per real one generated (integer). wa: numpy array of wavelenght covered by the spectrum. er: numpy array of error in the normalized flux of the spectrum for a given wavelenght. sl: significance level for the detection of the absorption line. From the error we calculate the Wmin = sl * wa * er / (1+z) / R, where z = wa/w0 - 1 (w0 is the rest frame wavelenght of the transition) and R is the resolution of the spectrograp. We then smooth Wmin with a boxcar (sharp edges). For the given absorber we transform (logN_obs,b_obs) to a W_obs assuming linear part of the curve-of-growth. We then compute the redshifts where W_obs could have been observed according to the given Wmin, and place Nrand new absorbers with the same properties as the given one accordingly. """ from astro.sampledist import RanDist from scipy.ndimage import gaussian_filter as gf absreal.sort(order='LOGN') #np.recarray.sort() sorted by column density Nrand = int(Nrand) absrand = absreal.repeat(Nrand) Ckms = 299792.458 if ion=='HI': w0 = 1215.67 # HI w0 in angstroms z = wa/w0 - 1. # spectrum in z coordinates er = np.where(er==0,1e10,er) er = np.where(np.isnan(er),1e10,er) Wmin = 3*sl*w0*er/R #3*sl*wa*er / (1. + z) / R Wmin = gf(Wmin.astype(float),10) # smoothed version for i in xrange(len(absreal)): Wr = logN_b_to_Wr(absreal.LOGN[i],absreal.B[i],ion='HI') zgood = (Wr > Wmin) & (z>0) rand_z = RanDist(z, zgood*1.) zrand = rand_z.random(Nrand) absrand.ZABS[i*Nrand:(i+1)*Nrand] = zrand return absrand
def random_abs(absreal,Nrand,wa,fl,er,sl=3.,R=20000,FWHM=10.,ion='HI'): """From a real absorber catalog it creates a random catalog. For a given real absorber with (z_obs,logN_obs,b_obs) it places it at a new z_rand, defined by where the line could have been observed. Input parameters: --- absreal: numpy rec array with the absorber catalog. Nrand: number of random lines per real one generated (integer). wa: numpy array of wavelenght covered by the spectrum. fl: numpy array of normalized flux. er: numpy array of error in the normalized flux of the spectrum for a given wavelenght. sl: significance level for the detection of the absorption line. R: resolution of the spectrograph, assumed constant FWHM: Full-width at half maximum in pixels (assumed constant). This parameter defines the smoothing scale for Wmin. ion: Name of the ion. Function only valid for HI so far. From the error we calculate the Wmin = sl * wa * er / (1+z) / R, where z = wa/w0 - 1 (w0 is the rest frame wavelenght of the transition) and R is the resolution of the spectrograp. We then smooth Wmin with a boxcar along FWHM pixels. For the given absorber we transform (logN_obs,b_obs) to a W_obs assuming linear part of the curve-of-growth. We then compute the redshifts where W_obs could have been observed according to the given Wmin, and place Nrand new absorbers with the same properties as the given one accordingly. """ from astro.sampledist import RanDist absreal.sort(order='LOGN') #np.recarray.sort() sorted by column density Nrand = int(Nrand) absrand = absreal.repeat(Nrand) Ckms = 299792.458 if ion=='HI': z_Lya, Wmin_Lya = compute_Wmin(wa,fl,er,sl=sl,R=R,FWHM=FWHM,ion='HI') z_Lyb, Wmin_Lyb = compute_Wmin(wa,fl,er,sl=sl,R=R,FWHM=FWHM,ion='HILyb') for i in xrange(len(absreal)): if absreal.ZABS[i]>np.max(z_Lya): # lines that were observed through Lyb Wr = logN_b_to_Wr(absreal.LOGN[i],absreal.B[i],ion='HILyb') z = z_Lyb z = np.where(z<=z_Lya,-1.,z) #mask out region with Lya coverage Wmin = Wmin_Lyb else: #lines that were observed through Lya only Wr = logN_b_to_Wr(absreal.LOGN[i],absreal.B[i],ion='HI') z = z_Lya Wmin = Wmin_Lya zgood = (Wr > Wmin) & (z>0) assert np.sum(zgood)>0, \ 'There are not regions in the spectrum with Wmin<%s A. Addjust significance.' %(Wr) rand_z = RanDist(z, zgood*1.) zrand = rand_z.random(Nrand) absrand.ZABS[i*Nrand:(i+1)*Nrand] = zrand return absrand
def random_abs(zobs, Wobs, Nrand, wa, fl, er, sl=3., R=20000, FWHM=10., wa0=1215.67, zmax=None, zmin=None): """From a list of observed redshifts (zobs) and observed rest-frame equivalent widths (Wobs), it creates a random catalog. For a given real absorber with Wobs it creates Nrand random ones at the new zrand, defined by where the line could have been observed. It returns those zrand. Inputs ------ zobs: observed redshifts. Wobs: observed rest-frame equivalent widths (in A). Nrand: number of randWr = logN_b_to_Wr()om lines per real one generated (integer). wa: numpy array of wavelenght covered by the spectrum. fl: numpy array of normalized flux. er: numpy array of error in the normalized flux of the spectrum for a given wavelenght. sl: significance level for the detection of the absorption line. R: resolution of the spectrograph, assumed constant FWHM: Full-width at half maximum in pixels (assumed constant). This parameter defines the smoothing scale for Wmin. wa0: rest-frame wavelenght (in A). zmax: if given, is the maximum redshift allowed for the randoms zmin: if given, is the minimum redshift allowed for the randoms We first compute Wmin (see abslines.Wmin). We compute the redshifts where Wobs could have been observed according to the given Wmin, and place Nrand new absorbers with the same properties as the given one accordingly. """ zobs = np.array(zobs) Wobs = np.array(Wobs) wa = np.array(wa) fl = np.array(fl) er = np.array(er) assert len(zobs)==len(Wobs), \ 'zobs and Wobs do not have same dimensions!' assert (len(wa)==len(fl)) and (len(wa)==len(er)),\ 'wa,fl and er do not have same dimensions!' Nrand = int(Nrand) zrand = zobs.repeat(Nrand) z, Wmin = compute_Wmin(wa, fl, er, sl=sl, R=R, FWHM=FWHM, wa0=wa0) if zmax is None: zmax = 1000. ## Here, sort out zlims if zmin is None: zmin = 0. for i in xrange(len(Wobs)): zgood = (Wobs[i] > Wmin) & (z >= zmin) & (z < zmax) if np.sum(zgood) == 0: #This is not good so plot situation. pl.plot(z, Wmin, drawstyle='steps-mid') pl.axis([z[0], z[-1], 0, 0.1]) pl.show() print Wmin assert np.sum(zgood)>0, \ 'There are not regions in the spectrum with Wmin<{} A. The minimum is {} A. Adjust significance.'.format(Wobs,np.min(Wmin)) rand_z = RanDist(z, zgood * 1.) aux = rand_z.random(Nrand) zrand[i * Nrand:(i + 1) * Nrand] = aux return zrand
def random_abs(zobs,Wobs,Nrand,wa,fl,er,sl=3.,R=20000,FWHM=10.,wa0=1215.67,zmax=None,zmin=None): """From a list of observed redshifts (zobs) and observed rest-frame equivalent widths (Wobs), it creates a random catalog. For a given real absorber with Wobs it creates Nrand random ones at the new zrand, defined by where the line could have been observed. It returns those zrand. Inputs ------ zobs: observed redshifts. Wobs: observed rest-frame equivalent widths (in A). Nrand: number of randWr = logN_b_to_Wr()om lines per real one generated (integer). wa: numpy array of wavelenght covered by the spectrum. fl: numpy array of normalized flux. er: numpy array of error in the normalized flux of the spectrum for a given wavelenght. sl: significance level for the detection of the absorption line. R: resolution of the spectrograph, assumed constant FWHM: Full-width at half maximum in pixels (assumed constant). This parameter defines the smoothing scale for Wmin. wa0: rest-frame wavelenght (in A). zmax: if given, is the maximum redshift allowed for the randoms zmin: if given, is the minimum redshift allowed for the randoms We first compute Wmin (see abslines.Wmin). We compute the redshifts where Wobs could have been observed according to the given Wmin, and place Nrand new absorbers with the same properties as the given one accordingly. """ zobs = np.array(zobs) Wobs = np.array(Wobs) wa = np.array(wa) fl = np.array(fl) er = np.array(er) assert len(zobs)==len(Wobs), \ 'zobs and Wobs do not have same dimensions!' assert (len(wa)==len(fl)) and (len(wa)==len(er)),\ 'wa,fl and er do not have same dimensions!' Nrand = int(Nrand) zrand = zobs.repeat(Nrand) z, Wmin = compute_Wmin(wa,fl,er,sl=sl,R=R,FWHM=FWHM,wa0=wa0) if zmax is None: zmax = 1000. ## Here, sort out zlims if zmin is None: zmin = 0. for i in xrange(len(Wobs)): zgood = (Wobs[i] > Wmin) & (z >= zmin) & ( z < zmax) if np.sum(zgood)==0: #This is not good so plot situation. pl.plot(z,Wmin,drawstyle='steps-mid') pl.axis([z[0],z[-1],0,0.1]) pl.show() print Wmin assert np.sum(zgood)>0, \ 'There are not regions in the spectrum with Wmin<{} A. The minimum is {} A. Adjust significance.'.format(Wobs,np.min(Wmin)) rand_z = RanDist(z, zgood*1.) aux = rand_z.random(Nrand) zrand[i*Nrand:(i+1)*Nrand] = aux return zrand