class TestAdaptiveGrid(object): def setup(self): deltaPix = 1. transform_pix2angle = np.array([[1, 0], [0, 1]]) * deltaPix ra_at_xy_0, dec_at_xy_0 = -5, -5 nx, ny = 11, 11 self._supersampling_factor = 4 supersampling_indexes = np.zeros((nx, ny)) supersampling_indexes = np.array(supersampling_indexes, dtype=bool) supersampling_indexes[5, 5] = True self._supersampling_indexes = supersampling_indexes self.nx, self.ny = nx, ny self._adaptive_grid = AdaptiveGrid(nx, ny, transform_pix2angle, ra_at_xy_0, dec_at_xy_0, supersampling_indexes, self._supersampling_factor) def test_coordinates_evaluate(self): x_grid, y_grid = self._adaptive_grid.coordinates_evaluate print(np.shape(x_grid), 'test shape') assert len(x_grid) == self._supersampling_factor**2 + self.nx * self.ny - 1 def test_subpixel_coordinates(self): subpixel_x, subpixel_y = self._adaptive_grid._high_res_coordinates assert len(subpixel_x) == 4**2 assert subpixel_x[0] == -0.375 assert subpixel_y[0] == -0.375 assert subpixel_y[3] == -0.375 assert subpixel_x[3] == 0.375 def test_average_subgrid(self): subpixel_x, subpixel_y = self._adaptive_grid._high_res_coordinates model = LightModel(light_model_list=['GAUSSIAN']) kwargs_light = [{'center_x': 0, 'center_y': 0, 'sigma': 1, 'amp': 1}] subgrid_values = model.surface_brightness(subpixel_x, subpixel_y, kwargs_light) supersampled_values = self._adaptive_grid._average_subgrid(subgrid_values) assert len(supersampled_values) == 1 def test_merge_low_high_res(self): subpixel_x, subpixel_y = self._adaptive_grid._high_res_coordinates x, y = self._adaptive_grid._x_low_res, self._adaptive_grid._x_low_res model = LightModel(light_model_list=['GAUSSIAN']) kwargs_light = [{'center_x': 0, 'center_y': 0, 'sigma': 1, 'amp': 1}] subgrid_values = model.surface_brightness(subpixel_x, subpixel_y, kwargs_light) image1d = model.surface_brightness(x, y, kwargs_light) image_added = self._adaptive_grid._merge_low_high_res(image1d, subgrid_values) added_array = util.image2array(image_added) supersampled_values = self._adaptive_grid._average_subgrid(subgrid_values) assert added_array[util.image2array(self._supersampling_indexes)] == supersampled_values image_high_res = self._adaptive_grid._high_res_image(subgrid_values) assert len(image_high_res) == self.nx * self._supersampling_factor def test_flux_array2image_low_high(self): x, y = self._adaptive_grid.coordinates_evaluate model = LightModel(light_model_list=['GAUSSIAN']) kwargs_light = [{'center_x': 0, 'center_y': 0, 'sigma': 1, 'amp': 1}] flux_values = model.surface_brightness(x, y, kwargs_light) image_low_res, image_high_res = self._adaptive_grid.flux_array2image_low_high(flux_values) assert len(image_high_res) == self.nx * self._supersampling_factor
class AdaptiveNumerics(object): """ this class manages and computes a surface brightness convolved image in an adaptive approach. The strategie applied are: 1.1 surface brightness computation only where significant flux is expected 1.2 super sampled surface brightness only in regimes of high spacial variability in the surface brightness and at high contrast 2.1 convolution only applied where flux is present (avoid convolving a lot of zeros) 2.2 simplified Multi-Gaussian convolution in regimes of low contrast 2.3 (super-) sampled PSF convolution only at high contrast of highly variable sources the class performs the convolution with two different input arrays, one with low resolution and one on a subpart with high resolution """ def __init__(self, nx, ny, transform_pix2angle, ra_at_xy_0, dec_at_xy_0, flux_evaluate_indexes, compute_indexes, supersampled_indexes, supersampling_factor, supersampling_kernel_size, kernel_super): self._grid = AdaptiveGrid(nx, ny, transform_pix2angle, ra_at_xy_0, dec_at_xy_0, supersampled_indexes, supersampling_factor, flux_evaluate_indexes) 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) def re_size_convolve(self, flux_array): """ :param flux_array: 1d array, flux values corresponding to coordinates_evaluate :param array_low_res_partial: regular sampled surface brightness, 1d array :return: convolved image on regular pixel grid, 2d array """ # add supersampled region to lower resolution on image_low_res, image_high_res_partial = self._grid.flux_array2image_low_high( flux_array) # convolve low res grid and high res grid image_conv = self._conv.re_size_convolve(image_low_res, image_high_res_partial) return image_conv @property def coordinates_evaluate(self): """ :return: 1d array of all coordinates being evaluated to perform the image computation """ return self._grid.coordinates_evaluate