def test_magnification_finite_adaptive(self): lens_model_list = ['EPL', 'SHEAR'] z_source = 1.5 kwargs_lens = [{ 'theta_E': 1., 'gamma': 2., 'e1': 0.02, 'e2': -0.09, 'center_x': 0, 'center_y': 0 }, { 'gamma1': 0.01, 'gamma2': 0.03 }] lensmodel = LensModel(lens_model_list) extension = LensModelExtensions(lensmodel) solver = LensEquationSolver(lensmodel) source_x, source_y = 0.07, 0.03 x_image, y_image = solver.findBrightImage(source_x, source_y, kwargs_lens) source_fwhm_parsec = 40. pc_per_arcsec = 1000 / self.cosmo.arcsec_per_kpc_proper(z_source).value source_sigma = source_fwhm_parsec / pc_per_arcsec / 2.355 grid_size = auto_raytracing_grid_size(source_fwhm_parsec) grid_resolution = auto_raytracing_grid_resolution(source_fwhm_parsec) # make this even higher resolution to show convergence grid_number = int(2 * grid_size / grid_resolution) window_size = 2 * grid_size mag_square_grid = extension.magnification_finite( x_image, y_image, kwargs_lens, source_sigma=source_sigma, grid_number=grid_number, window_size=window_size) flux_ratios_square_grid = mag_square_grid / max(mag_square_grid) mag_adaptive_grid = extension.magnification_finite_adaptive( x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=self.cosmo) flux_ratios_adaptive_grid = mag_adaptive_grid / max(mag_adaptive_grid) mag_adaptive_grid_2 = extension.magnification_finite_adaptive( x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=self.cosmo, axis_ratio=0) flux_ratios_adaptive_grid_2 = mag_adaptive_grid_2 / max( mag_adaptive_grid_2) # tests the default cosmology _ = extension.magnification_finite_adaptive(x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=None, tol=0.0001) # test smallest eigenvalue _ = extension.magnification_finite_adaptive( x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=None, tol=0.0001, use_largest_eigenvalue=False) # tests the r_max > sqrt(2) * grid_radius stop criterion _ = extension.magnification_finite_adaptive(x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=None, tol=0.0001, step_size=1000) mag_point_source = abs( lensmodel.magnification(x_image, y_image, kwargs_lens)) quarter_precent_precision = [0.0025] * 4 npt.assert_array_less( flux_ratios_square_grid / flux_ratios_adaptive_grid - 1, quarter_precent_precision) npt.assert_array_less( flux_ratios_square_grid / flux_ratios_adaptive_grid_2 - 1, quarter_precent_precision) half_percent_precision = [0.005] * 4 npt.assert_array_less(mag_square_grid / mag_adaptive_grid - 1, half_percent_precision) npt.assert_array_less(mag_square_grid / mag_adaptive_grid_2 - 1, half_percent_precision) npt.assert_array_less(mag_adaptive_grid / mag_point_source - 1, half_percent_precision) flux_array = np.array([0., 0.]) x_image, y_image = [x_image[0]], [y_image[0]] grid_x = np.array([0., source_sigma]) grid_y = np.array([0., 0.]) grid_r = np.hypot(grid_x, grid_y) source_model = LightModel(['GAUSSIAN']) kwargs_source = [{ 'amp': 1., 'center_x': source_x, 'center_y': source_y, 'sigma': source_sigma }] r_min = 0. r_max = source_sigma * 0.9 flux_array = extension._magnification_adaptive_iteration( flux_array, x_image, y_image, grid_x, grid_y, grid_r, r_min, r_max, lensmodel, kwargs_lens, source_model, kwargs_source) bx, by = lensmodel.ray_shooting(x_image[0], y_image[0], kwargs_lens) sb_true = source_model.surface_brightness(bx, by, kwargs_source) npt.assert_equal(True, flux_array[0] == sb_true) npt.assert_equal(True, flux_array[1] == 0.) r_min = source_sigma * 0.9 r_max = 2 * source_sigma flux_array = extension._magnification_adaptive_iteration( flux_array, x_image, y_image, grid_x, grid_y, grid_r, r_min, r_max, lensmodel, kwargs_lens, source_model, kwargs_source) bx, by = lensmodel.ray_shooting(x_image[0] + source_sigma, y_image[0], kwargs_lens) sb_true = source_model.surface_brightness(bx, by, kwargs_source) npt.assert_equal(True, flux_array[1] == sb_true)
def test_magnification_finite_adaptive(self): lens_model_list = ['EPL', 'SHEAR'] z_source = 1.5 kwargs_lens = [{ 'theta_E': 1., 'gamma': 2., 'e1': 0.02, 'e2': -0.09, 'center_x': 0, 'center_y': 0 }, { 'gamma1': 0.01, 'gamma2': 0.03 }] lensmodel = LensModel(lens_model_list) extension = LensModelExtensions(lensmodel) solver = LensEquationSolver(lensmodel) source_x, source_y = 0.07, 0.03 x_image, y_image = solver.findBrightImage(source_x, source_y, kwargs_lens) source_fwhm_parsec = 40. pc_per_arcsec = 1000 / self.cosmo.arcsec_per_kpc_proper(z_source).value source_sigma = source_fwhm_parsec / pc_per_arcsec / 2.355 grid_size = auto_raytracing_grid_size(source_fwhm_parsec) grid_resolution = auto_raytracing_grid_resolution(source_fwhm_parsec) # make this even higher resolution to show convergence grid_number = int(2 * grid_size / grid_resolution) window_size = 2 * grid_size mag_square_grid = extension.magnification_finite( x_image, y_image, kwargs_lens, source_sigma=source_sigma, grid_number=grid_number, window_size=window_size) flux_ratios_square_grid = mag_square_grid / max(mag_square_grid) mag_adaptive_grid = extension.magnification_finite_adaptive( x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=self.cosmo) flux_ratios_adaptive_grid = mag_adaptive_grid / max(mag_adaptive_grid) mag_adaptive_grid_fixed_aperture_size = extension.magnification_finite_adaptive( x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=self.cosmo, fixed_aperture_size=True, grid_radius_arcsec=0.2) flux_ratios_fixed_aperture_size = mag_adaptive_grid_fixed_aperture_size / max( mag_adaptive_grid_fixed_aperture_size) mag_adaptive_grid_2 = extension.magnification_finite_adaptive( x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=self.cosmo, axis_ratio=0) flux_ratios_adaptive_grid_2 = mag_adaptive_grid_2 / max( mag_adaptive_grid_2) # tests the default cosmology _ = extension.magnification_finite_adaptive(x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=None, tol=0.0001) # test smallest eigenvalue _ = extension.magnification_finite_adaptive( x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=None, tol=0.0001, use_largest_eigenvalue=False) # tests the r_max > sqrt(2) * grid_radius stop criterion _ = extension.magnification_finite_adaptive(x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=None, tol=0.0001, step_size=1000) mag_point_source = abs( lensmodel.magnification(x_image, y_image, kwargs_lens)) quarter_precent_precision = [0.0025] * 4 npt.assert_array_less( flux_ratios_square_grid / flux_ratios_adaptive_grid - 1, quarter_precent_precision) npt.assert_array_less( flux_ratios_fixed_aperture_size / flux_ratios_adaptive_grid - 1, quarter_precent_precision) npt.assert_array_less( flux_ratios_square_grid / flux_ratios_adaptive_grid_2 - 1, quarter_precent_precision) half_percent_precision = [0.005] * 4 npt.assert_array_less(mag_square_grid / mag_adaptive_grid - 1, half_percent_precision) npt.assert_array_less(mag_square_grid / mag_adaptive_grid_2 - 1, half_percent_precision) npt.assert_array_less(mag_adaptive_grid / mag_point_source - 1, half_percent_precision) flux_array = np.array([0., 0.]) grid_x = np.array([0., source_sigma]) grid_y = np.array([0., 0.]) grid_r = np.hypot(grid_x, grid_y) # test that the double gaussian profile has 2x the flux when dx, dy = 0 magnification_double_gaussian = extension.magnification_finite_adaptive( x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=self.cosmo, source_light_model='DOUBLE_GAUSSIAN', dx=0., dy=0., amp_scale=1., size_scale=1.) npt.assert_almost_equal(magnification_double_gaussian, 2 * mag_adaptive_grid) grid_radius = 0.3 npix = 400 _x = _y = np.linspace(-grid_radius, grid_radius, npix) resolution = 2 * grid_radius / npix xx, yy = np.meshgrid(_x, _y) for i in range(0, 4): beta_x, beta_y = lensmodel.ray_shooting(x_image[i] + xx.ravel(), y_image[i] + yy.ravel(), kwargs_lens) source_light_model = LightModel(['GAUSSIAN'] * 2) amp_scale, dx, dy, size_scale = 0.2, 0.005, -0.005, 1. kwargs_source = [{ 'amp': 1., 'center_x': source_x, 'center_y': source_y, 'sigma': source_sigma }, { 'amp': amp_scale, 'center_x': source_x + dx, 'center_y': source_y + dy, 'sigma': source_sigma * size_scale }] sb = source_light_model.surface_brightness(beta_x, beta_y, kwargs_source) magnification_double_gaussian_reference = np.sum( sb) * resolution**2 magnification_double_gaussian = extension.magnification_finite_adaptive( [x_image[i]], [y_image[i]], source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=self.cosmo, source_light_model='DOUBLE_GAUSSIAN', dx=dx, dy=dy, amp_scale=amp_scale, size_scale=size_scale, grid_resolution=resolution, grid_radius_arcsec=grid_radius, axis_ratio=1.) npt.assert_almost_equal( magnification_double_gaussian / magnification_double_gaussian_reference, 1., 3) source_model = LightModel(['GAUSSIAN']) kwargs_source = [{ 'amp': 1., 'center_x': source_x, 'center_y': source_y, 'sigma': source_sigma }] r_min = 0. r_max = source_sigma * 0.9 flux_array = extension._magnification_adaptive_iteration( flux_array, x_image[0], y_image[0], grid_x, grid_y, grid_r, r_min, r_max, lensmodel, kwargs_lens, source_model, kwargs_source) bx, by = lensmodel.ray_shooting(x_image[0], y_image[0], kwargs_lens) sb_true = source_model.surface_brightness(bx, by, kwargs_source) npt.assert_equal(True, flux_array[0] == sb_true) npt.assert_equal(True, flux_array[1] == 0.) r_min = source_sigma * 0.9 r_max = 2 * source_sigma flux_array = extension._magnification_adaptive_iteration( flux_array, x_image[0], y_image[0], grid_x, grid_y, grid_r, r_min, r_max, lensmodel, kwargs_lens, source_model, kwargs_source) bx, by = lensmodel.ray_shooting(x_image[0] + source_sigma, y_image[0], kwargs_lens) sb_true = source_model.surface_brightness(bx, by, kwargs_source) npt.assert_equal(True, flux_array[1] == sb_true)
def plot_quasar_images(lens_model, x_image, y_image, source_x, source_y, kwargs_lens, source_fwhm_parsec, z_source, cosmo=None, grid_resolution=None, grid_radius_arcsec=None, source_light_model='SINGLE_GAUSSIAN', dx=None, dy=None, size_scale=None, amp_scale=None): """ This function plots the surface brightness in the image plane of a background source modeled as either a single Gaussian or two Gaussian light profiles. The flux is computed inside a circular aperture with radius grid_radius_arcsec. If grid_radius_arcsec is not specified a default value will be assumed. :param lens_model: an instance of LensModel :param x_image: a list or array of x coordinates [units arcsec] :param y_image: a list or array of y coordinates [units arcsec] :param kwargs_lens: keyword arguments for the lens model :param source_fwhm_parsec: the size of the background source [units parsec] :param z_source: the source redshift :param cosmo: (optional) an instance of astropy.cosmology; if not specified, a default cosmology will be used :param grid_resolution: the grid resolution in units arcsec/pixel; if not specified, an appropriate value will be estimated from the source size :param grid_radius_arcsec: (optional) the size of the ray tracing region in arcsec; if not specified, an appropriate value will be estimated from the source size :param source_light_model: the model for background source light; currently implemented are 'SINGLE_GAUSSIAN' and 'DOUBLE_GAUSSIAN'. :param dx: used with source model 'DOUBLE_GAUSSIAN', the offset of the second source light profile from the first [arcsec] :param dy: used with source model 'DOUBLE_GAUSSIAN', the offset of the second source light profile from the first [arcsec] :param size_scale: used with source model 'DOUBLE_GAUSSIAN', the size of the second source light profile relative to the first :param amp_scale: used with source model 'DOUBLE_GAUSSIAN', the peak brightness of the second source light profile relative to the first :return: Four images of the background source in the image plane """ lens_model_extension = LensModelExtensions(lens_model) magnifications = [] images = [] grid_x_0, grid_y_0, source_model, kwargs_source, grid_resolution, grid_radius_arcsec = \ setup_mag_finite(cosmo, lens_model, grid_radius_arcsec, grid_resolution, source_fwhm_parsec, source_light_model, z_source, source_x, source_y, dx, dy, amp_scale, size_scale) shape0 = grid_x_0.shape grid_x_0, grid_y_0 = grid_x_0.ravel(), grid_y_0.ravel() for xi, yi in zip(x_image, y_image): flux_array = np.zeros_like(grid_x_0) r_min = 0 r_max = grid_radius_arcsec grid_r = np.hypot(grid_x_0, grid_y_0) flux_array = lens_model_extension._magnification_adaptive_iteration( flux_array, xi, yi, grid_x_0, grid_y_0, grid_r, r_min, r_max, lens_model, kwargs_lens, source_model, kwargs_source) m = np.sum(flux_array) * grid_resolution**2 magnifications.append(m) images.append(flux_array.reshape(shape0)) magnifications = np.array(magnifications) flux_ratios = magnifications / max(magnifications) import matplotlib.pyplot as plt fig = plt.figure(1) fig.set_size_inches(16, 6) N = len(images) for i, (image, mag, fr) in enumerate(zip(images, magnifications, flux_ratios)): ax = plt.subplot(1, N, i + 1) ax.imshow(image, origin='lower', extent=[ -grid_radius_arcsec, grid_radius_arcsec, -grid_radius_arcsec, grid_radius_arcsec ]) ax.annotate('magnification: ' + str(np.round(mag, 3)), xy=(0.05, 0.9), xycoords='axes fraction', color='w', fontsize=12) ax.annotate('flux ratio: ' + str(np.round(fr, 3)), xy=(0.05, 0.8), xycoords='axes fraction', color='w', fontsize=12) plt.show()