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)
Пример #3
0
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()