def test_pixel_kernel(self): kernel = np.zeros((5, 5)) kernel[1, 1] = 1 pixel_conv = PixelKernelConvolution(kernel=kernel) npt.assert_equal(pixel_conv.pixel_kernel(), kernel) npt.assert_equal(pixel_conv.pixel_kernel(num_pix=3), kernel[1:-1, 1:-1])
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
def test_copy_transpose(self): kernel = np.zeros((3, 3)) kernel[1, 1] = 1 pixel_conv = PixelKernelConvolution(kernel=kernel) pixel_conv_t = pixel_conv.copy_transpose() image_convolved = pixel_conv.convolution2d(self.model) image_convolved_t = pixel_conv_t.convolution2d(self.model) npt.assert_equal(image_convolved, image_convolved_t)
def test_convolve2d(self): kernel = np.zeros((3, 3)) kernel[1, 1] = 1 pixel_conv = PixelKernelConvolution(kernel=kernel) image_convolved = pixel_conv.convolution2d(self.model) npt.assert_almost_equal(np.sum(image_convolved), np.sum(self.model), decimal=2)
def test_convolve2d(self): conv_pixels = np.ones_like(self.model) conv_pixels = np.array(conv_pixels, dtype=bool) numba_conv = NumbaConvolution(kernel=self.kernel, conv_pixels=conv_pixels, compute_pixels=conv_pixels) model_conv_numba = numba_conv.convolve2d(self.model) pixel_conv = PixelKernelConvolution(kernel=self.kernel) image_convolved = pixel_conv.convolution2d(self.model) npt.assert_almost_equal(model_conv_numba, image_convolved, decimal=10)
def test_convolve2d(self): conv_pixels = np.ones_like(self.model) conv_pixels = np.array(conv_pixels, dtype=bool) numba_conv = SubgridNumbaConvolution(kernel_super=self.kernel_super, conv_pixels=conv_pixels, compute_pixels=conv_pixels, supersampling_factor=self.supersampling_factor) model_conv_numba = numba_conv.convolve2d(self.model_super) pixel_conv = PixelKernelConvolution(kernel=self.kernel_super) image_convolved = pixel_conv.convolution2d(self.model_super) image_convolved = image_util.re_size(image_convolved, factor=self.supersampling_factor) npt.assert_almost_equal(model_conv_numba, image_convolved, decimal=10)
class AdaptiveConvolution(object): """ This class performs convolutions of a subset of pixels at higher supersampled resolution Goal: speed up relative to higher resolution FFT when only considereing a (small) subset of pixels to be convolved on the higher resolution grid. strategy: 1. lower resolution convolution over full image with FFT 2. subset of pixels with higher resolution Numba convolution (with smaller kernel) 3. the same subset of pixels with low resolution Numba convolution (with same kernel as step 2) adaptive solution is 1 + 2 -3 """ 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 def re_size_convolve(self, image_low_res, image_high_res): """ :param image_high_res: supersampled image/model to be convolved on a regular pixel grid :return: convolved and re-sized image """ image_low_res_conv = self._low_res_conv.convolution2d(image_low_res) image_low_res_partial_conv = self._low_res_partial.convolve2d(image_low_res) image_high_res_partial_conv = self._hig_res_partial.convolve2d(image_high_res) return image_low_res_conv + image_high_res_partial_conv - image_low_res_partial_conv def convolve2d(self, image_high_res): """ :param image_high_res: supersampled image/model to be convolved on a regular pixel grid :return: convolved and re-sized image """ image_low_res = image_util.re_size(image_high_res, factor=self._supersampling_factor) return self.re_size_convolve(image_low_res, image_high_res)
def __init__(self, pixel_grid, psf, supersampling_factor=1, compute_mode='regular', supersampling_convolution=False, supersampling_kernel_size=5, flux_evaluate_indexes=None, supersampled_indexes=None, compute_indexes=None, point_source_supersampling_factor=1, convolution_kernel_size=None, convolution_type='fft_static', truncation=4): """ :param pixel_grid: PixelGrid() class instance :param psf: PSF() class instance :param compute_mode: options are: 'regular', 'adaptive' :param supersampling_factor: int, factor of higher resolution sub-pixel sampling of surface brightness :param supersampling_convolution: bool, if True, performs (part of) the convolution on the super-sampled grid/pixels :param supersampling_kernel_size: int (odd number), size (in regular pixel units) of the super-sampled convolution :param flux_evaluate_indexes: boolean 2d array of size of image (or None, then initiated as gird of True's). Pixels indicated with True will be used to perform the surface brightness computation (and possible lensing ray-shooting). Pixels marked as False will be assigned a flux value of zero (or ignored in the adaptive convolution) :param supersampled_indexes: 2d boolean array (only used in mode='adaptive') of pixels to be supersampled (in surface brightness and if supersampling_convolution=True also in convolution) :param compute_indexes: 2d boolean array (only used in mode='adaptive'), marks pixel that the resonse after convolution is computed (all others =0). This can be set to likelihood_mask in the Likelihood module for consistency. :param point_source_supersampling_factor: super-sampling resolution of the point source placing :param convolution_kernel_size: int, odd number, size of convolution kernel. If None, takes size of point_source_kernel :param convolution_type: string, 'fft', 'grid', 'fft_static' mode of 2d convolution """ if compute_mode not in ['regular', 'adaptive']: raise ValueError( 'compute_mode specified as %s not valid. Options are "adaptive", "regular"' ) # if no super sampling, turn the supersampling convolution off self._psf_type = psf.psf_type if not isinstance(supersampling_factor, int): raise TypeError( 'supersampling_factor needs to be an integer! Current type is %s' % type(supersampling_factor)) if supersampling_factor == 1: supersampling_convolution = False self._pixel_width = pixel_grid.pixel_width nx, ny = pixel_grid.num_pixel_axes transform_pix2angle = pixel_grid.transform_pix2angle ra_at_xy_0, dec_at_xy_0 = pixel_grid.radec_at_xy_0 if supersampled_indexes is None: supersampled_indexes = np.zeros((nx, ny), dtype=bool) if compute_mode == 'adaptive': # or (compute_mode == 'regular' and supersampling_convolution is False and supersampling_factor > 1): self._grid = AdaptiveGrid(nx, ny, transform_pix2angle, ra_at_xy_0, dec_at_xy_0, supersampled_indexes, supersampling_factor, flux_evaluate_indexes) else: self._grid = RegularGrid(nx, ny, transform_pix2angle, ra_at_xy_0, dec_at_xy_0, supersampling_factor, flux_evaluate_indexes) if self._psf_type == 'PIXEL': if compute_mode == 'adaptive' and supersampling_convolution is True: from lenstronomy.ImSim.Numerics.adaptive_numerics import AdaptiveConvolution kernel_super = psf.kernel_point_source_supersampled( supersampling_factor) kernel_super = self._supersampling_cut_kernel( kernel_super, convolution_kernel_size, supersampling_factor) self._conv = AdaptiveConvolution( kernel_super, supersampling_factor, conv_supersample_pixels=supersampled_indexes, supersampling_kernel_size=supersampling_kernel_size, compute_pixels=compute_indexes, nopython=True, cache=True, parallel=False) elif compute_mode == 'regular' and supersampling_convolution is True: kernel_super = psf.kernel_point_source_supersampled( supersampling_factor) if convolution_kernel_size is not None: kernel_super = psf.kernel_point_source_supersampled( supersampling_factor) kernel_super = self._supersampling_cut_kernel( kernel_super, convolution_kernel_size, supersampling_factor) self._conv = SubgridKernelConvolution( kernel_super, supersampling_factor, supersampling_kernel_size=supersampling_kernel_size, convolution_type=convolution_type) else: kernel = psf.kernel_point_source kernel = self._supersampling_cut_kernel( kernel, convolution_kernel_size, supersampling_factor=1) self._conv = PixelKernelConvolution( kernel, convolution_type=convolution_type) elif self._psf_type == 'GAUSSIAN': pixel_scale = pixel_grid.pixel_width fwhm = psf.fwhm # FWHM in units of angle sigma = util.fwhm2sigma(fwhm) sigma_list = [sigma] fraction_list = [1] self._conv = MultiGaussianConvolution(sigma_list, fraction_list, pixel_scale, supersampling_factor, supersampling_convolution, truncation=truncation) elif self._psf_type == 'NONE': self._conv = None else: raise ValueError( 'psf_type %s not valid! Chose either NONE, GAUSSIAN or PIXEL.' % self._psf_type) super(Numerics, self).__init__( pixel_grid=pixel_grid, supersampling_factor=point_source_supersampling_factor, psf=psf) if supersampling_convolution is True: self._high_res_return = True else: self._high_res_return = False