Пример #1
0
    def psf_configure(self, psf_type="GAUSSIAN", fwhm=1, kernelsize=11, deltaPix=1, truncate=6, kernel=None):
        """

        :param psf_type:
        :param fwhm:
        :param pixel_grid:
        :return:
        """
        # psf_type: 'NONE', 'gaussian', 'pixel'
        # 'pixel': kernel, kernel_large
        # 'gaussian': 'sigma', 'truncate'
        if psf_type == 'GAUSSIAN':
            sigma = util.fwhm2sigma(fwhm)
            sigma_axis = sigma
            x_grid, y_grid = util.make_grid(kernelsize, deltaPix)
            kernel_large = self.gaussian.function(x_grid, y_grid, amp=1., sigma_x=sigma_axis, sigma_y=sigma_axis, center_x=0, center_y=0)
            kernel_large /= np.sum(kernel_large)
            kernel_large = util.array2image(kernel_large)
            kernel_pixel = kernel_util.pixel_kernel(kernel_large)
            kwargs_psf = {'psf_type': psf_type, 'fwhm': fwhm, 'truncation': truncate*fwhm, 'kernel_point_source': kernel_large, 'kernel_pixel': kernel_pixel, 'pixel_size': deltaPix}
        elif psf_type == 'PIXEL':
            kernel_large = copy.deepcopy(kernel)
            kernel_large = kernel_util.cut_psf(kernel_large, psf_size=kernelsize)
            kernel_small = copy.deepcopy(kernel)
            kernel_small = kernel_util.cut_psf(kernel_small, psf_size=kernelsize)
            kwargs_psf = {'psf_type': "PIXEL", 'kernel_pixel': kernel_small, 'kernel_point_source': kernel_large}
        elif psf_type == 'NONE':
            kwargs_psf = {'psf_type': 'NONE'}
        else:
            raise ValueError("psf type %s not supported!" % psf_type)
        psf_class = PSF(kwargs_psf)
        return psf_class
Пример #2
0
    def update_psf(self, kwargs_psf, kwargs_lens, kwargs_source, kwargs_lens_light, kwargs_ps, factor=1, symmetry=1):
        """

        :param kwargs_data:
        :param kwargs_psf:
        :param kwargs_options:
        :param kwargs_lens:
        :param kwargs_source:
        :param kwargs_lens_light:
        :param kwargs_ps:
        :return:
        """
        psf_class = PSF(kwargs_psf)
        self._image_model_class.update_psf(psf_class)
        self._image_model_class.update_numerics(self._kwargs_numerics)

        kernel_old = psf_class.kernel_point_source
        kernel_small = psf_class.kernel_pixel
        kernel_size = len(kernel_old)
        kernelsize_small = len(kernel_small)
        kwargs_numerics_psf = copy.deepcopy(self._kwargs_numerics)
        kwargs_numerics_psf['psf_error_map'] = False
        self._image_model_class.update_numerics(kwargs_numerics_psf)
        image_single_point_source_list = self.image_single_point_source(self._image_model_class, kwargs_lens, kwargs_source, kwargs_lens_light, kwargs_ps)
        ra_image, dec_image, amp = self._image_model_class.PointSource.point_source_list(kwargs_ps, kwargs_lens)
        x_, y_ = self._image_model_class.Data.map_coord2pix(ra_image, dec_image)
        mask = self._image_model_class.ImageNumerics.mask
        x_grid, y_grid = self._image_model_class.Data.coordinates
        deltaPix = self._image_model_class.Data.deltaPix
        #fwhm = self._image_model_class.PSF.psf_fwhm(kwargs_psf, deltaPix)
        radius = kwargs_psf.get("block_neighbour", 0.) / 2.
        mask_point_source_list = self.mask_point_sources(ra_image, dec_image, x_grid, y_grid, radius)
        point_source_list = self.cutout_psf(x_, y_, image_single_point_source_list, kernel_size, mask, mask_point_source_list, kernel_old, symmetry=symmetry)
        kernel_old_array = np.zeros((symmetry, kernel_size, kernel_size))
        for i in range(symmetry):
            kernel_old_array[i, :, :] = kernel_old
        kernel_new, error_map = self.combine_psf(point_source_list, kernel_old_array,
                                                 sigma_bkg=self._image_model_class.Data.background_rms, factor=factor)
        kernel_new_small = copy.deepcopy(kernel_new)
        kernel_new_small = kernel_util.pixel_kernel(kernel_new_small, subgrid_res=3)
        kernel_new_small = kernel_util.cut_psf(kernel_new_small, psf_size=kernelsize_small)
        kernel_new = kernel_util.cut_psf(kernel_new, psf_size=kernel_size)
        kwargs_psf_new = copy.deepcopy(kwargs_psf)
        if not self._kwargs_numerics.get('psf_keep_small', False):
            kwargs_psf_new['kernel_pixel'] = kernel_new_small
        kwargs_psf_new['kernel_point_source'] = kernel_new

        self._image_model_class.update_psf(PSF(kwargs_psf_new))
        self._image_model_class.update_numerics(self._kwargs_numerics)
        logL_after = self._image_model_class.likelihood_data_given_model(kwargs_lens, kwargs_source,
                                                               kwargs_lens_light, kwargs_ps)
        if not self._kwargs_numerics.get('psf_keep_error_map', False):
            kwargs_psf_new['psf_error_map'] = error_map
        return kwargs_psf_new, logL_after
Пример #3
0
    def subgrid_point_source_kernel(self, subgrid_res):
        """

        :return:
        """
        if hasattr(self, '_kernel_point_source_subsampled'
                   ) and self._point_source_subsampling_factor == subgrid_res:
            pass
        else:
            kernel = kernel_util.subgrid_kernel(self.kernel_point_source,
                                                subgrid_res,
                                                odd=True,
                                                num_iter=5)
            n = len(self.kernel_point_source)
            n_new = n * subgrid_res
            if n_new % 2 == 0:
                n_new -= 1
            if hasattr(self, '_kernel_point_source_subsampled'):
                print(
                    "Warning: subsampled point source kernel overwritten due to different subsampling size requested."
                )
            self._kernel_point_source_subsampled = kernel_util.cut_psf(
                kernel, psf_size=n_new)
            self._point_source_subsampling_factor = subgrid_res
        return self._kernel_point_source_subsampled
Пример #4
0
    def subgrid_point_source_kernel(self, subgrid_res):
        """

        :return:
        """
        if hasattr(self, '_kernel_point_source_subsampled') and self._point_source_subsampling_factor == subgrid_res:
            pass
        else:
            if self.psf_type == 'GAUSSIAN':
                kernel_numPix = self._truncation / self._pixel_size * subgrid_res
                kernel_numPix = int(round(kernel_numPix))
                if kernel_numPix % 2 == 0:
                    kernel_numPix += 1
                self._kernel_point_source_subsampled = kernel_util.kernel_gaussian(kernel_numPix, self._pixel_size/subgrid_res, self._fwhm)
            elif self.psf_type == 'PIXEL':
                kernel = kernel_util.subgrid_kernel(self.kernel_point_source, subgrid_res, odd=True, num_iter=5)
                n = len(self.kernel_point_source)
                n_new = n * subgrid_res
                if n_new % 2 == 0:
                    n_new -= 1
                if hasattr(self, '_kernel_point_source_subsampled'):
                    print("Warning: subsampled point source kernel overwritten due to different subsampling size requested.")
                self._kernel_point_source_subsampled = kernel_util.cut_psf(kernel, psf_size=n_new)
                self._point_source_subsampling_factor = subgrid_res
        return self._kernel_point_source_subsampled
Пример #5
0
    def subgrid_pixel_kernel(self, subgrid_res):
        """

        :return:
        """
        if hasattr(self, '_kernel_pixel_subsampled'
                   ) and self._pixel_subsampling_factor == subgrid_res:
            pass
        elif hasattr(self, '_kernel_point_source_subsampled'):
            # if the subsampling scale matches the one from the point source - take it!
            if self._point_source_subsampling_factor == subgrid_res:
                self._kernel_pixel_subsampled = self._kernel_point_source_subsampled
                self._pixel_subsampling_factor = self._point_source_subsampling_factor
        else:
            kernel = kernel_util.subgrid_kernel(self.kernel_point_source,
                                                subgrid_res,
                                                odd=True,
                                                num_iter=5)
            n = len(self.kernel_pixel)
            n_new = n * subgrid_res
            if n_new % 2 == 0:
                n_new -= 1
            self._kernel_pixel_subsampled = kernel_util.cut_psf(kernel,
                                                                psf_size=n_new)
            self._pixel_subsampling_factor = subgrid_res
        return self._kernel_pixel_subsampled
Пример #6
0
def instantiate_PSF_kwargs(psf_type, pixel_scale, seeing, kernel_size, which_psf_maps):
    """Instantiate PSF kwargs by reading in template PSF maps

    Parameters
    ----------
    psf_config : dict
        copy of the PSF config
    pixel_scale : float
        pixel scale in arcsec/pix

    Returns
    -------
    dict
        dict with lenstronomy psf kwargs

    """
    if psf_type == 'PIXEL':
        psf_kwargs = []
        psf_id_list = which_psf_maps
        random_psf_id = psf_id_list[np.random.randint(len(psf_id_list))]
        psf_path = resource_filename('baobab.in_data', 'psf_maps/psf_{:d}.fits'.format(random_psf_id))
        psf_map = pyfits.getdata(psf_path)
        kernel_cut = kernel_util.cut_psf(psf_map, kernel_size)
        psf_kwargs = {'psf_type': 'PIXEL', 'pixel_size': pixel_scale, 'kernel_point_source': kernel_cut}
        return psf_kwargs
    elif psf_type == 'GAUSSIAN':
        psf_kwargs = {'psf_type': 'GAUSSIAN', 'fwhm': seeing, 'pixel_size': pixel_scale}
        return psf_kwargs
    else:
        return {'psf_type': 'NONE'}
Пример #7
0
    def pixel_kernel(self, num_pix=None):
        """
        access pixelated kernel

        :param num_pix: size of returned kernel (odd number per axis). If None, return the original kernel.
        :return: pixel kernel centered
        """
        if num_pix is not None:
            return kernel_util.cut_psf(self._kernel, num_pix)
        return self._kernel
Пример #8
0
    def update_psf(self, kwargs_psf, kwargs_params, stacking_method='median', psf_symmetry=1, psf_iter_factor=1.,
                   block_center_neighbour=0, error_map_radius=None):
        """

        :param kwargs_psf: keyword arguments to construct the PSF() class
        :param kwargs_params: keyword arguments of the parameters of the model components (e.g. 'kwargs_lens' etc)
        :param stacking_method: 'median', 'mean'; the different estimates of the PSF are stacked and combined together.
         The choices are:
         'mean': mean of pixel values as the estimator (not robust to outliers)
         'median': median of pixel values as the estimator (outlier rejection robust but needs >2 point sources in the data
        :param psf_symmetry: number of rotational invariant symmetries in the estimated PSF.
         =1 mean no additional symmetries. =4 means 90 deg symmetry. This is enforced by a rotatioanl stack according to
         the symmetry specified. These additional imposed symmetries can help stabelize the PSF estimate when there are
         limited constraints/number of point sources in the image.
        :param psf_iter_factor: factor in (0, 1] of ratio of old vs new PSF in the update in the iteration.
        :param block_center_neighbour: angle, radius of neighbouring point sources around their centers the estimates
         is ignored. Default is zero, meaning a not optimal subtraction of the neighbouring point sources might
         contaminate the estimate.
        :param error_map_radius: float, radius (in arc seconds) of the outermost error in the PSF estimate
         (e.g. to avoid double counting of overlapping PSF errors)
        :return: kwargs_psf_new, logL_after, error_map
        """

        psf_class = PSF(**kwargs_psf)
        self._image_model_class.update_psf(psf_class)

        kernel_old = psf_class.kernel_point_source
        kernel_size = len(kernel_old)
        kwargs_psf_copy = copy.deepcopy(kwargs_psf)
        kwargs_psf_new = {'psf_type': 'PIXEL', 'kernel_point_source': kwargs_psf_copy['kernel_point_source']}
        if 'psf_error_map' in kwargs_psf_copy:
            kwargs_psf_new['psf_error_map'] = kwargs_psf_copy['psf_error_map'] / 10
        self._image_model_class.update_psf(PSF(**kwargs_psf_new))
        image_single_point_source_list = self.image_single_point_source(self._image_model_class, kwargs_params)
        kwargs_ps = kwargs_params.get('kwargs_ps', None)
        kwargs_lens = kwargs_params.get('kwargs_lens', None)
        ra_image, dec_image, amp = self._image_model_class.PointSource.point_source_list(kwargs_ps, kwargs_lens)
        x_, y_ = self._image_model_class.Data.map_coord2pix(ra_image, dec_image)

        psf_kernel_list, star_cutout_list = self.cutout_psf(ra_image, dec_image, x_, y_, image_single_point_source_list,
                                                            kernel_size, kernel_old,
                                                            block_center_neighbour=block_center_neighbour)

        kernel_new = self.combine_psf(psf_kernel_list, kernel_old, factor=psf_iter_factor,
                                      stacking_option=stacking_method, symmetry=psf_symmetry)
        kernel_new = kernel_util.cut_psf(kernel_new, psf_size=kernel_size)
        error_map = self.error_map_estimate(kernel_new, star_cutout_list, amp, x_, y_, error_map_radius=error_map_radius)

        kwargs_psf_new['kernel_point_source'] = kernel_new
        kwargs_psf_new['point_source_supersampling_factor'] = 1
        if 'psf_error_map' in kwargs_psf_new:
            kwargs_psf_new['psf_error_map'] *= 10
        self._image_model_class.update_psf(PSF(**kwargs_psf_new))
        logL_after = self._image_model_class.likelihood_data_given_model(**kwargs_params)
        return kwargs_psf_new, logL_after, error_map
Пример #9
0
    def kernel_point_source_supersampled(self,
                                         supersampling_factor,
                                         updata_cache=True):
        """
        generates (if not already available) a supersampled PSF with ood numbers of pixels centered

        :param supersampling_factor: int >=1, supersampling factor relative to pixel resolution
        :param updata_cache: boolean, if True, updates the cached supersampling PSF if generated.
         Attention, this will overwrite a previously used supersampled PSF if the resolution is changing.
        :return: super-sampled PSF as 2d numpy array
        """
        if hasattr(
                self, '_kernel_point_source_supersampled'
        ) and self._point_source_supersampling_factor == supersampling_factor:
            kernel_point_source_supersampled = self._kernel_point_source_supersampled
        else:
            if self.psf_type == 'GAUSSIAN':
                kernel_numPix = self._truncation / self._pixel_size * supersampling_factor
                kernel_numPix = int(round(kernel_numPix))
                if kernel_numPix > 10000:
                    raise ValueError(
                        'The pixelized Gaussian kernel has a grid of %s pixels with a truncation at '
                        '%s times the sigma of the Gaussian, exceeding the limit allowed.'
                        % (kernel_numPix, self._truncation))
                if kernel_numPix % 2 == 0:
                    kernel_numPix += 1
                kernel_point_source_supersampled = kernel_util.kernel_gaussian(
                    kernel_numPix, self._pixel_size / supersampling_factor,
                    self._fwhm)

            elif self.psf_type == 'PIXEL':

                kernel = kernel_util.subgrid_kernel(self.kernel_point_source,
                                                    supersampling_factor,
                                                    odd=True,
                                                    num_iter=5)
                n = len(self.kernel_point_source)
                n_new = n * supersampling_factor
                if n_new % 2 == 0:
                    n_new -= 1
                if hasattr(self, '_kernel_point_source_supersampled'):
                    warnings.warn(
                        "Super-sampled point source kernel over-written due to different subsampling"
                        " size requested.", Warning)
                kernel_point_source_supersampled = kernel_util.cut_psf(
                    kernel, psf_size=n_new)
            elif self.psf_type == 'NONE':
                kernel_point_source_supersampled = self._kernel_point_source
            else:
                raise ValueError('psf_type %s not valid!' % self.psf_type)
            if updata_cache is True:
                self._kernel_point_source_supersampled = kernel_point_source_supersampled
                self._point_source_supersampling_factor = supersampling_factor
        return kernel_point_source_supersampled
Пример #10
0
def instantiate_PSF_models(psf_config, pixel_scale):
    """Instantiate PSF models by reading in template PSF maps

    Parameters
    ----------
    psf_config : dict
        copy of the PSF config
    pixel_scale : float
        pixel scale in arcsec/pix

    Returns
    -------
    list
        list of lenstronomy PSF instances
        
    """
    if psf_config['type'] == 'PIXEL':
        psf_models = []
        if psf_config['which_psf_maps'] is None:
            # Instantiate PSF with all available PSF maps
            #FIXME: equate psf_id with psf_i since seed number is meaningless
            psf_id_list = [
                101, 102, 103, 104, 105, 107, 108, 109, 110, 111, 113, 114,
                115, 116, 117, 118
            ]
        else:
            psf_id_list = [psf_config['which_psf_maps']]

        for psf_i, psf_id in enumerate(psf_id_list):
            psf_path = resource_filename(
                'baobab.in_data', 'psf_maps/psf_{:d}.fits'.format(psf_id))
            psf_map = pyfits.getdata(psf_path)
            kernel_cut = kernel_util.cut_psf(psf_map,
                                             psf_config['kernel_size'])
            kwargs_psf = {
                'psf_type': 'PIXEL',
                'pixel_size': pixel_scale,
                'kernel_point_source': kernel_cut
            }
            psf_models.append(PSF(**kwargs_psf))
            return psf_models
    elif psf_config['type'] == 'GAUSSIAN':
        kwargs_psf = {
            'psf_type': 'GAUSSIAN',
            'fwhm': psf_config['PSF_FWHM'],
            'pixel_size': pixel_scale
        }
        psf_model = PSF(**kwargs_psf)
        return [psf_model]
    else:
        psf_model = PSF(psf_type='NONE')
        return [psf_model]
Пример #11
0
    def _subgrid_kernel(self, subgrid_res):
        """

        :return:
        """
        if not hasattr(self, '_subgrid_kernel_out'):
            kernel = kernel_util.subgrid_kernel(self.kernel_point_source, subgrid_res, odd=True)
            n = len(self._kernel_pixel)
            n_new = n * subgrid_res
            if n_new % 2 == 0:
                n_new -= 1
            self._subgrid_kernel_out = kernel_util.cut_psf(kernel, psf_size=n_new)
        return self._subgrid_kernel_out
Пример #12
0
def psf_configure_simple(psf_type="GAUSSIAN",
                         fwhm=1,
                         kernelsize=11,
                         deltaPix=1,
                         truncate=6,
                         kernel=None):
    """
    this routine generates keyword arguments to initialize a PSF() class in lenstronomy. Have a look at the PSF class
    documentation to see the full possibilities.

    :param psf_type: string, type of PSF model
    :param fwhm: Full width at half maximum of PSF (if GAUSSIAN psf)
    :param kernelsize: size in pixel of kernel (use odd numbers), only applicable for PIXEL kernels
    :param deltaPix: pixel size in angular units (only needed for GAUSSIAN kernel
    :param truncate: how many sigmas out is the truncation happening
    :param kernel: 2d numpy arra centered PSF (odd number per axis)
    :return: keyword arguments
    """

    if psf_type == 'GAUSSIAN':
        sigma = util.fwhm2sigma(fwhm)
        sigma_axis = sigma
        gaussian = Gaussian()
        x_grid, y_grid = util.make_grid(kernelsize, deltaPix)
        kernel_large = gaussian.function(x_grid,
                                         y_grid,
                                         amp=1.,
                                         sigma_x=sigma_axis,
                                         sigma_y=sigma_axis,
                                         center_x=0,
                                         center_y=0)
        kernel_large /= np.sum(kernel_large)
        kernel_large = util.array2image(kernel_large)
        kernel_pixel = kernel_util.pixel_kernel(kernel_large)
        kwargs_psf = {
            'psf_type': psf_type,
            'fwhm': fwhm,
            'truncation': truncate * fwhm,
            'kernel_point_source': kernel_large,
            'kernel_pixel': kernel_pixel,
            'pixel_size': deltaPix
        }
    elif psf_type == 'PIXEL':
        kernel_large = copy.deepcopy(kernel)
        kernel_large = kernel_util.cut_psf(kernel_large, psf_size=kernelsize)
        kwargs_psf = {'psf_type': "PIXEL", 'kernel_point_source': kernel_large}
    elif psf_type == 'NONE':
        kwargs_psf = {'psf_type': 'NONE'}
    else:
        raise ValueError("psf type %s not supported!" % psf_type)
    return kwargs_psf
Пример #13
0
    def _supersampling_cut_kernel(kernel_super, convolution_kernel_size, supersampling_factor):
        """

        :param kernel_super: super-sampled kernel
        :param convolution_kernel_size: size of convolution kernel in units of regular pixels (odd)
        :param supersampling_factor: super-sampling factor of convolution kernel
        :return: cut out kernel in super-sampling size
        """
        if convolution_kernel_size is not None:
            size = convolution_kernel_size * supersampling_factor
            if size % 2 == 0:
                size += 1
            kernel_cut = kernel_util.cut_psf(kernel_super, size)
            return kernel_cut
        else:
            return kernel_super
Пример #14
0
    def kernel_point_source_supersampled(self,
                                         supersampling_factor,
                                         updata_cache=True):
        """

        :return:
        """
        if hasattr(
                self, '_kernel_point_source_supersampled'
        ) and self._point_source_supersampling_factor == supersampling_factor:
            kernel_point_source_supersampled = self._kernel_point_source_supersampled
        else:
            if self.psf_type == 'GAUSSIAN':
                kernel_numPix = self._truncation / self._pixel_size * supersampling_factor
                kernel_numPix = int(round(kernel_numPix))
                if kernel_numPix % 2 == 0:
                    kernel_numPix += 1
                kernel_point_source_supersampled = kernel_util.kernel_gaussian(
                    kernel_numPix, self._pixel_size / supersampling_factor,
                    self._fwhm)

            elif self.psf_type == 'PIXEL':

                kernel = kernel_util.subgrid_kernel(self.kernel_point_source,
                                                    supersampling_factor,
                                                    odd=True,
                                                    num_iter=5)
                n = len(self.kernel_point_source)
                n_new = n * supersampling_factor
                if n_new % 2 == 0:
                    n_new -= 1
                if hasattr(self, '_kernel_point_source_supersampled'):
                    warnings.warn(
                        "Super-sampled point source kernel over-written due to different subsampling"
                        " size requested.", Warning)
                kernel_point_source_supersampled = kernel_util.cut_psf(
                    kernel, psf_size=n_new)
            elif self.psf_type == 'NONE':
                kernel_point_source_supersampled = self._kernel_point_source
            else:
                raise ValueError('psf_type %s not valid!' % self.psf_type)
            if updata_cache is True:
                self._kernel_point_source_supersampled = kernel_point_source_supersampled
                self._point_source_supersampling_factor = supersampling_factor
        return kernel_point_source_supersampled
Пример #15
0
    def update_psf(self, kwargs_psf, kwargs_params, stacking_method='median',
                 psf_symmetry=1, psf_iter_factor=1., block_center_neighbour=0):
        """

        :param kwargs_data:
        :param kwargs_psf:
        :param kwargs_options:
        :param kwargs_lens:
        :param kwargs_source:
        :param kwargs_lens_light:
        :param kwargs_ps:
        :return:
        """
        psf_class = PSF(**kwargs_psf)
        self._image_model_class.update_psf(psf_class)

        kernel_old = psf_class.kernel_point_source
        kernel_size = len(kernel_old)
        #kwargs_numerics_psf['psf_error_map'] = False
        kwargs_psf_copy = copy.deepcopy(kwargs_psf)
        kwargs_psf_new = {'psf_type': 'PIXEL', 'kernel_point_source': kwargs_psf_copy['kernel_point_source']}
        if 'psf_error_map' in kwargs_psf_copy:
            kwargs_psf_new['psf_error_map'] = kwargs_psf_copy['psf_error_map'] / 10
        self._image_model_class.update_psf(PSF(**kwargs_psf_new))
        image_single_point_source_list = self.image_single_point_source(self._image_model_class, kwargs_params)
        kwargs_ps = kwargs_params.get('kwargs_ps', None)
        kwargs_lens = kwargs_params.get('kwargs_lens', None)
        ra_image, dec_image, amp = self._image_model_class.PointSource.point_source_list(kwargs_ps, kwargs_lens)
        x_, y_ = self._image_model_class.Data.map_coord2pix(ra_image, dec_image)

        point_source_list = self.cutout_psf(ra_image, dec_image, x_, y_, image_single_point_source_list, kernel_size, kernel_old, block_center_neighbour=block_center_neighbour)

        kernel_new, error_map = self.combine_psf(point_source_list, kernel_old,
                                                 sigma_bkg=self._image_model_class.Data.background_rms, factor=psf_iter_factor,
                                                 stacking_option=stacking_method, symmetry=psf_symmetry)
        kernel_new = kernel_util.cut_psf(kernel_new, psf_size=kernel_size)

        kwargs_psf_new['kernel_point_source'] = kernel_new
        kwargs_psf_new['point_source_supersampling_factor'] = 1
        if 'psf_error_map' in kwargs_psf_new:
            kwargs_psf_new['psf_error_map'] *= 10
        self._image_model_class.update_psf(PSF(**kwargs_psf_new))
        logL_after = self._image_model_class.likelihood_data_given_model(**kwargs_params)
        return kwargs_psf_new, logL_after, error_map
Пример #16
0
    def setup(self):

        # we define a model consisting of a singe Sersric profile
        from lenstronomy.LightModel.light_model import LightModel
        light_model_list = ['SERSIC_ELLIPSE']
        self.lightModel = LightModel(light_model_list=light_model_list)
        self.kwargs_light = [
            {'amp': 100, 'R_sersic': 0.5, 'n_sersic': 3, 'e1': 0, 'e2': 0, 'center_x': 0.02, 'center_y': 0}]

        # we define a pixel grid and a higher resolution super sampling factor
        self._supersampling_factor = 5
        numPix = 61  # cutout pixel size
        deltaPix = 0.05  # pixel size in arcsec (area per pixel = deltaPix**2)
        x, y, ra_at_xy_0, dec_at_xy_0, x_at_radec_0, y_at_radec_0, Mpix2coord, Mcoord2pix = util.make_grid_with_coordtransform(
            numPix=numPix, deltapix=deltaPix, subgrid_res=1, left_lower=False, inverse=False)
        flux = self.lightModel.surface_brightness(x, y, kwargs_list=self.kwargs_light)
        flux = util.array2image(flux)
        flux_max = np.max(flux)
        conv_pixels_partial = np.zeros((numPix, numPix), dtype=bool)
        conv_pixels_partial[flux >= flux_max / 20] = True
        self._conv_pixels_partial = conv_pixels_partial

        # high resolution ray-tracing and high resolution convolution, the full calculation
        self.kwargs_numerics_true = {'supersampling_factor': self._supersampling_factor,
                                # super sampling factor of (partial) high resolution ray-tracing
                                'compute_mode': 'regular',  # 'regular' or 'adaptive'
                                'supersampling_convolution': True,
                                # bool, if True, performs the supersampled convolution (either on regular or adaptive grid)
                                'supersampling_kernel_size': None,
                                # size of the higher resolution kernel region (can be smaller than the original kernel). None leads to use the full size
                                'flux_evaluate_indexes': None,  # bool mask, if None, it will evaluate all (sub) pixels
                                'supersampled_indexes': None,
                                # bool mask of pixels to be computed in supersampled grid (only for adaptive mode)
                                'compute_indexes': None,
                                # bool mask of pixels to be computed the PSF response (flux being added to). Only used for adaptive mode and can be set =likelihood mask.
                                'point_source_supersampling_factor': 1,
                                # int, supersampling factor when rendering a point source (not used in this script)
                                }

        # high resolution convolution on a smaller PSF with low resolution convolution on the edges of the PSF and high resolution ray tracing
        self.kwargs_numerics_high_res_narrow = {'supersampling_factor': self._supersampling_factor,
                                           'compute_mode': 'regular',
                                           'supersampling_convolution': True,
                                           'supersampling_kernel_size': 5,
                                           }

        # low resolution convolution based on high resolution ray-tracing grid
        self.kwargs_numerics_low_conv_high_grid = {'supersampling_factor': self._supersampling_factor,
                                              'compute_mode': 'regular',
                                              'supersampling_convolution': False,
                                              # does not matter for supersampling_factor=1
                                              'supersampling_kernel_size': None,
                                              # does not matter for supersampling_factor=1
                                              }

        # low resolution convolution with a subset of pixels with high resolution ray-tracing
        self.kwargs_numerics_low_conv_high_adaptive = {'supersampling_factor': self._supersampling_factor,
                                                  'compute_mode': 'adaptive',
                                                  'supersampling_convolution': False,
                                                  # does not matter for supersampling_factor=1
                                                  'supersampling_kernel_size': None,
                                                  # does not matter for supersampling_factor=1
                                                  'supersampled_indexes': self._conv_pixels_partial,
                                                       'convolution_kernel_size': 9,
                                                  }

        # low resolution convolution with a subset of pixels with high resolution ray-tracing and high resoluton convolution on smaller kernel size
        self.kwargs_numerics_high_adaptive = {'supersampling_factor': self._supersampling_factor,
                                         'compute_mode': 'adaptive',
                                         'supersampling_convolution': True,
                                         # does not matter for supersampling_factor=1
                                         'supersampling_kernel_size': 5,  # does not matter for supersampling_factor=1
                                         'supersampled_indexes': self._conv_pixels_partial,
                                              'convolution_kernel_size': 9,
                                         }

        # low resolution convolution and low resolution ray tracing, the simplest calculation
        self.kwargs_numerics_low_res = {'supersampling_factor': 1,
                                   'compute_mode': 'regular',
                                   'supersampling_convolution': False,  # does not matter for supersampling_factor=1
                                   'supersampling_kernel_size': None,  # does not matter for supersampling_factor=1
                                        'convolution_kernel_size': 9,
                                   }

        flux_evaluate_indexes = np.zeros((numPix, numPix), dtype=bool)
        flux_evaluate_indexes[flux >= flux_max / 1000] = True
        # low resolution convolution on subframe
        self.kwargs_numerics_partial = {'supersampling_factor': 1,
                                        'compute_mode': 'regular',
                                        'supersampling_convolution': False,
                                        # does not matter for supersampling_factor=1
                                        'supersampling_kernel_size': None,  # does not matter for supersampling_factor=1
                                        'flux_evaluate_indexes': flux_evaluate_indexes,
                                        'convolution_kernel_size': 9
                                        }


        # import PSF file
        kernel_super = kernel_util.kernel_gaussian(kernel_numPix=11 * self._supersampling_factor,
                                                                     deltaPix=deltaPix / self._supersampling_factor, fwhm=0.1)


        kernel_size = 9
        kernel_super = kernel_util.cut_psf(psf_data=kernel_super, psf_size=kernel_size * self._supersampling_factor)

        # make instance of the PixelGrid class
        from lenstronomy.Data.pixel_grid import PixelGrid
        kwargs_grid = {'nx': numPix, 'ny': numPix, 'transform_pix2angle': Mpix2coord, 'ra_at_xy_0': ra_at_xy_0,
                       'dec_at_xy_0': dec_at_xy_0}
        self.pixel_grid = PixelGrid(**kwargs_grid)

        # make instance of the PSF class
        from lenstronomy.Data.psf import PSF
        kwargs_psf = {'psf_type': 'PIXEL', 'kernel_point_source': kernel_super,
                      'point_source_supersampling_factor': self._supersampling_factor}
        self.psf_class = PSF(**kwargs_psf)



        # without convolution
        image_model_true = ImageModel(self.pixel_grid, self.psf_class, lens_light_model_class=self.lightModel,
                                      kwargs_numerics=self.kwargs_numerics_true)
        self.image_true = image_model_true.image(kwargs_lens_light=self.kwargs_light)
Пример #17
0
    def pick_psf(self,
                 ra=None,
                 dec=None,
                 r_cut=15,
                 pixel_size=None,
                 kernel_size=None,
                 pick=True):
        """
        select psf
        :param x:  x coordinate.
        :param y:  y coordinate.
        :param r_cut: radius size of the psf.
        :param deltaPix: pixel size of the psf.
        :param kernel_size: kernel size of the psf.
        :return: kwargs_psf
        """
        if ra is not None:
            x_psf, y_psf = self.radec2detector(ra, dec)
            image_psf = self.cut_image_psf(x_psf, y_psf, r_cut)
        else:
            data_process = dxhDataProcess(fov_image=self.image,
                                          target_pos=[0, 0],
                                          pos_type='pixel',
                                          zp=0)
            if self.interaction & pick:
                psfyn = input(
                    'Hint: do you want to pick up the PSF youself? (y/n): ')
                if psfyn == 'y':
                    print((
                        'Please only pick 1 psf, otherwise only the 1st will be chosen'
                    ))
                    data_process.find_PSF(radius=r_cut, user_option=True)
                    image_psf = data_process.PSF_list[0]
                elif psfyn == 'n':
                    data_process.find_PSF(radius=r_cut, user_option=False)
                    image_psf = data_process.PSF_list[0]
                else:
                    raise ValueError("Please input 'y' or 'n' !")
            else:
                data_process.find_PSF(radius=r_cut, user_option=False)
                image_psf = data_process.PSF_list[0]

        if kernel_size is None:
            kernel_size = np.shape(image_psf)[0]

        image_psf_cut = kernel_util.cut_psf(
            image_psf, psf_size=kernel_size)  #why using kernel ?

        if pixel_size is None:
            pixel_size = self.deltaPix
        else:
            pixel_size = pixel_size

        kwargs_psf = {
            'psf_type': 'PIXEL',
            'kernel_point_source': image_psf_cut,
            'pixel_size': pixel_size
        }
        self.psf = image_psf_cut
        # TODO adding simulated psf
        return kwargs_psf
Пример #18
0
def test_cut_psf():
    image = np.ones((7, 7))
    psf_cut = kernel_util.cut_psf(image, 5)
    assert len(psf_cut) == 5
Пример #19
0
    def update_psf(self,
                   kwargs_psf,
                   kwargs_params,
                   stacking_method='median',
                   psf_symmetry=1,
                   psf_iter_factor=.2,
                   block_center_neighbour=0,
                   error_map_radius=None,
                   block_center_neighbour_error_map=None,
                   new_procedure=True):
        """

        :param kwargs_psf: keyword arguments to construct the PSF() class
        :param kwargs_params: keyword arguments of the parameters of the model components (e.g. 'kwargs_lens' etc)
        :param stacking_method: 'median', 'mean'; the different estimates of the PSF are stacked and combined together.
         The choices are:
         'mean': mean of pixel values as the estimator (not robust to outliers)
         'median': median of pixel values as the estimator (outlier rejection robust but needs >2 point sources in the
         data
        :param psf_symmetry: number of rotational invariant symmetries in the estimated PSF.
         =1 mean no additional symmetries. =4 means 90 deg symmetry. This is enforced by a rotatioanl stack according to
         the symmetry specified. These additional imposed symmetries can help stabelize the PSF estimate when there are
         limited constraints/number of point sources in the image.
        :param psf_iter_factor: factor in (0, 1] of ratio of old vs new PSF in the update in the iteration.
        :param block_center_neighbour: angle, radius of neighbouring point sources around their centers the estimates
         is ignored. Default is zero, meaning a not optimal subtraction of the neighbouring point sources might
         contaminate the estimate.
        :param block_center_neighbour_error_map: angle, radius of neighbouring point sources around their centers the
         estimates of the ERROR MAP is ignored. If None, then the value of block_center_neighbour is used (recommended)
        :param error_map_radius: float, radius (in arc seconds) of the outermost error in the PSF estimate
         (e.g. to avoid double counting of overlapping PSF errors), if None, all of the pixels are considered
         (unless blocked through other means)
        :param new_procedure: boolean, uses post lenstronomy 1.9.2 procedure which is more optimal for super-sampled
         PSF's
        :return: kwargs_psf_new, logL_after, error_map
        """
        if block_center_neighbour_error_map is None:
            block_center_neighbour_error_map = block_center_neighbour
        psf_class = PSF(**kwargs_psf)
        kwargs_psf_copy = copy.deepcopy(kwargs_psf)

        point_source_supersampling_factor = kwargs_psf_copy.get(
            'point_source_supersampling_factor', 1)
        kwargs_psf_new = {
            'psf_type': 'PIXEL',
            'kernel_point_source': kwargs_psf_copy['kernel_point_source'],
            'point_source_supersampling_factor':
            point_source_supersampling_factor,
            'psf_error_map': kwargs_psf_copy.get('psf_error_map', None)
        }
        # if 'psf_error_map' in kwargs_psf_copy:
        #    kwargs_psf_new['psf_error_map'] = kwargs_psf_copy['psf_error_map'] / 10
        self._image_model_class.update_psf(PSF(**kwargs_psf_new))

        model, error_map_image, cov_param, param = self._image_model_class.image_linear_solve(
            **kwargs_params)
        kwargs_ps = kwargs_params.get('kwargs_ps', None)
        kwargs_lens = kwargs_params.get('kwargs_lens', None)
        ra_image, dec_image, point_amp = self._image_model_class.PointSource.point_source_list(
            kwargs_ps, kwargs_lens)
        x_, y_ = self._image_model_class.Data.map_coord2pix(
            ra_image, dec_image)
        kernel_old = psf_class.kernel_point_source
        kernel_size = len(kernel_old)

        if not new_procedure:
            image_single_point_source_list = self.image_single_point_source(
                self._image_model_class, kwargs_params)
            star_cutout_list = self.point_like_source_cutouts(
                x_pos=x_,
                y_pos=y_,
                image_list=image_single_point_source_list,
                cutout_size=kernel_size)
            psf_kernel_list = self.cutout_psf(
                ra_image,
                dec_image,
                x_,
                y_,
                image_single_point_source_list,
                kernel_size,
                kernel_old,
                block_center_neighbour=block_center_neighbour)

            kernel_new = self.combine_psf(psf_kernel_list,
                                          kernel_old,
                                          factor=psf_iter_factor,
                                          stacking_option=stacking_method,
                                          symmetry=psf_symmetry)
            kernel_new = kernel_util.cut_psf(kernel_new, psf_size=kernel_size)
            error_map = self.error_map_estimate(
                kernel_new,
                star_cutout_list,
                point_amp,
                x_,
                y_,
                error_map_radius=error_map_radius,
                block_center_neighbour=block_center_neighbour_error_map)

            if point_source_supersampling_factor > 1:
                # The current version of using a super-sampled PSF in the iterative reconstruction is to first
                # constrain a down-sampled version and then in a second step perform a super-sampling of it. This is not
                # optimal and should be changed in the future that the corrections of the super-sampled version is done
                # rather than constraining a totally new PSF first
                kernel_new = kernel_util.subgrid_kernel(
                    kernel_new,
                    subgrid_res=point_source_supersampling_factor,
                    odd=True,
                    num_iter=10)
                # chop edges
                n_kernel = len(kwargs_psf['kernel_point_source'])
                kernel_new = kernel_util.cut_psf(kernel_new, psf_size=n_kernel)

        else:
            kernel_old_high_res = psf_class.kernel_point_source_supersampled(
                supersampling_factor=point_source_supersampling_factor)
            kernel_size_high = len(kernel_old_high_res)
            data = self._image_model_class.Data.data
            residuals = data - model

            psf_kernel_list = self.psf_estimate_individual(
                ra_image,
                dec_image,
                point_amp,
                residuals,
                cutout_size=kernel_size,
                kernel_guess=kernel_old_high_res,
                supersampling_factor=point_source_supersampling_factor,
                block_center_neighbour=block_center_neighbour)

            kernel_new = self.combine_psf(psf_kernel_list,
                                          kernel_old_high_res,
                                          factor=psf_iter_factor,
                                          stacking_option=stacking_method,
                                          symmetry=psf_symmetry)
            kernel_new = kernel_util.cut_psf(kernel_new,
                                             psf_size=kernel_size_high)

            # resize kernel for error_map estimate
            # kernel_new_low = kernel_util.degrade_kernel(kernel_new, point_source_supersampling_factor)
            # compute error map on pixel level
            error_map = self.error_map_estimate_new(
                kernel_new,
                psf_kernel_list,
                ra_image,
                dec_image,
                point_amp,
                point_source_supersampling_factor,
                error_map_radius=error_map_radius)

        kwargs_psf_new['kernel_point_source'] = kernel_new
        # if 'psf_error_map' in kwargs_psf_new:
        #    kwargs_psf_new['psf_error_map'] *= 10
        self._image_model_class.update_psf(PSF(**kwargs_psf_new))
        logL_after = self._image_model_class.likelihood_data_given_model(
            **kwargs_params)
        return kwargs_psf_new, logL_after, error_map
Пример #20
0
        ID, fr))
    # agn_stdd = pyfits.getdata('./allscience/{0}_{1}_stdd.fits'.format(ID,fr))
    stdd = 4  #Measurement from empty retion, 0.016*0.08**2/0.13**2/np.sqrt(8)
    agn_stdd = (abs(agn_image / exp_time) + stdd**2)**0.5

    print("The fitting image:")
    plt.imshow(agn_image, norm=LogNorm(), origin='lower')
    plt.savefig('./zoutput/{0}_agn.png'.format(ID))
    if pltshow == 0:
        plt.close()
    else:
        plt.show()

    print("The adopted PSF:")

    psf = kernel_util.cut_psf(psf, psf_size=kernel_size)

    plt.imshow(psf, norm=LogNorm(), origin='lower')
    plt.savefig('./zoutput/{0}_psf.png'.format(ID))
    if pltshow == 0:
        plt.close()
    else:
        plt.show()

    from mask_objects import mask_obj
    _, _, deblend_sources = mask_obj(agn_image,
                                     snr=snratio,
                                     npixels=numberpixels,
                                     return_deblend=True)

    print("deblend image to find the ID for the Objects for the mask:")