def test_center_kernel(): x_grid, y_gird = Util.make_grid(31, 1) sigma = 2 flux = gaussian.function(x_grid, y_gird, amp=1, sigma=sigma) kernel = Util.array2image(flux) kernel = kernel_util.kernel_norm(kernel) # kernel being centered kernel_new = kernel_util.center_kernel(kernel, iterations=20) kernel_new = kernel_util.kernel_norm(kernel_new) npt.assert_almost_equal(kernel_new/kernel, 1, decimal=8) # kernel shifted in x kernel_shifted = interp.shift(kernel, [-.1, 0], order=1) kernel_new = kernel_util.center_kernel(kernel_shifted, iterations=5) kernel_new = kernel_util.kernel_norm(kernel_new) npt.assert_almost_equal((kernel_new + 0.00001) / (kernel + 0.00001), 1, decimal=4) # kernel shifted in y kernel_shifted = interp.shift(kernel, [0, -0.4], order=1) kernel_new = kernel_util.center_kernel(kernel_shifted, iterations=5) kernel_new = kernel_util.kernel_norm(kernel_new) npt.assert_almost_equal((kernel_new + 0.01) / (kernel + 0.01), 1, decimal=3) # kernel shifted in x and y kernel_shifted = interp.shift(kernel, [0.2, -0.3], order=1) kernel_new = kernel_util.center_kernel(kernel_shifted, iterations=5) kernel_new = kernel_util.kernel_norm(kernel_new) npt.assert_almost_equal((kernel_new + 0.01) / (kernel + 0.01), 1, decimal=3)
def test_subgrid_rebin(): kernel_size = 11 subgrid_res = 3 sigma = 1 from lenstronomy.LightModel.Profiles.gaussian import Gaussian gaussian = Gaussian() x_grid, y_gird = Util.make_grid(kernel_size, 1. / subgrid_res, subgrid_res) flux = gaussian.function(x_grid, y_gird, amp=1, sigma_x=sigma, sigma_y=sigma) kernel = Util.array2image(flux) print(np.shape(kernel)) kernel = util.averaging(kernel, numGrid=kernel_size * subgrid_res, numPix=kernel_size) kernel = kernel_util.kernel_norm(kernel) subgrid_kernel = kernel_util.subgrid_kernel(kernel, subgrid_res=subgrid_res, odd=True) kernel_pixel = util.averaging(subgrid_kernel, numGrid=kernel_size * subgrid_res, numPix=kernel_size) kernel_pixel = kernel_util.kernel_norm(kernel_pixel) assert np.sum((kernel_pixel - kernel)**2) < 0.1
def combine_psf(kernel_list_new, kernel_old, sigma_bkg, factor=1, stacking_option='median', symmetry=1): """ updates psf estimate based on old kernel and several new estimates :param kernel_list_new: list of new PSF kernels estimated from the point sources in the image :param kernel_old: old PSF kernel :param sigma_bkg: estimated background noise in the image :param factor: weight of updated estimate based on new and old estimate, factor=1 means new estimate, factor=0 means old estimate :param stacking_option: option of stacking, mean or median :param symmetry: imposed symmetry of PSF estimate :return: updated PSF estimate and error_map associated with it """ n = int(len(kernel_list_new) * symmetry) angle = 360. / symmetry kernelsize = len(kernel_old) kernel_list = np.zeros((n, kernelsize, kernelsize)) i = 0 for kernel_new in kernel_list_new: for k in range(symmetry): kernel_rotated = image_util.rotateImage(kernel_new, angle * k) kernel_norm = kernel_util.kernel_norm(kernel_rotated) kernel_list[i, :, :] = kernel_norm i += 1 kernel_old_rotated = np.zeros((symmetry, kernelsize, kernelsize)) for i in range(symmetry): kernel_old_rotated[i, :, :] = kernel_old kernel_list_new = np.append(kernel_list, kernel_old_rotated, axis=0) if stacking_option == 'median': kernel_new = np.median(kernel_list_new, axis=0) elif stacking_option == 'mean': kernel_new = np.mean(kernel_list_new, axis=0) else: raise ValueError( " stack_option must be 'median' or 'mean', %s is not supported." % stacking_option) kernel_new[kernel_new < 0] = 0 kernel_new = kernel_util.kernel_norm(kernel_new) kernel_return = factor * kernel_new + (1. - factor) * kernel_old kernel_bkg = copy.deepcopy(kernel_return) kernel_bkg[kernel_bkg < sigma_bkg] = sigma_bkg error_map = np.var(kernel_list_new, axis=0) / kernel_bkg**2 / 2. return kernel_return, error_map
def test_subgrid_rebin(): kernel_size = 11 subgrid_res = 3 sigma = 1 x_grid, y_gird = Util.make_grid(kernel_size, 1./subgrid_res, subgrid_res) flux = gaussian.function(x_grid, y_gird, amp=1, sigma=sigma) kernel = Util.array2image(flux) print(np.shape(kernel)) kernel = util.averaging(kernel, numGrid=kernel_size * subgrid_res, numPix=kernel_size) kernel = kernel_util.kernel_norm(kernel) subgrid_kernel = kernel_util.subgrid_kernel(kernel, subgrid_res=subgrid_res, odd=True) kernel_pixel = util.averaging(subgrid_kernel, numGrid=kernel_size * subgrid_res, numPix=kernel_size) kernel_pixel = kernel_util.kernel_norm(kernel_pixel) assert np.sum((kernel_pixel - kernel)**2) < 0.1
def test_fwhm_kernel(): x_grid, y_gird = Util.make_grid(101, 1) sigma = 20 flux = gaussian.function(x_grid, y_gird, amp=1, sigma=sigma) kernel = Util.array2image(flux) kernel = kernel_util.kernel_norm(kernel) fwhm_kernel = kernel_util.fwhm_kernel(kernel) fwhm = Util.sigma2fwhm(sigma) npt.assert_almost_equal(fwhm/fwhm_kernel, 1, 2)
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 test_fwhm_kernel(): x_grid, y_gird = Util.make_grid(101, 1) sigma = 20 from lenstronomy.LightModel.Profiles.gaussian import Gaussian gaussian = Gaussian() flux = gaussian.function(x_grid, y_gird, amp=1, sigma_x=sigma, sigma_y=sigma) kernel = Util.array2image(flux) kernel = kernel_util.kernel_norm(kernel) fwhm_kernel = kernel_util.fwhm_kernel(kernel) fwhm = Util.sigma2fwhm(sigma) npt.assert_almost_equal(fwhm / fwhm_kernel, 1, 2)
def combine_psf(self, kernel_list, kernel_old, sigma_bkg, factor=1): """ updates psf estimate based on old kernel and several new estimates :param kernel_list: :param kernel_old: :return: """ kernel_list_new = np.append(kernel_list, kernel_old, axis=0) kernel_new = np.median(kernel_list_new, axis=0) kernel_new[kernel_new < 0] = 0 kernel_new = kernel_util.kernel_norm(kernel_new) kernel_return = factor * kernel_new + (1.-factor)*np.mean(kernel_old, axis=0) kernel_bkg = copy.deepcopy(kernel_return) kernel_bkg[kernel_bkg < sigma_bkg] = sigma_bkg error_map = np.var(kernel_list_new, axis=0)/(kernel_bkg)**2 return kernel_return, error_map
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