示例#1
0
    def test_kernel_subsampled(self):
        deltaPix = 0.05  # pixel size of image
        numPix = 40  # number of pixels per axis
        subsampling_res = 3  # subsampling scale factor (in each dimension)
        fwhm = 0.3  # FWHM of the PSF kernel
        fwhm_object = 0.2  # FWHM of the Gaussian source to be convolved

        # create Gaussian/Pixelized kernels
        # first we create the sub-sampled kernel
        kernel_point_source_subsampled = kernel_util.kernel_gaussian(kernel_numPix=11*subsampling_res, deltaPix=deltaPix/subsampling_res, fwhm=fwhm)
        # to have the same consistent kernel, we re-size (average over the sub-sampled pixels) the sub-sampled kernel
        kernel_point_source = image_util.re_size(kernel_point_source_subsampled, subsampling_res)
        # here we create the two PSF() classes
        kwargs_pixel_subsampled = {'psf_type': 'PIXEL', 'kernel_point_source': kernel_point_source_subsampled,
                                   'point_source_supersampling_factor': subsampling_res}
        psf_pixel_subsampled = PSF(**kwargs_pixel_subsampled)
        psf_pixel_subsampled.kernel_point_source_supersampled(supersampling_factor=subsampling_res+1)
        kernel_point_source /= np.sum(kernel_point_source)
        kwargs_pixel = {'psf_type': 'PIXEL',
                        'kernel_point_source': kernel_point_source}
        psf_pixel = PSF(**kwargs_pixel)

        kernel_point_source = psf_pixel.kernel_point_source
        kernel_super = psf_pixel.kernel_point_source_supersampled(supersampling_factor=3)
        npt.assert_almost_equal(np.sum(kernel_point_source), np.sum(kernel_super), decimal=8)
        npt.assert_almost_equal(np.sum(kernel_point_source), 1, decimal=8)

        deltaPix = 0.05  # pixel size of image
        numPix = 40  # number of pixels per axis
        subsampling_res = 4  # subsampling scale factor (in each dimension)
        fwhm = 0.3  # FWHM of the PSF kernel
        fwhm_object = 0.2  # FWHM of the Gaussian source to be convolved

        # create Gaussian/Pixelized kernels
        # first we create the sub-sampled kernel
        kernel_point_source_subsampled = kernel_util.kernel_gaussian(kernel_numPix=11 * subsampling_res + 1,
                                                                     deltaPix=deltaPix / subsampling_res, fwhm=fwhm)

        kwargs_pixel_subsampled = {'psf_type': 'PIXEL', 'kernel_point_source': kernel_point_source_subsampled,
                                   'point_source_supersampling_factor': subsampling_res}
        psf_pixel_subsampled = PSF(**kwargs_pixel_subsampled)
        kernel_point_source /= np.sum(kernel_point_source)
        kwargs_pixel = {'psf_type': 'PIXEL',
                        'kernel_point_source': kernel_point_source}
        psf_pixel = PSF(**kwargs_pixel)
        kernel_point_source = psf_pixel.kernel_point_source
        kernel_point_source_new = psf_pixel_subsampled.kernel_point_source
        npt.assert_almost_equal(np.sum(kernel_point_source), np.sum(kernel_point_source_new), decimal=8)
        npt.assert_almost_equal(np.sum(kernel_point_source), 1, decimal=8)

        psf_none = PSF(psf_type='NONE')
        kernel_super = psf_none.kernel_point_source_supersampled(supersampling_factor=5)
        npt.assert_almost_equal(kernel_super, psf_none.kernel_point_source, decimal=9)
示例#2
0
    def test_raise(self):
        psf = PSF(psf_type='PIXEL', kernel_point_source=np.ones((3, 3)))
        psf.psf_type = 'WRONG'
        with self.assertRaises(ValueError):
            PSF(psf_type='GAUSSIAN')
        with self.assertRaises(ValueError):
            PSF(psf_type='PIXEL')
        with self.assertRaises(ValueError):
            PSF(psf_type='PIXEL', kernel_point_source=np.ones((2, 2)))
        with self.assertRaises(ValueError):
            PSF(psf_type='WRONG')
        with self.assertRaises(ValueError):
            PSF(psf_type='PIXEL', kernel_point_source=np.ones((3, 3)), psf_error_map=np.ones((5, 5)))
            psf.kernel_point_source_supersampled(supersampling_factor=3)
        with self.assertRaises(ValueError):
            psf = PSF(psf_type='PIXEL', kernel_point_source=np.ones((3, 3)))
            psf.psf_type = 'WRONG'
            psf.kernel_point_source_supersampled(supersampling_factor=3)
        with self.assertRaises(ValueError):
            psf = PSF(psf_type='GAUSSIAN', fwhm=100, pixel_size=0.0001)
            psf.kernel_point_source_supersampled(supersampling_factor=3)

        with warnings.catch_warnings(record=True) as w:
            # Cause all warnings to always be triggered.
            warnings.simplefilter("always")
            # Trigger a warning.
            kernel_point_source_subsampled = np.ones((9, 9))
            subsampling_res = 3
            kwargs_pixel_subsampled = {'psf_type': 'PIXEL', 'kernel_point_source': kernel_point_source_subsampled,
                                       'point_source_supersampling_factor': subsampling_res}
            psf_pixel_subsampled = PSF(**kwargs_pixel_subsampled)
            psf_pixel_subsampled.kernel_point_source_supersampled(supersampling_factor=subsampling_res + 4)
            # Verify some things
            assert 1 == 1
示例#3
0
    def test_kernel_point_source(self):
        kernel_gaussian = self.psf_gaussian.kernel_point_source
        kernel_pixel = self.psf_pixel.kernel_point_source
        assert len(kernel_gaussian) == 21
        assert len(kernel_pixel) == 21

        kwargs_psf = {'psf_type': 'GAUSSIAN', 'fwhm': 0.2, 'truncation': 3, 'pixel_size': 0.05}
        psf_class = PSF(**kwargs_psf)
        kernel_point_source = psf_class.kernel_point_source
        assert len(kernel_point_source) == 13
        kernel_super = psf_class.kernel_point_source_supersampled(supersampling_factor=3)
        assert np.sum(kernel_point_source) == np.sum(kernel_super)
        assert np.sum(kernel_point_source) == 1
示例#4
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