def temporal_smearing(self, lobs, zsource, cosmo=None): """ Temporal smearing due to turbulent scattering Parameters ---------- lobs : Quantity Observed wavelength zsource : float cosmo : astropy.cosmology, optional Returns ------- tau : Quantity temporal broadening """ # Cosmology if cosmo is None: from astropy.cosmology import Planck15 as cosmo D_S = cosmo.angular_diameter_distance(zsource) D_L = cosmo.angular_diameter_distance(self.zL) D_LS = cosmo.angular_diameter_distance_z1z2(self.zL, zsource) # Angular theta = self.angular_broadening(lobs, zsource, cosmo=cosmo) # Calculate tau = D_L * D_S * (theta.to('radian').value)**2 / D_LS / const.c / ( 1 + self.zL) # Return return tau.to('ms')
def update(val): zL,zS = slzL.val,slzS.val xL,yL = slxL.val, slyL.val ML,eL,PAL = slML.val,sleL.val,slPAL.val sh,sha = slss.val,slsa.val xs,ys = slxs.val, slys.val Fs,ws = slFs.val, slws.val ns,ars,pas = slns.val,slars.val,slPAs.val newDd = cosmo.angular_diameter_distance(zL).value newDs = cosmo.angular_diameter_distance(zS).value newDds= cosmo.angular_diameter_distance_z1z2(zL,zS).value newLens = vl.SIELens(zLens,xL,yL,10**ML,eL,PAL) newShear = vl.ExternalShear(sh,sha) newSource = vl.SersicSource(zS,True,xs,ys,Fs,ws,ns,ars,pas) xs,ys = vl.LensRayTrace(xim,yim,[newLens,newShear],newDd,newDs,newDds) imbg = vl.SourceProfile(xim,yim,newSource,[newLens,newShear]) imlensed = vl.SourceProfile(xs,ys,newSource,[newLens,newShear]) caustics = vl.CausticsSIE(newLens,newDd,newDs,newDds,newShear) ax.cla() ax.imshow(imbg,cmap=cmbg,extent=[xim.min(),xim.max(),yim.min(),yim.max()],origin='lower') ax.imshow(imlensed,cmap=cmlens,extent=[xim.min(),xim.max(),yim.min(),yim.max()],origin='lower') mu = imlensed.sum()*(xim[0,1]-xim[0,0])**2 / newSource.flux['value'] ax.text(0.9,1.02,'$\\mu$ = {0:.2f}'.format(mu),transform=ax.transAxes) #for i in range(caustics.shape[0]): # ax.plot(caustics[i,0,:],caustics[i,1,:],'k-') for caustic in caustics: ax.plot(caustic[:,0],caustic[:,1],'k-') f.canvas.draw_idle()
def create_modelimage(lens,source,xmap,ymap,xemit,yemit,indices, Dd=None,Ds=None,Dds=None,sourcedatamap=None): """ Creates a model lensed image given the objects and map coordinates specified. Supposed to be common for both image fitting and visibility fitting, so we don't need any data here. Returns: immap A 2D array representing the field evaluated at xmap,ymap with all sources included. mus: A numpy array of length N_sources containing the magnifications of each source (1 if unlensed). """ lens = list(np.array([lens]).flatten()) # Ensure lens(es) are a list source = list(np.array([source]).flatten()) # Ensure source(s) are a list mus = np.zeros(len(source)) immap, imsrc = np.zeros(xmap.shape), np.zeros(xemit.shape) # If we didn't get pre-calculated distances, figure them here assuming Planck15 if np.any((Dd is None,Ds is None, Dds is None)): from astropy.cosmology import Planck15 as cosmo Dd = cosmo.angular_diameter_distance(lens[0].z).value Ds = cosmo.angular_diameter_distance(source[0].z).value Dds= cosmo.angular_diameter_distance_z1z2(lens[0].z,source[0].z).value # Do the raytracing for this set of lens & shear params xsrc,ysrc = LensRayTrace(xemit,yemit,lens,Dd,Ds,Dds) if sourcedatamap is not None: # ... then particular source(s) are specified for this map for jsrc in sourcedatamap: if source[jsrc].lensed: ims = SourceProfile(xsrc,ysrc,source[jsrc],lens) imsrc += ims mus[jsrc] = ims.sum()*(xemit[0,1]-xemit[0,0])**2./source[jsrc].flux['value'] else: immap += SourceProfile(xmap,ymap,source[jsrc],lens); mus[jsrc] = 1. else: # Assume we put all sources in this map/field for j,src in enumerate(source): if src.lensed: ims = SourceProfile(xsrc,ysrc,src,lens) imsrc += ims mus[j] = ims.sum()*(xemit[0,1]-xemit[0,0])**2./src.flux['value'] else: immap += SourceProfile(xmap,ymap,src,lens); mus[j] = 1. # Try to reproduce matlab's antialiasing thing; this uses a 3lobe lanczos low-pass filter imsrc = Image.fromarray(imsrc) resize = np.array(imsrc.resize((int(indices[1]-indices[0]),int(indices[3]-indices[2])),Image.ANTIALIAS)) immap[indices[2]:indices[3],indices[0]:indices[1]] += resize # Flip image to match sky coords (so coordinate convention is +y = N, +x = W, angle is deg E of N) immap = immap[::-1,:] # last, correct for pixel size. immap *= (xmap[0,1]-xmap[0,0])**2. return immap,mus
def set_up_global(self): """ Set some global variables so don't need to recompute each time """ self.z_s = self.global_dict["z_s"] self.z_l = self.global_dict["z_l"] self.D_s = Planck15.angular_diameter_distance(z=self.z_s).value * Mpc self.D_l = Planck15.angular_diameter_distance(z=self.z_l).value * Mpc self.Sigma_crit = 1.0 / (4 * np.pi * GN) * self.D_s / ((self.D_s - self.D_l) * self.D_l)
def sigma_crit(self,zl=[],zs=[],cosmo=None): #ds=cosmo_h.comoving_transverse_distance(zs) #dl=cosmo_h.comoving_transverse_distance(zl) ds=cosmo.angular_diameter_distance(zs) dl=cosmo.angular_diameter_distance(zl) ddls=1-np.multiply.outer(1./ds,dl)#(ds-dl)/ds w=(3./2.)*((cosmo.H0/c)**2)*(1+zl)*dl/self.Rho_crit(cosmo) sigma_c=1./(ddls*w) x=ddls<=0 #zs<zl sigma_c[x]=np.inf return sigma_c
def cl_z(self, z=[], l=np.arange(2000) + 1, pk_params=None, cosmo=None, pk_func=None): if not pk_func: pk_func = self.class_pk nz = len(z) nl = len(l) pk, kh = pk_func(z=z, pk_params=pk_params) cls = np.zeros((nz, nl), dtype='float32') * u.Mpc**2 for i in np.arange(nz): DC_i = cosmo.angular_diameter_distance( z[i]).value #because camb k in h/mpc lz = kh * DC_i - 0.5 pk_int = interp1d(lz, pk[i] / DC_i**2, bounds_error=False, fill_value=0) cls[i][:] += pk_int(l) * u.Mpc * (c / (cosmo.efunc(z[i]) * cosmo.H0)) return cls
def ang2proj(self, theta, z): from astropy.cosmology import Planck15 as cosmodel from astropy import units as u d_A = cosmodel.angular_diameter_distance(z) distance_Mpc = (theta * d_A).to(u.kpc, u.dimensionless_angles()) return (distance_Mpc)
def cal_einstein_radius_in_arcsec(z_l,z_s,sigma): #b_sie = 4*pi * sigma^2/c^2 * D_ls/D_s c = const.c.value / 1000 #to km/s v_fac = (sigma/c)**2 d_fac = cosmo.angular_diameter_distance_z1z2(z_l, z_s).value/cosmo.angular_diameter_distance(z_s).value radian_to_arcsec = 180.0/np.pi*60*60 return 4.0*np.pi*v_fac*d_fac*radian_to_arcsec
def write_defmap(mass, pixscale, z_lens, sample_fits, ra_off=0, dec_off=0): """ Calculate and write deflection maps given a mass sheet. Note that the lensing efficiency is built into map_utils and so is not implemented here. Parameters ---------- mass : ndarray Two dimensional array representing mass sheet pixscale : float Pixel size in arcsec z_lens : float redshift of lens sample_fits : str path to template fits file for header generation ra_off : float ra offset in arcsec from template fits file ra reference dec_off : float dec offset in arcsec from template fits file dec reference Returns -> None Writes 'deflectionx.fits' and 'deflectiony.fits' """ D_d = cosmo.angular_diameter_distance(z_lens) npix = mass.shape[0] pix_area = pixscale**2 center = int(npix / 2) image_radius = center * pixscale y, x = np.mgrid[-1 * image_radius:image_radius:1j * npix, -1 * image_radius:image_radius:1j * npix] # # 4G/c^2 is the usual prefactor. pix_area is to get mass density to mass. "/kpc is to get 1/r to kpc deflection_prefactor = units.rad.to('arcsec')**2 * 4 * G * pix_area * units.M_sun.to('kg') / (c**2 * D_d * units.Mpc.to('m')) defy, defx = np.zeros((2, npix, npix)) for indx in range(npix): for indy in range(npix): r_2 = (y[indy, indx] - y)**2 + (x[indy, indx] - x)**2 r_2[r_2 == 0.0] = np.nan defy[indy, indx] = np.nansum((y[indy, indx] - y) * mass / r_2) defx[indy, indx] = np.nansum((x[indy, indx] - x) * mass / r_2) defy *= deflection_prefactor.value defx *= deflection_prefactor.value header = fits.getheader(sample_fits) header['CDELT2'] = pixscale / 3600. header['CDELT1'] = -1 * pixscale / 3600. header['NAXIS1'] = npix header['NAXIS2'] = npix header['CRVAL1'] = ra_off header['CRVAL2'] = dec_off header['CRPIX1'] = int(center) header['CRPIX2'] = int(center) fits.writeto('deflectionx.fits', defx, header=header, overwrite=True) fits.writeto('deflectiony.fits', defy, header=header, overwrite=True)
def update(val): zL, zS = slzL.val, slzS.val xL, yL = slxL.val, slyL.val ML, eL, PAL = slML.val, sleL.val, slPAL.val sh, sha = slss.val, slsa.val xs, ys = slxs.val, slys.val Fs, ws = slFs.val, slws.val ns, ars, pas = slns.val, slars.val, slPAs.val newDd = cosmo.angular_diameter_distance(zL).value newDs = cosmo.angular_diameter_distance(zS).value newDds = cosmo.angular_diameter_distance_z1z2(zL, zS).value newLens = vl.SIELens(zLens, xL, yL, 10**ML, eL, PAL) newShear = vl.ExternalShear(sh, sha) newSource = vl.SersicSource(zS, True, xs, ys, Fs, ws, ns, ars, pas) xs, ys = vl.LensRayTrace(xim, yim, [newLens, newShear], newDd, newDs, newDds) imbg = vl.SourceProfile(xim, yim, newSource, [newLens, newShear]) imlensed = vl.SourceProfile(xs, ys, newSource, [newLens, newShear]) caustics = vl.CausticsSIE(newLens, newDd, newDs, newDds, newShear) ax.cla() ax.imshow(imbg, cmap=cmbg, extent=[xim.min(), xim.max(), yim.min(), yim.max()], origin='lower') ax.imshow(imlensed, cmap=cmlens, extent=[xim.min(), xim.max(), yim.min(), yim.max()], origin='lower') mu = imlensed.sum() * (xim[0, 1] - xim[0, 0])**2 / newSource.flux['value'] ax.text(0.9, 1.02, '$\\mu$ = {0:.2f}'.format(mu), transform=ax.transAxes) #for i in range(caustics.shape[0]): # ax.plot(caustics[i,0,:],caustics[i,1,:],'k-') for caustic in caustics: ax.plot(caustic[:, 0], caustic[:, 1], 'k-') f.canvas.draw_idle()
def update(val): zL,zS = slzL.val,slzS.val xL,yL = slxL.val, slyL.val ML,eL,PAL = slML.val,sleL.val,slPAL.val sh,sha = slss.val,slsa.val newDd = cosmo.angular_diameter_distance(zL).value newDs = cosmo.angular_diameter_distance(zS).value newDds= cosmo.angular_diameter_distance_z1z2(zL,zS).value newLens = vl.SIELens(zLens,xL,yL,10**ML,eL,PAL) newShear = vl.ExternalShear(sh,sha) xsource,ysource = vl.LensRayTrace(xim,yim,[newLens,newShear],newDd,newDs,newDds) caustics = vl.get_caustics([newLens,newShear],newDd,newDs,newDds) ax.cla() ax.plot(xsource,ysource,'b-') for caustic in caustics: ax.plot(caustic[:,0],caustic[:,1],'k-') #ax.set_xlim(-0.5,0.5) #ax.set_ylim(-0.5,0.5) #for i in range(len(xs)): # p[i].set_xdata(xs[i]) # p[i].set_ydata(ys[i]) f.canvas.draw_idle()
def red_sequence_cut(config, data, **kwargs): """ Identify RS galaxies using color-magnitude diagram. First do a radial cut on catalogue and identify the RS from the inner galaxies --> increase the contrast of the RS Then go back and apply the cut on the entire catalogue as some RS galaxies are located far away from the centre Returns bool array, where False means the object does not pass the cut List of available kwargs: :param float mag_cut: rband magnitude cut - default is 25 :param float plot: if keywords exists, plot stuff for visual inspection """ mcut = kwargs.get('mag_cut', 25.) plot = kwargs.get('plot', False) da = cosmo.angular_diameter_distance( config['redshift']) # Mpc - using Planck15 cosmo rcut_rs = 1 * u.Mpc sub_sample = cdata.filter_around(data, config, exclude_outer=N.arctan(rcut_rs / da).value, unit='rad', plot=plot) color_gr = sub_sample['modelfit_CModel_mag'][sub_sample['filter'] == 'g'] - \ sub_sample['modelfit_CModel_mag'][sub_sample['filter'] == 'r'] mag = sub_sample['modelfit_CModel_mag'][sub_sample['filter'] == 'r'] params = fit_red_sequence( color_gr, mag, plot=plot) # slopes and intercepts of the RS band # apply cut to entire dataset color_gr = data['modelfit_CModel_mag'][data['filter'] == 'g'] - \ data['modelfit_CModel_mag'][data['filter'] == 'r'] mag = data['modelfit_CModel_mag'][data['filter'] == 'r'] lower_bound = params[0][0] * mag + params[0][1] upper_bound = params[1][0] * mag + params[1][1] filt = ((color_gr < lower_bound) & (mag < mcut)) | ((color_gr > upper_bound) & (mag < mcut)) return filt
def red_sequence_cut(config, data, **kwargs): """ Identify RS galaxies using color-magnitude diagram. First do a radial cut on catalogue and identify the RS from the inner galaxies --> increase the contrast of the RS Then go back and apply the cut on the entire catalogue as some RS galaxies are located far away from the centre Returns bool array, where False means the object does not pass the cut List of available kwargs: :param float mag_cut: rband magnitude cut - default is 25 :param float plot: if keywords exists, plot stuff for visual inspection """ mcut = kwargs.get('mag_cut', 25.) plot = kwargs.get('plot', False) da = cosmo.angular_diameter_distance( config['redshift']) # Mpc - using Planck15 cosmo rcut_rs = 1 * u.Mpc sub_sample = cutils.filter_around(data, config, exclude_outer=N.arctan(rcut_rs / da).value, unit='rad', plot=plot) color_gr = sub_sample['modelfit_CModel_mag'][sub_sample['filter'] == 'g'] \ - sub_sample['modelfit_CModel_mag'][sub_sample['filter'] == 'r'] mag = sub_sample['modelfit_CModel_mag'][sub_sample['filter'] == 'r'] # slopes and intercepts of the RS band params = fit_red_sequence(color_gr, mag, plot=plot) # apply cut to entire dataset color_gr = data['modelfit_CModel_mag'][data['filter'] == 'g'] \ - data['modelfit_CModel_mag'][data['filter'] == 'r'] mag = data['modelfit_CModel_mag'][data['filter'] == 'r'] lower_bound = params[0][0] * mag + params[0][1] upper_bound = params[1][0] * mag + params[1][1] filt = ((color_gr < lower_bound) & (mag < mcut)) | ( (color_gr > upper_bound) & (mag < mcut)) return filt
def physical_size(redshift, angular_size): ''' Calculates the physical size of a source in Kpc ''' # physical distance corresponding to 1 radian at redshift z size = Planck15.angular_diameter_distance(redshift) # to not adjust the actual size column angular_size = np.copy(angular_size) # angular_size is in arcsec, convert to radian angular_size /= 3600 # to degrees angular_size *= np.pi / 180 # to radians # physical distance corresponding to angular distance size *= angular_size size = size.to(u.kpc) return size
def angular_broadening(self, lobs, zsource, cosmo=None): """ Broadening of a point source due to turbulent scattering Parameters ---------- lobs : Quantity Observed wavelength zsource : float Redshift of radio source Returns ------- theta : Quantity Angular broadening. Radius (half-width at half-max) """ if self.regime == 0: raise ValueError("Need to set rdiff and the regime first!") if cosmo is None: from astropy.cosmology import Planck15 as cosmo # f if (self.regime == 1) or np.isclose(self.beta, 4.): f = 1.18 elif (self.regime == 2) and np.isclose(self.beta, 11 / 3.): f = 1.01 # Distances D_S = cosmo.angular_diameter_distance(zsource) D_LS = cosmo.angular_diameter_distance_z1z2(self.zL, zsource) if self.verbose: print("D_LS={}, D_S={}".format(D_LS, D_S)) D_LS_D_S = D_LS / D_S # Evaluate k = 2 * np.pi / (lobs / (1 + self.zL) ) # Are we sure about this (1+z) factor?! self.theta = f * D_LS_D_S / (k * self.rdiff) * u.radian return self.theta.to('arcsec')
import numpy as np import matplotlib.pyplot as plt import pandas as pd from tqdm import * from plot_skylocs import LimitPlot from astropy.cosmology import Planck15 import argparse parser = argparse.ArgumentParser() parser.add_argument("--imc", action="store", dest="imc", default=0,type=int) results = parser.parse_args() imc = results.imc catalog = pd.read_csv("/tigress/nrodd/DM-Catalog-Scan/DataFiles/Catalogs/2MRSTully_ALL_DATAPAPER_Planck15_v4.csv") nobj = 1000 lb_cat = [] for iobj in tqdm(range(nobj)): rep_angext = np.array([0.02785567,0.12069876,0.21354185,0.30638494,0.39922802,0.49207111,0.5849142,0.67775728,0.77060037,0.86344346,0.95628654,1.04912963,1.14197272,1.2348158,1.32765889,1.42050198,1.51334507,1.60618815,1.69903124,1.79187433]) obj_angext = 2*catalog[u'rs'].values[iobj] / \ (Planck15.angular_diameter_distance(catalog[u'z'].values[iobj]).value*1000) \ * 180./np.pi rep_index = (np.abs(rep_angext-obj_angext)).argmin() lb_cat.append(np.loadtxt("../data/Tully_randlocs"+str(int(np.loadtxt("../data/Tully_skylocs"+str(imc)+"/skyloc_obj"+str(iobj)+".txt")))+"/lb_obj"+str(rep_index)+".dat")) np.save("../data/Tully_skylocs/lb_cat_mc"+str(imc)+".npy",lb_cat)
def check_arguments(): if len(sys.argv[1:]): try: opts, args = getopt.getopt(sys.argv[1:], 'f:o:r:d:z:R:jmN:F:', ['help', 'dec=']) except getopt.GetoptError: # unrecognized argument passed print 'getopt error' opts, args = None, None usage() provided_args = [i[0] for i in opts] if '--help' in provided_args: # print verbose help usage(v=True) if '-f' not in provided_args: # user has not provided an input json file (batch running for instance) if not all(a in provided_args for a in ['-o', '-r', '-z', '-R']) and not \ (('-d' in provided_args) or ('--dec' in provided_args)): # check correct provided arguments print 'Missing argument, require -o -r -d -z -R all with values in this mode.' usage() else: try: args_obsid = re.match( '^[0-9]+$', opts[provided_args.index('-o')][1]).group() args_ra = float(opts[provided_args.index('-r')][1]) if '-d' in provided_args: args_dec = float(opts[provided_args.index('-d')][1]) elif '--dec' in provided_args: args_dec = float(opts[provided_args.index('--dec')][1]) else: args_dec = None usage() # this should never happen args_z = float(opts[provided_args.index('-z')][1]) args_r500 = u.Quantity( float(opts[provided_args.index('-R')][1]), u.kpc) d_a = Cosmo.angular_diameter_distance(args_z) args_r500_arcseconds = (180.0 / np.pi) * float( args_r500 / d_a) * 3600 username = (subprocess.Popen( 'whoami', stdout=subprocess.PIPE)).stdout.read() return_dict = { 'ObsID': args_obsid, 'ra': args_ra, 'dec': args_dec, 'z': args_z, 'r500 kpc': float(args_r500 / u.Quantity(1.0, u.kpc)), 'r500 arcseconds': args_r500_arcseconds, 'u_name': str( username ) # Knowing username allows for correct file path to be used for Lustre } if '-j' in provided_args: return_dict['enable jobs'] = True else: return_dict['enable jobs'] = False if '-N' in provided_args: return_dict['N'] = int( opts[provided_args.index('-N')][1]) if '-F' in provided_args: return_dict['N'] = float( opts[provided_args.index('-F')][1]) return return_dict # return a dictionary with session information except ValueError as err: print err usage() else: # user has provided an input json file, check it has all required keywords json_args = {} try: if os.path.isfile(opts[provided_args.index('-f')][1]): with open(opts[provided_args.index('-f')] [1]) as json_args_file: json_args = json.load(json_args_file) else: print "Could not find JSON file, check the file path" except ValueError as err: print err usage() json_keys = json_args.keys() if all(k in json_keys for k in ['ObsID', 'ra', 'dec', 'z', 'r500']): return_dict = {k: v for k, v in json_args} valid_file = True valid_file &= re.match('^[0-9]+$', json_args['ObsID']).group( ) # ensure a valid ObsID is provided try: # ensure all provided core arguments valid # TODO: make this more robust - check or ignore other arguments float(json_args['ra']) float(json_args['dec']) float(json_args['z']) float(json_args['r500']) int(json_args.get('N', 1)) float(json_args.get('F', 1.0)) except ValueError: valid_file &= False if not valid_file: print 'Invalid JSON file' usage() if '-j' in provided_args: return_dict['enable jobs'] = True else: return_dict['enable jobs'] = return_dict.get( 'enable jobs', False) return return_dict else: print 'Invalid json input' usage() else: usage()
counts_gals_rand += count_gal_rand n = n + 1 return counts_gals_rand / float(num_p) for z in np.arange(1.5, 2.0, 0.1): print('=============' + str(z) + '================') cat_massive_z_slice = cat_massive_gal[ abs(cat_massive_gal['ZPHOT'] - z) < 0.1] # massive galaxies in this z slice cat_all_z_slice = cat_gal[abs(cat_gal['ZPHOT'] - z) < 0.1] # all galaxies in this z slice dis = Planck15.angular_diameter_distance(z).value search_r = 0.5 / dis / np.pi * 180 / 0.17 # HSC plate scale 0.17 arcsec/pix cat_massive_z_slice['RA'].unit = u.deg cat_massive_z_slice['DEC'].unit = u.deg coord_massive_gal = SkyCoord.guess_from_table(cat_massive_z_slice) # counting neighbors for each massive central galaxy counts_gals_sf = np.zeros(10) counts_gals_q = np.zeros(10) counts_sf = 0 counts_q = 0 for gal in cat_massive_z_slice: coord_all_z_slice = SkyCoord(cat_all_z_slice['RA'] * u.deg, cat_all_z_slice['DEC'] * u.deg) coord_gal = SkyCoord(gal['RA'] * u.deg, gal['DEC'] * u.deg)
def lens_efficiency(z_lens, z_src): """Calculates the efficiency of the lensing system given source and lens redshifts.""" dist_lens_source = cosmo.angular_diameter_distance_z1z2(z_lens, z_src).value dist_observer_source = cosmo.angular_diameter_distance(z_src).value return dist_lens_source / dist_observer_source
def run(dt, nupeak, fpeak, p, z): """ dt: time in days (observer frame) nupeak: peak frequency in GHz (observed I think) fpeak: peak flux density in Jy p: Lorentz factor power index z: redshift to the source """ # To convert from flux density to luminosity, # you need to use the luminosity distance DL_cm = Planck15.luminosity_distance(z=z).cgs.value print("lpeak", fpeak * 1E-23 * 4 * np.pi * DL_cm**2) # In the Chevalier 98 equation, D is the angular diameter distance DA_mpc = Planck15.angular_diameter_distance(z=z).value R = get_R(fpeak, nupeak, DA_mpc) print("R", R / 10**15) V = (4 / 3) * f * np.pi * R**3 # volume B = get_B(fpeak, nupeak, DA_mpc) print("B", B) # Convert time to rest-frame...or maybe not? dt_rest = dt / (1 + z) #dt_rest = dt v = R / (86400 * dt_rest) print("v/c", v / 3E10) gammabeta = v / c print("gamma beta", gammabeta) beta = 1 / (1 + (3E10 / v)**2)**0.5 print("Beta", beta) gamma = 1 / (1 - beta**2) print("gamma", gamma) P = B**2 / (8 * np.pi * eps_B) rho = (4 * P / 3) / v**2 print("rho", rho) n_p = rho / m_p n_e = n_p print("ne", n_e) UB = V * (B**2) / (8 * np.pi) U = get_U(fpeak, nupeak, DA_mpc) print("E", U) tauff = 8.235E-2 * n_e**2 * (R / 3.086E18) * (8000)**(-1.35) print("tau_ff", tauff) Te = 1.2E6 nuff = (1 / (68 * (Te / 8000)**(-1.35)))**(-1 / 2.1) print("nu_ff [GHz]", nuff) Lff = 1.43E-27 * n_e**2 * Te**(1 / 2) * (4 / 3) * np.pi * (6E16)**3 print("L_ff", Lff) # Gamma_m gammam = eps_e * (m_p / m_e) * ((p - 2) / (p - 1)) * beta**2 print("gamma_m", gammam) # Gyrofrequency gammag = q_e * B / (2 * np.pi * m_e * c) print("gyrofrequency [MHz]", gammag / 1E6) # nu_m num = gammam**2 * gammag print("nu_m [GHz]", num / 1E9) # Cooling frequency gammac = 6 * np.pi * m_e * c / (sigmat * B**2 * dt * 86400) print("gammac", gammac) nuc = gammac**2 * q_e * B / (2 * np.pi * m_e * c) print("nu_cc [GHz]", nuc / 1E9)
def get_power_lightcone_beam(fname, numin=150., numax=161.15, get_delta=True, bins=50, beam_model=CircularGaussian): """ Calculate the spherically-averaged power spectrum in a segment of a lightcone, after attenuation by a given beam. Parameters ---------- fname : str Filename of 21cmFAST simulation box. Should *not* be a lighttravel box. numin, numax : float Min/Max frequencies of the "observation", in MHz. Used to cut the box before PS estimation. get_delta : bool, optional If True, return the dimensionless power spectrum, Delta^2, otherwise, return the volume-normalised power. bins : int, optional Number of k-bins to use (linearly spaced) beam_model : `spore.model.beam.CircularBeam` subclass Defines the beam model Returns ------- pk : array The power spectrum as a function of k. Has units mK^2 if `get_delta` is True, otherwise has units mK^2 Mpc^3. kbins : array The k values corresponding to pk. Has units 1/Mpc. """ box, N, L, d, nu, z = get_cut_box(fname, numin, numax) # INITIALISE A BEAM MODEL beam = beam_model(nu.min(), np.linspace(1, nu.max() / nu.min(), len(nu))) # ATTENUATE BOX BY THE BEAM width = L / Planck15.angular_diameter_distance(z).value vol = np.ones_like(box) for i in range(len(nu)): dl = width[i] / N l = np.sin( np.linspace(-width[i] / 2 + dl / 2, width[i] / 2 - dl / 2, N)) X, M = np.meshgrid(l, l) vol[:, :, i] = np.exp(-(X**2 + M**2) / (2 * beam.sigma[i]**2)) box[:, :, i] = box[:, :, i] * vol[:, :, i] volfrac = np.sum(vol) / np.product(vol.shape) pk, kbins = get_power(box, [L, L, np.abs(d[-1] - d[0])], bins=bins) if get_delta: pk *= kbins**3 / (2 * np.pi**2) return pk, kbins, volfrac
def __init__( self, mag_zero=25.5, mag_iso=22.5, exposure=1610.0, fwhm_psf=0.18, pixel_size=0.1, n_xy=64, f_sub=0.05, beta=-1.9, m_min_calib=1e6 * M_s, m_max_sub_div_M_hst_calib=0.01, m_200_min_sub=1e7 * M_s, m_200_max_sub_div_M_hst=0.01, M_200_sigma_v_scatter=False, params_eval=None, calculate_joint_score=False, calculate_msub_derivatives=False, calculate_sub_residuals=False, draw_host_mass=True, draw_host_redshift=True, draw_alignment=True, roi_size=2., ): """ Class to simulation an observation strong lensing image, with substructure sprinkled in. :param mag_zero: Zero-point magnitude of observation :param mag_iso: Magnitude of isotropic sky brightness :param exposure: Exposure time of observation, in seconds (including gain) :param fwhm_psf: FWHM of Gaussian PSF, in arcsecs :param pixel_size: Pixel side size, in arcsecs :param n_xy: Number of pixels (along x and y) of observation :param f_sub: Fraction of total contained mass in substructure :param beta: Slope in the subhaalo mass function :param m_min_calib: Minimum mass above which subhalo mass fraction is `f_sub` :param m_max_sub_div_M_hst_calib: Maximum mass below which subhalo mass fraction is `f_sub`, in units of the host halo mass :param m_200_min_sub: Lowest mass of subhalos to draw :param m_200_max_sub_div_M_hst: Maximum mass of subhalos to draw, in units of host halo mass :param M_200_sigma_v_scatter: Whether to apply lognormal scatter in sigma_v to M_200_host mapping :param params_eval: Parameters (f_sub, beta) for which p(x,z|params) will be calculated :param calculate_joint_score: Whether grad_params log p(x,z|params) will be calculated :param calculate_msub_derivatives: Whether to calculate derivatives of image wrt subhalos masses :param calculate_residuals: Whether to calculate residual images wrt subhalos """ # beta = -2.0 is forbidden! if np.abs((beta + 2.)) < 1.e-3: beta = -2.001 # Store input self.mag_zero = mag_zero self.mag_iso = mag_iso self.exposure = exposure self.fwhm_psf = fwhm_psf self.pixel_size = pixel_size self.n_xy = n_xy self.f_sub = f_sub self.beta = beta self.m_min_calib = m_min_calib self.m_max_sub_div_M_hst_calib = m_max_sub_div_M_hst_calib self.m_200_min_sub = m_200_min_sub self.m_200_max_sub_div_M_hst = m_200_max_sub_div_M_hst self.M_200_sigma_v_scatter = M_200_sigma_v_scatter self.params_eval = params_eval self.calculate_joint_score = calculate_joint_score self.draw_host_mass = draw_host_mass self.draw_host_redshift = draw_host_redshift self.draw_alignment = draw_alignment self.coordinate_limit = pixel_size * n_xy / 2.0 # Draw lens properties consistent with Collett et al [1507.02657] # Clip lens redshift `z_l` to be less than 1; high-redshift lenses no good for our purposes! if self.draw_host_redshift: self.z_l = 2.0 while self.z_l > 1.0: self.z_l = 10 ** np.random.normal(-0.25, 0.25) else: self.z_l = 10.0 ** -0.25 if self.draw_host_mass: self.sigma_v = np.random.normal(225, 50) else: self.sigma_v = 225.0 if self.draw_alignment: self.theta_x_0 = np.random.normal(0, 0.2) self.theta_y_0 = np.random.normal(0, 0.2) else: self.theta_x_0 = 0.0 self.theta_y_0 = 0.0 q = 1 # For now, hard-code host to be spherical # Fix the source properties to reasonable mean-ish values self.theta_s_e = 0.2 self.z_s = 1.5 self.mag_s = 23.0 # Get relevant distances self.D_l = Planck15.angular_diameter_distance(z=self.z_l).value * Mpc D_s = Planck15.angular_diameter_distance(z=self.z_s).value * Mpc D_ls = Planck15.angular_diameter_distance_z1z2(z1=self.z_l, z2=self.z_s).value * Mpc # Get properties for NFW host DM halo if draw_host_mass: self.M_200_hst = self.M_200_sigma_v(self.sigma_v * Kmps, scatter=M_200_sigma_v_scatter) else: self.M_200_hst = self.M_200_sigma_v(self.sigma_v * Kmps, scatter=0.0) c_200_hst = MassProfileNFW.c_200_SCP(self.M_200_hst) r_s_hst, rho_s_hst = MassProfileNFW.get_r_s_rho_s_NFW(self.M_200_hst, c_200_hst) # Get properties for SIE host self.theta_E = MassProfileSIE.theta_E(self.sigma_v * Kmps, D_ls, D_s) # Don't consider configuration with subhalo fraction > 1! self.f_sub_realiz = 2.0 while self.f_sub_realiz > 1.0: # Generate a subhalo population... ps = SubhaloPopulation( f_sub=f_sub, beta=beta, M_hst=self.M_200_hst, c_hst=c_200_hst, m_min=m_200_min_sub, m_max=m_200_max_sub_div_M_hst * self.M_200_hst, m_min_calib=m_min_calib, m_max_calib=m_max_sub_div_M_hst_calib * self.M_200_hst, theta_s=r_s_hst / self.D_l, theta_roi=roi_size * self.theta_E, theta_E=self.theta_E, params_eval=params_eval, calculate_joint_score=calculate_joint_score, ) # ... and grab its properties self.m_subs = ps.m_sample self.n_sub_roi = ps.n_sub_roi self.theta_xs = ps.theta_x_sample self.theta_ys = ps.theta_y_sample self.f_sub_realiz = ps.f_sub_realiz self.n_sub_in_ring = ps.n_sub_in_ring self.f_sub_in_ring = ps.f_sub_in_ring self.n_sub_near_ring = ps.n_sub_near_ring self.f_sub_near_ring = ps.f_sub_near_ring # Convert magnitude for source and isotropic component to expected counts self.S_tot = self._mag_to_flux(self.mag_s, self.mag_zero) self.f_iso = self._mag_to_flux(self.mag_iso, self.mag_zero) # Set host properties. Host assumed to be at the center of the image. self.hst_param_dict = {"profile": "SIE", "theta_x_0": 0.0, "theta_y_0": 0.0, "theta_E": self.theta_E, "q": q} lens_list = [self.hst_param_dict] # Set subhalo properties for i_sub, (m, theta_x, theta_y) in enumerate(zip(self.m_subs, self.theta_xs, self.theta_ys)): c = MassProfileNFW.c_200_SCP(m) r_s, rho_s = MassProfileNFW.get_r_s_rho_s_NFW(m, c) sub_param_dict = {"profile": "NFW", "theta_x_0": theta_x, "theta_y_0": theta_y, "M_200": m, "r_s": r_s, "rho_s": rho_s} lens_list.append(sub_param_dict) # Set source properties src_param_dict = {"profile": "Sersic", "theta_x_0": self.theta_x_0, "theta_y_0": self.theta_y_0, "S_tot": self.S_tot, "theta_e": self.theta_s_e, "n_srsc": 1} # Set observation and global properties observation_dict = { "n_x": n_xy, "n_y": n_xy, "theta_x_lims": (-self.coordinate_limit, self.coordinate_limit), "theta_y_lims": (-self.coordinate_limit, self.coordinate_limit), "exposure": exposure, "f_iso": self.f_iso, } global_dict = {"z_s": self.z_s, "z_l": self.z_l} # Inititalize lensing class and produce lensed image lsi = LensingSim(lens_list, [src_param_dict], global_dict, observation_dict) self.image = lsi.lensed_image() self.image_poiss = np.random.poisson(self.image) # Poisson fluctuate self.image_poiss_psf = self._convolve_psf(self.image_poiss, fwhm_psf, pixel_size) # Convolve with PSF # Augmented data self.joint_log_probs = ps.joint_log_probs self.joint_scores = ps.joint_scores # Optionally, compute derivatives of image wrt each subahlo mass (takes ~1s/subhalo) if calculate_msub_derivatives: self._calculate_derivs() # Optionally, compute derivatives of image wrt each subahlo mass (takes ~1s/subhalo) if calculate_sub_residuals: self._calculate_residuals()
contains(point('ICRS',cat.ra,cat.dec),circle('ICRS',mt.ra,mt.dec,0.01))=1 and Radial_Velocity > 0 ORDER by cat.ra""" zcattable = heasarc_tap_services[0].service.run_async(query, uploads={'mysources': 'data/my_sources.xml'}) #zcattable = heasarc_tap_services[0].search(query, uploads={'mysources': 'data/my_sources.xml'}) mytable = zcattable.to_table() mytable ## The column 'radial_velocity' is c*z but doesn't include the unit; it is km/s ## Get the speed of light from astropy.constants and express in km/s c = const.c.to(u.km/u.s).value redshifts = mytable['radial_velocity']/c mytable['redshift'] = redshifts physdist = 0.05*u.Mpc # 50 kpc physical distance angDdist = Planck15.angular_diameter_distance(mytable['redshift']) angDrad = np.arctan(physdist/angDdist) mytable['angDdeg'] = angDrad.to(u.deg) mytable ## In memory only, use an IO stream. vot_obj=io.BytesIO() apvot.writeto(apvot.from_table(mytable),vot_obj) ## (Reset the "file-like" object to the beginning.) vot_obj.seek(0) query="""SELECT mt.ra, mt.dec, cat.ra, cat.dec, cat.Radial_Velocity, cat.morph_type, cat.bmag FROM zcat cat, tap_upload.mytable mt WHERE contains(point('ICRS',cat.ra,cat.dec),circle('ICRS',mt.ra,mt.dec,mt.angDdeg))=1 and cat.Radial_Velocity > 0 and cat.radial_velocity != mt.radial_velocity
def plot_images(data, mcmcresult, returnimages=False, plotcombined=False, plotall=False, imsize=256, pixsize=0.2, taper=0., **kwargs): """ Create a five-panel figure from data and chains, showing data, best-fit model, residuals, high-res image, source plane Inputs: data: The visdata object(s) to be imaged. If more than one is passed, they'll be imaged/differenced separately. chains: A result from running LensModelMCMC. returnimages: bool, optional If True, will also return a list of numpy arrays containing the imaged data, interpolated model, and full-res model. Default is False. plotcombined: bool, optional, default False If True, plots only a single row of images, after combining all datasets in `data' and applying any necessary rescaling/shifting contained in `mcmcresult'. plotall: bool, optional, default False If True, plots each dataset in its own row *and* the combined dataset in an extra row. Returns: If returnimages is False: f, axarr: A matplotlib figure and array of Axes objects. If returnimages is True: f,axarr,imagelist: Same as above; imagelist is a list of length (# of datasets), containing four arrays each, representing the data, interpolated model, full-resolution model, and source plane. """ limits = kwargs.pop('limits', [ -imsize * pixsize / 2., +imsize * pixsize / 2., -imsize * pixsize / 2., +imsize * pixsize / 2. ]) cmap = kwargs.pop('cmap', cm.Greys) mapcontours = kwargs.pop('mapcontours', np.delete(np.arange(-21, 22, 3), 7)) rescontours = kwargs.pop('rescontours', np.array([-6, -5, -4, -3, -2, 2, 3, 4, 5, 6])) level = kwargs.pop('level', None) logmodel = kwargs.pop('logmodel', False) datasets = list(np.array([data]).flatten()) # shorthand for later c = copy.deepcopy(mcmcresult['chains']) # Now all these things are saved separately, don't have to do the BS above lens = mcmcresult['best-fit']['lens'] source = mcmcresult['best-fit']['source'] scaleamp = mcmcresult['best-fit']['scaleamp'] if 'scaleamp' in mcmcresult[ 'best-fit'].keys() else np.ones(len(datasets)) shiftphase = mcmcresult['best-fit'][ 'shiftphase'] if 'shiftphase' in mcmcresult['best-fit'].keys( ) else np.zeros((len(datasets), 2)) sourcedatamap = mcmcresult[ 'sourcedatamap'] if 'sourcedatamap' in mcmcresult.keys( ) else [None] * len(datasets) modelcal = mcmcresult['modelcal'] if 'modelcal' in mcmcresult.keys( ) else [False] * len(datasets) if plotall: f, axarr = plt.subplots(len(datasets) + 1, 5, figsize=(14, 4 * (len(datasets) + 1))) axarr = np.atleast_2d(axarr) images = [[] for _ in range(len(datasets) + 1)] if sourcedatamap[0] is not None: warnings.warn( "sourcedatamap[0] is not None. Are you sure you want plotall=True?" ) sourcedatamap.append(None) f.subplots_adjust(left=0.05, bottom=0.05, top=0.95, right=0.99) elif plotcombined: f, axarr = plt.subplots(1, 5, figsize=(14, 4)) axarr = np.atleast_2d(axarr) images = [[]] if sourcedatamap[0] is not None: warnings.warn( "sourcedatamap[0] is not None, and has been set to None. Are you sure you want plotcombined=True? This could break the source plane plot." ) sourcedatamap = [None] f.subplots_adjust(left=0.05, bottom=0.05, top=0.95, right=0.99) else: f, axarr = plt.subplots(len(datasets), 5, figsize=(14, 4 * len(datasets))) axarr = np.atleast_2d(axarr) images = [[] for _ in range(len(datasets))] # effing mutable lists. f.subplots_adjust(left=0.05, bottom=0.05, top=0.95, right=0.99) plotdata, plotinterp = [], [] for i, dset in enumerate(datasets): # Get us some coordinates. xmap,ymap,xemit,yemit,ix = GenerateLensingGrid(datasets,mcmcresult['xmax'],\ mcmcresult['highresbox'],mcmcresult['fieldres'],mcmcresult['emitres']) # Create model image immap,_ = create_modelimage(lens,source,xmap,ymap,xemit,yemit,\ ix,sourcedatamap=sourcedatamap[i]) # And interpolate onto uv-coords of dataset interpdata = fft_interpolate(dset,immap,xmap,ymap,ug=None,\ scaleamp=scaleamp[i],shiftphase=shiftphase[i]) if modelcal[i]: selfcal, _ = model_cal(dset, interpdata) else: selfcal = copy.deepcopy(dset) plotdata.append(selfcal) plotinterp.append(interpdata) if plotall: plotdata.append(concatvis(plotdata)) plotinterp.append(concatvis(plotinterp)) elif plotcombined: plotdata = [concatvis(plotdata)] plotinterp = [concatvis(plotinterp)] for row in range(axarr.shape[0]): # Image the data imdata = uvimageslow(plotdata[row], imsize, pixsize, taper) # Image the model immodel = uvimageslow(plotinterp[row], imsize, pixsize, taper) # And the residuals imdiff = imdata - immodel if returnimages: images[row].append(imdata) images[row].append(immodel) # Plot everything up ext = [ -imsize * pixsize / 2., imsize * pixsize / 2., -imsize * pixsize / 2., imsize * pixsize / 2. ] # Figure out what to use as the noise level; sum of weights if no user-supplied value if level is None: s = ((plotdata[row].sigma**-2.).sum())**-0.5 else: try: s = [e for e in level][i] except TypeError: s = float(level) print("Data - Model rms: {0:0.3e}".format(imdiff.std())) axarr[row, 0].imshow(imdata, interpolation='nearest', extent=ext, cmap=cmap) axarr[row, 0].contour(imdata, extent=ext, colors='k', origin='image', levels=s * mapcontours) axarr[row, 0].set_xlim(limits[0], limits[1]) axarr[row, 0].set_ylim(limits[2], limits[3]) axarr[row,1].imshow(immodel,interpolation='nearest',extent=ext,cmap=cmap,\ vmin=imdata.min(),vmax=imdata.max()) axarr[row, 1].contour(immodel, extent=ext, colors='k', origin='image', levels=s * mapcontours) axarr[row, 1].set_xlim(limits[0], limits[1]) axarr[row, 1].set_ylim(limits[2], limits[3]) axarr[row,2].imshow(imdiff,interpolation='nearest',extent=ext,cmap=cmap,\ vmin=imdata.min(),vmax=imdata.max()) axarr[row, 2].contour(imdiff, extent=ext, colors='k', origin='image', levels=s * rescontours) axarr[row, 2].set_xlim(limits[0], limits[1]) axarr[row, 2].set_ylim(limits[2], limits[3]) if np.log10(s) < -6.: sig, unit = 1e9 * s, 'nJy' elif np.log10(s) < -3.: sig, unit = 1e6 * s, '$\mu$Jy' elif np.log10(s) < 0.: sig, unit = 1e3 * s, 'mJy' else: sig, unit = s, 'Jy' axarr[row, 2].text(0.05, 0.05, "Data 1$\sigma$ = {0:.1f}{1:s}".format(sig, unit), transform=axarr[row, 2].transAxes, bbox=dict(fc='w')) # For the last two panels, give the apparent emission at higher resolution # and the intrinsic source plane structure. # Create model image at higher res, remove unlensed sources src = [src for src in source if src.lensed] imemit,_ = create_modelimage(lens,src,xemit,yemit,xemit,yemit,\ [0,xemit.shape[1],0,xemit.shape[0]],sourcedatamap=sourcedatamap[row]) images[row].append(imemit) xcen = center_of_mass(imemit)[1] * (xemit[0, 1] - xemit[0, 0]) + xemit.min() ycen = -center_of_mass(imemit)[0] * (xemit[0, 1] - xemit[0, 0]) + yemit.max() dx = 0.5 * (xemit.max() - xemit.min()) dy = 0.5 * (yemit.max() - yemit.min()) if logmodel: norm = SymLogNorm( 0.01 * imemit.max() ) #imemit = np.log10(imemit); vmin = imemit.min()-2. else: norm = None #vmin = imemit.min() axarr[row,3].imshow(imemit,interpolation='nearest',\ extent=[xemit.min(),xemit.max(),yemit.min(),yemit.max()],cmap=cmap,norm=norm) axarr[row, 3].set_xlim(xcen - dx, xcen + dx) axarr[row, 3].set_ylim(ycen - dy, ycen + dy) # And create source plane using the exact grids the code used during fitting. imsource = np.zeros(xemit.shape) for s in src: imsource += SourceProfile(xemit, yemit, s, lens) * (xemit[0, 1] - xemit[0, 0])**2. images[row].append(imsource) xcen = center_of_mass(imsource)[1] * (xemit[0, 1] - xemit[0, 0]) + xemit.min() ycen = -center_of_mass(imemit)[0] * (xemit[0, 1] - xemit[0, 0]) + yemit.max() dx = 0.5 * (xemit.max() - xemit.min()) dy = 0.5 * (yemit.max() - yemit.min()) axarr[row, 4].imshow( imsource, interpolation='nearest', extent=[xemit.min(), xemit.max(), yemit.min(), yemit.max()], cmap=cmap, norm=SymLogNorm(0.01 * imsource.max()), origin='lower') axarr[row, 4].set_xlim(xcen - dx, xcen + dx) axarr[row, 4].set_ylim(ycen - dy, ycen + dy) # Need to precalculate distances to get caustics Dd = Planck15.angular_diameter_distance(lens[0].z).value Ds = Planck15.angular_diameter_distance(source[0].z).value Dds = Planck15.angular_diameter_distance_z1z2(lens[0].z, source[0].z).value caustics = get_caustics(lens, Dd, Ds, Dds, highresbox=mcmcresult['highresbox'], numres=mcmcresult['emitres']) for caustic in caustics: axarr[row, 3].plot(caustic[:, 0], caustic[:, 1], ls='-', marker='', lw=1, color='r') axarr[row, 4].plot(caustic[:, 0], caustic[:, 1], ls='-', marker='', lw=1, color='r') s = imdiff.std() if np.log10(s) < -6.: sig, unit = 1e9 * s, 'nJy' elif np.log10(s) < -3.: sig, unit = 1e6 * s, '$\mu$Jy' elif np.log10(s) < 0.: sig, unit = 1e3 * s, 'mJy' else: sig, unit = s, 'Jy' # Label some axes and such axarr[row, 0].set_title(plotdata[row].filename + '\nDirty Image') axarr[row, 1].set_title('Model Dirty Image') axarr[row, 2].set_title('Residual Map rms={0:.1f}{1:s}'.format(sig, unit)) if logmodel: axarr[row, 3].set_title('High-res Model (log-scale)') else: axarr[row, 3].set_title('High-res Model') axarr[row, 4].set_title('Source Plane Model') if returnimages: return f, axarr, images else: return f, axarr
def monte_tau(zeval, nrand=100, nHI=0.1, avg_ne=-2.6, sigma_ne=0.5, cosmo=None, lobs=50*u.cm, turb=None): """ Generate random draws of tau at a series of redshifts Parameters ---------- zeval : ndarray Array of redshifts for evaluation nrand : int, optional Number of samples on NHI avg_ne : float, optional Average log10 electron density / cm**3 sigma_ne : float, optional Error in log10 ne nHI : float, optional Fiducial value for n_HI; used for DL value lobs : Quantity Wavelength for analysis turb : Turbulence object, optional Usually defined internally and that is the highly recommended approach cosmo : astropy.cosmology, optional Defaults to Planck15 Returns ------- rand_tau : ndarray (nrand, nz) Random tau values reported in ms (but without explicit astropy Units) """ # Init ne_param = dict(value=avg_ne, sigma=sigma_ne) # Neeleman+15 dla_fits = load_dla_fits() if cosmo is None: from astropy.cosmology import Planck15 as cosmo # Setup NHI lgNmax = np.linspace(20.3, 22., 10000) intfN = _int_dbl_pow(dla_fits['fN']['dpow'], lgNmax=lgNmax) # Spline interp_fN = interp1d(intfN/intfN[-1], lgNmax)#, kind='cubic') # Setup z zvals = np.linspace(0., 7., 10000) nz_s = _dla_nz(zvals) nz_s[0] = 0. # Turbulence if turb is None: turb = _init_dla_turb() f_ne=turb.ne zsource = 2. turb.set_rdiff(lobs) fiducial_tau = turb.temporal_smearing(lobs, zsource) # Take out the cosmology f_D_S = cosmo.angular_diameter_distance(zsource) f_D_L = cosmo.angular_diameter_distance(turb.zL) f_D_LS = cosmo.angular_diameter_distance_z1z2(turb.zL, zsource) fiducial_tau = fiducial_tau / f_D_LS / f_D_L * f_D_S * (1+turb.zL)**3 # ms/Mpc kpc_cm = (1*u.kpc).to('cm').value rand_tau = np.zeros((nrand, zeval.size)) # Loop on zeval for ss,izeval in enumerate(zeval): avg_nz = _dla_nz(izeval) rn = np.random.poisson(avg_nz, size=nrand) ndla = np.sum(rn) if ndla == 0: continue # Get random NHI rval = np.random.uniform(size=ndla) rNHI = interp_fN(rval) DL = 10.**rNHI / nHI / kpc_cm # Get random z imin = np.argmin(np.abs(zvals-izeval)) interp_z = interp1d(nz_s[0:imin]/nz_s[imin-1], zvals[0:imin])#, kind='cubic') rval = np.random.uniform(size=ndla) rz = interp_z(rval) # Cosmology D_S = cosmo.angular_diameter_distance(izeval) D_L = cosmo.angular_diameter_distance(rz) D_LS = cosmo.angular_diameter_distance_z1z2(rz, izeval) # Get random n_e rne = 10.**(ne_param['value'] + ne_param['sigma']*np.random.normal(size=ndla)) # Calculate (scale) rtau = fiducial_tau * (D_LS * D_L / D_S) * (rne/f_ne.to('cm**-3').value)**2 / (1+rz)**3 # Generate, fill taus = np.zeros((nrand, np.max(rn))) kk = 0 for jj,irn in enumerate(rn): if irn > 0: taus[jj,0:irn] = rtau[kk:kk+irn] kk += irn # Finish -- add in quadrature final_tau = np.sqrt(np.sum(taus**2, axis=1)) # Save rand_tau[:,ss] = final_tau # Return return rand_tau
yim = np.arange(-2., 2., .02) xim, yim = np.meshgrid(xim, yim) zLens, zSource = 0.8, 5.656 xLens, yLens = 0., 0. MLens, eLens, PALens = 2.87e11, 0.5, 70. xSource, ySource, FSource = 0.216, 0.24, 0.02 # arcsec, arcsec, Jy aSource, nSource, arSource, PAsource = 0.1, 0.5, 1.0, 120. - 90 # arcsec,[],[],deg CCW from x-axis shear, shearangle = 0.12, 120. Lens = vl.SIELens(zLens, xLens, yLens, MLens, eLens, PALens) Shear = vl.ExternalShear(shear, shearangle) Source = vl.SersicSource(zSource, True, xSource, ySource, FSource, aSource, nSource, arSource, PAsource) Dd = cosmo.angular_diameter_distance(zLens).value Ds = cosmo.angular_diameter_distance(zSource).value Dds = cosmo.angular_diameter_distance_z1z2(zLens, zSource).value xsource, ysource = vl.LensRayTrace(xim, yim, [Lens, Shear], Dd, Ds, Dds) imbg = vl.SourceProfile(xim, yim, Source, [Lens, Shear]) imlensed = vl.SourceProfile(xsource, ysource, Source, [Lens, Shear]) caustics = vl.CausticsSIE(Lens, Dd, Ds, Dds, Shear) f = pl.figure(figsize=(12, 6)) ax = f.add_subplot(111, aspect='equal') pl.subplots_adjust(right=0.48, top=0.97, bottom=0.03, left=0.05) cmbg = cm.cool cmbg._init()
def postprocess(self): ############################## # Get intensity without xsec # ############################## m_ary = np.array([1.00000000e+01,1.50000000e+01,2.00000000e+01,2.50000000e+01,3.00000000e+01,4.00000000e+01,5.00000000e+01,6.00000000e+01,7.00000000e+01,8.00000000e+01,9.00000000e+01,1.00000000e+02,1.10000000e+02,1.20000000e+02,1.30000000e+02,1.40000000e+02,1.50000000e+02,1.60000000e+02,1.80000000e+02,2.00000000e+02,2.20000000e+02,2.40000000e+02,2.60000000e+02,2.80000000e+02,3.00000000e+02,3.30000000e+02,3.60000000e+02,4.00000000e+02,4.50000000e+02,5.00000000e+02,5.50000000e+02,6.00000000e+02,6.50000000e+02,7.00000000e+02,7.50000000e+02,8.00000000e+02,9.00000000e+02,1.00000000e+03,1.10000000e+03,1.20000000e+03,1.30000000e+03,1.50000000e+03,1.70000000e+03,2.00000000e+03,2.50000000e+03,3.00000000e+03,4.00000000e+03,5.00000000e+03,6.00000000e+03,7.00000000e+03,8.00000000e+03,9.00000000e+03,1.00000000e+04]) if self.channel == 'mu': self.channel = '\\[Mu]' if self.channel == 'tau': self.channel = '\\[Tau]' # If b use the precomputed value if self.channel == 'b': PPnoxsec_ary = np.load(work_dir + '/DataFiles//PP-Factor/PPnoxsec_b_ary.npy')[:,self.emin:self.emax+2] else: dNdLogx_df = pd.read_csv(work_dir + '/DataFiles//PP-Factor/AtProduction_gammas.dat', delim_whitespace=True) PPnoxsec_ary = np.zeros(shape=(len(m_ary),len(self.ebins)-1)) for mi in range(len(m_ary)): dNdLogx_ann_df = dNdLogx_df.query('mDM == ' + (str(np.int(float(m_ary[mi])))))[['Log[10,x]',self.channel]] Egamma = np.array(m_ary[mi]*(10**dNdLogx_ann_df['Log[10,x]'])) dNdEgamma = np.array(dNdLogx_ann_df[self.channel]/(Egamma*np.log(10))) dNdE_interp = interpolate.interp1d(Egamma, dNdEgamma) for ei in range(len(self.ebins)-1): # -1 because self.ebins-1 bins, self.ebins edges if self.ebins[ei] < m_ary[mi]: # Only have flux if m > Ebin if self.ebins[ei+1] < m_ary[mi]: # Whole bin is inside PPnoxsec_ary[mi,ei] = 1.0/(8*np.pi*m_ary[mi]**2)*integrate.quad(lambda x: dNdE_interp(x), self.ebins[ei], self.ebins[ei+1])[0] else: # Bin only partially contained PPnoxsec_ary[mi,ei] = 1.0/(8*np.pi*m_ary[mi]**2)*integrate.quad(lambda x: dNdE_interp(x), self.ebins[ei], m_ary[mi])[0] ######################################## # Load appropriate J-factor and errors # ######################################## if self.Burkert: if self.boost: mulog10J = self.catalog[u'mulog10JB_inf'].values[self.iobj] siglog10J = self.catalog[u'siglog10JB_inf'].values[self.iobj] else: mulog10J = self.catalog[u'mulog10JBnb_inf'].values[self.iobj] siglog10J = self.catalog[u'siglog10JBnb_inf'].values[self.iobj] else: if self.boost: mulog10J = self.catalog[u'mulog10J_inf'].values[self.iobj] siglog10J = self.catalog[u'siglog10J_inf'].values[self.iobj] else: mulog10J = self.catalog[u'mulog10Jnb_inf'].values[self.iobj] siglog10J = self.catalog[u'siglog10Jnb_inf'].values[self.iobj] ############################################# # Interpolate intensity LLs to get xsec LLs # ############################################# # If randloc load a representative halo in size at if self.randlocs: # Representative values rep_angext = np.array([0.02785567,0.12069876,0.21354185,0.30638494,0.39922802,0.49207111,0.5849142,0.67775728,0.77060037,0.86344346,0.95628654,1.04912963,1.14197272,1.2348158,1.32765889,1.42050198,1.51334507,1.60618815,1.69903124,1.79187433]) obj_angext = 2*self.catalog[u'rs'].values[self.iobj] / \ (Planck15.angular_diameter_distance(self.catalog[u'z'].values[self.iobj]).value*1000) \ * 180./np.pi rep_index = (np.abs(rep_angext-obj_angext)).argmin() # Choose a random sky location skyloc = np.random.randint(200) np.savetxt(self.save_dir + "/skyloc_obj"+str(self.iobj)+".txt",[skyloc]) LL_inten_file = np.load(self.load_dir[:-1] + str(skyloc) + '/LL_inten_o'+str(rep_index)+'_data.npz') else: LL_inten_file = np.load(self.load_dir+'LL_inten_o'+str(self.iobj)+self.mc_tag+'.npz') LL_inten_ary, inten_ary = LL_inten_file['LL'], LL_inten_file['intens'] xsecs = np.logspace(-33,-18,301) LL2_xsec_m_ary = np.zeros((len(m_ary),len(xsecs))) # 2 x LL, ready for TS # Interpolate to the limit without profiling over the J uncertainty if specified if self.noJprof: for im in tqdm(range(len(m_ary)), disable = 1 - self.verbose): for ixsec, xsec in enumerate(xsecs): for iebin in range(len(self.ebins)-1): intval = PPnoxsec_ary[im][iebin]*10**mulog10J*xsec LL2_xsec_m_ary[im,ixsec] += 2*np.interp(intval,inten_ary[iebin], LL_inten_ary[iebin]) # Otherwise profile over the error in J else: for im in tqdm(range(len(m_ary)), disable = 1 - self.verbose): LL2_xsec_m_ary[im] = Litx.construct_xsec_LL(xsecs,self.ebins,PPnoxsec_ary[im],LL_inten_ary,inten_ary,mulog10J,siglog10J) #################################################### # Calculate val, loc and xsec of max TS, and limit # #################################################### TS_m_xsec = np.zeros(3) TS_m_xsec[2] = xsecs[0] lim_ary = np.zeros(len(m_ary)) for im in range(len(m_ary)): TS_xsec_ary = LL2_xsec_m_ary[im] - LL2_xsec_m_ary[im][0] # Find value, location and xsec at the max TS (as a fn of mass) max_loc = np.argmax(TS_xsec_ary) max_TS = TS_xsec_ary[max_loc] if max_TS > TS_m_xsec[0]: TS_m_xsec[0] = max_TS TS_m_xsec[1] = im TS_m_xsec[2] = xsecs[max_loc] # Calculate limit for xi in range(max_loc,len(xsecs)): val = TS_xsec_ary[xi] - max_TS if val < -2.71: scale = (TS_xsec_ary[xi-1]-max_TS+2.71)/(TS_xsec_ary[xi-1]-TS_xsec_ary[xi]) lim_ary[im] = 10**(np.log10(xsecs[xi-1])+scale*(np.log10(xsecs[xi])-np.log10(xsecs[xi-1]))) break ##################################### # Setup save string and output data # ##################################### save_LLx_str = 'LL2_TSmx_lim_'+self.channel if not self.boost: save_LLx_str += '_nb' if self.Burkert: save_LLx_str += '_Burk' if self.noJprof: save_LLx_str += '_noJprof' save_LLx_str += '_o'+str(self.iobj) save_LLx_str += self.mc_tag np.savez(self.save_dir + save_LLx_str, LL2=LL2_xsec_m_ary, TSmx=TS_m_xsec, lim=lim_ary)
xim = np.arange(-3,3,.03) yim = np.arange(-3,3,.03) xim,yim = np.meshgrid(xim,yim) zLens,zSource = 0.8,5.656 xLens,yLens = 0.,0. MLens,eLens,PALens = 2.87e11,0.5,90. xSource,ySource,FSource,sSource = 0.216,-0.24,0.023,0.074 Lens = vl.SIELens(zLens,xLens,yLens,MLens,eLens,PALens) Shear= vl.ExternalShear(0.,0.) lens = [Lens,Shear] Source = vl.GaussSource(zSource,True,xSource,ySource,FSource,sSource) Dd = cosmo.angular_diameter_distance(zLens).value Ds = cosmo.angular_diameter_distance(zSource).value Dds = cosmo.angular_diameter_distance_z1z2(zLens,zSource).value caustics = vl.get_caustics(lens,Dd,Ds,Dds) xsource,ysource = vl.LensRayTrace(xim,yim,lens,Dd,Ds,Dds) f = pl.figure() ax = f.add_subplot(111,aspect='equal') pl.subplots_adjust(bottom=0.25,top=0.98) ax.plot(xsource,ysource,'b-') for caustic in caustics: ax.plot(caustic[:,0],caustic[:,1],'k-')