import numpy as np import numexpr as ne from .constants import * # ----------------------------------------------------------------------------- # Generic profile generator # ----------------------------------------------------------------------------- class KSZ_Profile(object): R_star= 0.0 # 15 kpc/h L_gal0 = 10**(0.4*(tmpp_cat['Msun']-tmpp_cat['Mstar'])) def __init__(self,sculpt): """Base class for KSZ profiles Arguments: sculpt (float): If negative, do not sculpt. If positive, there will be a 2d suppression of the profile with a radius given by sculpt (in arcmins). """ self.sculpt = sculpt * np.pi/180/60. self.rGalaxy = 1.0 def evaluate_profile(self, r): raise NotImplementedError("Abstract function") def projected_profile(self, cos_theta,angularDistance): idx_base = idx = np.where(cos_theta > 0)[0] tan_theta_2 = 1/(cos_theta[idx]**2) - 1 tan_theta_2_max = (self.rGalaxy/angularDistance)**2 tan_theta_2_min = (self.R_star/angularDistance)**2 idx0 = np.where((tan_theta_2 < tan_theta_2_max)) idx = idx_base[idx0] tan_theta_2 = tan_theta_2[idx0] tan_theta = np.sqrt(tan_theta_2) r = (tan_theta*angularDistance) m,idx_mask = self.evaluate_profile(r) idx_mask = idx[idx_mask] idx_mask = np.append(idx_mask,idx[np.where(tan_theta_2 0: idx_mask = np.append(idx_mask,idx[tan_theta_2.argmin()]) if self.sculpt > 0: theta = np.arctan(tan_theta) cond = theta < self.sculpt m[cond] *= (theta[cond]/self.sculpt)**2 return idx,idx_mask,m # ----------------------------------------------------------------------------- # Isothermal profile generator # ----------------------------------------------------------------------------- class KSZ_Isothermal(KSZ_Profile): sigma_FP=160e3 #m/s R_innergal = 0.030 def __init__(self, Lgal, x, y=0.0, sculpt=-1): """Support for Isothermal profile Arguments: Lgal (float): Galaxy luminosity in solar units x (float): extent of halo in virial radius units Keyword arguments: y (float): Inner part where there is no halo sculpt (float): If negative, do not sculpt. If positive, there will be a 2d suppression of the profile with a radius given by sculpt (in arcmins). """ super(KSZ_Isothermal,self).__init__(sculpt) self.R_gal = 0.226 * x self.R_innergal *= y self.rho0 = self.sigma_FP**2/(2*np.pi*G) # * (Lgal/L_gal0)**(2./3) self.rGalaxy = self.R_gal*(Lgal/self.L_gal0)**(1./3) self.rInnerGalaxy = self.R_innergal*(Lgal/self.L_gal0)**(1./3) self._prepare() def _prepare(self): pass def evaluate_profile(self,r): rho0, rGalaxy, rInner = self.rho0, self.rGalaxy, self.rInnerGalaxy D = {'rho0':rho0, 'rGalaxy':rGalaxy, 'rInner': rInner, 'Mpc':Mpc } Q = np.zeros(r.size) cond = (r<=1e-10) Q[cond] = rho0*2/Mpc * (rGalaxy-rInner)/(rGalaxy*rInner) cond = (r>0)*(r <= rInner) D['r'] = r[cond] Q[cond] = ne.evaluate('rho0*2/(Mpc*r) * (arctan(sqrt( (rGalaxy/r)**2 -1 )) - arctan(sqrt( (rInner/r)**2 - 1 )))', local_dict=D) cond = (r > rInner)*(r <= rGalaxy) D['r'] = r[cond] Q[cond] = ne.evaluate('rho0*2/(Mpc*r) * arctan(sqrt( (rGalaxy/r)**2 -1 ))', local_dict=D) return Q,[] #np.where(r