예제 #1
0
    def __init__(self, kernel_super, supersampling_factor, conv_supersample_pixels, supersampling_kernel_size=None,
                 compute_pixels=None, nopython=True, cache=True, parallel=False):
        """

        :param kernel_super: convolution kernel in units of super sampled pixels provided, odd length per axis
        :param supersampling_factor: factor of supersampling relative to pixel grid
        :param conv_supersample_pixels: bool array same size as data, pixels to be convolved and their light to be blurred
        :param supersampling_kernel_size: number of pixels (in units of the image pixels) that are convolved with the
        supersampled kernel
        :param compute_pixels: bool array of size of image, these pixels (if True) will get blurred light from other pixels
        :param nopython: bool, numba jit setting to use python or compiled.
        :param cache: bool, numba jit setting to use cache
        :param parallel: bool, numba jit setting to use parallel mode
        """
        kernel = kernel_util.degrade_kernel(kernel_super, degrading_factor=supersampling_factor)
        self._low_res_conv = PixelKernelConvolution(kernel, convolution_type='fft')
        if supersampling_kernel_size is None:
            supersampling_kernel_size = len(kernel)

        n_cut_super = supersampling_kernel_size * supersampling_factor
        if n_cut_super % 2 == 0:
            n_cut_super += 1
        #kernel_super_cut = image_util.cut_edges(kernel_super, n_cut_super)
        #kernel_cut = kernel_util.degrade_kernel(kernel_super_cut, degrading_factor=supersampling_factor)
        kernel_super_cut = image_util.cut_edges(kernel_super, n_cut_super)
        kernel_cut = kernel_util.degrade_kernel(kernel_super_cut, degrading_factor=supersampling_factor)

        self._low_res_partial = NumbaConvolution(kernel_cut, conv_supersample_pixels, compute_pixels=compute_pixels,
                                                 nopython=nopython, cache=cache, parallel=parallel, memory_raise=True)
        self._hig_res_partial = SubgridNumbaConvolution(kernel_super_cut, supersampling_factor, conv_supersample_pixels,
                                                        compute_pixels=compute_pixels, nopython=nopython, cache=cache,
                                                        parallel=parallel)#, kernel_size=len(kernel_cut))
        self._supersampling_factor = supersampling_factor
예제 #2
0
def test_degrade_kernel():
    subgrid_res = 2

    x_grid, y_gird = Util.make_grid(19, 1., 1)
    sigma = 1.5
    flux = gaussian.function(x_grid, y_gird, amp=1, sigma=sigma)
    kernel_super = Util.array2image(flux)/np.sum(flux)

    kernel_degraded = kernel_util.degrade_kernel(kernel_super, degrading_factor=subgrid_res)
    npt.assert_almost_equal(np.sum(kernel_degraded), 1, decimal=8)

    kernel_degraded = kernel_util.degrade_kernel(kernel_super, degrading_factor=3)
    npt.assert_almost_equal(np.sum(kernel_degraded), 1, decimal=8)

    kernel_degraded = kernel_util.degrade_kernel(kernel_super, degrading_factor=1)
    npt.assert_almost_equal(np.sum(kernel_degraded), 1, decimal=8)
예제 #3
0
파일: psf.py 프로젝트: aymgal/lenstronomy
    def __init__(self, psf_type='NONE', fwhm=None, truncation=5, pixel_size=None, kernel_point_source=None,
                 psf_error_map=None, point_source_supersampling_factor=1, kernel_point_source_init=None):
        """

        :param psf_type: string, type of PSF: options are 'NONE', 'PIXEL', 'GAUSSIAN'
        :param fwhm: float, full width at half maximum, only required for 'GAUSSIAN' model
        :param truncation: float, Gaussian truncation (in units of sigma), only required for 'GAUSSIAN' model
        :param pixel_size: width of pixel (required for Gaussian model, not required when using in combination with ImageModel modules)
        :param kernel_point_source: 2d numpy array, odd length, centered PSF of a point source
         (if not normalized, will be normalized)
        :param psf_error_map: uncertainty in the PSF model per pixel (size of data, not super-sampled). 2d numpy array.
        Size can be larger or smaller than the pixel-sized PSF model and if so, will be matched.
        This error will be added to the pixel error around the position of point sources as follows:
        sigma^2_i += 'psf_error_map'_j * (point_source_flux_i)**2
        :param point_source_supersampling_factor: int, supersampling factor of kernel_point_source
        :param kernel_point_source_init: memory of an initial point source kernel that gets passed through the psf iteration
        """
        self.psf_type = psf_type
        self._pixel_size = pixel_size
        self.kernel_point_source_init = kernel_point_source_init
        if self.psf_type == 'GAUSSIAN':
            if fwhm is None:
                raise ValueError('fwhm must be set for GAUSSIAN psf type!')
            self._fwhm = fwhm
            self._sigma_gaussian = util.fwhm2sigma(self._fwhm)
            self._truncation = truncation
            self._point_source_supersampling_factor = 0
        elif self.psf_type == 'PIXEL':
            if kernel_point_source is None:
                raise ValueError('kernel_point_source needs to be specified for PIXEL PSF type!')
            if len(kernel_point_source) % 2 == 0:
                raise ValueError('kernel needs to have odd axis number, not ', np.shape(kernel_point_source))
            if point_source_supersampling_factor > 1:
                self._kernel_point_source_supersampled = kernel_point_source
                self._point_source_supersampling_factor = point_source_supersampling_factor
                kernel_point_source = kernel_util.degrade_kernel(self._kernel_point_source_supersampled, self._point_source_supersampling_factor)
            self._kernel_point_source = kernel_point_source / np.sum(kernel_point_source)

        elif self.psf_type == 'NONE':
            self._kernel_point_source = np.zeros((3, 3))
            self._kernel_point_source[1, 1] = 1
        else:
            raise ValueError("psf_type %s not supported!" % self.psf_type)
        if psf_error_map is not None:
            n_kernel = len(self.kernel_point_source)
            self._psf_error_map = kernel_util.match_kernel_size(psf_error_map, n_kernel)
            if self.psf_type == 'PIXEL' and point_source_supersampling_factor > 1:
                if len(psf_error_map) == len(self._kernel_point_source_supersampled):
                    Warning('psf_error_map has the same size as the super-sampled kernel. Make sure the units in the'
                            'psf_error_map are on the down-sampled pixel scale.')
            self.psf_error_map_bool = True
        else:
            self.psf_error_map_bool = False
예제 #4
0
def test_degrade_kernel():

    x_grid, y_gird = Util.make_grid(19 * 5, 1., 1)
    sigma = 1.5
    amp = 2
    flux = gaussian.function(x_grid, y_gird, amp=2, sigma=sigma)
    kernel_super = Util.array2image(flux) / np.sum(flux) * amp

    for degrading_factor in range(7):
        kernel_degraded = kernel_util.degrade_kernel(
            kernel_super, degrading_factor=degrading_factor + 1)
        npt.assert_almost_equal(np.sum(kernel_degraded), amp, decimal=8)
예제 #5
0
    def error_map_estimate_new(self,
                               psf_kernel,
                               psf_kernel_list,
                               ra_image,
                               dec_image,
                               point_amp,
                               supersampling_factor,
                               error_map_radius=None):
        """
        relative uncertainty in the psf model (in quadrature) per pixel based on residuals achieved in the image

        :param psf_kernel: PSF kernel (super-sampled)
        :param psf_kernel_list: list of individual best PSF kernel estimates
        :param ra_image: image positions in angles
        :param dec_image: image positions in angles
        :param point_amp: image amplitude
        :param supersampling_factor: super-sampling factor
        :param error_map_radius: radius (in angle) to cut the error map
        :return: psf error map such that square of the uncertainty gets boosted by error_map * (psf * amp)**2
        """
        kernel_low = kernel_util.degrade_kernel(psf_kernel,
                                                supersampling_factor)
        error_map_list = np.zeros(
            (len(psf_kernel_list), len(kernel_low), len(kernel_low)))
        x_pos, y_pos = self._image_model_class.Data.map_coord2pix(
            ra_image, dec_image)

        for i, psf_kernel_i in enumerate(psf_kernel_list):
            kernel_low_i = kernel_util.degrade_kernel(psf_kernel_i,
                                                      supersampling_factor)

            x, y, amp_i = x_pos[i], y_pos[i], point_amp[i]
            x_int = int(round(x))
            y_int = int(round(y))

            C_D_cutout = kernel_util.cutout_source(
                x_int,
                y_int,
                self._image_model_class.Data.C_D,
                len(kernel_low_i),
                shift=False)
            residuals_i = np.abs(kernel_low - kernel_low_i)
            residuals_i -= np.sqrt(C_D_cutout) / amp_i
            residuals_i[residuals_i < 0] = 0
            error_map_list[i, :, :] = residuals_i**2

        error_map = np.median(error_map_list, axis=0)
        error_map[kernel_low > 0] /= kernel_low[kernel_low > 0]**2
        error_map = np.nan_to_num(error_map)
        error_map[error_map > 1] = 1  # cap on error to be the same

        # mask the error map outside a certain radius (can avoid double counting of errors when map is overlapping
        if error_map_radius is not None:
            pixel_scale = self._image_model_class.Data.pixel_width
            x_grid, y_grid = util.make_grid(numPix=len(error_map),
                                            deltapix=pixel_scale)
            mask = mask_util.mask_azimuthal(x_grid,
                                            y_grid,
                                            center_x=0,
                                            center_y=0,
                                            r=error_map_radius)
            error_map *= util.array2image(mask)
        return error_map