def test_gnfw(self): from lenstronomy.LensModel.Profiles.general_nfw import GNFW gnfw = GNFW() deltaPix = 0.005 numPix = 2000 x_grid, y_grid = util.make_grid(numPix=numPix, deltapix=deltaPix) kwargs_lens = { 'alpha_Rs': 1.2, 'Rs': 0.8, 'gamma_inner': 1.5, 'gamma_outer': 3.4 } f_xx, _, _, f_yy = gnfw.hessian(x_grid, y_grid, **kwargs_lens) f_x, f_y = gnfw.derivatives(x_grid, y_grid, **kwargs_lens) f_x = util.array2image(f_x) kappa = util.array2image((f_xx + f_yy) / 2.) f_x_num, f_y_num = convergence_integrals.deflection_from_kappa_grid( kappa, deltaPix) x1, y1 = 500, 550 npt.assert_almost_equal(f_x[x1, y1], f_x_num[x1, y1], decimal=2) kwargs_lens = { 'alpha_Rs': 1.2, 'Rs': 0.8, 'gamma_inner': 2.3, 'gamma_outer': 3.45 } f_xx, _, _, f_yy = gnfw.hessian(x_grid, y_grid, **kwargs_lens) f_x, f_y = gnfw.derivatives(x_grid, y_grid, **kwargs_lens) f_x = util.array2image(f_x) kappa = util.array2image((f_xx + f_yy) / 2.) f_x_num, f_y_num = convergence_integrals.deflection_from_kappa_grid( kappa, deltaPix) x1, y1 = 500, 550 npt.assert_almost_equal(f_x[x1, y1], f_x_num[x1, y1], decimal=2)
def test_deflection_from_kappa(self): sis = SIS() deltaPix = 0.01 x_grid, y_grid = util.make_grid(numPix=1000, deltapix=deltaPix) kwargs_sis = {'theta_E': 1., 'center_x': 0, 'center_y': 0} f_xx, f_yy, _ = sis.hessian(x_grid, y_grid, **kwargs_sis) f_x, f_y = sis.derivatives(x_grid, y_grid, **kwargs_sis) f_x = util.array2image(f_x) kappa = util.array2image((f_xx + f_yy) / 2.) f_x_num, f_y_num = convergence_integrals.deflection_from_kappa_grid( kappa, deltaPix) x1, y1 = 550, 500 # test relative potential at two different point way inside the kappa map npt.assert_almost_equal(f_x[x1, y1], f_x_num[x1, y1], decimal=2)
def __init__(self, mass_map, grid_spacing, redshift): """ :param mass_map: 2d numpy array of mass map (in units physical Msol) :param grid_spacing: grid spacing of the mass map (in units physical Mpc) :param redshift: redshift """ nx, ny = np.shape(mass_map) if nx != ny: raise ValueError('Shape of mass map needs to be square!, set as %s %s' % (nx, ny)) self._mass_map = mass_map self._grid_spacing = grid_spacing self._redshift = redshift self._f_x_mass, self._f_y_mass = convergence_integrals.deflection_from_kappa_grid(self._mass_map, self._grid_spacing) self._f_mass = convergence_integrals.potential_from_kappa_grid(self._mass_map, self._grid_spacing) x_grid, y_grid = util.make_grid(numPix=len(self._mass_map), deltapix=self._grid_spacing) self._x_axes_mpc, self._y_axes_mpc = util.get_axes(x_grid, y_grid)
def test_sersic(self): from lenstronomy.LensModel.Profiles.sersic import Sersic from lenstronomy.LightModel.Profiles.sersic import Sersic as SersicLight sersic_lens = Sersic() sersic_light = SersicLight() kwargs_light = { 'n_sersic': 2, 'R_sersic': 0.5, 'I0_sersic': 1, 'center_x': 0, 'center_y': 0 } kwargs_lens = { 'n_sersic': 2, 'R_sersic': 0.5, 'k_eff': 1, 'center_x': 0, 'center_y': 0 } deltaPix = 0.01 numPix = 1000 x_grid, y_grid = util.make_grid(numPix=numPix, deltapix=deltaPix) x_grid2d = util.array2image(x_grid) y_grid2d = util.array2image(y_grid) f_xx, f_yy, _ = sersic_lens.hessian(x_grid, y_grid, **kwargs_lens) f_x, f_y = sersic_lens.derivatives(x_grid, y_grid, **kwargs_lens) f_x = util.array2image(f_x) kappa = util.array2image((f_xx + f_yy) / 2.) f_x_num, f_y_num = convergence_integrals.deflection_from_kappa_grid( kappa, deltaPix) x1, y1 = 500, 550 x0, y0 = int(numPix / 2.), int(numPix / 2.) npt.assert_almost_equal(f_x[x1, y1], f_x_num[x1, y1], decimal=2) f_num = convergence_integrals.potential_from_kappa_grid( kappa, deltaPix) f_ = sersic_lens.function(x_grid2d[x1, y1], y_grid2d[x1, y1], **kwargs_lens) f_00 = sersic_lens.function(x_grid2d[x0, y0], y_grid2d[x0, y0], **kwargs_lens) npt.assert_almost_equal(f_ - f_00, f_num[x1, y1] - f_num[x0, y0], decimal=2)
def light2mass_interpol(lens_light_model_list, kwargs_lens_light, numPix=100, deltaPix=0.05, subgrid_res=5, center_x=0, center_y=0): """ takes a lens light model and turns it numerically in a lens model (with all lensmodel quantities computed on a grid). Then provides an interpolated grid for the quantities. :param kwargs_lens_light: lens light keyword argument list :param numPix: number of pixels per axis for the return interpolation :param deltaPix: interpolation/pixel size :param center_x: center of the grid :param center_y: center of the grid :param subgrid_res: subgrid for the numerical integrals :return: """ # make super-sampled grid x_grid_sub, y_grid_sub = util.make_grid(numPix=numPix * 5, deltapix=deltaPix, subgrid_res=subgrid_res) import lenstronomy.Util.mask_util as mask_util mask = mask_util.mask_sphere(x_grid_sub, y_grid_sub, center_x, center_y, r=1) x_grid, y_grid = util.make_grid(numPix=numPix, deltapix=deltaPix) # compute light on the subgrid lightModel = LightModel(light_model_list=lens_light_model_list) flux = lightModel.surface_brightness(x_grid_sub, y_grid_sub, kwargs_lens_light) flux_norm = np.sum(flux[mask == 1]) / np.sum(mask) flux /= flux_norm from lenstronomy.LensModel import convergence_integrals as integral # compute lensing quantities with subgrid convergence_sub = util.array2image(flux) f_x_sub, f_y_sub = integral.deflection_from_kappa_grid( convergence_sub, grid_spacing=deltaPix / float(subgrid_res)) f_sub = integral.potential_from_kappa_grid(convergence_sub, grid_spacing=deltaPix / float(subgrid_res)) # interpolation function on lensing quantities x_axes_sub, y_axes_sub = util.get_axes(x_grid_sub, y_grid_sub) from lenstronomy.LensModel.Profiles.interpol import Interpol interp_func = Interpol() interp_func.do_interp(x_axes_sub, y_axes_sub, f_sub, f_x_sub, f_y_sub) # compute lensing quantities on sparser grid x_axes, y_axes = util.get_axes(x_grid, y_grid) f_ = interp_func.function(x_grid, y_grid) f_x, f_y = interp_func.derivatives(x_grid, y_grid) # numerical differentials for second order differentials from lenstronomy.LensModel.lens_model import LensModel lens_model = LensModel(lens_model_list=['INTERPOL']) kwargs = [{ 'grid_interp_x': x_axes_sub, 'grid_interp_y': y_axes_sub, 'f_': f_sub, 'f_x': f_x_sub, 'f_y': f_y_sub }] f_xx, f_xy, f_yx, f_yy = lens_model.hessian(x_grid, y_grid, kwargs, diff=0.00001) kwargs_interpol = { 'grid_interp_x': x_axes, 'grid_interp_y': y_axes, 'f_': util.array2image(f_), 'f_x': util.array2image(f_x), 'f_y': util.array2image(f_y), 'f_xx': util.array2image(f_xx), 'f_xy': util.array2image(f_xy), 'f_yy': util.array2image(f_yy) } return kwargs_interpol
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.