def test_cut_edges(): image = np.zeros((51, 51)) image[25][25] = 1 numPix = 21 resized = image_util.cut_edges(image, numPix) nx, ny = resized.shape assert nx == numPix assert ny == numPix assert resized[10][10] == 1 image = np.zeros((5, 5)) image[2, 2] = 1 numPix = 3 image_cut = image_util.cut_edges(image, numPix) assert len(image_cut) == numPix assert image_cut[1, 1] == 1 image = np.zeros((6, 6)) image[3, 2] = 1 numPix = 4 image_cut = image_util.cut_edges(image, numPix) assert len(image_cut) == numPix assert image_cut[2, 1] == 1 image = np.zeros((6, 8)) image[3, 2] = 1 numPix = 4 image_cut = image_util.cut_edges(image, numPix) assert len(image_cut) == numPix assert image_cut[2, 0] == 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_pixel = kernel_util.kernel_average_pixel(kernel_super, supersampling_factor) n_high = len(kernel_super) numPix = int(n_high / supersampling_factor) if supersampling_factor % 2 == 0: kernel = kernel_util.averaging_even_kernel(kernel_super, supersampling_factor) else: kernel = util.averaging(kernel_super, numGrid=n_high, numPix=numPix) kernel *= supersampling_factor**2 self._low_res_conv = PixelKernelConvolution(kernel, convolution_type='fft') if supersampling_kernel_size is None: supersampling_kernel_size = len(kernel) kernel_cut = image_util.cut_edges(kernel, supersampling_kernel_size) kernel_super_cut = image_util.cut_edges( kernel_super, supersampling_kernel_size * 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 __init__(self, kernel_super, supersampling_factor, conv_pixels, compute_pixels=None, kernel_size=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_pixels: bool array same size as data, pixels to be convolved and their light to be blurred :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 """ self._nx, self._ny = conv_pixels.shape self._supersampling_factor = supersampling_factor # loop through the different supersampling sectors self._numba_conv_list = [] if compute_pixels is None: compute_pixels = np.ones_like(conv_pixels) compute_pixels = np.array(compute_pixels, dtype=bool) for i in range(supersampling_factor): for j in range(supersampling_factor): # compute shifted psf kernel kernel = self._partial_kernel(kernel_super, i, j) if kernel_size is not None: kernel = image_util.cut_edges(kernel, kernel_size) numba_conv = NumbaConvolution(kernel, conv_pixels, compute_pixels=compute_pixels, nopython=nopython, cache=cache, parallel=parallel) self._numba_conv_list.append(numba_conv)
def test_cut_edges(): image = np.zeros((51, 51)) image[25][25] = 1 numPix = 21 resized = image_util.cut_edges(image, numPix) nx, ny = resized.shape assert nx == numPix assert ny == numPix assert resized[10][10] == 1
def cut_psf(psf_data, psf_size): """ cut the psf properly :param psf_data: image of PSF :param psf_size: size of psf :return: re-sized and re-normalized PSF """ kernel = image_util.cut_edges(psf_data, psf_size) kernel = kernel_norm(kernel) return kernel
def cutout_psf_single(x, y, image, mask, kernel_size, kernel_init): """ :param x: x-coordinate of point source :param y: y-coordinate of point source :param image: image (i.e. data - all models subtracted, except a single point source) :param mask: mask of pixels in the image not to be considered in the PSF estimate (being replaced by kernel_init) :param kernel_size: width in pixel of the kernel :param kernel_init: initial guess of kernel (pixels that are masked are replaced by those values) :return: estimate of the PSF based on the image and position of the point source """ # cutout the star x_int = int(round(x)) y_int = int(round(y)) star_cutout = kernel_util.cutout_source(x_int, y_int, image, kernel_size + 2, shift=False) # cutout the mask mask_cutout = kernel_util.cutout_source(x_int, y_int, mask, kernel_size + 2, shift=False) # enlarge the initial PSF kernel to the new cutout size kernel_enlarged = np.zeros((kernel_size + 2, kernel_size + 2)) kernel_enlarged[1:-1, 1:-1] = kernel_init # shift the initial kernel to the shift of the star shift_x = x_int - x shift_y = y_int - y kernel_shifted = ndimage.shift(kernel_enlarged, shift=[-shift_y, -shift_x], order=1) # compute normalization of masked and unmasked region of the shifted kernel # norm_masked = np.sum(kernel_shifted[mask_i == 0]) norm_unmasked = np.sum(kernel_shifted[mask_cutout == 1]) # normalize star within the unmasked region to the norm of the initial kernel of the same region star_cutout /= np.sum(star_cutout[mask_cutout == 1]) * norm_unmasked # replace mask with shifted initial kernel (+2 size) star_cutout[mask_cutout == 0] = kernel_shifted[mask_cutout == 0] star_cutout[star_cutout < 0] = 0 # de-shift kernel kernel_deshifted = kernel_util.de_shift_kernel( star_cutout, shift_x, shift_y, iterations=20, fractional_step_size=0.1) # re-size kernel kernel_deshifted = image_util.cut_edges(kernel_deshifted, kernel_size) # re-normalize kernel again kernel_deshifted = kernel_util.kernel_norm(kernel_deshifted) return kernel_deshifted
def cut_edges(): image = np.zeros((5, 5)) image[2, 2] = 1 numPix = 3 image_cut = image_util.cut_edges(image, numPix) assert len(image_cut) == numPix assert image_cut[1, 1] == 1 image = np.zeros((6, 6)) image[3, 2] = 1 numPix = 4 image_cut = image_util.cut_edges(image, numPix) assert len(image_cut) == numPix assert image[2, 1] == 1 image = np.zeros((6, 8)) image[3, 2] = 1 numPix = 4 image_cut = image_util.cut_edges(image, numPix) assert len(image_cut) == numPix assert image[2, 0] == 1
def fit_sample(self, star_list, mean, sigma, poisson, n_walk=100, n_iter=100, threadCount=1, psf_type='gaussian'): """ routine to fit a sample of several stars and to show the variation :param mean: :param sigma: :param poisson: :param walkerRatio: :param n_run: :param n_burn: :param threadCount: :return: """ n = len(star_list) # number of different objects if psf_type == 'gaussian' or psf_type == 'pixel': numParam = 4 elif psf_type == 'moffat': numParam = 5 else: raise ValueError('type %s is not a valid input' % (type)) mean_list = np.zeros((n, numParam)) for i in range(n): image = star_list[i] image = image_util.cut_edges(image, 33) if psf_type == 'gaussian' or psf_type == 'pixel': mean_list[i] = self.gaussian_fit(image, mean, sigma, poisson, n_walker=n_walk, n_iter=n_iter, threadCount=threadCount) elif psf_type == 'moffat': mean_list[i] = self.moffat_fit(image, mean, sigma, poisson, n_walker=n_walk, n_iter=n_iter, threadCount=threadCount) return mean_list
def test_raise(self): with self.assertRaises(ValueError): grid2d = np.zeros((7, 7)) x_pos, y_pos = 4, 1 kernel = np.ones((2, 2)) added = image_util.add_layer2image_int(grid2d, x_pos, y_pos, kernel) with self.assertRaises(ValueError): image = np.ones((5, 5)) image_util.re_size(image, factor=2) with self.assertRaises(ValueError): image = np.ones((5, 5)) image_util.re_size(image, factor=0.5) with self.assertRaises(ValueError): image = np.ones((5, 5)) image_util.cut_edges(image, numPix=7) with self.assertRaises(ValueError): image = np.ones((5, 6)) image_util.cut_edges(image, numPix=3) with self.assertRaises(ValueError): image = np.ones((5, 5)) image_util.cut_edges(image, numPix=2)
def psf_estimate_individual(self, ra_image, dec_image, point_amp, residuals, cutout_size, kernel_guess, supersampling_factor, block_center_neighbour): """ :param ra_image: list; position in angular units of the image :param dec_image: list; position in angular units of the image :param point_amp: list of model amplitudes of point sources :param residuals: data - model :param cutout_size: pixel size of cutout around single star/quasar to be considered for the psf reconstruction :param kernel_guess: initial guess of super-sampled PSF :param supersampling_factor: int, super-sampling factor :param block_center_neighbour: :return: list of best-guess PSF's for each star based on the residual patterns """ mask = self._image_model_class.likelihood_mask ra_grid, dec_grid = self._image_model_class.Data.pixel_coordinates ra_grid = util.image2array(ra_grid) dec_grid = util.image2array(dec_grid) radius = block_center_neighbour x_, y_ = self._image_model_class.Data.map_coord2pix( ra_image, dec_image) kernel_list = [] for l in range(len(ra_image)): mask_point_source = self.mask_point_source(ra_image, dec_image, ra_grid, dec_grid, radius, i=l) mask_i = mask * mask_point_source # cutout residuals x_int = int(round(x_[l])) y_int = int(round(y_[l])) residual_cutout = kernel_util.cutout_source(x_int, y_int, residuals, cutout_size + 2, shift=False) # cutout the mask mask_cutout = kernel_util.cutout_source(x_int, y_int, mask_i, cutout_size + 2, shift=False) # apply mask residual_cutout_mask = residual_cutout * mask_cutout # re-scale residuals with point source brightness residual_cutout_mask /= point_amp[l] # enlarge residuals by super-sampling factor residual_cutout_mask = residual_cutout_mask.repeat( supersampling_factor, axis=0).repeat(supersampling_factor, axis=1) # inverse shift residuals shift_x = (x_int - x_[l]) * supersampling_factor shift_y = (y_int - y_[l]) * supersampling_factor # for odd number super-sampling if supersampling_factor % 2 == 1: residuals_shifted = ndimage.shift(residual_cutout_mask, shift=[shift_y, shift_x], order=1) else: # for even number super-sampling half a super-sampled pixel offset needs to be performed residuals_shifted = ndimage.shift( residual_cutout_mask, shift=[shift_y - 0.5, shift_x - 0.5], order=1) # and the last column and row need to be removed residuals_shifted = residuals_shifted[:-1, :-1] # re-size shift residuals psf_size = len(kernel_guess) residuals_shifted = image_util.cut_edges(residuals_shifted, psf_size) # normalize residuals correction = residuals_shifted - np.mean(residuals_shifted) # correct old PSF with inverse shifted residuals kernel_new = kernel_guess + correction kernel_list.append(kernel_new) return kernel_list
def cutout_psf(self, x, y, image_list, kernelsize, mask, mask_point_source_list, kernel_init, symmetry=1): """ :param x_: :param y_: :param image_list: list of images (i.e. data - all models subtracted, except a single point source) :param kernelsize: :return: """ n = len(x) * symmetry angle = 360. / symmetry kernel_list = np.zeros((n, kernelsize, kernelsize)) i = 0 for l in range(len(x)): # cutout the star x_, y_ = x[l], y[l] x_int = int(round(x_)) y_int = int(round(y_)) star_cutout = kernel_util.cutout_source(x_int, y_int, image_list[l], kernelsize + 2, shift=False) # cutout the mask mask_i = mask * mask_point_source_list[l] mask_cutout = kernel_util.cutout_source(x_int, y_int, mask_i, kernelsize + 2, shift=False) # enlarge the initial PSF kernel to the new cutout size kernel_enlarged = np.zeros((kernelsize+2, kernelsize+2)) kernel_enlarged[1:-1, 1:-1] = kernel_init # shift the initial kernel to the shift of the star shift_x = x_int - x_ shift_y = y_int - y_ kernel_shifted = interp.shift(kernel_enlarged, [-shift_y, -shift_x], order=1) # compute normalization of masked and unmasked region of the shifted kernel # norm_masked = np.sum(kernel_shifted[mask_i == 0]) norm_unmaksed = np.sum(kernel_shifted[mask_cutout == 1]) # normalize star within the unmasked region to the norm of the initial kernel of the same region star_cutout /= np.sum(star_cutout[mask_cutout == 1]) * norm_unmaksed # replace mask with shifted initial kernel (+2 size) star_cutout[mask_cutout == 0] = kernel_shifted[mask_cutout == 0] star_cutout[star_cutout < 0] = 0 # de-shift kernel kernel_deshifted = kernel_util.de_shift_kernel(star_cutout, shift_x, shift_y) # re-size kernel kernel_deshifted = image_util.cut_edges(kernel_deshifted, kernelsize) # re-normalize kernel again kernel_deshifted = kernel_util.kernel_norm(kernel_deshifted) """ kernel_shifted = kernel_util.cutout_source(x_[l], y_[l], image_list[l], kernelsize + 2) # don't de-shift it here mask_i = mask * mask_point_source_list[l] mask_cutout = kernel_util.cutout_source(int(round(x_[l])), int(round(x_[l])), mask_i, kernelsize + 2, shift=False) kernel_shifted[kernel_shifted < 0] = 0 kernel_shifted *= mask_cutout kernel_init = kernel_util.kernel_norm(kernel_init) mask_cutout = image_util.cut_edges(mask_cutout, kernelsize) kernel_shifted = image_util.cut_edges(kernel_shifted, kernelsize) kernel_norm = np.sum(kernel_init[mask_cutout == 1]) kernel_shifted = kernel_util.kernel_norm(kernel_shifted) kernel_shifted *= kernel_norm kernel_shifted[mask_cutout == 0] = kernel_init[mask_cutout == 0] #kernel_shifted[mask_cutout == 1] /= (np.sum(kernel_init[mask_cutout == 1]) * np.sum(kernel_shifted[mask_cutout == 1])) """ for k in range(symmetry): kernel_rotated = image_util.rotateImage(kernel_deshifted, angle * k) kernel_norm = kernel_util.kernel_norm(kernel_rotated) try: kernel_list[i, :, :] = kernel_norm except: raise ValueError("cutout kernel has not the same shape as the PSF." " This is probably because the cutout of the psf hits the boarder of the data." "Use a smaller PSF or a larger data frame for the modelling.") i += 1 return kernel_list