def test_convolutional_grid(self):
     npixel = 256
     nvis = 10000
     nchan = 1
     npol = 4
     uvgrid = numpy.zeros([nchan, npol, npixel, npixel], dtype='complex')
     gcf, kernel = anti_aliasing_calculate((npixel, npixel), 8)
     # kernel has shape [kernel_oversampling, kernel_oversampling, npixel, npixel] The fractional
     # part of the coordinate maps onto the first two axes.
     # Make some uv coordinates with random locations
     uvcoords = numpy.array(
         [[random.uniform(-0.25, 0.25),
           random.uniform(-0.25, 0.25)] for ivis in range(nvis)])
     # Make some visibilities, all complex unity
     vis = numpy.ones([nvis, nchan, npol], dtype='complex')
     visweights = numpy.ones([nvis, nchan, npol])
     kernels = (numpy.zeros([nvis], dtype='int'), [kernel])
     frequencymap = numpy.zeros([nvis], dtype='int')
     # On my laptop the following takes about 34ss for 4e6 * 50 = 2e8 points so about 170 ns per point
     uvgrid, sumwt = convolutional_grid(kernels, uvgrid, vis, visweights,
                                        uvcoords, frequencymap)
     assert numpy.sum(sumwt) > 0.0
     assert uvgrid.shape[0] == nchan
     assert uvgrid.shape[1] == npol
     assert uvgrid.shape[2] == npixel
     assert uvgrid.shape[3] == npixel
Ejemplo n.º 2
0
def standard_kernel_list(vis, shape, oversampling=8, support=3):
    """Return a lambda function to calculate the standard visibility kernel

    :param vis: visibility
    :param shape: tuple with 2D shape of grid
    :param oversampling: Oversampling factor
    :param support: Support of kernel
    :returns: Function to look up gridding kernel
    """
    return [anti_aliasing_calculate(shape, oversampling, support)[1]]
Ejemplo n.º 3
0
def standard_kernel_list(vis, shape, oversampling=8, support=3):
    """Return a generator to calculate the standard visibility kernel

    :param vis: visibility
    :param shape: tuple with 2D shape of grid
    :param oversampling: Oversampling factor
    :param support: Support of kernel
    :return: Function to look up gridding kernel
    """
    return numpy.zeros_like(vis.w, dtype='int'), [anti_aliasing_calculate(shape, oversampling, support)[1]]
Ejemplo n.º 4
0
def get_kernel_list(vis: Visibility, im, **kwargs):
    """Get the list of kernels, one per visibility
    
    """

    shape = im.data.shape
    npixel = shape[3]
    cellsize = numpy.pi * im.wcs.wcs.cdelt[1] / 180.0

    kernelname = get_parameter(kwargs, "kernel", "2d")
    oversampling = get_parameter(kwargs, "oversampling", 8)
    padding = get_parameter(kwargs, "padding", 2)

    gcf, _ = anti_aliasing_calculate((padding * npixel, padding * npixel),
                                     oversampling)

    wabsmax = numpy.max(numpy.abs(vis.w))
    if kernelname == 'wprojection' and wabsmax > 0.0:

        # wprojection needs a lot of commentary!
        log.debug("get_kernel_list: Using wprojection kernel")

        # The field of view must be as padded!
        fov = cellsize * npixel * padding
        r_f = (cellsize * npixel / 2)**2 / abs(cellsize)
        log.debug("get_kernel_list: Fresnel number = %f" % (r_f))
        delA = get_parameter(kwargs, 'wloss', 0.02)

        advice = advise_wide_field(vis, delA)
        wstep = get_parameter(kwargs, "wstep",
                              advice['w_sampling_primary_beam'])

        log.debug("get_kernel_list: Using w projection with wstep = %f" %
                  (wstep))

        # Now calculate the maximum support for the w kernel
        npixel_kernel = get_parameter(
            kwargs, "kernelwidth",
            (2 * int(round(numpy.sin(0.5 * fov) * npixel / 4.0))))
        assert npixel_kernel % 2 == 0
        log.debug("get_kernel_list: Maximum w kernel full width = %d pixels" %
                  (npixel_kernel))
        kernel_list = w_kernel_list(vis, (npixel, npixel),
                                    fov,
                                    wstep=wstep,
                                    npixel_kernel=npixel_kernel,
                                    oversampling=oversampling)
    else:
        kernelname = '2d'
        kernel_list = standard_kernel_list(
            vis, (padding * npixel, padding * npixel),
            oversampling=8,
            support=3)

    return kernelname, gcf, kernel_list
Ejemplo n.º 5
0
def get_kernel_list(vis: Visibility, im: Image, **kwargs):
    """Get the list of kernels, one per visibility
    
    """
    
    shape = im.data.shape
    npixel = shape[3]
    cellsize = numpy.pi * im.wcs.wcs.cdelt[1] / 180.0
    
    kernelname = get_parameter(kwargs, "kernel", "2d")
    oversampling = get_parameter(kwargs, "oversampling", 8)
    padding = get_parameter(kwargs, "padding", 2)

    gcf, _ = anti_aliasing_calculate((padding * npixel, padding * npixel), oversampling)
    
    wabsmax = numpy.max(numpy.abs(vis.w))
    if kernelname == 'wprojection' and wabsmax > 0.0:
        
        # wprojection needs a lot of commentary!
        log.debug("get_kernel_list: Using wprojection kernel")
        
        # The field of view must be as padded! R_F is for reporting only so that
        # need not be padded.
        fov = cellsize * npixel * padding
        r_f = (cellsize * npixel / 2) ** 2 / abs(cellsize)
        log.debug("get_kernel_list: Fresnel number = %f" % (r_f))
        delA = get_parameter(kwargs, 'wloss', 0.02)
        
        advice = advise_wide_field(vis, delA)
        wstep = get_parameter(kwargs, "wstep", advice['w_sampling_primary_beam'])
        
        log.debug("get_kernel_list: Using w projection with wstep = %f" % (wstep))
        
        # Now calculate the maximum support for the w kernel
        kernelwidth = get_parameter(kwargs, "kernelwidth",
                                    (2 * int(round(numpy.sin(0.5 * fov) * npixel * wabsmax * cellsize))))
        kernelwidth = max(kernelwidth, 8)
        assert kernelwidth % 2 == 0
        log.debug("get_kernel_list: Maximum w kernel full width = %d pixels" % (kernelwidth))
        padded_shape=[im.shape[0], im.shape[1], im.shape[2] * padding, im.shape[3] * padding]

        remove_shift = get_parameter(kwargs, "remove_shift", True)
        padded_image = pad_image(im, padded_shape)
        kernel_list = w_kernel_list(vis, padded_image, oversampling=oversampling, wstep=wstep,
                                    kernelwidth=kernelwidth, remove_shift=remove_shift)
    else:
        kernelname = '2d'
        kernel_list = standard_kernel_list(vis, (padding * npixel, padding * npixel),
                                           oversampling=oversampling)
    
    return kernelname, gcf, kernel_list
    def test_convolutional_degrid(self):
        npixel = 256
        nvis = 100000
        nchan = 1
        npol = 4
        uvgrid = numpy.ones([nchan, npol, npixel, npixel], dtype='complex')
        gcf, kernel = anti_aliasing_calculate((npixel, npixel), 8)
        # kernel has shape [kernel_oversampling, kernel_oversampling, npixel, npixel] The fractional
        # part of the coordinate maps onto the first two axes.
        # Make some uv coordinates with random locations
        uvcoords = numpy.array(
            [[random.uniform(-0.25, 0.25),
              random.uniform(-0.25, 0.25)] for ivis in range(nvis)])
        vshape = [nvis, npol]
        kernels = (numpy.zeros([nvis], dtype='int'), [kernel])
        frequencymap = numpy.zeros([nvis], dtype='int')

        vis = convolutional_degrid(kernels, vshape, uvgrid, uvcoords,
                                   frequencymap)
        assert vis.shape[0] == nvis
        assert vis.shape[1] == npol
 def test_anti_aliasing_calculate(self):
     for shape in [(64, 64), (128, 128), (256, 256)]:
         _, aaf = anti_aliasing_calculate(shape, 8)
         self.assertAlmostEqual(
             numpy.max(aaf[..., aaf.shape[1] // 2, aaf.shape[0] // 2]),
             0.18712109669890534)
Ejemplo n.º 8
0
def w_kernel_list(vis: Visibility,
                  im: Image,
                  oversampling=1,
                  wstep=50.0,
                  kernelwidth=16,
                  **kwargs):
    """ Calculate w convolution kernels
    
    Uses create_w_term_like to calculate the w screen. This is exactly as wstacking does.

    Returns (indices to the w kernel for each row, kernels)

    Each kernel has axes [centre_v, centre_u, offset_v, offset_u]. We currently use the same
    convolution function for all channels and polarisations. Changing that behaviour would
    require modest changes here and to the gridding/degridding routines.

    :param vis: visibility
    :param image: Template image (padding, if any, occurs before this)
    :param oversampling: Oversampling factor
    :param wstep: Step in w between cached functions
    :return: (indices to the w kernel for each row, kernels)
    """

    nchan, npol, ny, nx = im.shape
    gcf, _ = anti_aliasing_calculate((ny, nx))

    assert oversampling % 2 == 0 or oversampling == 1, "oversampling must be unity or even"
    assert kernelwidth % 2 == 0, "kernelwidth must be even"

    wmaxabs = numpy.max(numpy.abs(vis.w))
    log.debug(
        "w_kernel_list: Maximum absolute w = %.1f, step is %.1f wavelengths" %
        (wmaxabs, wstep))

    def digitise(w, wstep):
        return numpy.ceil((w + wmaxabs) / wstep).astype('int')

    # Find all the unique indices for which we need a kernel
    nwsteps = digitise(wmaxabs, wstep) + 1
    w_list = numpy.linspace(-wmaxabs, +wmaxabs, nwsteps)

    print('====', nwsteps, wstep, len(w_list))

    wtemplate = copy_image(im)

    wtemplate.data = numpy.zeros(wtemplate.shape, dtype=im.data.dtype)

    padded_shape = list(wtemplate.shape)
    padded_shape[3] *= oversampling
    padded_shape[2] *= oversampling

    # For all the unique indices, calculate the corresponding w kernel
    kernels = list()
    for w in w_list:
        # Make a w screen
        wscreen = create_w_term_like(wtemplate, w, vis.phasecentre, **kwargs)
        wscreen.data /= gcf
        assert numpy.max(numpy.abs(wscreen.data)) > 0.0, 'w screen is empty'
        wscreen_padded = pad_image(wscreen, padded_shape)

        wconv = fft_image(wscreen_padded)
        wconv.data *= float(oversampling)**2
        # For the moment, ignore the polarisation and channel axes
        kernels.append(
            convert_image_to_kernel(wconv, oversampling,
                                    kernelwidth).data[0, 0, ...])

    # Now make a lookup table from row number of vis to the kernel
    kernel_indices = digitise(vis.w, wstep)
    assert numpy.max(kernel_indices) < len(kernels), "wabsmax %f wstep %f" % (
        wmaxabs, wstep)
    assert numpy.min(kernel_indices) >= 0, "wabsmax %f wstep %f" % (wmaxabs,
                                                                    wstep)
    return kernel_indices, kernels