def invert_2d_from_grid(uv_grid_vis, sumwt, im: Image, normalize: bool = True, **kwargs): """ Perform the 2d fourier transform on the gridded uv visibility :param uv_grid_vis: the gridded uv visibility :param sumwt: the weight for the uv visibility :param im: image template (not changed) :param return: resulting image[nchan, npol, ny, nx], sum of weights[nchan, npol] """ ### Calculate gcf -> grid correction function ### # 2D Prolate spheroidal angular function is separable npixel = get_parameter(kwargs, "npixel", 512) nx = npixel ny = npixel nu = numpy.abs(2.0 * (numpy.arange(nx) - nx // 2) / nx) gcf1d, _ = grdsf(nu) gcf = numpy.outer(gcf1d, gcf1d) gcf[gcf > 0.0] = gcf.max() / gcf[gcf > 0.0] result = numpy.real(ifft(uv_grid_vis)) * gcf #Create image array resultimage = create_image_from_array(result, im.wcs) if normalize: resultimage = normalize_sumwt(resultimage, sumwt) return resultimage, sumwt
def test_ifft(data_dir, shape): ia = create_random_data(shape, -100, 100, 'complex') start = time.time() a = ifft(ia) stop = time.time() print('Original Time: {:.2f}s'.format(stop - start)) store_data(os.path.join(data_dir, 'ia.dat'), ia) store_data(os.path.join(data_dir, 'a.dat'), a)
def fft_image(im, template_image=None): """ FFT an image, transform WCS as well Prefer to use axes 'UU---SIN' and 'VV---SIN' but astropy will not accept. :param im: :param template: :return: """ assert len(im.shape) == 4 d2r = numpy.pi / 180.0 ft_wcs = copy.deepcopy(im.wcs) ft_shape = im.shape if im.wcs.wcs.ctype[0] == 'RA---SIN' and im.wcs.wcs.ctype[1] == 'DEC--SIN': ft_wcs.wcs.axis_types[0] = 0 ft_wcs.wcs.axis_types[1] = 0 ft_wcs.wcs.crval[0] = 0.0 ft_wcs.wcs.crval[1] = 0.0 ft_wcs.wcs.crpix[0] = ft_shape[3] // 2 + 1 ft_wcs.wcs.crpix[1] = ft_shape[2] // 2 + 1 ft_wcs.wcs.ctype[0] = 'UU' ft_wcs.wcs.ctype[1] = 'VV' ft_wcs.wcs.cdelt[0] = 1.0 / (ft_shape[3] * d2r * im.wcs.wcs.cdelt[0]) ft_wcs.wcs.cdelt[1] = 1.0 / (ft_shape[2] * d2r * im.wcs.wcs.cdelt[1]) ft_data = ifft(im.data.astype('complex')) return create_image_from_array( ft_data, wcs=ft_wcs, polarisation_frame=im.polarisation_frame) elif im.wcs.wcs.ctype[0] == 'UU' and im.wcs.wcs.ctype[1] == 'VV': ft_wcs.wcs.crval[0] = template_image.wcs.wcs.crval[0] ft_wcs.wcs.crval[1] = template_image.wcs.wcs.crval[1] ft_wcs.wcs.crpix[0] = template_image.wcs.wcs.crpix[0] ft_wcs.wcs.crpix[0] = template_image.wcs.wcs.crpix[1] ft_wcs.wcs.ctype[0] = template_image.wcs.wcs.ctype[0] ft_wcs.wcs.ctype[1] = template_image.wcs.wcs.ctype[1] ft_wcs.wcs.cdelt[0] = template_image.wcs.wcs.cdelt[0] ft_wcs.wcs.cdelt[1] = template_image.wcs.wcs.cdelt[1] ft_data = fft(im.data.astype('complex')) return create_image_from_array( ft_data, wcs=ft_wcs, polarisation_frame=im.polarisation_frame) else: raise NotImplementedError("Cannot FFT specified axes")
def invert_2d_base_timing(vis: Visibility, im: Image, dopsf: bool = False, normalize: bool = True, **kwargs) \ -> (Image, numpy.ndarray, tuple): """ Invert using 2D convolution function, including w projection optionally Use the image im as a template. Do PSF in a separate call. This is at the bottom of the layering i.e. all transforms are eventually expressed in terms of this function. . Any shifting needed is performed here. :param vis: Visibility to be inverted :param im: image template (not changed) :param dopsf: Make the psf instead of the dirty image :param normalize: Normalize by the sum of weights (True) :return: resulting image """ opt = get_parameter(kwargs, 'opt', False) if not opt: log.debug('Using original algorithm') else: log.debug('Using optimized algorithm') if not isinstance(vis, Visibility): svis = coalesce_visibility(vis, **kwargs) else: svis = copy_visibility(vis) if dopsf: svis.data['vis'] = numpy.ones_like(svis.data['vis']) svis = shift_vis_to_image(svis, im, tangent=True, inverse=False) nchan, npol, ny, nx = im.data.shape padding = {} if get_parameter(kwargs, "padding", False): padding = {'padding': get_parameter(kwargs, "padding", False)} spectral_mode, vfrequencymap = get_frequency_map(svis, im, opt) polarisation_mode, vpolarisationmap = get_polarisation_map(svis, im) uvw_mode, shape, padding, vuvwmap = get_uvw_map(svis, im, **padding) kernel_name, gcf, vkernellist = get_kernel_list(svis, im, **kwargs) # Optionally pad to control aliasing imgridpad = numpy.zeros( [nchan, npol, int(round(padding * ny)), int(round(padding * nx))], dtype='complex') # Use original algorithm if not opt: time_grid = -time.time() imgridpad, sumwt = convolutional_grid(vkernellist, imgridpad, svis.data['vis'], svis.data['imaging_weight'], vuvwmap, vfrequencymap, vpolarisationmap) time_grid += time.time() # Use optimized algorithm else: time_grid = -time.time() kernel_indices, kernels = vkernellist ks0, ks1, ks2, ks3 = kernels[0].shape kernels_c = numpy.zeros((len(kernels), ks0, ks1, ks2, ks3), dtype=kernels[0].dtype) for i in range(len(kernels)): kernels_c[i, ...] = kernels[i] vfrequencymap_c = numpy.array(vfrequencymap, dtype=numpy.int32) sumwt = numpy.zeros((imgridpad.shape[0], imgridpad.shape[1]), dtype=numpy.float64) convolutional_grid_c(imgridpad, sumwt, native_order(svis.data['vis']), native_order(svis.data['imaging_weight']), native_order(kernels_c), native_order(kernel_indices), native_order(vuvwmap), native_order(vfrequencymap_c)) time_grid += time.time() # Fourier transform the padded grid to image, multiply by the gridding correction # function, and extract the unpadded inner part. # Normalise weights for consistency with transform sumwt /= float(padding * int(round(padding * nx)) * ny) imaginary = get_parameter(kwargs, "imaginary", False) if imaginary: log.debug("invert_2d_base: retaining imaginary part of dirty image") result = extract_mid(ifft(imgridpad) * gcf, npixel=nx) resultreal = create_image_from_array(result.real, im.wcs) resultimag = create_image_from_array(result.imag, im.wcs) if normalize: resultreal = normalize_sumwt(resultreal, sumwt) resultimag = normalize_sumwt(resultimag, sumwt) return resultreal, sumwt, resultimag else: # Use original algorithm if not opt: time_ifft = -time.time() inarr = ifft(imgridpad) time_ifft += time.time() # Use optimized algorithm else: time_ifft = -time.time() inarr = numpy.zeros(imgridpad.shape, dtype=imgridpad.dtype) ifft_c(inarr, imgridpad) time_ifft += time.time() result = extract_mid(numpy.real(inarr) * gcf, npixel=nx) resultimage = create_image_from_array(result, im.wcs) if normalize: resultimage = normalize_sumwt(resultimage, sumwt) return resultimage, sumwt, (time_grid, time_ifft)
def invert_2d_base(vis: Visibility, im: Image, dopsf: bool = False, normalize: bool = True, **kwargs) \ -> (Image, numpy.ndarray): """ Invert using 2D convolution function, including w projection optionally Use the image im as a template. Do PSF in a separate call. This is at the bottom of the layering i.e. all transforms are eventually expressed in terms of this function. . Any shifting needed is performed here. :param vis: Visibility to be inverted :param im: image template (not changed) :param dopsf: Make the psf instead of the dirty image :param normalize: Normalize by the sum of weights (True) :return: resulting image """ if type(vis) is not Visibility: svis = coalesce_visibility(vis, **kwargs) else: svis = copy_visibility(vis) if dopsf: svis.data['vis'] = numpy.ones_like(svis.data['vis']) svis = shift_vis_to_image(svis, im, tangent=True, inverse=False) nchan, npol, ny, nx = im.data.shape spectral_mode, vfrequencymap = get_frequency_map(svis, im) polarisation_mode, vpolarisationmap = get_polarisation_map( svis, im, **kwargs) uvw_mode, shape, padding, vuvwmap = get_uvw_map(svis, im, **kwargs) kernel_name, gcf, vkernellist = get_kernel_list(svis, im, **kwargs) # Optionally pad to control aliasing imgridpad = numpy.zeros( [nchan, npol, int(round(padding * ny)), int(round(padding * nx))], dtype='complex') imgridpad, sumwt = convolutional_grid(vkernellist, imgridpad, svis.data['vis'], svis.data['imaging_weight'], vuvwmap, vfrequencymap, vpolarisationmap) # Fourier transform the padded grid to image, multiply by the gridding correction # function, and extract the unpadded inner part. # Normalise weights for consistency with transform sumwt /= float(padding * int(round(padding * nx)) * ny) imaginary = get_parameter(kwargs, "imaginary", False) if imaginary: log.debug("invert_2d_base: retaining imaginary part of dirty image") result = extract_mid(ifft(imgridpad) * gcf, npixel=nx) resultreal = create_image_from_array(result.real, im.wcs) resultimag = create_image_from_array(result.imag, im.wcs) if normalize: resultreal = normalize_sumwt(resultreal, sumwt) resultimag = normalize_sumwt(resultimag, sumwt) return resultreal, sumwt, resultimag else: result = extract_mid(numpy.real(ifft(imgridpad)) * gcf, npixel=nx) resultimage = create_image_from_array(result, im.wcs) if normalize: resultimage = normalize_sumwt(resultimage, sumwt) return resultimage, sumwt