Exemplo n.º 1
0
    def test_create_solver_class(self):
        from slitronomy.Optimization.solver_source import SparseSolverSource
        source_model_class = LightModel(['SLIT_STARLETS'])
        lens_light_model_class = LightModel([])
        point_source_class = PointSource(point_source_type_list=[])
        source_numerics_class = NumericsSubFrame(self.imageModel.Data,
                                                 self.imageModel.PSF,
                                                 supersampling_factor=2)
        solver_class = class_util.create_solver_class(
            self.imageModel.Data, self.imageModel.PSF,
            self.imageModel.ImageNumerics, source_numerics_class,
            self.imageModel.LensModel, source_model_class,
            lens_light_model_class, point_source_class,
            self.imageModel._extinction, self.kwargs_sparse_solver)
        assert isinstance(solver_class, SparseSolverSource)

        from slitronomy.Optimization.solver_source_lens import SparseSolverSourceLens
        source_model_class = LightModel(['SLIT_STARLETS'])
        lens_light_model_class = LightModel(['SLIT_STARLETS'])
        point_source_class = PointSource(point_source_type_list=[])
        source_numerics_class = NumericsSubFrame(self.imageModel.Data,
                                                 self.imageModel.PSF,
                                                 supersampling_factor=2)
        solver_class = class_util.create_solver_class(
            self.imageModel.Data, self.imageModel.PSF,
            self.imageModel.ImageNumerics, source_numerics_class,
            self.imageModel.LensModel, source_model_class,
            lens_light_model_class, point_source_class,
            self.imageModel._extinction, self.kwargs_sparse_solver)
        assert isinstance(solver_class, SparseSolverSourceLens)
Exemplo n.º 2
0
    def __init__(self,
                 data_class,
                 psf_class,
                 lens_model_class=None,
                 source_model_class=None,
                 lens_light_model_class=None,
                 point_source_class=None,
                 extinction_class=None,
                 kwargs_numerics=None):
        """
        :param data_class: instance of ImageData() or PixelGrid() class
        :param psf_class: instance of PSF() class
        :param lens_model_class: instance of LensModel() class
        :param source_model_class: instance of LightModel() class describing the source parameters
        :param lens_light_model_class: instance of LightModel() class describing the lens light parameters
        :param point_source_class: instance of PointSource() class describing the point sources
        :param kwargs_numerics: keyword argument with various numeric description (see ImageNumerics class for options)
        """
        self.type = 'single-band'
        self.PSF = psf_class
        self.Data = data_class
        self.PSF.set_pixel_size(self.Data.pixel_width)
        if kwargs_numerics is None:
            kwargs_numerics = {}
        self.ImageNumerics = NumericsSubFrame(pixel_grid=self.Data,
                                              psf=self.PSF,
                                              **kwargs_numerics)
        if lens_model_class is None:
            lens_model_class = LensModel(lens_model_list=[])
        self.LensModel = lens_model_class
        if point_source_class is None:
            point_source_class = PointSource(point_source_type_list=[])
        self.PointSource = point_source_class
        self.PointSource.update_lens_model(lens_model_class=lens_model_class)
        x_center, y_center = self.Data.center
        self.PointSource.update_search_window(
            search_window=np.max(self.Data.width),
            x_center=x_center,
            y_center=y_center,
            min_distance=self.Data.pixel_width,
            only_from_unspecified=True)
        self._psf_error_map = self.PSF.psf_error_map_bool

        if source_model_class is None:
            source_model_class = LightModel(light_model_list=[])
        self.SourceModel = source_model_class
        if lens_light_model_class is None:
            lens_light_model_class = LightModel(light_model_list=[])
        self.LensLightModel = lens_light_model_class
        self.source_mapping = Image2SourceMapping(
            lensModel=lens_model_class, sourceModel=source_model_class)
        self.num_bands = 1
        self._kwargs_numerics = kwargs_numerics
        if extinction_class is None:
            extinction_class = DifferentialExtinction(optical_depth_model=[])
        self._extinction = extinction_class
Exemplo n.º 3
0
    def setup(self):
        self.num_pix = 20  # cutout pixel size
        delta_pix = 0.2
        background_rms = 0.05
        _, _, ra_at_xy_0, dec_at_xy_0, _, _, Mpix2coord, _ \
            = l_util.make_grid_with_coordtransform(numPix=self.num_pix, deltapix=delta_pix, subgrid_res=1,
                                                   inverse=False, left_lower=False)
        # imaging data class
        kwargs_data = {
            'ra_at_xy_0': ra_at_xy_0,
            'dec_at_xy_0': dec_at_xy_0,
            'transform_pix2angle': Mpix2coord,
            'image_data': np.zeros((self.num_pix, self.num_pix)),
            'background_rms': background_rms,
            'noise_map': background_rms * np.ones(
                (self.num_pix, self.num_pix)),
        }
        data_class = ImageData(**kwargs_data)

        # lens mass class
        lens_model_class = LensModel(['SPEP'])
        self.kwargs_lens = [{
            'theta_E': 1,
            'gamma': 2,
            'center_x': 0,
            'center_y': 0,
            'e1': -0.05,
            'e2': 0.05
        }]

        # source light class
        source_model_class = LightModel(['SLIT_STARLETS'])
        self.kwargs_source = [{
            'coeffs': 0,
            'n_scales': 3,
            'n_pixels': self.num_pix**2
        }]

        # define numerics classes
        image_numerics_class = NumericsSubFrame(pixel_grid=data_class,
                                                psf=PSF(psf_type='NONE'))
        source_numerics_class = NumericsSubFrame(pixel_grid=data_class,
                                                 psf=PSF(psf_type='NONE'),
                                                 supersampling_factor=1)

        # init sparse solver
        self.solver = SparseSolverSource(data_class,
                                         lens_model_class,
                                         image_numerics_class,
                                         source_numerics_class,
                                         source_model_class,
                                         num_iter_source=10)

        # init the tracker
        self.tracker_alone = SolverTracker(self.solver, verbose=True)
 def test_raise(self):
     with self.assertRaises(ValueError):
         num_pix = 10
         data = ImageData(np.zeros((num_pix, num_pix)))
         lens_model = LensModel(['SPEP'])
         image_grid_class = NumericsSubFrame(data, PSF('NONE')).grid_class
         source_grid_class = NumericsSubFrame(data, PSF('NONE')).grid_class
         lensing_op = LensingOperator(lens_model,
                                      image_grid_class,
                                      source_grid_class,
                                      num_pix,
                                      source_interpolation='sth')
Exemplo n.º 5
0
    def update_psf(self, psf_class):
        """

        update the instance of the class with a new instance of PSF() with a potentially different point spread function

        :param psf_class:
        :return: no return. Class is updated.
        """
        self.PSF = psf_class
        self.PSF.set_pixel_size(self.Data.pixel_width)
        self.ImageNumerics = NumericsSubFrame(pixel_grid=self.Data,
                                              psf=self.PSF,
                                              **self._kwargs_numerics)
Exemplo n.º 6
0
    def __init__(self, *args, **kwargs):
        super(TestRaise, self).__init__(*args, **kwargs)
        self.num_pix = 49  # cutout pixel size
        self.subgrid_res_source = 1
        self.num_pix_source = self.num_pix * self.subgrid_res_source

        delta_pix = 0.24
        _, _, ra_at_xy_0, dec_at_xy_0, _, _, Mpix2coord, _ \
            = l_util.make_grid_with_coordtransform(numPix=self.num_pix, deltapix=delta_pix, subgrid_res=1,
                                                         inverse=False, left_lower=False)
        image_data = np.random.rand(self.num_pix, self.num_pix)
        self.kwargs_data = {
            'ra_at_xy_0': ra_at_xy_0,
            'dec_at_xy_0': dec_at_xy_0,
            'transform_pix2angle': Mpix2coord,
            'image_data': image_data,
            'background_rms': 0.01,
            'noise_map': 0.01 * np.ones_like(image_data),
        }
        self.data = ImageData(**self.kwargs_data)
        self.lens_model_class = LensModel(['SPEP'])
        self.kwargs_lens = [{
            'theta_E': 1,
            'gamma': 2,
            'center_x': 0,
            'center_y': 0,
            'e1': -0.05,
            'e2': 0.05
        }]
        self.source_model_class = LightModel(['SLIT_STARLETS'])
        self.lens_light_model_class = LightModel(['SLIT_STARLETS'])
        self.kwargs_source = [{'n_scales': 4}]

        self.kwargs_lens_light = [{'n_scales': 4}]
        psf = PSF(psf_type='NONE')
        self.numerics = NumericsSubFrame(pixel_grid=self.data, psf=psf)
        self.source_numerics = NumericsSubFrame(
            pixel_grid=self.data,
            psf=psf,
            supersampling_factor=self.subgrid_res_source)
        self.solver_source_lens = SparseSolverSourceLens(
            self.data,
            self.lens_model_class,
            self.numerics,
            self.source_numerics,
            self.source_model_class,
            self.lens_light_model_class,
            num_iter_source=1,
            num_iter_lens=1,
            num_iter_weights=1)
Exemplo n.º 7
0
    def setup(self):
        self.num_pix = 25  # cutout pixel size
        self.subgrid_res_source = 2
        delta_pix = 0.32
        _, _, ra_at_xy_0, dec_at_xy_0, _, _, Mpix2coord, _ \
            = l_util.make_grid_with_coordtransform(numPix=self.num_pix, deltapix=delta_pix, subgrid_res=1,
                                                         inverse=False, left_lower=False)
        kwargs_data = {
            'ra_at_xy_0': ra_at_xy_0,
            'dec_at_xy_0': dec_at_xy_0,
            'transform_pix2angle': Mpix2coord,
            'image_data': np.zeros((self.num_pix, self.num_pix))
        }

        data_class = ImageData(**kwargs_data)
        numerics_image = NumericsSubFrame(data_class, PSF('NONE'))
        numerics_source = NumericsSubFrame(
            data_class,
            PSF('NONE'),
            supersampling_factor=self.subgrid_res_source)
        self.source_plane = SizeablePlaneGrid(numerics_source.grid_class,
                                              verbose=True)

        # create a mask mimicking the real case of lensing operation
        lens_model_class = LensModel(['SIE'])
        kwargs_lens = [{
            'theta_E': 1.5,
            'center_x': 0,
            'center_y': 0,
            'e1': 0.1,
            'e2': 0.1
        }]
        lensing_op = LensingOperator(lens_model_class,
                                     numerics_image.grid_class,
                                     numerics_source.grid_class, self.num_pix,
                                     self.subgrid_res_source)
        lensing_op.update_mapping(kwargs_lens)
        unit_image = np.ones((self.num_pix, self.num_pix))
        mask_image = np.zeros((self.num_pix, self.num_pix))
        mask_image[2:-2, 2:-2] = 1  # some binary image that mask out borders
        self.unit_image_mapped = lensing_op.image2source_2d(unit_image,
                                                            no_flux_norm=False)
        self.mask_mapped = lensing_op.image2source_2d(mask_image)
Exemplo n.º 8
0
 def __init__(self, *args, **kwargs):
     super(TestRaise, self).__init__(*args, **kwargs)
     self.num_pix = 10
     _, _, ra_at_xy_0, dec_at_xy_0, _, _, Mpix2coord, _ \
         = l_util.make_grid_with_coordtransform(numPix=self.num_pix, deltapix=0.5, subgrid_res=1,
                                                inverse=False, left_lower=False)
     kwargs_data_nonsquare = {
         'ra_at_xy_0': ra_at_xy_0,
         'dec_at_xy_0': dec_at_xy_0,
         'transform_pix2angle': Mpix2coord,
         'image_data': np.zeros(
             (self.num_pix, self.num_pix + 10)),  # non-square image
     }
     kwargs_data = {
         'ra_at_xy_0': ra_at_xy_0,
         'dec_at_xy_0': dec_at_xy_0,
         'transform_pix2angle': Mpix2coord,
         'image_data': np.zeros(
             (self.num_pix, self.num_pix)),  # non-square image
     }
     self.data_nonsquare = ImageData(**kwargs_data_nonsquare)
     self.data = ImageData(**kwargs_data)
     psf = PSF('NONE')
     self.numerics = NumericsSubFrame(self.data, psf)
     lens_model = LensModel(['SPEP'])
     self.source_model_class = LightModel(['SLIT_STARLETS'])
     self.lens_light_model_class = LightModel(['SLIT_STARLETS'])
     # get grid classes
     image_grid_class = self.numerics.grid_class
     source_numerics = NumericsSubFrame(self.data,
                                        psf,
                                        supersampling_factor=1)
     source_grid_class = source_numerics.grid_class
     self.lensing_op = LensingOperator(lens_model, image_grid_class,
                                       source_grid_class, self.num_pix)
     self.model_op = ModelOperators(self.data, self.lensing_op,
                                    self.numerics)
     self.model_op.add_lens_light(self.lens_light_model_class)
     self.model_op_nolens = ModelOperators(self.data, self.lensing_op,
                                           self.numerics)
Exemplo n.º 9
0
 def setup(self):
     self.num_pix = 25  # cutout pixel size
     self.delta_pix = 0.24
     _, _, ra_at_xy_0, dec_at_xy_0, _, _, Mpix2coord, _ \
         = l_util.make_grid_with_coordtransform(numPix=self.num_pix, deltapix=self.delta_pix, subgrid_res=1,
                                                      inverse=False, left_lower=False)
     kwargs_data = {
         'ra_at_xy_0': ra_at_xy_0,
         'dec_at_xy_0': dec_at_xy_0,
         'transform_pix2angle': Mpix2coord,
         'image_data': np.zeros((self.num_pix, self.num_pix))
     }
     numerics = NumericsSubFrame(ImageData(**kwargs_data), PSF('NONE'))
     self.plane_grid = PlaneGrid(numerics.grid_class)
Exemplo n.º 10
0
    def test_source_plane_coordinates(self):
        lensing_op = LensingOperator(self.lens_model, self.image_grid_class,
                                     self.source_grid_class_default,
                                     self.num_pix)
        theta_x, theta_y = lensing_op.source_plane_coordinates
        assert theta_x.size == self.num_pix**2
        assert theta_y.size == self.num_pix**2

        subgrid_res = 2
        source_grid_class = NumericsSubFrame(
            self.data, self.psf, supersampling_factor=subgrid_res).grid_class
        lensing_op = LensingOperator(self.lens_model, self.image_grid_class,
                                     source_grid_class, self.num_pix)
        theta_x, theta_y = lensing_op.source_plane_coordinates
        assert theta_x.size == self.num_pix**2 * subgrid_res**2
        assert theta_y.size == self.num_pix**2 * subgrid_res**2
Exemplo n.º 11
0
 def test_raise(self):
     with self.assertRaises(ValueError):
         # test rectangular size
         num_pix_x = 25
         num_pix_y = 30
         delta_pix = 0.24
         _, _, ra_at_xy_0, dec_at_xy_0, _, _, Mpix2coord, _ \
             = l_util.make_grid_with_coordtransform(numPix=num_pix_x, deltapix=delta_pix, subgrid_res=1,
                                                          inverse=False, left_lower=False)
         kwargs_data = {
             'ra_at_xy_0': ra_at_xy_0,
             'dec_at_xy_0': dec_at_xy_0,
             'transform_pix2angle': Mpix2coord,
             'image_data': np.zeros((num_pix_x, num_pix_y))
         }
         numerics = NumericsSubFrame(ImageData(**kwargs_data), PSF('NONE'))
         plane_grid = PlaneGrid(numerics.grid_class)
Exemplo n.º 12
0
    def _setup_pixelbased_source_numerics(self, kwargs_numerics,
                                          kwargs_pixelbased):
        """
        Check if model requirement are compatible with support pixel-based solver,
        and creates a new numerics class specifically for source plane.

        :param kwargs_numerics: keyword argument with various numeric description (see ImageNumerics class for options)
        :param kwargs_pixelbased: keyword argument with various settings related to the pixel-based solver (see SLITronomy documentation)
        """
        # check that the required convolution type is compatible with pixel-based modelling (in current implementation)
        psf_type = self.PSF.psf_type
        supersampling_convolution = kwargs_numerics.get(
            'supersampling_convolution', False)
        supersampling_factor = kwargs_numerics.get('supersampling_factor', 1)
        compute_mode = kwargs_numerics.get('compute_mode', 'regular')
        if psf_type not in ['PIXEL', 'NONE']:
            raise ValueError(
                "Only convolution using a pixelated kernel is supported for pixel-based modelling"
            )
        if compute_mode != 'regular':
            raise ValueError(
                "Only regular coordinate grid is supported for pixel-based modelling"
            )
        if (supersampling_convolution is True and supersampling_factor > 1):
            raise ValueError(
                "Only non-supersampled convolution is supported for pixel-based modelling"
            )

        # setup the source numerics with a (possibily) different supersampling resolution
        supersampling_factor_source = kwargs_pixelbased.pop(
            'supersampling_factor_source', 1)
        kwargs_numerics_source = kwargs_numerics.copy()
        kwargs_numerics_source[
            'supersampling_factor'] = supersampling_factor_source
        kwargs_numerics_source['compute_mode'] = 'regular'
        source_numerics_class = NumericsSubFrame(pixel_grid=self.Data,
                                                 psf=self.PSF,
                                                 **kwargs_numerics_source)
        return source_numerics_class
Exemplo n.º 13
0
    def setup(self):

        # data specifics
        sigma_bkg = .05  # background noise per pixel
        exp_time = 100  # exposure time (arbitrary units, flux per pixel is in units #photons/exp_time unit)
        self.num_pix = 100  # cutout pixel size
        delta_pix = 0.05  # pixel size in arcsec (area per pixel = delta_pix**2)
        fwhm = 0.5  # full width half max of PSF

        # supersampling factor for source plane
        self.subgrid_res_source = 1
        self.num_pix_source = self.num_pix * self.subgrid_res_source

        # wavelets scales for lens and source
        self.n_scales_source = 4
        self.n_scales_lens = 3

        # prepare data simulation
        kwargs_data = sim_util.data_configure_simple(self.num_pix,
                                                     delta_pix,
                                                     exp_time,
                                                     sigma_bkg,
                                                     inverse=True)
        data_class = ImageData(**kwargs_data)

        # generate sa pixelated gaussian PSF kernel
        kwargs_psf = {
            'psf_type': 'GAUSSIAN',
            'fwhm': fwhm,
            'truncation': 5,
            'pixel_size': delta_pix
        }
        psf_class = PSF(**kwargs_psf)
        kernel = psf_class.kernel_point_source
        kwargs_psf = {
            'psf_type': 'PIXEL',
            'kernel_point_source': kernel,
            'psf_error_map': np.ones_like(kernel) * 0.001
        }
        psf_class = PSF(**kwargs_psf)

        # 'EXERNAL_SHEAR': external shear
        kwargs_shear = {
            'gamma1': 0.01,
            'gamma2': 0.01
        }  # gamma_ext: shear strength, psi_ext: shear angel (in radian)
        phi, q = 0.2, 0.8
        e1, e2 = param_util.phi_q2_ellipticity(phi, q)
        kwargs_spemd = {
            'theta_E': 1.,
            'gamma': 1.8,
            'center_x': 0,
            'center_y': 0,
            'e1': e1,
            'e2': e2
        }

        lens_model_list = ['SPEP', 'SHEAR']
        self.kwargs_lens = [kwargs_spemd, kwargs_shear]
        self.lens_model_class = LensModel(lens_model_list=lens_model_list)
        # list of light profiles (for lens and source)
        # 'SERSIC': spherical Sersic profile
        kwargs_sersic = {
            'amp': 1.,
            'R_sersic': 0.1,
            'n_sersic': 2,
            'center_x': 0,
            'center_y': 0
        }
        # 'SERSIC_ELLIPSE': elliptical Sersic profile
        phi, q = 0.2, 0.9
        e1, e2 = param_util.phi_q2_ellipticity(phi, q)
        kwargs_sersic_ellipse = {
            'amp': 1.,
            'R_sersic': .6,
            'n_sersic': 7,
            'center_x': 0,
            'center_y': 0,
            'e1': e1,
            'e2': e2
        }

        lens_light_model_list = ['SERSIC']
        kwargs_lens_light = [kwargs_sersic]
        lens_light_model_class = LightModel(
            light_model_list=lens_light_model_list)
        source_model_list = ['SERSIC_ELLIPSE']
        kwargs_source = [kwargs_sersic_ellipse]
        source_model_class = LightModel(light_model_list=source_model_list)

        # list of lens light profiles
        point_source_class = PointSource(['LENSED_POSITION'])
        lens_eq_solver = LensEquationSolver(lensModel=self.lens_model_class)
        ra_image, dec_image = lens_eq_solver.image_position_from_source(
            sourcePos_x=kwargs_source[0]['center_x'],
            sourcePos_y=kwargs_source[0]['center_y'],
            kwargs_lens=self.kwargs_lens)
        point_amp = np.ones_like(ra_image)
        kwargs_ps = [{
            'ra_image': ra_image,
            'dec_image': dec_image,
            'point_amp': point_amp
        }]

        # simulate data
        kwargs_numerics = {'supersampling_factor': 1}
        imageModel = ImageModel(data_class,
                                psf_class,
                                self.lens_model_class,
                                source_model_class,
                                lens_light_model_class,
                                point_source_class,
                                kwargs_numerics=kwargs_numerics)
        self.image_sim = sim_util.simulate_simple(imageModel, self.kwargs_lens,
                                                  kwargs_source,
                                                  kwargs_lens_light, kwargs_ps)
        data_class.update_data(self.image_sim)

        # retrieve the point source data only (for initial guess for source+PS solver)
        self.ps_sim = imageModel.image(self.kwargs_lens,
                                       kwargs_source,
                                       kwargs_lens_light,
                                       kwargs_ps,
                                       source_add=False,
                                       lens_light_add=False,
                                       point_source_add=True)

        # define some mask
        self.likelihood_mask = np.zeros((self.num_pix, self.num_pix))
        self.likelihood_mask[5:-5, 5:-5] = 1

        # get a numerics classes
        numerics = NumericsSubFrame(pixel_grid=data_class, psf=psf_class)
        source_numerics = NumericsSubFrame(
            pixel_grid=data_class,
            psf=psf_class,
            supersampling_factor=self.subgrid_res_source)

        self.num_iter_source = 20
        self.num_iter_lens = 10
        self.num_iter_global = 7
        self.num_iter_weights = 2

        # source grid offsets
        self.kwargs_special = {
            'delta_x_source_grid': 0,
            'delta_y_source_grid': 0,
        }

        # init the solvers

        # SOLVER SOURCE, with analysis formulation
        self.source_model_class = LightModel(['SLIT_STARLETS'])
        self.kwargs_source = [{'n_scales': self.n_scales_source}]
        self.solver_source_ana = SparseSolverSource(
            data_class,
            self.lens_model_class,
            numerics,
            source_numerics,
            self.source_model_class,
            source_interpolation='bilinear',
            minimal_source_plane=False,
            use_mask_for_minimal_source_plane=True,
            min_num_pix_source=20,
            sparsity_prior_norm=1,
            force_positivity=True,
            formulation='analysis',
            verbose=False,
            show_steps=False,
            min_threshold=5,
            threshold_increment_high_freq=1,
            threshold_decrease_type='exponential',
            num_iter_source=self.num_iter_source,
            num_iter_weights=self.num_iter_weights)
        self.solver_source_ana.set_likelihood_mask(self.likelihood_mask)

        # SOLVER SOURCE + LENS, with synthesis formulation
        self.lens_light_model_class = LightModel(['SLIT_STARLETS'])
        self.kwargs_lens_light = [{'n_scales': self.n_scales_lens}]
        self.solver_lens_syn = SparseSolverSourceLens(
            data_class,
            self.lens_model_class,
            numerics,
            source_numerics,
            self.source_model_class,
            self.lens_light_model_class,
            source_interpolation='bilinear',
            minimal_source_plane=False,
            use_mask_for_minimal_source_plane=True,
            min_num_pix_source=20,
            sparsity_prior_norm=1,
            force_positivity=True,
            formulation='synthesis',
            verbose=False,
            show_steps=False,
            min_threshold=3,
            threshold_increment_high_freq=1,
            threshold_decrease_type='linear',
            num_iter_global=self.num_iter_global,
            num_iter_source=self.num_iter_source,
            num_iter_lens=self.num_iter_lens,
            num_iter_weights=self.num_iter_weights)
        self.solver_lens_syn.set_likelihood_mask(self.likelihood_mask)
Exemplo n.º 14
0
class ImageModel(object):
    """
    this class uses functions of lens_model and source_model to make a lensed image
    """
    def __init__(self,
                 data_class,
                 psf_class,
                 lens_model_class=None,
                 source_model_class=None,
                 lens_light_model_class=None,
                 point_source_class=None,
                 extinction_class=None,
                 kwargs_numerics=None,
                 kwargs_pixelbased=None):
        """
        :param data_class: instance of ImageData() or PixelGrid() class
        :param psf_class: instance of PSF() class
        :param lens_model_class: instance of LensModel() class
        :param source_model_class: instance of LightModel() class describing the source parameters
        :param lens_light_model_class: instance of LightModel() class describing the lens light parameters
        :param point_source_class: instance of PointSource() class describing the point sources
        :param kwargs_numerics: keyword arguments with various numeric description (see ImageNumerics class for options)
        :param kwargs_pixelbased: keyword arguments with various settings related to the pixel-based solver (see SLITronomy documentation)
        """
        self.type = 'single-band'
        self.num_bands = 1
        self.PSF = psf_class
        self.Data = data_class
        self.PSF.set_pixel_size(self.Data.pixel_width)
        if kwargs_numerics is None:
            kwargs_numerics = {}
        self.ImageNumerics = NumericsSubFrame(pixel_grid=self.Data,
                                              psf=self.PSF,
                                              **kwargs_numerics)
        if lens_model_class is None:
            lens_model_class = LensModel(lens_model_list=[])
        self.LensModel = lens_model_class
        if point_source_class is None:
            point_source_class = PointSource(point_source_type_list=[])
        self.PointSource = point_source_class
        self.PointSource.update_lens_model(lens_model_class=lens_model_class)
        x_center, y_center = self.Data.center
        self.PointSource.update_search_window(
            search_window=np.max(self.Data.width),
            x_center=x_center,
            y_center=y_center,
            min_distance=self.Data.pixel_width,
            only_from_unspecified=True)
        self._psf_error_map = self.PSF.psf_error_map_bool

        if source_model_class is None:
            source_model_class = LightModel(light_model_list=[])
        self.SourceModel = source_model_class
        if lens_light_model_class is None:
            lens_light_model_class = LightModel(light_model_list=[])
        self.LensLightModel = lens_light_model_class
        self._kwargs_numerics = kwargs_numerics
        if extinction_class is None:
            extinction_class = DifferentialExtinction(optical_depth_model=[])
        self._extinction = extinction_class
        if kwargs_pixelbased is None:
            kwargs_pixelbased = {}
        else:
            kwargs_pixelbased = kwargs_pixelbased.copy()
        self._pixelbased_bool = self._detect_pixelbased_models()
        if self._pixelbased_bool is True:
            from slitronomy.Util.class_util import create_solver_class  # requirement on SLITronomy is exclusively here
            self.SourceNumerics = self._setup_pixelbased_source_numerics(
                kwargs_numerics, kwargs_pixelbased)
            self.PixelSolver = create_solver_class(
                self.Data, self.PSF, self.ImageNumerics, self.SourceNumerics,
                self.LensModel, self.SourceModel, self.LensLightModel,
                self.PointSource, self._extinction, kwargs_pixelbased)
            self.source_mapping = None  # handled with pixelated operator
        else:
            self.source_mapping = Image2SourceMapping(
                lensModel=lens_model_class, sourceModel=source_model_class)

    def reset_point_source_cache(self, cache=True):
        """
        deletes all the cache in the point source class and saves it from then on

        :param cache: boolean, if True, saves the next occuring point source positions in the cache
        :return: None
        """
        self.PointSource.delete_lens_model_cache()
        self.PointSource.set_save_cache(cache)

    def update_psf(self, psf_class):
        """

        update the instance of the class with a new instance of PSF() with a potentially different point spread function

        :param psf_class:
        :return: no return. Class is updated.
        """
        self.PSF = psf_class
        self.PSF.set_pixel_size(self.Data.pixel_width)
        self.ImageNumerics = NumericsSubFrame(pixel_grid=self.Data,
                                              psf=self.PSF,
                                              **self._kwargs_numerics)

    def source_surface_brightness(self,
                                  kwargs_source,
                                  kwargs_lens=None,
                                  kwargs_extinction=None,
                                  kwargs_special=None,
                                  unconvolved=False,
                                  de_lensed=False,
                                  k=None,
                                  update_pixelbased_mapping=True):
        """

        computes the source surface brightness distribution

        :param kwargs_source: list of keyword arguments corresponding to the superposition of different source light profiles
        :param kwargs_lens: list of keyword arguments corresponding to the superposition of different lens profiles
        :param kwargs_extinction: list of keyword arguments of extinction model
        :param unconvolved: if True: returns the unconvolved light distribution (prefect seeing)
        :param de_lensed: if True: returns the un-lensed source surface brightness profile, otherwise the lensed.
        :param k: integer, if set, will only return the model of the specific index
        :return: 2d array of surface brightness pixels
        """
        if len(self.SourceModel.profile_type_list) == 0:
            return np.zeros(self.Data.num_pixel_axes)
        if self._pixelbased_bool is True:
            return self._source_surface_brightness_pixelbased(
                kwargs_source,
                kwargs_lens=kwargs_lens,
                kwargs_extinction=kwargs_extinction,
                kwargs_special=kwargs_special,
                unconvolved=unconvolved,
                de_lensed=de_lensed,
                k=k,
                update_mapping=update_pixelbased_mapping)
        else:
            return self._source_surface_brightness_analytical(
                kwargs_source,
                kwargs_lens=kwargs_lens,
                kwargs_extinction=kwargs_extinction,
                kwargs_special=kwargs_special,
                unconvolved=unconvolved,
                de_lensed=de_lensed,
                k=k)

    def _source_surface_brightness_analytical(self,
                                              kwargs_source,
                                              kwargs_lens=None,
                                              kwargs_extinction=None,
                                              kwargs_special=None,
                                              unconvolved=False,
                                              de_lensed=False,
                                              k=None):
        """

        computes the source surface brightness distribution

        :param kwargs_source: list of keyword arguments corresponding to the superposition of different source light profiles
        :param kwargs_lens: list of keyword arguments corresponding to the superposition of different lens profiles
        :param kwargs_extinction: list of keyword arguments of extinction model
        :param unconvolved: if True: returns the unconvolved light distribution (prefect seeing)
        :param de_lensed: if True: returns the un-lensed source surface brightness profile, otherwise the lensed.
        :param k: integer, if set, will only return the model of the specific index
        :return: 2d array of surface brightness pixels
        """
        ra_grid, dec_grid = self.ImageNumerics.coordinates_evaluate
        if de_lensed is True:
            source_light = self.SourceModel.surface_brightness(ra_grid,
                                                               dec_grid,
                                                               kwargs_source,
                                                               k=k)
        else:
            source_light = self.source_mapping.image_flux_joint(ra_grid,
                                                                dec_grid,
                                                                kwargs_lens,
                                                                kwargs_source,
                                                                k=k)
            source_light *= self._extinction.extinction(
                ra_grid,
                dec_grid,
                kwargs_extinction=kwargs_extinction,
                kwargs_special=kwargs_special)
        source_light_final = self.ImageNumerics.re_size_convolve(
            source_light, unconvolved=unconvolved)
        return source_light_final

    def _source_surface_brightness_pixelbased(self,
                                              kwargs_source,
                                              kwargs_lens=None,
                                              kwargs_extinction=None,
                                              kwargs_special=None,
                                              unconvolved=False,
                                              de_lensed=False,
                                              k=None,
                                              update_mapping=True):
        """
        computes the source surface brightness distribution, using pixel-based solver for light profiles (from SLITronomy)

        :param kwargs_source: list of keyword arguments corresponding to the superposition of different source light profiles
        :param kwargs_lens: list of keyword arguments corresponding to the superposition of different lens profiles
        :param kwargs_extinction: list of keyword arguments of extinction model
        :param unconvolved: if True: returns the unconvolved light distribution (prefect seeing)
        :param de_lensed: if True: returns the un-lensed source surface brightness profile, otherwise the lensed.
        :param k: integer, if set, will only return the model of the specific index
        :param update_mapping: if False, prevent the pixelated lensing mapping to be updated (saves computation time if previously computed). 
        :return: 2d array of surface brightness pixels
        """
        ra_grid, dec_grid = self.SourceNumerics.coordinates_evaluate
        source_light = self.SourceModel.surface_brightness(ra_grid,
                                                           dec_grid,
                                                           kwargs_source,
                                                           k=k)
        if de_lensed is True:
            source_light = self.SourceNumerics.re_size_convolve(
                source_light, unconvolved=unconvolved)
        else:
            source_mapping = self.PixelSolver.lensingOperator
            source_light = source_mapping.source2image(
                source_light,
                kwargs_lens=kwargs_lens,
                kwargs_special=kwargs_special,
                update_mapping=update_mapping,
                original_source_grid=True)
            source_light = self.ImageNumerics.re_size_convolve(
                source_light, unconvolved=unconvolved)
        # undo flux normalization performed by re_size_convolve (already handled in SLITronomy)
        source_light_final = source_light / self.Data.pixel_width**2
        return source_light_final

    def lens_surface_brightness(self,
                                kwargs_lens_light,
                                unconvolved=False,
                                k=None):
        """

        computes the lens surface brightness distribution

        :param kwargs_lens_light: list of keyword arguments corresponding to different lens light surface brightness profiles
        :param unconvolved: if True, returns unconvolved surface brightness (perfect seeing), otherwise convolved with PSF kernel
        :return: 2d array of surface brightness pixels
        """
        if self._pixelbased_bool is True:
            if unconvolved is True:
                raise ValueError(
                    "Lens light pixel-based modelling does not perform deconvolution"
                )
            return self._lens_surface_brightness_pixelbased(kwargs_lens_light,
                                                            k=k)
        else:
            return self._lens_surface_brightness_analytical(
                kwargs_lens_light, unconvolved=unconvolved, k=k)

    def _lens_surface_brightness_analytical(self,
                                            kwargs_lens_light,
                                            unconvolved=False,
                                            k=None):
        """

        computes the lens surface brightness distribution

        :param kwargs_lens_light: list of keyword arguments corresponding to different lens light surface brightness profiles
        :param unconvolved: if True, returns unconvolved surface brightness (perfect seeing), otherwise convolved with PSF kernel
        :return: 2d array of surface brightness pixels
        """
        ra_grid, dec_grid = self.ImageNumerics.coordinates_evaluate
        lens_light = self.LensLightModel.surface_brightness(ra_grid,
                                                            dec_grid,
                                                            kwargs_lens_light,
                                                            k=k)
        lens_light_final = self.ImageNumerics.re_size_convolve(
            lens_light, unconvolved=unconvolved)
        return lens_light_final

    def _lens_surface_brightness_pixelbased(self, kwargs_lens_light, k=None):
        """

        computes the lens surface brightness distribution , using pixel-based solver for light profiles (from SLITronomy)
        Important: SLITronomy does not solve for deconvolved lens light, hence the returned map is convolved with the PSF.

        :param kwargs_lens_light: list of keyword arguments corresponding to different lens light surface brightness profiles
        :return: 2d array of surface brightness pixels
        """
        ra_grid, dec_grid = self.ImageNumerics.coordinates_evaluate
        lens_light = self.LensLightModel.surface_brightness(ra_grid,
                                                            dec_grid,
                                                            kwargs_lens_light,
                                                            k=k)
        lens_light_final = util.array2image(lens_light)
        return lens_light_final

    def point_source(self,
                     kwargs_ps,
                     kwargs_lens=None,
                     kwargs_special=None,
                     unconvolved=False,
                     k=None):
        """

        computes the point source positions and paints PSF convolutions on them

        :param kwargs_ps:
        :param k:
        :return:
        """
        point_source_image = np.zeros((self.Data.num_pixel_axes))
        if unconvolved or self.PointSource is None:
            return point_source_image
        ra_pos, dec_pos, amp = self.PointSource.point_source_list(
            kwargs_ps, kwargs_lens=kwargs_lens, k=k)
        ra_pos, dec_pos = self._displace_astrometry(
            ra_pos, dec_pos, kwargs_special=kwargs_special)
        point_source_image += self.ImageNumerics.point_source_rendering(
            ra_pos, dec_pos, amp)
        return point_source_image

    def image(self,
              kwargs_lens=None,
              kwargs_source=None,
              kwargs_lens_light=None,
              kwargs_ps=None,
              kwargs_extinction=None,
              kwargs_special=None,
              unconvolved=False,
              source_add=True,
              lens_light_add=True,
              point_source_add=True):
        """

        make an image with a realisation of linear parameter values "param"

        :param kwargs_lens: list of keyword arguments corresponding to the superposition of different lens profiles
        :param kwargs_source: list of keyword arguments corresponding to the superposition of different source light profiles
        :param kwargs_lens_light: list of keyword arguments corresponding to different lens light surface brightness profiles
        :param kwargs_ps: keyword arguments corresponding to "other" parameters, such as external shear and point source image positions
        :param unconvolved: if True: returns the unconvolved light distribution (prefect seeing)
        :param source_add: if True, compute source, otherwise without
        :param lens_light_add: if True, compute lens light, otherwise without
        :param point_source_add: if True, add point sources, otherwise without
        :return: 2d array of surface brightness pixels of the simulation
        """
        model = np.zeros((self.Data.num_pixel_axes))
        if source_add is True:
            model += self.source_surface_brightness(
                kwargs_source,
                kwargs_lens,
                kwargs_extinction=kwargs_extinction,
                kwargs_special=kwargs_special,
                unconvolved=unconvolved)
        if lens_light_add is True:
            model += self.lens_surface_brightness(kwargs_lens_light,
                                                  unconvolved=unconvolved)
        if point_source_add is True:
            model += self.point_source(kwargs_ps,
                                       kwargs_lens,
                                       kwargs_special=kwargs_special,
                                       unconvolved=unconvolved)
        return model

    def extinction_map(self, kwargs_extinction=None, kwargs_special=None):
        """
        differential extinction per pixel

        :param kwargs_extinction: list of keyword arguments corresponding to the optical depth models tau, such that extinction is exp(-tau)
        :param kwargs_special: keyword arguments, additional parameter to the extinction
        :return: 2d array of size of the image
        """
        ra_grid, dec_grid = self.ImageNumerics.coordinates_evaluate
        extinction = self._extinction.extinction(
            ra_grid,
            dec_grid,
            kwargs_extinction=kwargs_extinction,
            kwargs_special=kwargs_special)
        extinction_array = np.ones_like(ra_grid) * extinction
        extinction = self.ImageNumerics.re_size_convolve(extinction_array,
                                                         unconvolved=True)
        return extinction

    def _displace_astrometry(self, x_pos, y_pos, kwargs_special=None):
        """
        displaces point sources by shifts specified in kwargs_special

        :param x_pos: list of point source positions according to point source model list
        :param y_pos: list of point source positions according to point source model list
        :param kwargs_special: keyword arguments, can contain 'delta_x_image' and 'delta_y_image'
        The list is defined in order of the image positions
        :return: shifted image positions in same format as input
        """
        if kwargs_special is not None:
            if 'delta_x_image' in kwargs_special:
                delta_x, delta_y = kwargs_special[
                    'delta_x_image'], kwargs_special['delta_y_image']
                delta_x_new = np.zeros(len(x_pos))
                delta_x_new[0:len(delta_x)] = delta_x[:]
                delta_y_new = np.zeros(len(y_pos))
                delta_y_new[0:len(delta_y)] = delta_y
                x_pos = x_pos + delta_x_new
                y_pos = y_pos + delta_y_new
        return x_pos, y_pos

    def _detect_pixelbased_models(self):
        """
        Returns True if light profiles specific to pixel-based modelling are present in source model list.
        Otherwise returns False.

        Currently, pixel-based light profiles are: 'SLIT_STARLETS', 'SLIT_STARLETS_GEN2'.
        """
        source_model_list = self.SourceModel.profile_type_list
        if 'SLIT_STARLETS' in source_model_list or 'SLIT_STARLETS_GEN2' in source_model_list:
            if len(source_model_list) > 1:
                raise ValueError(
                    "'SLIT_STARLETS' or 'SLIT_STARLETS_GEN2' must be the only source model list for pixel-based modelling"
                )
            return True
        return False

    def _setup_pixelbased_source_numerics(self, kwargs_numerics,
                                          kwargs_pixelbased):
        """
        Check if model requirement are compatible with support pixel-based solver,
        and creates a new numerics class specifically for source plane.

        :param kwargs_numerics: keyword argument with various numeric description (see ImageNumerics class for options)
        :param kwargs_pixelbased: keyword argument with various settings related to the pixel-based solver (see SLITronomy documentation)
        """
        # check that the required convolution type is compatible with pixel-based modelling (in current implementation)
        psf_type = self.PSF.psf_type
        supersampling_convolution = kwargs_numerics.get(
            'supersampling_convolution', False)
        supersampling_factor = kwargs_numerics.get('supersampling_factor', 1)
        compute_mode = kwargs_numerics.get('compute_mode', 'regular')
        if psf_type not in ['PIXEL', 'NONE']:
            raise ValueError(
                "Only convolution using a pixelated kernel is supported for pixel-based modelling"
            )
        if compute_mode != 'regular':
            raise ValueError(
                "Only regular coordinate grid is supported for pixel-based modelling"
            )
        if (supersampling_convolution is True and supersampling_factor > 1):
            raise ValueError(
                "Only non-supersampled convolution is supported for pixel-based modelling"
            )

        # setup the source numerics with a (possibily) different supersampling resolution
        supersampling_factor_source = kwargs_pixelbased.pop(
            'supersampling_factor_source', 1)
        kwargs_numerics_source = kwargs_numerics.copy()
        kwargs_numerics_source[
            'supersampling_factor'] = supersampling_factor_source
        kwargs_numerics_source['compute_mode'] = 'regular'
        source_numerics_class = NumericsSubFrame(pixel_grid=self.Data,
                                                 psf=self.PSF,
                                                 **kwargs_numerics_source)
        return source_numerics_class
Exemplo n.º 15
0
    def __init__(self,
                 data_class,
                 psf_class,
                 lens_model_class=None,
                 source_model_class=None,
                 lens_light_model_class=None,
                 point_source_class=None,
                 extinction_class=None,
                 kwargs_numerics=None,
                 kwargs_pixelbased=None):
        """
        :param data_class: instance of ImageData() or PixelGrid() class
        :param psf_class: instance of PSF() class
        :param lens_model_class: instance of LensModel() class
        :param source_model_class: instance of LightModel() class describing the source parameters
        :param lens_light_model_class: instance of LightModel() class describing the lens light parameters
        :param point_source_class: instance of PointSource() class describing the point sources
        :param kwargs_numerics: keyword arguments with various numeric description (see ImageNumerics class for options)
        :param kwargs_pixelbased: keyword arguments with various settings related to the pixel-based solver (see SLITronomy documentation)
        """
        self.type = 'single-band'
        self.num_bands = 1
        self.PSF = psf_class
        self.Data = data_class
        self.PSF.set_pixel_size(self.Data.pixel_width)
        if kwargs_numerics is None:
            kwargs_numerics = {}
        self.ImageNumerics = NumericsSubFrame(pixel_grid=self.Data,
                                              psf=self.PSF,
                                              **kwargs_numerics)
        if lens_model_class is None:
            lens_model_class = LensModel(lens_model_list=[])
        self.LensModel = lens_model_class
        if point_source_class is None:
            point_source_class = PointSource(point_source_type_list=[])
        self.PointSource = point_source_class
        self.PointSource.update_lens_model(lens_model_class=lens_model_class)
        x_center, y_center = self.Data.center
        self.PointSource.update_search_window(
            search_window=np.max(self.Data.width),
            x_center=x_center,
            y_center=y_center,
            min_distance=self.Data.pixel_width,
            only_from_unspecified=True)
        self._psf_error_map = self.PSF.psf_error_map_bool

        if source_model_class is None:
            source_model_class = LightModel(light_model_list=[])
        self.SourceModel = source_model_class
        if lens_light_model_class is None:
            lens_light_model_class = LightModel(light_model_list=[])
        self.LensLightModel = lens_light_model_class
        self._kwargs_numerics = kwargs_numerics
        if extinction_class is None:
            extinction_class = DifferentialExtinction(optical_depth_model=[])
        self._extinction = extinction_class
        if kwargs_pixelbased is None:
            kwargs_pixelbased = {}
        else:
            kwargs_pixelbased = kwargs_pixelbased.copy()
        self._pixelbased_bool = self._detect_pixelbased_models()
        if self._pixelbased_bool is True:
            from slitronomy.Util.class_util import create_solver_class  # requirement on SLITronomy is exclusively here
            self.SourceNumerics = self._setup_pixelbased_source_numerics(
                kwargs_numerics, kwargs_pixelbased)
            self.PixelSolver = create_solver_class(
                self.Data, self.PSF, self.ImageNumerics, self.SourceNumerics,
                self.LensModel, self.SourceModel, self.LensLightModel,
                self.PointSource, self._extinction, kwargs_pixelbased)
            self.source_mapping = None  # handled with pixelated operator
        else:
            self.source_mapping = Image2SourceMapping(
                lensModel=lens_model_class, sourceModel=source_model_class)
Exemplo n.º 16
0
 def test_raise(self):
     with self.assertRaises(ValueError):
         source_model_class = LightModel(['SERSIC'])  # not supported
         lens_light_model_class = LightModel(['SLIT_STARLETS'])
         point_source_class = PointSource(point_source_type_list=[])
         source_numerics_class = NumericsSubFrame(self.imageModel.Data,
                                                  self.imageModel.PSF,
                                                  supersampling_factor=2)
         solver_class = class_util.create_solver_class(
             self.imageModel.Data, self.imageModel.PSF,
             self.imageModel.ImageNumerics, source_numerics_class,
             self.imageModel.LensModel, source_model_class,
             lens_light_model_class, point_source_class,
             self.imageModel._extinction, self.kwargs_sparse_solver)
     with self.assertRaises(ValueError):
         source_model_class = LightModel(['SLIT_STARLETS'])
         lens_light_model_class = LightModel(['SERSIC'])  # not supported
         point_source_class = PointSource(point_source_type_list=[])
         source_numerics_class = NumericsSubFrame(self.imageModel.Data,
                                                  self.imageModel.PSF,
                                                  supersampling_factor=2)
         solver_class = class_util.create_solver_class(
             self.imageModel.Data, self.imageModel.PSF,
             self.imageModel.ImageNumerics, source_numerics_class,
             self.imageModel.LensModel, source_model_class,
             lens_light_model_class, point_source_class,
             self.imageModel._extinction, self.kwargs_sparse_solver)
     with self.assertRaises(ValueError):
         source_model_class = LightModel(['SLIT_STARLETS',
                                          'SLIT_STARLETS'])  # not supported
         lens_light_model_class = LightModel(['SLIT_STARLETS'
                                              ])  # not supported
         point_source_class = PointSource(point_source_type_list=[])
         source_numerics_class = NumericsSubFrame(self.imageModel.Data,
                                                  self.imageModel.PSF,
                                                  supersampling_factor=2)
         solver_class = class_util.create_solver_class(
             self.imageModel.Data, self.imageModel.PSF,
             self.imageModel.ImageNumerics, source_numerics_class,
             self.imageModel.LensModel, source_model_class,
             lens_light_model_class, point_source_class,
             self.imageModel._extinction, self.kwargs_sparse_solver)
     with self.assertRaises(ValueError):
         source_model_class = LightModel(['SLIT_STARLETS'])
         lens_light_model_class = LightModel(
             ['SLIT_STARLETS', 'SLIT_STARLETS'])  # not supported
         point_source_class = PointSource(point_source_type_list=[])
         source_numerics_class = NumericsSubFrame(self.imageModel.Data,
                                                  self.imageModel.PSF,
                                                  supersampling_factor=2)
         solver_class = class_util.create_solver_class(
             self.imageModel.Data, self.imageModel.PSF,
             self.imageModel.ImageNumerics, source_numerics_class,
             self.imageModel.LensModel, source_model_class,
             lens_light_model_class, point_source_class,
             self.imageModel._extinction, self.kwargs_sparse_solver)
     with self.assertRaises(ValueError):
         source_model_class = LightModel([])  # not supported
         lens_light_model_class = LightModel(['SLIT_STARLETS'])
         point_source_class = PointSource(point_source_type_list=[])
         source_numerics_class = NumericsSubFrame(self.imageModel.Data,
                                                  self.imageModel.PSF,
                                                  supersampling_factor=2)
         solver_class = class_util.create_solver_class(
             self.imageModel.Data, self.imageModel.PSF,
             self.imageModel.ImageNumerics, source_numerics_class,
             self.imageModel.LensModel, source_model_class,
             lens_light_model_class, point_source_class,
             self.imageModel._extinction, self.kwargs_sparse_solver)
     with self.assertRaises(NotImplementedError):
         # ask for source + point sources: no more supported temporarily
         source_model_class = LightModel(['SLIT_STARLETS'])
         lens_light_model_class = LightModel([])
         point_source_class = PointSource(
             point_source_type_list=['SOURCE_POSITION'])
         source_numerics_class = NumericsSubFrame(self.imageModel.Data,
                                                  self.imageModel.PSF,
                                                  supersampling_factor=2)
         solver_class = class_util.create_solver_class(
             self.imageModel.Data, self.imageModel.PSF,
             self.imageModel.ImageNumerics, source_numerics_class,
             self.imageModel.LensModel, source_model_class,
             lens_light_model_class, point_source_class,
             self.imageModel._extinction, self.kwargs_sparse_solver)
     with self.assertRaises(NotImplementedError):
         # ask for source + lens light + point sources: not supported
         source_model_class = LightModel(['SLIT_STARLETS'])
         lens_light_model_class = LightModel(['SLIT_STARLETS'])
         point_source_class = PointSource(
             point_source_type_list=['SOURCE_POSITION'])
         source_numerics_class = NumericsSubFrame(self.imageModel.Data,
                                                  self.imageModel.PSF,
                                                  supersampling_factor=2)
         solver_class = class_util.create_solver_class(
             self.imageModel.Data, self.imageModel.PSF,
             self.imageModel.ImageNumerics, source_numerics_class,
             self.imageModel.LensModel, source_model_class,
             lens_light_model_class, point_source_class,
             self.imageModel._extinction, self.kwargs_sparse_solver)
Exemplo n.º 17
0
    def setup(self):
        self.num_pix = 49  # cutout pixel size
        self.subgrid_res_source = 2
        self.num_pix_source = self.num_pix * self.subgrid_res_source
        self.background_rms = 0.05
        self.noise_map = self.background_rms * np.ones(
            (self.num_pix, self.num_pix))

        delta_pix = 0.24
        _, _, ra_at_xy_0, dec_at_xy_0, _, _, Mpix2coord, _ \
            = l_util.make_grid_with_coordtransform(numPix=self.num_pix, deltapix=delta_pix, subgrid_res=1,
                                                         inverse=False, left_lower=False)

        self.image_data = np.random.rand(self.num_pix, self.num_pix)
        kwargs_data = {
            'ra_at_xy_0': ra_at_xy_0,
            'dec_at_xy_0': dec_at_xy_0,
            'transform_pix2angle': Mpix2coord,
            'image_data': self.image_data,
            'background_rms': self.background_rms,
            'noise_map': self.noise_map,
        }
        data = ImageData(**kwargs_data)

        gaussian_func = Gaussian()
        x, y = l_util.make_grid(41, 1)
        gaussian = gaussian_func.function(x,
                                          y,
                                          amp=1,
                                          sigma=0.02,
                                          center_x=0,
                                          center_y=0)
        self.psf_kernel = gaussian / gaussian.sum()

        lens_model = LensModel(['SPEP'])
        self.kwargs_lens = [{
            'theta_E': 1,
            'gamma': 2,
            'center_x': 0,
            'center_y': 0,
            'e1': -0.05,
            'e2': 0.05
        }]

        # wavelets scales for lens and source
        self.n_scales_source = 4
        self.n_scales_lens = 3

        # list of source light profiles
        self.source_model = LightModel(['SLIT_STARLETS'])
        self.kwargs_source = [{'n_scales': self.n_scales_source}]

        # list of lens light profiles
        self.lens_light_model = LightModel(['SLIT_STARLETS'])
        self.kwargs_lens_light = [{'n_scales': self.n_scales_lens}]

        # get grid classes
        image_grid_class = NumericsSubFrame(data, PSF('NONE')).grid_class
        source_grid_class = NumericsSubFrame(
            data, PSF('NONE'),
            supersampling_factor=self.subgrid_res_source).grid_class

        # get a lensing operator
        self.lensing_op = LensingOperator(lens_model, image_grid_class,
                                          source_grid_class, self.num_pix)

        self.noise_class = NoiseLevels(
            data,
            subgrid_res_source=self.subgrid_res_source,
            include_regridding_error=False)
        self.noise_class_regrid = NoiseLevels(
            data,
            subgrid_res_source=self.subgrid_res_source,
            include_regridding_error=True)
Exemplo n.º 18
0
def test_supersampling_simple():
    """

    :return:
    """
    from lenstronomy.Data.psf import PSF
    from lenstronomy.SimulationAPI.data_api import DataAPI

    detector_pixel_scale = 0.04
    numpix = 64
    supersampling_factor = 2
    # generate a Gaussian image

    x, y = util.make_grid(numPix=numpix * supersampling_factor,
                          deltapix=detector_pixel_scale / supersampling_factor)
    from lenstronomy.LightModel.Profiles.gaussian import Gaussian
    gaussian = Gaussian()
    image_1d = gaussian.function(x, y, amp=1, sigma=0.1)
    image = util.array2image(image_1d)

    # generate psf kernal supersampled
    kernel_super = kernel_util.kernel_gaussian(
        kernel_numPix=21 * supersampling_factor + 1,
        deltaPix=detector_pixel_scale / supersampling_factor,
        fwhm=0.2)

    psf_parameters = {
        'psf_type': 'PIXEL',
        'kernel_point_source': kernel_super,
        'point_source_supersampling_factor': supersampling_factor
    }
    kwargs_detector = {
        'pixel_scale': detector_pixel_scale,
        'ccd_gain': 2.5,
        'read_noise': 4.0,
        'magnitude_zero_point': 25.0,
        'exposure_time': 5400.0,
        'sky_brightness': 22,
        'num_exposures': 1,
        'background_noise': None
    }
    kwargs_numerics = {
        'supersampling_factor': 2,
        'supersampling_convolution': True,
        'point_source_supersampling_factor': 2,
        'supersampling_kernel_size': 21
    }
    psf_model = PSF(**psf_parameters)
    data_class = DataAPI(numpix=numpix, **kwargs_detector).data_class

    from lenstronomy.ImSim.Numerics.numerics_subframe import NumericsSubFrame
    image_numerics = NumericsSubFrame(pixel_grid=data_class,
                                      psf=psf_model,
                                      **kwargs_numerics)

    conv_class = image_numerics.convolution_class
    conv_flat = conv_class.convolution2d(image)
    print(np.shape(conv_flat), 'shape of output')

    # psf_helper = lenstronomy_utils.PSFHelper(data_class, psf_model, kwargs_numerics)

    # Convolve with lenstronomy and with scipy
    # helper_image = psf_helper.psf_model(image)
    from scipy import signal

    scipy_image = signal.fftconvolve(image, kernel_super, mode='same')
    from lenstronomy.Util import image_util
    image_scipy_resized = image_util.re_size(scipy_image, supersampling_factor)
    image_unconvolved = image_util.re_size(image, supersampling_factor)

    # Compare the outputs

    # low res convolution as comparison
    kwargs_numerics_low_res = {
        'supersampling_factor': 2,
        'supersampling_convolution': False,
        'point_source_supersampling_factor': 2,
    }
    image_numerics_low_res = NumericsSubFrame(pixel_grid=data_class,
                                              psf=psf_model,
                                              **kwargs_numerics_low_res)
    conv_class_low_res = image_numerics_low_res.convolution_class
    conv_flat_low_res = conv_class_low_res.convolution2d(image_unconvolved)

    #import matplotlib.pyplot as plt
    #plt.matshow(image_scipy_resized - image_unconvolved)
    #plt.colorbar()
    #plt.show()

    #plt.matshow(image_scipy_resized - conv_flat)
    #plt.colorbar()
    #plt.show()

    #plt.matshow(image_scipy_resized - conv_flat_low_res)
    #plt.colorbar()
    #plt.show()

    np.testing.assert_almost_equal(conv_flat, image_scipy_resized)
Exemplo n.º 19
0
    def setup(self):
        self.num_pix = 20  # cutout pixel size
        delta_pix = 0.2
        _, _, ra_at_xy_0, dec_at_xy_0, _, _, Mpix2coord, _ \
            = l_util.make_grid_with_coordtransform(numPix=self.num_pix, deltapix=delta_pix, subgrid_res=1,
                                                   inverse=False, left_lower=False)
        # imaging data class
        gaussian = Gaussian()
        x, y = l_util.make_grid(self.num_pix, 1)
        gaussian1 = gaussian.function(x,
                                      y,
                                      amp=5,
                                      sigma=1,
                                      center_x=-7,
                                      center_y=-7)
        gaussian2 = gaussian.function(x,
                                      y,
                                      amp=20,
                                      sigma=2,
                                      center_x=-3,
                                      center_y=-3)
        gaussian3 = gaussian.function(x,
                                      y,
                                      amp=60,
                                      sigma=4,
                                      center_x=+5,
                                      center_y=+5)
        image_data = util.array2image(gaussian1 + gaussian2 + gaussian3)
        background_rms = 0.1
        image_data += background_rms * np.random.randn(self.num_pix,
                                                       self.num_pix)
        kwargs_data = {
            'ra_at_xy_0': ra_at_xy_0,
            'dec_at_xy_0': dec_at_xy_0,
            'transform_pix2angle': Mpix2coord,
            'image_data': image_data,
            'background_rms': background_rms,
            'noise_map': background_rms * np.ones_like(image_data),
        }
        data_class = ImageData(**kwargs_data)

        # lens mass class
        lens_model_class = LensModel(['SPEP'])
        self.kwargs_lens = [{
            'theta_E': 1,
            'gamma': 2,
            'center_x': 0,
            'center_y': 0,
            'e1': -0.05,
            'e2': 0.05
        }]

        # source light class
        source_model_class = LightModel(['SLIT_STARLETS'])
        self.kwargs_source = [{
            'coeffs': 0,
            'n_scales': 3,
            'n_pixels': self.num_pix**2
        }]

        # define numerics classes
        image_numerics_class = NumericsSubFrame(pixel_grid=data_class,
                                                psf=PSF(psf_type='NONE'))
        source_numerics_class = NumericsSubFrame(pixel_grid=data_class,
                                                 psf=PSF(psf_type='NONE'),
                                                 supersampling_factor=1)

        # init sparse solver
        self.solver = SparseSolverSource(data_class,
                                         lens_model_class,
                                         image_numerics_class,
                                         source_numerics_class,
                                         source_model_class,
                                         num_iter_source=10)

        # init the plotter
        self.plotter = SolverPlotter(self.solver, show_now=False)
Exemplo n.º 20
0
class ImageModel(object):
    """
    this class uses functions of lens_model and source_model to make a lensed image
    """
    def __init__(self,
                 data_class,
                 psf_class,
                 lens_model_class=None,
                 source_model_class=None,
                 lens_light_model_class=None,
                 point_source_class=None,
                 extinction_class=None,
                 kwargs_numerics={}):
        """
        :param data_class: instance of ImageData() or PixelGrid() class
        :param psf_class: instance of PSF() class
        :param lens_model_class: instance of LensModel() class
        :param source_model_class: instance of LightModel() class describing the source parameters
        :param lens_light_model_class: instance of LightModel() class describing the lens light parameters
        :param point_source_class: instance of PointSource() class describing the point sources
        :param kwargs_numerics: keyword argument with various numeric description (see ImageNumerics class for options)
        """
        self.type = 'single-band'
        self.PSF = psf_class
        self.Data = data_class
        self.PSF.set_pixel_size(self.Data.pixel_width)
        self.ImageNumerics = NumericsSubFrame(pixel_grid=self.Data,
                                              psf=self.PSF,
                                              **kwargs_numerics)
        if lens_model_class is None:
            lens_model_class = LensModel(lens_model_list=[])
        self.LensModel = lens_model_class
        if point_source_class is None:
            point_source_class = PointSource(point_source_type_list=[])
        self.PointSource = point_source_class
        self.PointSource.update_lens_model(lens_model_class=lens_model_class)
        x_center, y_center = self.Data.center
        self.PointSource.update_search_window(
            search_window=np.max(self.Data.width),
            x_center=x_center,
            y_center=y_center,
            min_distance=self.Data.pixel_width)
        self._psf_error_map = self.PSF.psf_error_map_bool

        if source_model_class is None:
            source_model_class = LightModel(light_model_list=[])
        self.SourceModel = source_model_class
        if lens_light_model_class is None:
            lens_light_model_class = LightModel(light_model_list=[])
        self.LensLightModel = lens_light_model_class
        self.source_mapping = Image2SourceMapping(
            lensModel=lens_model_class, sourceModel=source_model_class)
        self.num_bands = 1
        self._kwargs_numerics = kwargs_numerics
        if extinction_class is None:
            extinction_class = DifferentialExtinction(optical_depth_model=[])
        self._extinction = extinction_class

    def reset_point_source_cache(self, bool=True):
        """
        deletes all the cache in the point source class and saves it from then on

        :param bool: boolean, if True, saves the next occuring point source positions in the cache
        :return: None
        """
        self.PointSource.delete_lens_model_cache()
        self.PointSource.set_save_cache(bool)

    def update_psf(self, psf_class):
        """

        update the instance of the class with a new instance of PSF() with a potentially different point spread function

        :param psf_class:
        :return: no return. Class is updated.
        """
        self.PSF = psf_class
        self.PSF.set_pixel_size(self.Data.pixel_width)
        self.ImageNumerics = NumericsSubFrame(pixel_grid=self.Data,
                                              psf=self.PSF,
                                              **self._kwargs_numerics)

    def source_surface_brightness(self,
                                  kwargs_source,
                                  kwargs_lens=None,
                                  kwargs_extinction=None,
                                  kwargs_special=None,
                                  unconvolved=False,
                                  de_lensed=False,
                                  k=None):
        """

        computes the source surface brightness distribution

        :param kwargs_source: list of keyword arguments corresponding to the superposition of different source light profiles
        :param kwargs_lens: list of keyword arguments corresponding to the superposition of different lens profiles
        :param kwargs_extinction: list of keyword arguments of extinction model
        :param unconvolved: if True: returns the unconvolved light distribution (prefect seeing)
        :param de_lensed: if True: returns the un-lensed source surface brightness profile, otherwise the lensed.
        :param k: integer, if set, will only return the model of the specific index
        :return: 1d array of surface brightness pixels
        """
        if len(self.SourceModel.profile_type_list) == 0:
            return np.zeros((self.Data.num_pixel_axes))
        ra_grid, dec_grid = self.ImageNumerics.coordinates_evaluate
        if de_lensed is True:
            source_light = self.SourceModel.surface_brightness(ra_grid,
                                                               dec_grid,
                                                               kwargs_source,
                                                               k=k)
        else:
            source_light = self.source_mapping.image_flux_joint(ra_grid,
                                                                dec_grid,
                                                                kwargs_lens,
                                                                kwargs_source,
                                                                k=k)
            source_light *= self._extinction.extinction(
                ra_grid,
                dec_grid,
                kwargs_extinction=kwargs_extinction,
                kwargs_special=kwargs_special)
        source_light_final = self.ImageNumerics.re_size_convolve(
            source_light, unconvolved=unconvolved)
        return source_light_final

    def lens_surface_brightness(self,
                                kwargs_lens_light,
                                unconvolved=False,
                                k=None):
        """

        computes the lens surface brightness distribution

        :param kwargs_lens_light: list of keyword arguments corresponding to different lens light surface brightness profiles
        :param unconvolved: if True, returns unconvolved surface brightness (perfect seeing), otherwise convolved with PSF kernel
        :return: 1d array of surface brightness pixels
        """
        ra_grid, dec_grid = self.ImageNumerics.coordinates_evaluate
        lens_light = self.LensLightModel.surface_brightness(ra_grid,
                                                            dec_grid,
                                                            kwargs_lens_light,
                                                            k=k)
        lens_light_final = self.ImageNumerics.re_size_convolve(
            lens_light, unconvolved=unconvolved)
        return lens_light_final

    def point_source(self,
                     kwargs_ps,
                     kwargs_lens=None,
                     kwargs_special=None,
                     unconvolved=False,
                     k=None):
        """

        computes the point source positions and paints PSF convolutions on them

        :param kwargs_ps:
        :param k:
        :return:
        """
        point_source_image = np.zeros((self.Data.num_pixel_axes))
        if unconvolved or self.PointSource is None:
            return point_source_image
        ra_pos, dec_pos, amp, n_points = self.PointSource.linear_response_set(
            kwargs_ps, kwargs_lens, with_amp=True, k=k)
        for i in range(n_points):
            point_source_image += self.ImageNumerics.point_source_rendering(
                ra_pos[i], dec_pos[i], amp[i])
        return point_source_image

    def image(self,
              kwargs_lens=None,
              kwargs_source=None,
              kwargs_lens_light=None,
              kwargs_ps=None,
              kwargs_extinction=None,
              kwargs_special=None,
              unconvolved=False,
              source_add=True,
              lens_light_add=True,
              point_source_add=True):
        """

        make an image with a realisation of linear parameter values "param"

        :param kwargs_lens: list of keyword arguments corresponding to the superposition of different lens profiles
        :param kwargs_source: list of keyword arguments corresponding to the superposition of different source light profiles
        :param kwargs_lens_light: list of keyword arguments corresponding to different lens light surface brightness profiles
        :param kwargs_ps: keyword arguments corresponding to "other" parameters, such as external shear and point source image positions
        :param unconvolved: if True: returns the unconvolved light distribution (prefect seeing)
        :param source_add: if True, compute source, otherwise without
        :param lens_light_add: if True, compute lens light, otherwise without
        :param point_source_add: if True, add point sources, otherwise without
        :return: 1d array of surface brightness pixels of the simulation
        """
        model = np.zeros((self.Data.num_pixel_axes))
        if source_add is True:
            model += self.source_surface_brightness(
                kwargs_source,
                kwargs_lens,
                kwargs_extinction=kwargs_extinction,
                kwargs_special=kwargs_special,
                unconvolved=unconvolved)
        if lens_light_add is True:
            model += self.lens_surface_brightness(kwargs_lens_light,
                                                  unconvolved=unconvolved)
        if point_source_add is True:
            model += self.point_source(kwargs_ps,
                                       kwargs_lens,
                                       kwargs_special=kwargs_special,
                                       unconvolved=unconvolved)
        return model

    def extinction_map(self, kwargs_extinction=None, kwargs_special=None):
        """
        differential extinction per pixel

        :param kwargs_extinction: list of keyword arguments corresponding to the optical depth models tau, such that extinction is exp(-tau)
        :param kwargs_special: keyword arguments, additional parameter to the extinction
        :return: 2d array of size of the image
        """
        ra_grid, dec_grid = self.ImageNumerics.coordinates_evaluate
        extinction = self._extinction.extinction(
            ra_grid,
            dec_grid,
            kwargs_extinction=kwargs_extinction,
            kwargs_special=kwargs_special)
        extinction_array = np.ones_like(ra_grid) * extinction
        extinction = self.ImageNumerics.re_size_convolve(extinction_array,
                                                         unconvolved=True)
        return extinction
Exemplo n.º 21
0
    def setup(self):
        self.num_pix = 49  # cutout pixel size
        self.subgrid_res_source = 2
        self.num_pix_source = self.num_pix * self.subgrid_res_source

        delta_pix = 0.24
        _, _, ra_at_xy_0, dec_at_xy_0, _, _, Mpix2coord, _ \
            = l_util.make_grid_with_coordtransform(numPix=self.num_pix, deltapix=delta_pix, subgrid_res=1,
                                                         inverse=False, left_lower=False)

        self.image_data = np.random.rand(self.num_pix, self.num_pix)
        kwargs_data = {
            'ra_at_xy_0': ra_at_xy_0,
            'dec_at_xy_0': dec_at_xy_0,
            'transform_pix2angle': Mpix2coord,
            'image_data': self.image_data,
        }
        data = ImageData(**kwargs_data)

        lens_model = LensModel(['SPEP'])
        kwargs_lens = [{
            'theta_E': 1,
            'gamma': 2,
            'center_x': 0,
            'center_y': 0,
            'e1': -0.05,
            'e2': 0.05
        }]

        # PSF
        kernel_pixel = np.zeros((self.num_pix, self.num_pix))
        kernel_pixel[int(self.num_pix / 2),
                     int(self.num_pix / 2)] = 1  # just a dirac here
        kwargs_psf = {'psf_type': 'PIXEL', 'kernel_point_source': kernel_pixel}
        psf = PSF(**kwargs_psf)

        # wavelets scales for lens and source
        self.n_scales_source = 4
        self.n_scales_lens = 3

        # list of source light profiles
        source_model = LightModel(['SLIT_STARLETS'])
        self.kwargs_source = [{'n_scales': self.n_scales_source}]

        # list of lens light profiles
        lens_light_model = LightModel(['SLIT_STARLETS'])
        self.kwargs_lens_light = [{'n_scales': self.n_scales_lens}]

        # define some mask
        likelihood_mask = np.ones((self.num_pix, self.num_pix))

        # get grid classes
        self.numerics = NumericsSubFrame(data, psf)
        image_grid_class = self.numerics.grid_class
        source_numerics = NumericsSubFrame(
            data, psf, supersampling_factor=self.subgrid_res_source)
        source_grid_class = source_numerics.grid_class

        # get a lensing operator
        self.lensing_op = LensingOperator(lens_model, image_grid_class,
                                          source_grid_class, self.num_pix)
        self.lensing_op.update_mapping(kwargs_lens)

        self.model_op = ModelOperators(data, self.lensing_op, self.numerics)
        self.model_op._set_likelihood_mask(likelihood_mask)
        self.model_op.add_source_light(source_model)
        self.model_op.add_lens_light(lens_light_model)
        self.model_op_nolens = ModelOperators(data, self.lensing_op,
                                              self.numerics)
        self.model_op_nolens._set_likelihood_mask(likelihood_mask)
        self.model_op_nolens.add_source_light(source_model)

        # define some test images in direct space
        self.X_s = np.random.rand(self.num_pix_source,
                                  self.num_pix_source)  # source light
        self.X_l = np.random.rand(self.num_pix, self.num_pix)  # lens light

        # define some test images in wavelets space
        self.alpha_s = np.random.rand(self.n_scales_source,
                                      self.num_pix_source,
                                      self.num_pix_source)  # source light
        self.alpha_l = np.random.rand(self.n_scales_lens, self.num_pix,
                                      self.num_pix)  # lens light
Exemplo n.º 22
0
    def setup(self):
        self.num_pix = 25  # cutout pixel size
        delta_pix = 0.24
        _, _, ra_at_xy_0, dec_at_xy_0, _, _, Mpix2coord, _ \
            = l_util.make_grid_with_coordtransform(numPix=self.num_pix, deltapix=delta_pix, subgrid_res=1,
                                                   inverse=False, left_lower=False)
        kwargs_data = {
            #'background_rms': background_rms,
            #'exposure_time': np.ones((self.num_pix, self.num_pix)) * exp_time,  # individual exposure time/weight per pixel
            'ra_at_xy_0': ra_at_xy_0,
            'dec_at_xy_0': dec_at_xy_0,
            'transform_pix2angle': Mpix2coord,
            'image_data': np.zeros((self.num_pix, self.num_pix))
        }
        self.data = ImageData(**kwargs_data)

        self.lens_model = LensModel(['SPEP'])
        self.kwargs_lens = [{
            'theta_E': 1,
            'gamma': 2,
            'center_x': 0,
            'center_y': 0,
            'e1': -0.05,
            'e2': 0.05
        }]
        self.kwargs_lens_null = [{
            'theta_E': 0,
            'gamma': 2,
            'center_x': 0,
            'center_y': 0,
            'e1': 0,
            'e2': 0
        }]

        # PSF specification
        kwargs_psf = {'psf_type': 'NONE'}
        self.psf = PSF(**kwargs_psf)

        # list of source light profiles
        source_model_list = ['SERSIC_ELLIPSE']
        kwargs_sersic_ellipse_source = {
            'amp': 2000,
            'R_sersic': 0.6,
            'n_sersic': 1,
            'e1': 0.1,
            'e2': 0.1,
            'center_x': 0.3,
            'center_y': 0.3
        }
        kwargs_source = [kwargs_sersic_ellipse_source]
        source_model = LightModel(light_model_list=source_model_list)

        # list of lens light profiles
        lens_light_model_list = []
        kwargs_lens_light = [{}]
        lens_light_model = LightModel(light_model_list=lens_light_model_list)

        kwargs_numerics = {
            'supersampling_factor': 1,
            'supersampling_convolution': False
        }
        self.image_model = ImageModel(self.data,
                                      self.psf,
                                      self.lens_model,
                                      source_model,
                                      lens_light_model,
                                      point_source_class=None,
                                      kwargs_numerics=kwargs_numerics)
        self.image_grid_class = self.image_model.ImageNumerics.grid_class
        self.source_grid_class_default = NumericsSubFrame(self.data,
                                                          self.psf).grid_class

        # create simulated image
        image_sim_no_noise = self.image_model.image(self.kwargs_lens,
                                                    kwargs_source,
                                                    kwargs_lens_light)
        self.source_light_lensed = image_sim_no_noise
        self.data.update_data(image_sim_no_noise)

        # source only, in source plane, on same grid as data
        self.source_light_delensed = self.image_model.source_surface_brightness(
            kwargs_source, unconvolved=False, de_lensed=True)

        # define some auto mask for tests
        self.likelihood_mask = np.zeros_like(self.source_light_lensed)
        self.likelihood_mask[self.source_light_lensed > 0.1 *
                             self.source_light_lensed.max()] = 1