def test_arrival_time(self): z_lens = 0.5 z_source = 1.5 x_image, y_image = 1., 0. lensModel = LensModel(lens_model_list=['SIS'], multi_plane=True, lens_redshift_list=[z_lens], z_source=z_source) kwargs = [{'theta_E': 1., 'center_x': 0., 'center_y': 0.}] arrival_time_mp = lensModel.arrival_time(x_image, y_image, kwargs) lensModel_sp = LensModel(lens_model_list=['SIS'], z_source=z_source, z_lens=z_lens) arrival_time_sp = lensModel_sp.arrival_time(x_image, y_image, kwargs) npt.assert_almost_equal(arrival_time_sp, arrival_time_mp, decimal=8)
def test_raise(self): with self.assertRaises(ValueError): kwargs = [{'alpha_Rs': 1, 'Rs': 0.5, 'center_x': 0, 'center_y': 0}] lensModel = LensModel(['NFW'], multi_plane=True, lens_redshift_list=[1], z_source=2) f_x, f_y = lensModel.alpha(1, 1, kwargs, diff=0.0001) with self.assertRaises(ValueError): lensModel = LensModel(['NFW'], multi_plane=True, lens_redshift_list=[1]) with self.assertRaises(ValueError): kwargs = [{'alpha_Rs': 1, 'Rs': 0.5, 'center_x': 0, 'center_y': 0}] lensModel = LensModel(['NFW'], multi_plane=False) t_arrival = lensModel.arrival_time(1, 1, kwargs) with self.assertRaises(ValueError): z_lens = 0.5 z_source = 1.5 x_image, y_image = 1., 0. lensModel = LensModel(lens_model_list=['SIS'], multi_plane=True, lens_redshift_list=[z_lens], z_source=z_source) kwargs = [{'theta_E': 1., 'center_x': 0., 'center_y': 0.}] fermat_pot = lensModel.fermat_potential(x_image, y_image, kwargs)
def test_fermat_potential(self): z_lens = 0.5 z_source = 1.5 x_image, y_image = 1., 0. lensModel = LensModel(lens_model_list=['SIS'], multi_plane=True, lens_redshift_list=[z_lens], z_lens=z_lens, z_source=z_source) kwargs = [{'theta_E': 1., 'center_x': 0., 'center_y': 0.}] fermat_pot = lensModel.fermat_potential(x_image, y_image, kwargs) arrival_time = lensModel.arrival_time(x_image, y_image, kwargs) arrival_time_from_fermat_pot = lensModel._lensCosmo.time_delay_units( fermat_pot) npt.assert_almost_equal(arrival_time_from_fermat_pot, arrival_time, decimal=8)
class TestLightCone(object): 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. def test_ray_shooting(self): beta_x, beta_y = self._lensmodel.ray_shooting(2., 1., self.kwargs_lens) beta_x_num, beta_y_num = self._lens_model_interp.ray_shooting( 2., 1., self.kwargs_lens_interp) npt.assert_almost_equal(beta_x_num, beta_x, decimal=1) npt.assert_almost_equal(beta_y_num, beta_y, decimal=1) lens_model, kwargs_lens = self.lightCone.cone_instance( z_source=self._z_source, cosmo=self._cosmo, multi_plane=True) assert len(lens_model.lens_model_list) == 3 beta_x_cone, beta_y_cone = lens_model.ray_shooting(2., 1., kwargs_lens) npt.assert_almost_equal(kwargs_lens[0]['grid_interp_x'], self.kwargs_lens_interp[0]['grid_interp_x'], decimal=5) npt.assert_almost_equal(kwargs_lens[0]['grid_interp_y'], self.kwargs_lens_interp[0]['grid_interp_y'], decimal=5) npt.assert_almost_equal(kwargs_lens[0]['f_x'], self.kwargs_lens_interp[0]['f_x'], decimal=5) npt.assert_almost_equal(kwargs_lens[0]['f_y'], self.kwargs_lens_interp[0]['f_y'], decimal=5) npt.assert_almost_equal(beta_x_cone, beta_x_num, decimal=5) npt.assert_almost_equal(beta_y_cone, beta_y_num, decimal=5) def test_deflection(self): alpha_x, alpha_y = self._lensmodel.alpha(2, 1, self.kwargs_lens) alpha_x_num, alpha_y_num = self._lens_model_interp.alpha( 2, 1, self.kwargs_lens_interp) npt.assert_almost_equal(alpha_x_num, alpha_x, decimal=3) npt.assert_almost_equal(alpha_y_num, alpha_y, decimal=3) lens_model, kwargs_lens = self.lightCone.cone_instance( z_source=self._z_source, cosmo=self._cosmo, multi_plane=True) alpha_x_cone, alpha_y_cone = lens_model.alpha(2, 1, kwargs_lens) npt.assert_almost_equal(alpha_x_cone, alpha_x, decimal=3) npt.assert_almost_equal(alpha_y_cone, alpha_y, decimal=3) def test_arrival_time(self): x = np.array([1, 1]) y = np.array([0, 1]) f_ = self._lensmodel.arrival_time(x, y, self.kwargs_lens) f_num = self._lens_model_interp.arrival_time(x, y, self.kwargs_lens_interp) npt.assert_almost_equal(f_num[0] - f_num[1], f_[0] - f_[1], decimal=1) lens_model, kwargs_lens = self.lightCone.cone_instance( z_source=self._z_source, cosmo=self._cosmo, multi_plane=True) f_cone = lens_model.arrival_time(x, y, kwargs_lens) npt.assert_almost_equal(f_cone[0] - f_cone[1], f_[0] - f_[1], decimal=1)
def test_logL(self): z_source = 1.5 z_lens = 0.5 cosmo = FlatLambdaCDM(H0=70, Om0=0.3, Ob0=0.) lensCosmo = LensCosmo(cosmo=cosmo, z_lens=z_lens, z_source=z_source) # make class instances for a chosen lens model type # chose a lens model lens_model_list = ['SPEP', 'SHEAR'] # make instance of LensModel class lensModel = LensModel(lens_model_list=lens_model_list, cosmo=cosmo, z_lens=z_lens, z_source=z_source) # we require routines accessible in the LensModelExtensions class # make instance of LensEquationSolver to solve the lens equation lensEquationSolver = LensEquationSolver(lensModel=lensModel) # make choice of lens model # we chose a source position (in units angle) x_source, y_source = 0.02, 0.01 # we chose a lens model kwargs_lens = [{'theta_E': 1., 'e1': 0.1, 'e2': 0.2, 'gamma': 2., 'center_x': 0, 'center_y': 0}, {'gamma1': 0.05, 'gamma2': -0.01}] # compute image positions and their (finite) magnifications # we solve for the image position(s) of the provided source position and lens model x_img, y_img = lensEquationSolver.image_position_from_source(kwargs_lens=kwargs_lens, sourcePos_x=x_source, sourcePos_y=y_source) point_source_list = ['LENSED_POSITION'] kwargs_ps = [{'ra_image': x_img, 'dec_image': y_img}] pointSource = PointSource(point_source_type_list=point_source_list) t_days = lensModel.arrival_time(x_img, y_img, kwargs_lens) time_delays_measured = t_days[1:] - t_days[0] time_delays_uncertainties = np.array([0.1, 0.1, 0.1]) self.td_likelihood = TimeDelayLikelihood(time_delays_measured, time_delays_uncertainties, lens_model_class=lensModel, point_source_class=pointSource) kwargs_cosmo = {'D_dt': lensCosmo.ddt} logL = self.td_likelihood.logL(kwargs_lens=kwargs_lens, kwargs_ps=kwargs_ps, kwargs_cosmo=kwargs_cosmo) npt.assert_almost_equal(logL, 0, decimal=8) time_delays_measured_new = copy.deepcopy(time_delays_measured) time_delays_measured_new[0] += 0.1 td_likelihood = TimeDelayLikelihood(time_delays_measured_new, time_delays_uncertainties, lens_model_class=lensModel, point_source_class=pointSource) kwargs_cosmo = {'D_dt': lensCosmo.ddt} logL = td_likelihood.logL(kwargs_lens=kwargs_lens, kwargs_ps=kwargs_ps, kwargs_cosmo=kwargs_cosmo) npt.assert_almost_equal(logL, -0.5, decimal=8) # Test a covariance matrix being used time_delays_cov = np.diag([0.1, 0.1, 0.1])**2 td_likelihood = TimeDelayLikelihood(time_delays_measured_new, time_delays_cov, lens_model_class=lensModel, point_source_class=pointSource) logL = td_likelihood.logL(kwargs_lens=kwargs_lens, kwargs_ps=kwargs_ps, kwargs_cosmo=kwargs_cosmo) npt.assert_almost_equal(logL, -0.5, decimal=8) # Test behaviour with a wrong number of images time_delays_measured_new = time_delays_measured_new[:-1] time_delays_uncertainties = time_delays_uncertainties[:-1] # remove last image td_likelihood = TimeDelayLikelihood(time_delays_measured_new, time_delays_uncertainties, lens_model_class=lensModel, point_source_class=pointSource) logL = td_likelihood.logL(kwargs_lens=kwargs_lens, kwargs_ps=kwargs_ps, kwargs_cosmo=kwargs_cosmo) npt.assert_almost_equal(logL, -10**15, decimal=8)
class TestTDCosmography(object): def setup(self): kwargs_model = { 'lens_light_model_list': ['HERNQUIST'], 'lens_model_list': ['SIE'], 'point_source_model_list': ['LENSED_POSITION'] } z_lens = 0.5 z_source = 2.5 R_slit = 3.8 dR_slit = 1. aperture_type = 'slit' kwargs_aperture = { 'aperture_type': aperture_type, 'center_ra': 0, 'width': dR_slit, 'length': R_slit, 'angle': 0, 'center_dec': 0 } psf_fwhm = 0.7 kwargs_seeing = {'psf_type': 'GAUSSIAN', 'fwhm': psf_fwhm} TDCosmography(z_lens, z_source, kwargs_model) from astropy.cosmology import FlatLambdaCDM cosmo = FlatLambdaCDM(H0=70, Om0=0.3, Ob0=0.05) self.td_cosmo = TDCosmography(z_lens, z_source, kwargs_model, cosmo_fiducial=cosmo, lens_model_kinematics_bool=None, kwargs_aperture=kwargs_aperture, kwargs_seeing=kwargs_seeing, light_model_kinematics_bool=None) self.lens = LensModel(lens_model_list=['SIE'], cosmo=cosmo, z_lens=z_lens, z_source=z_source) self.solver = LensEquationSolver(lensModel=self.lens) self.kwargs_lens = [{ 'theta_E': 1, 'e1': 0.1, 'e2': -0.2, 'center_x': 0, 'center_y': 0 }] source_x, source_y = 0, 0.05 image_x, image_y = self.solver.image_position_from_source( source_x, source_y, self.kwargs_lens, min_distance=0.1, search_window=10) self.kwargs_ps = [{'ra_image': image_x, 'dec_image': image_y}] self.image_x, self.image_y = image_x, image_y def test_time_delays(self): dt = self.td_cosmo.time_delays(self.kwargs_lens, self.kwargs_ps, kappa_ext=0) dt_true = self.lens.arrival_time(self.image_x, self.image_y, self.kwargs_lens) npt.assert_almost_equal(dt, dt_true, decimal=6) def test_fermat_potential(self): fermat_pot = self.td_cosmo.fermat_potential(self.kwargs_lens, self.kwargs_ps) fermat_pot_true = self.lens.fermat_potential(self.image_x, self.image_y, self.kwargs_lens) npt.assert_almost_equal(fermat_pot, fermat_pot_true, decimal=6) diff = 0.1 kwargs_ps = [{ 'ra_image': self.image_x + diff, 'dec_image': self.image_y }] fermat_pot = self.td_cosmo.fermat_potential(self.kwargs_lens, kwargs_ps) fermat_pot_true = self.lens.fermat_potential(self.image_x + diff, self.image_y, self.kwargs_lens) ratio = fermat_pot / fermat_pot_true assert np.max(np.abs(ratio)) > 1.05 def test_cosmo_inference(self): # set up a cosmology # compute image postions # compute J and velocity dispersion D_dt = self.td_cosmo._lens_cosmo.ddt D_d = self.td_cosmo._lens_cosmo.dd D_s = self.td_cosmo._lens_cosmo.ds D_ds = self.td_cosmo._lens_cosmo.dds fermat_potential_list = self.td_cosmo.fermat_potential( self.kwargs_lens, self.kwargs_ps) dt_list = self.td_cosmo.time_delays(self.kwargs_lens, self.kwargs_ps, kappa_ext=0) dt = dt_list[0] - dt_list[1] d_fermat = fermat_potential_list[0] - fermat_potential_list[1] D_dt_infered = self.td_cosmo.ddt_from_time_delay( d_fermat_model=d_fermat, dt_measured=dt) npt.assert_almost_equal(D_dt_infered, D_dt, decimal=5) r_eff = 0.5 kwargs_lens_light = [{ 'Rs': r_eff * 0.551, 'center_x': 0, 'center_y': 0 }] kwargs_anisotropy = {'r_ani': 1} anisotropy_model = 'OM' kwargs_numerics_galkin = { 'interpol_grid_num': 500, 'log_integration': True, 'max_integrate': 10, 'min_integrate': 0.001 } self.td_cosmo.kinematics_modeling_settings(anisotropy_model, kwargs_numerics_galkin, analytic_kinematics=True, Hernquist_approx=False, MGE_light=False, MGE_mass=False) J = self.td_cosmo.velocity_dispersion_dimension_less( self.kwargs_lens, kwargs_lens_light, kwargs_anisotropy, r_eff=r_eff, theta_E=self.kwargs_lens[0]['theta_E'], gamma=2) J_map = self.td_cosmo.velocity_dispersion_map_dimension_less( self.kwargs_lens, kwargs_lens_light, kwargs_anisotropy, r_eff=r_eff, theta_E=self.kwargs_lens[0]['theta_E'], gamma=2) assert len(J_map) == 1 npt.assert_almost_equal(J_map[0] / J, 1, decimal=1) sigma_v2 = J * D_s / D_ds * const.c**2 sigma_v = np.sqrt(sigma_v2) / 1000. # convert to [km/s] print(sigma_v, 'test sigma_v') Ds_Dds = self.td_cosmo.ds_dds_from_kinematics(sigma_v, J, kappa_s=0, kappa_ds=0) npt.assert_almost_equal(Ds_Dds, D_s / D_ds) # now we perform a mass-sheet transform in the observables but leave the models identical with a convergence correction kappa_s = 0.5 dt_list = self.td_cosmo.time_delays(self.kwargs_lens, self.kwargs_ps, kappa_ext=kappa_s) sigma_v_kappa = sigma_v * np.sqrt(1 - kappa_s) dt = dt_list[0] - dt_list[1] D_dt_infered, D_d_infered = self.td_cosmo.ddt_dd_from_time_delay_and_kinematics( d_fermat_model=d_fermat, dt_measured=dt, sigma_v_measured=sigma_v_kappa, J=J, kappa_s=kappa_s, kappa_ds=0, kappa_d=0) npt.assert_almost_equal(D_dt_infered, D_dt, decimal=6) npt.assert_almost_equal(D_d_infered, D_d, decimal=6)