class TestNFWMC(object): """ tests the Gaussian methods """ def setup(self): self.z_lens, self.z_source = 0.5, 2 from astropy.cosmology import FlatLambdaCDM cosmo = FlatLambdaCDM(H0=70, Om0=0.3, Ob0=0.05) self.nfw = NFW() self.nfwmc = NFWMC(z_source=self.z_source, z_lens=self.z_lens, cosmo=cosmo) self.lensCosmo = LensCosmo(z_lens=self.z_lens, z_source=self.z_source, cosmo=cosmo) def test_function(self): x, y = 1., 1. logM = 12 concentration = 10 f_mc = self.nfwmc.function(x, y, logM, concentration, center_x=0, center_y=0) Rs, alpha_Rs = self.lensCosmo.nfw_physical2angle(10**logM, concentration) f_ = self.nfw.function(x, y, Rs, alpha_Rs, center_x=0, center_y=0) npt.assert_almost_equal(f_mc, f_, decimal=8) def test_derivatives(self): x, y = 1., 1. logM = 12 concentration = 10 f_x_mc, f_y_mc = self.nfwmc.derivatives(x, y, logM, concentration, center_x=0, center_y=0) Rs, alpha_Rs = self.lensCosmo.nfw_physical2angle(10 ** logM, concentration) f_x, f_y = self.nfw.derivatives(x, y, Rs, alpha_Rs, center_x=0, center_y=0) npt.assert_almost_equal(f_x_mc, f_x, decimal=8) npt.assert_almost_equal(f_y_mc, f_y, decimal=8) def test_hessian(self): x, y = 1., 1. logM = 12 concentration = 10 f_xx_mc, f_xy_mc, f_yx_mc, f_yy_mc = self.nfwmc.hessian(x, y, logM, concentration, center_x=0, center_y=0) Rs, alpha_Rs = self.lensCosmo.nfw_physical2angle(10 ** logM, concentration) f_xx, f_xy, f_yx, f_yy = self.nfw.hessian(x, y, Rs, alpha_Rs, center_x=0, center_y=0) npt.assert_almost_equal(f_xx_mc, f_xx, decimal=8) npt.assert_almost_equal(f_yy_mc, f_yy, decimal=8) npt.assert_almost_equal(f_xy_mc, f_xy, decimal=8) npt.assert_almost_equal(f_yx_mc, f_yx, decimal=8) def test_static(self): x, y = 1., 1. logM = 12 concentration = 10 f_ = self.nfwmc.function(x, y, logM, concentration, center_x=0, center_y=0) self.nfwmc.set_static(logM, concentration) f_static = self.nfwmc.function(x, y, 0, 0, center_x=0, center_y=0) npt.assert_almost_equal(f_, f_static, decimal=8) self.nfwmc.set_dynamic() f_dyn = self.nfwmc.function(x, y, 11, 20, center_x=0, center_y=0) assert f_dyn != f_static
def physical2lensing_conversion(self, kwargs_mass): """ :param kwargs_mass: list of keyword arguments of all the lens models. Einstein radius 'theta_E' are replaced by 'sigma_v', velocity dispersion in km/s, 'alpha_Rs' and 'Rs' of NFW profiles are replaced by 'M200' and 'concentration' :return: kwargs_lens in reduced deflection angles compatible with the lensModel instance of this module """ kwargs_lens = copy.deepcopy(kwargs_mass) for i in range(len(kwargs_mass)): kwargs_mass_i = kwargs_mass[i] if self._lens_redshift_list is None: z_lens = self._z_lens else: z_lens = self._lens_redshift_list[i] lens_cosmo = LensCosmo(z_lens, self._z_source_convention, cosmo=self._cosmo) if 'sigma_v' in kwargs_mass_i: sigma_v = kwargs_mass_i['sigma_v'] theta_E = lens_cosmo.sis_sigma_v2theta_E(sigma_v) kwargs_lens[i]['theta_E'] = theta_E del kwargs_lens[i]['sigma_v'] elif 'M200' in kwargs_mass_i: M200 = kwargs_mass_i['M200'] c = kwargs_mass_i['concentration'] Rs, alpha_RS = lens_cosmo.nfw_physical2angle(M200, c) kwargs_lens[i]['Rs'] = Rs kwargs_lens[i]['alpha_Rs'] = alpha_RS del kwargs_lens[i]['M200'] del kwargs_lens[i]['concentration'] return kwargs_lens
def test_physical2lensing_conversion(self): lens_redshift_list = [0.5, 1] z_source_convention = 2 api = ModelAPI(lens_model_list=['SIS', 'NFW'], lens_redshift_list=lens_redshift_list, z_source_convention=z_source_convention, cosmo=None, z_source=z_source_convention) kwargs_mass = [{ 'sigma_v': 200, 'center_x': 0, 'center_y': 0 }, { 'M200': 10**13, 'concentration': 5, 'center_x': 1, 'center_y': 1 }] kwargs_lens = api.physical2lensing_conversion(kwargs_mass) theta_E = kwargs_lens[0]['theta_E'] lens_cosmo = LensCosmo(z_lens=lens_redshift_list[0], z_source=z_source_convention) theta_E_test = lens_cosmo.sis_sigma_v2theta_E( kwargs_mass[0]['sigma_v']) npt.assert_almost_equal(theta_E, theta_E_test, decimal=7) alpha_Rs = kwargs_lens[1]['alpha_Rs'] lens_cosmo = LensCosmo(z_lens=lens_redshift_list[1], z_source=z_source_convention) Rs_new, alpha_Rs_new = lens_cosmo.nfw_physical2angle( kwargs_mass[1]['M200'], kwargs_mass[1]['concentration']) npt.assert_almost_equal(alpha_Rs, alpha_Rs_new, decimal=7)
def get_nfw_kwargs(halo_mass, stellar_mass, halo_z, z_src, seed): c_200 = get_concentration(halo_mass, stellar_mass, seed=seed) n_halos = len(halo_mass) Rs_angle, alpha_Rs = np.empty(n_halos), np.empty(n_halos) lensing_eff = np.empty(n_halos) for h in range(n_halos): lens_cosmo = LensCosmo(z_lens=halo_z[h], z_source=z_src, cosmo=WMAP7) eff = lens_cosmo.dds / lens_cosmo.ds Rs_angle_h, alpha_Rs_h = lens_cosmo.nfw_physical2angle(M=halo_mass[h], c=c_200[h]) Rs_angle[h] = Rs_angle_h alpha_Rs[h] = alpha_Rs_h lensing_eff[h] = eff return Rs_angle, alpha_Rs, lensing_eff
class TestLensCosmo(object): """ tests the UnitManager class routines """ def setup(self): z_L = 0.8 z_S = 3.0 from astropy.cosmology import FlatLambdaCDM cosmo = FlatLambdaCDM(H0=70, Om0=0.3, Ob0=0.05) self.lensCosmo = LensCosmo(z_L, z_S, cosmo=cosmo) def test_ang_dist(self): npt.assert_almost_equal(self.lensCosmo.ds, 1588.9213590743666, decimal=8) npt.assert_almost_equal(self.lensCosmo.dd, 1548.7055203661785, decimal=8) npt.assert_almost_equal(self.lensCosmo.dds, 892.0038749095863, decimal=8) def test_epsilon_crit(self): npt.assert_almost_equal(self.lensCosmo.sigma_crit / 1.9121e+15, 1, decimal=3) def test_arcsec2phys(self): arcsec = np.array([1, 2]) # pixel coordinate from center physcoord = self.lensCosmo.arcsec2phys_lens(arcsec) npt.assert_almost_equal(physcoord[0], 0.0075083362428338641, decimal=8) npt.assert_almost_equal(physcoord[1], 0.015016672485667728, decimal=8) physcoord = self.lensCosmo.arcsec2phys_source(arcsec) npt.assert_almost_equal(physcoord[0], 0.007703308130864105, decimal=8) npt.assert_almost_equal(physcoord[1], 0.01540661626172821, decimal=8) def test_phys2arcsec_lens(self): phys = 1. arc_sec = self.lensCosmo.phys2arcsec_lens(phys) phys_new = self.lensCosmo.arcsec2phys_lens(arc_sec) npt.assert_almost_equal(phys_new, phys, decimal=8) def test_mass_in_phi_E(self): phi_E = 1.5 mass = self.lensCosmo.mass_in_theta_E(phi_E) npt.assert_almost_equal(mass, 761967261292.6725, decimal=2) def test_kappa2proj_mass(self): kappa = 0.5 mass = self.lensCosmo.kappa2proj_mass(kappa) npt.assert_almost_equal(mass, kappa * self.lensCosmo.sigma_crit, decimal=3) def test_mass_in_coin(self): theta_E = 1. m_coin = self.lensCosmo.mass_in_coin(theta_E) npt.assert_almost_equal(m_coin, 165279526936.52194, decimal=0) def test_D_dt_model(self): D_dt = self.lensCosmo.ddt npt.assert_almost_equal(D_dt, 4965.660384441859, decimal=8) def test_nfw_angle2physical(self): Rs_angle = 6. alpha_Rs = 1. rho0, Rs, c, r200, M200 = self.lensCosmo.nfw_angle2physical( Rs_angle, alpha_Rs) assert Rs * c == r200 def test_nfw_physical2angle(self): M = 10.**13.5 c = 4 Rs_angle, alpha_Rs = self.lensCosmo.nfw_physical2angle(M, c) rho0, Rs, c_out, r200, M200 = self.lensCosmo.nfw_angle2physical( Rs_angle, alpha_Rs) npt.assert_almost_equal(c_out, c, decimal=3) npt.assert_almost_equal(np.log10(M200), np.log10(M), decimal=4) def test_sis_theta_E2sigma_v(self): theta_E = 2. sigma_v = self.lensCosmo.sis_theta_E2sigma_v(theta_E) theta_E_out = self.lensCosmo.sis_sigma_v2theta_E(sigma_v) npt.assert_almost_equal(theta_E_out, theta_E, decimal=5) def test_fermat2delays(self): fermat_pot = 0.5 dt_days = self.lensCosmo.time_delay_units(fermat_pot) fermat_pot_out = self.lensCosmo.time_delay2fermat_pot(dt_days) npt.assert_almost_equal(fermat_pot, fermat_pot_out, decimal=10) def test_uldm_angular2phys(self): kappa_0, theta_c = 0.1, 3 mlog10, Mlog10 = self.lensCosmo.uldm_angular2phys(kappa_0, theta_c) npt.assert_almost_equal(mlog10, -24.3610006, decimal=5) npt.assert_almost_equal(Mlog10, 11.7195843, decimal=5) def test_uldm_mphys2angular(self): m_log10, M_log10 = -24, 11 kappa_0, theta_c = self.lensCosmo.uldm_mphys2angular(m_log10, M_log10) mcheck, Mcheck = self.lensCosmo.uldm_angular2phys(kappa_0, theta_c) npt.assert_almost_equal(mcheck, m_log10, decimal=4) npt.assert_almost_equal(Mcheck, M_log10, decimal=4) def test_a_z(self): a = self.lensCosmo.a_z(z=1) npt.assert_almost_equal(a, 0.5)
class NFWMC(LensProfileBase): """ this class contains functions parameterises the NFW profile with log10 M200 and the concentration rs/r200 relation are: R_200 = c * Rs ATTENTION: the parameterization is cosmology and redshift dependent! The cosmology to connect mass and deflection relations is fixed to default H0=70km/s Omega_m=0.3 flat LCDM. It is recommended to keep a given cosmology definition in the lens modeling as the observable reduced deflection angles are sensitive in this parameterization. If you do not want to impose a mass-concentration relation, it is recommended to use the default NFW lensing profile parameterized in reduced deflection angles. """ param_names = ['logM', 'concentration', 'center_x', 'center_y'] lower_limit_default = { 'logM': 0, 'concentration': 0.01, 'center_x': -100, 'center_y': -100 } upper_limit_default = { 'logM': 16, 'concentration': 1000, 'center_x': 100, 'center_y': 100 } def __init__(self, z_lens, z_source, cosmo=None, static=False): """ :param z_lens: redshift of lens :param z_source: redshift of source :param cosmo: astropy cosmology instance :param static: boolean, if True, only operates with fixed parameter values """ self._nfw = NFW() if cosmo is None: from astropy.cosmology import FlatLambdaCDM cosmo = FlatLambdaCDM(H0=70, Om0=0.3, Ob0=0.05) self._lens_cosmo = LensCosmo(z_lens, z_source, cosmo=cosmo) self._static = static super(NFWMC, self).__init__() def _m_c2deflections(self, logM, concentration): """ :param logM: log10 mass in M200 stellar masses :param concentration: halo concentration c = r_200 / r_s :return: Rs (in arc seconds), alpha_Rs (in arc seconds) """ if self._static is True: return self._Rs_static, self._alpha_Rs_static M = 10**logM Rs, alpha_Rs = self._lens_cosmo.nfw_physical2angle(M, concentration) return Rs, alpha_Rs def set_static(self, logM, concentration, center_x=0, center_y=0): """ :param logM: :param concentration: :param center_x: :param center_y: :return: """ self._static = True M = 10**logM self._Rs_static, self._alpha_Rs_static = self._lens_cosmo.nfw_physical2angle( M, concentration) def set_dynamic(self): """ :return: """ self._static = False if hasattr(self, '_Rs_static'): del self._Rs_static if hasattr(self, '_alpha_Rs_static'): del self._alpha_Rs_static def function(self, x, y, logM, concentration, center_x=0, center_y=0): """ :param x: angular position :param y: angular position :param Rs: angular turn over point :param alpha_Rs: deflection at Rs :param center_x: center of halo :param center_y: center of halo :return: """ Rs, alpha_Rs = self._m_c2deflections(logM, concentration) return self._nfw.function(x, y, alpha_Rs=alpha_Rs, Rs=Rs, center_x=center_x, center_y=center_y) def derivatives(self, x, y, logM, concentration, center_x=0, center_y=0): """ returns df/dx and df/dy of the function (integral of NFW) """ Rs, alpha_Rs = self._m_c2deflections(logM, concentration) return self._nfw.derivatives(x, y, Rs, alpha_Rs, center_x, center_y) def hessian(self, x, y, logM, concentration, center_x=0, center_y=0): """ returns Hessian matrix of function d^2f/dx^2, d^f/dy^2, d^2/dxdy """ Rs, alpha_Rs = self._m_c2deflections(logM, concentration) return self._nfw.hessian(x, y, Rs, alpha_Rs, center_x, center_y)
def setup(self): # define a cosmology cosmo = FlatLambdaCDM(H0=70, Om0=0.3, Ob0=0.05) self._cosmo = cosmo redshift_list = [0.1, 0.3, 0.8] # list of redshift of the deflectors z_source = 2 # source redshift self._z_source = z_source # analytic profile class in multi plane self._lensmodel = LensModel(lens_model_list=['NFW', 'NFW', 'NFW'], lens_redshift_list=redshift_list, multi_plane=True, z_source_convention=z_source, cosmo=cosmo, z_source=z_source) # a single plane class from which the convergence/mass maps are computeded single_plane = LensModel(lens_model_list=['NFW'], multi_plane=False) # multi-plane class with three interpolation grids self._lens_model_interp = LensModel( lens_model_list=['INTERPOL', 'INTERPOL', 'INTERPOL'], lens_redshift_list=redshift_list, multi_plane=True, z_source_convention=z_source, cosmo=cosmo, z_source=z_source) # deflector parameterisation in units of reduced deflection angles to the source convention redshift logM_200_list = [8, 9, 10] # log 10 halo masses of the three deflectors c_list = [20, 10, 8] # concentrations of the three halos kwargs_lens = [] kwargs_lens_interp = [] grid_spacing = 0.01 # spacing of the convergence grid in units arc seconds x_grid, y_grid = util.make_grid( numPix=500, deltapix=grid_spacing ) # we create the grid coordinates centered at zero x_axes, y_axes = util.get_axes( x_grid, y_grid) # we need the axes only for the interpolation mass_map_list = [] grid_spacing_list_mpc = [] for i, z in enumerate( redshift_list): # loop through the three deflectors lens_cosmo = LensCosmo( z_lens=z, z_source=z_source, cosmo=cosmo ) # instance of LensCosmo, a class that manages cosmology relevant quantities of a lens alpha_Rs, Rs = lens_cosmo.nfw_physical2angle( M=10**(logM_200_list[i]), c=c_list[i] ) # we turn the halo mass and concentration in reduced deflection angles and angles on the sky kwargs_nfw = { 'Rs': Rs, 'alpha_Rs': alpha_Rs, 'center_x': 0, 'center_y': 0 } # lensing parameters of the NFW profile in lenstronomy conventions kwargs_lens.append(kwargs_nfw) kappa_map = single_plane.kappa( x_grid, y_grid, [kwargs_nfw]) # convergence map of a single NFW profile kappa_map = util.array2image(kappa_map) mass_map = lens_cosmo.epsilon_crit_angle * kappa_map * grid_spacing**2 # projected mass per pixel on the gird mass_map_list.append(mass_map) npt.assert_almost_equal( np.log10(np.sum(mass_map)), logM_200_list[i], decimal=0 ) # check whether the sum of mass roughtly correspoonds the mass definition grid_spacing_mpc = lens_cosmo.arcsec2phys_lens( grid_spacing) # turn grid spacing from arcseconds into Mpc grid_spacing_list_mpc.append(grid_spacing_mpc) f_x, f_y = convergence_integrals.deflection_from_kappa_grid( kappa_map, grid_spacing ) # perform the deflection calculation from the convergence map f_ = convergence_integrals.potential_from_kappa_grid( kappa_map, grid_spacing ) # perform the lensing potential calculation from the convergence map (attention: arbitrary normalization) kwargs_interp = { 'grid_interp_x': x_axes, 'grid_interp_y': y_axes, 'f_': f_, 'f_x': f_x, 'f_y': f_y } # keyword arguments of the interpolation model kwargs_lens_interp.append(kwargs_interp) self.kwargs_lens = kwargs_lens self.kwargs_lens_interp = kwargs_lens_interp self.lightCone = LightCone( mass_map_list, grid_spacing_list_mpc, redshift_list ) # here we make the instance of the LightCone class based on the mass map, physical grid spacing and redshifts.
class TestLensCosmo(object): """ tests the UnitManager class routines """ def setup(self): z_L = 0.8 z_S = 3.0 from astropy.cosmology import FlatLambdaCDM cosmo = FlatLambdaCDM(H0=70, Om0=0.3, Ob0=0.05) self.lensCosmo = LensCosmo(z_L, z_S, cosmo=cosmo) def test_ang_dist(self): npt.assert_almost_equal(self.lensCosmo.D_s, 1588.9213590743666, decimal=8) npt.assert_almost_equal(self.lensCosmo.D_d, 1548.7055203661785, decimal=8) npt.assert_almost_equal(self.lensCosmo.D_ds, 892.0038749095863, decimal=8) def test_epsilon_crit(self): npt.assert_almost_equal(self.lensCosmo.epsilon_crit / 1.9121e+15, 1, decimal=3) def test_arcsec2phys(self): arcsec = np.array([1, 2]) # pixel coordinate from center physcoord = self.lensCosmo.arcsec2phys_lens(arcsec) assert physcoord[0] == 0.0075083362428338641 assert physcoord[1] == 0.015016672485667728 physcoord = self.lensCosmo.arcsec2phys_source(arcsec) assert physcoord[0] == 0.007703308130864105 assert physcoord[1] == 0.01540661626172821 def test_phys2arcsec_lens(self): phys = 1. arc_sec = self.lensCosmo.phys2arcsec_lens(phys) phys_new = self.lensCosmo.arcsec2phys_lens(arc_sec) assert phys_new == phys def test_mass_in_phi_E(self): phi_E = 1.5 mass = self.lensCosmo.mass_in_theta_E(phi_E) assert mass == 761967261292.6725 def test_kappa2proj_mass(self): kappa = 0.5 mass = self.lensCosmo.kappa2proj_mass(kappa) npt.assert_almost_equal(mass, kappa * self.lensCosmo.epsilon_crit, decimal=3) def test_mass_in_coin(self): theta_E = 1. m_coin = self.lensCosmo.mass_in_coin(theta_E) npt.assert_almost_equal(m_coin, 165279526936.52194, decimal=0) def test_D_dt_model(self): D_dt = self.lensCosmo.D_dt assert D_dt == 4965.660384441859 def test_nfw_angle2physical(self): Rs_angle = 6. theta_Rs = 1. rho0, Rs, c, r200, M200 = self.lensCosmo.nfw_angle2physical( Rs_angle, theta_Rs) assert Rs * c == r200 def test_nfw_physical2angle(self): M = 10.**13.5 c = 4 Rs_angle, theta_Rs = self.lensCosmo.nfw_physical2angle(M, c) rho0, Rs, c_out, r200, M200 = self.lensCosmo.nfw_angle2physical( Rs_angle, theta_Rs) npt.assert_almost_equal(c_out, c, decimal=3) npt.assert_almost_equal(np.log10(M200), np.log10(M), decimal=4) def test_sis_theta_E2sigma_v(self): theta_E = 2. sigma_v = self.lensCosmo.sis_theta_E2sigma_v(theta_E) theta_E_out = self.lensCosmo.sis_sigma_v2theta_E(sigma_v) npt.assert_almost_equal(theta_E_out, theta_E, decimal=5)