Example #1
0
 def test_fftim(self):
     self.m31image = create_test_image(cellsize=0.001,
                                       frequency=[1e8],
                                       canonical=True)
     m31_fft = fft_image(self.m31image)
     m31_fft_ifft = fft_image(m31_fft, self.m31image)
     numpy.testing.assert_array_almost_equal(self.m31image.data,
                                             m31_fft_ifft.data.real, 12)
     m31_fft.data = numpy.abs(m31_fft.data)
     export_image_to_fits(m31_fft,
                          fitsfile='%s/test_m31_fft.fits' % (self.dir))
Example #2
0
 def test_tapering_Gaussian(self):
     self.actualSetUp()
     size_required = 0.003542
     self.componentvis, _, _ = weight_visibility(self.componentvis,
                                                 self.model,
                                                 algoritm='uniform')
     self.componentvis = taper_visibility_gaussian(self.componentvis,
                                                   beam=size_required)
     psf, sumwt = invert_2d(self.componentvis, self.model, dopsf=True)
     export_image_to_fits(
         psf, '%s/test_weighting_gaussian_taper_psf.fits' % self.dir)
     xfr = fft_image(psf)
     xfr.data = xfr.data.real.astype('float')
     export_image_to_fits(
         xfr, '%s/test_weighting_gaussian_taper_xfr.fits' % self.dir)
     npixel = psf.data.shape[3]
     sl = slice(npixel // 2 - 7, npixel // 2 + 8)
     fit = fit_2dgaussian(psf.data[0, 0, sl, sl])
     if fit.x_stddev <= 0.0 or fit.y_stddev <= 0.0:
         raise ValueError('Error in fitting to psf')
     # fit_2dgaussian returns sqrt of variance. We need to convert that to FWHM.
     # https://en.wikipedia.org/wiki/Full_width_at_half_maximum
     scale_factor = numpy.sqrt(8 * numpy.log(2.0))
     size = numpy.sqrt(fit.x_stddev * fit.y_stddev) * scale_factor
     # Now we need to convert to radians
     size *= numpy.pi * self.model.wcs.wcs.cdelt[1] / 180.0
     # Very impressive! Desired 0.01 Acheived 0.0100006250829
     assert numpy.abs(size - size_required) < 0.001 * size_required, \
         "Fit should be %f, actually is %f" % (size_required, size)
Example #3
0
 def test_fftim_factors(self):
     for i in [3, 5, 7]:
         npixel = 256 * i
         m31image = create_test_image(cellsize=0.001,
                                      frequency=[1e8],
                                      canonical=True)
         padded = pad_image(m31image, [1, 1, npixel, npixel])
         assert padded.shape == (1, 1, npixel, npixel)
         padded_fft = fft_image(padded)
         padded_fft_ifft = fft_image(padded_fft, m31image)
         numpy.testing.assert_array_almost_equal(padded.data,
                                                 padded_fft_ifft.data.real,
                                                 12)
         padded_fft.data = numpy.abs(padded_fft.data)
         export_image_to_fits(padded_fft,
                              fitsfile='%s/test_m31_fft_%d.fits' %
                              (self.dir, npixel))
Example #4
0
 def test_convert_image_to_kernel(self):
     m31image = create_test_image(cellsize=0.001,
                                  frequency=[1e8],
                                  canonical=True)
     screen = create_w_term_like(m31image, w=20000.0, remove_shift=True)
     screen_fft = fft_image(screen)
     converted = convert_image_to_kernel(screen_fft, 8, 8)
     assert converted.shape == (1, 1, 8, 8, 8, 8)
     with self.assertRaises(AssertionError):
         converted = convert_image_to_kernel(m31image, 15, 1)
     with self.assertRaises(AssertionError):
         converted = convert_image_to_kernel(m31image, 15, 1000)
Example #5
0
 def test_tapering_Tukey(self):
     self.actualSetUp()
     self.componentvis, _, _ = weight_visibility(self.componentvis,
                                                 self.model,
                                                 algoritm='uniform')
     self.componentvis = taper_visibility_tukey(self.componentvis,
                                                tukey=1.0)
     psf, sumwt = invert_2d(self.componentvis, self.model, dopsf=True)
     export_image_to_fits(
         psf, '%s/test_weighting_tukey_taper_psf.fits' % self.dir)
     xfr = fft_image(psf)
     xfr.data = xfr.data.real.astype('float')
     export_image_to_fits(
         xfr, '%s/test_weighting_tukey_taper_xfr.fits' % self.dir)
Example #6
0
def create_awterm_convolutionfunction(im,
                                      make_pb=None,
                                      nw=1,
                                      wstep=1e15,
                                      oversampling=8,
                                      support=6,
                                      use_aaf=True,
                                      maxsupport=512):
    """ Fill AW projection kernel into a GridData.

    :param im: Image template
    :param make_pb: Function to make the primary beam model image
    :param nw: Number of w planes
    :param wstep: Step in w (wavelengths)
    :param oversampling: Oversampling of the convolution function in uv space
    :return: griddata correction Image, griddata kernel as GridData
    """
    d2r = numpy.pi / 180.0

    # We only need the griddata correction function for the PSWF so we make
    # it for the shape of the image
    nchan, npol, ony, onx = im.data.shape

    assert isinstance(im, Image)
    # Calculate the template convolution kernel.
    cf = create_convolutionfunction_from_image(im,
                                               oversampling=oversampling,
                                               support=support)

    cf_shape = list(cf.data.shape)
    cf_shape[2] = nw
    cf.data = numpy.zeros(cf_shape).astype('complex')

    cf.grid_wcs.wcs.crpix[4] = nw // 2 + 1.0
    cf.grid_wcs.wcs.cdelt[4] = wstep
    cf.grid_wcs.wcs.ctype[4] = 'WW'
    if numpy.abs(wstep) > 0.0:
        w_list = cf.grid_wcs.sub([5]).wcs_pix2world(range(nw), 0)[0]
    else:
        w_list = [0.0]

    assert isinstance(oversampling, int)
    assert oversampling > 0

    nx = max(maxsupport, 2 * oversampling * support)
    ny = max(maxsupport, 2 * oversampling * support)

    qnx = nx // oversampling
    qny = ny // oversampling

    cf.data[...] = 0.0

    subim = copy_image(im)
    ccell = onx * numpy.abs(d2r * subim.wcs.wcs.cdelt[0]) / qnx

    subim.data = numpy.zeros([nchan, npol, qny, qnx])
    subim.wcs.wcs.cdelt[0] = -ccell / d2r
    subim.wcs.wcs.cdelt[1] = +ccell / d2r
    subim.wcs.wcs.crpix[0] = qnx // 2 + 1.0
    subim.wcs.wcs.crpix[1] = qny // 2 + 1.0

    if use_aaf:
        this_pswf_gcf, _ = create_pswf_convolutionfunction(subim,
                                                           oversampling=1,
                                                           support=6)
        norm = 1.0 / this_pswf_gcf.data
    else:
        norm = 1.0

    if make_pb is not None:
        pb = make_pb(subim)
        rpb, footprint = reproject_image(pb, subim.wcs, shape=subim.shape)
        rpb.data[footprint.data < 1e-6] = 0.0
        norm *= rpb.data

    # We might need to work with a larger image
    padded_shape = [nchan, npol, ny, nx]
    thisplane = copy_image(subim)
    thisplane.data = numpy.zeros(thisplane.shape, dtype='complex')
    for z, w in enumerate(w_list):
        thisplane.data[...] = 0.0 + 0.0j
        thisplane = create_w_term_like(thisplane, w, dopol=True)
        thisplane.data *= norm
        paddedplane = pad_image(thisplane, padded_shape)
        paddedplane = fft_image(paddedplane)

        ycen, xcen = ny // 2, nx // 2
        for y in range(oversampling):
            ybeg = y + ycen + (support * oversampling) // 2 - oversampling // 2
            yend = y + ycen - (support * oversampling) // 2 - oversampling // 2
            vv = range(ybeg, yend, -oversampling)
            for x in range(oversampling):
                xbeg = x + xcen + (support *
                                   oversampling) // 2 - oversampling // 2
                xend = x + xcen - (support *
                                   oversampling) // 2 - oversampling // 2

                uu = range(xbeg, xend, -oversampling)
                for chan in range(nchan):
                    for pol in range(npol):
                        cf.data[chan, pol, z, y, x, :, :] = paddedplane.data[
                            chan, pol, :, :][vv, :][:, uu]

    cf.data /= numpy.sum(
        numpy.real(cf.data[0, 0, nw // 2, oversampling // 2,
                           oversampling // 2, :, :]))
    cf.data = numpy.conjugate(cf.data)

    if use_aaf:
        pswf_gcf, _ = create_pswf_convolutionfunction(im,
                                                      oversampling=1,
                                                      support=6)
    else:
        pswf_gcf = create_empty_image_like(im)
        pswf_gcf.data[...] = 1.0

    return pswf_gcf, cf
def create_awterm_convolutionfunction(im,
                                      make_pb=None,
                                      nw=1,
                                      wstep=1e15,
                                      oversampling=8,
                                      support=6,
                                      use_aaf=True,
                                      maxsupport=512,
                                      **kwargs):
    """ Fill AW projection kernel into a GridData.

    :param im: Image template
    :param make_pb: Function to make the primary beam model image (hint: use a partial)
    :param nw: Number of w planes
    :param wstep: Step in w (wavelengths)
    :param oversampling: Oversampling of the convolution function in uv space
    :return: griddata correction Image, griddata kernel as GridData
    """
    d2r = numpy.pi / 180.0

    # We only need the griddata correction function for the PSWF so we make
    # it for the shape of the image
    nchan, npol, ony, onx = im.data.shape

    assert isinstance(im, Image)
    # Calculate the template convolution kernel.
    cf = create_convolutionfunction_from_image(im,
                                               oversampling=oversampling,
                                               support=support)

    cf_shape = list(cf.data.shape)
    cf_shape[2] = nw
    cf.data = numpy.zeros(cf_shape).astype('complex')

    cf.grid_wcs.wcs.crpix[4] = nw // 2 + 1.0
    cf.grid_wcs.wcs.cdelt[4] = wstep
    cf.grid_wcs.wcs.ctype[4] = 'WW'
    if numpy.abs(wstep) > 0.0:
        w_list = cf.grid_wcs.sub([5]).wcs_pix2world(range(nw), 0)[0]
    else:
        w_list = [0.0]

    assert isinstance(oversampling, int)
    assert oversampling > 0

    nx = max(maxsupport, 2 * oversampling * support)
    ny = max(maxsupport, 2 * oversampling * support)

    qnx = nx // oversampling
    qny = ny // oversampling

    cf.data[...] = 0.0

    subim = copy_image(im)
    ccell = onx * numpy.abs(d2r * subim.wcs.wcs.cdelt[0]) / qnx

    subim.data = numpy.zeros([nchan, npol, qny, qnx])
    subim.wcs.wcs.cdelt[0] = -ccell / d2r
    subim.wcs.wcs.cdelt[1] = +ccell / d2r
    subim.wcs.wcs.crpix[0] = qnx // 2 + 1.0
    subim.wcs.wcs.crpix[1] = qny // 2 + 1.0

    if use_aaf:
        this_pswf_gcf, _ = create_pswf_convolutionfunction(subim,
                                                           oversampling=1,
                                                           support=6)
        norm = 1.0 / this_pswf_gcf.data
    else:
        norm = 1.0

    if make_pb is not None:
        pb = make_pb(subim)
        rpb, footprint = reproject_image(pb, subim.wcs, shape=subim.shape)
        rpb.data[footprint.data < 1e-6] = 0.0
        norm *= rpb.data

    # We might need to work with a larger image
    padded_shape = [nchan, npol, ny, nx]
    thisplane = copy_image(subim)
    thisplane.data = numpy.zeros(thisplane.shape, dtype='complex')
    for z, w in enumerate(w_list):
        thisplane.data[...] = 0.0 + 0.0j
        thisplane = create_w_term_like(thisplane, w, dopol=True)
        thisplane.data *= norm
        paddedplane = pad_image(thisplane, padded_shape)
        paddedplane = fft_image(paddedplane)

        ycen, xcen = ny // 2, nx // 2
        for y in range(oversampling):
            ybeg = y + ycen + (support * oversampling) // 2 - oversampling // 2
            yend = y + ycen - (support * oversampling) // 2 - oversampling // 2
            # vv = range(ybeg, yend, -oversampling)
            for x in range(oversampling):
                xbeg = x + xcen + (support *
                                   oversampling) // 2 - oversampling // 2
                xend = x + xcen - (support *
                                   oversampling) // 2 - oversampling // 2

                # uu = range(xbeg, xend, -oversampling)
                cf.data[..., z, y,
                        x, :, :] = paddedplane.data[...,
                                                    ybeg:yend:-oversampling,
                                                    xbeg:xend:-oversampling]
                # for chan in range(nchan):
                #     for pol in range(npol):
                #         cf.data[chan, pol, z, y, x, :, :] = paddedplane.data[chan, pol, :, :][vv, :][:, uu]

    cf.data /= numpy.sum(
        numpy.real(cf.data[0, 0, nw // 2, oversampling // 2,
                           oversampling // 2, :, :]))
    cf.data = numpy.conjugate(cf.data)

    #====================================
    #Use ASKAPSoft routine to crop the support size
    crop_ASKAPSOft_like = True
    if crop_ASKAPSOft_like:
        #Hardcode the cellsize: 1 / FOV
        #uv_cellsize = 57.3;#N=1200 pixel and pixelsize is 3 arcseconds
        #uv_cellsize = 43.97;#N=1600 pixel and pixelsize is 3 arcseconds
        #uv_cellsize = 114.6;#N=1800 pixel with 1 arcsecond pixelsize
        #uv_cellsize = 57.3;#N=1800 pixel with 2 arcsecond pixelsize
        #uv_cellsize = 1145.91509915;#N=1800 pixxel with 0.1 arcsecond pixelsize

        #Get from **kwargs
        if kwargs is None:
            #Safe solution works for baselines up to > 100km and result in small kernels
            uv_cellsize = 1145.91509915
            #N=1800 pixxel with 0.1 arcsecond pixelsize

        if 'UVcellsize' in kwargs.keys():
            uv_cellsize = kwargs['UVcellsize']

        #print(uv_cellsize);

        #Cutoff param in ASKAPSoft hardcoded as well
        ASKAPSoft_cutof = 0.1

        wTheta_list = numpy.zeros(len(w_list))
        for i in range(0, len(w_list)):
            if w_list[i] == 0:
                wTheta_list[i] = 0.9
                #This is due to the future if statements cause if it is small, the kernel will be 3 which is a clear cutoff
            else:
                wTheta_list[i] = numpy.fabs(
                    w_list[i]) / (uv_cellsize * uv_cellsize)

        kernel_size_list = []

        #We rounded the kernels according to conventional rounding rules
        for i in range(0, len(wTheta_list)):
            #if wTheta_list[i] < 1:
            if wTheta_list[i] < 1:  #Change to ASKAPSoft
                kernel_size_list.append(int(3.))
            elif ASKAPSoft_cutof < 0.01:
                kernel_size_list.append(int(6 + 1.14 * wTheta_list[i]))
            else:
                kernel_size_list.append(
                    int(numpy.sqrt(49 + wTheta_list[i] * wTheta_list[i])))

        log.info('W-kernel w-terms:')
        log.info(w_list)
        log.info('Corresponding w-kernel sizes:')
        log.info(kernel_size_list)

        print(numpy.unique(kernel_size_list))
        #print(kernel_size_list);

        crop_list = []
        #another rounding according to conventional rounding rules
        for i in range(0, len(kernel_size_list)):
            if support - kernel_size_list[i] <= 0:
                crop_list.append(int(0))
            else:
                crop_list.append(int((support - kernel_size_list[i]) / 2))

        #Crop original suppor
        for i in range(0, nw):
            if crop_list[i] != 0:
                cf.data[0, 0, i, :, :, 0:crop_list[i], :] = 0
                cf.data[0, 0, i, :, :, -crop_list[i]:, :] = 0
                cf.data[0, 0, i, :, :, :, 0:crop_list[i]] = 0
                cf.data[0, 0, i, :, :, :, -crop_list[i]:] = 0
            else:
                pass

            #Plot
            #import matplotlib.pyplot as plt
            #cf.data[0,0,i,0,0,...][cf.data[0,0,i,0,0,...] != 0.] = 1+0.j;
            #plt.imshow(numpy.real(cf.data[0,0,i,0,0,...]))

            #plt.show(block=True)
            #plt.close();

    #====================================

    if use_aaf:
        pswf_gcf, _ = create_pswf_convolutionfunction(im,
                                                      oversampling=1,
                                                      support=6)
    else:
        pswf_gcf = create_empty_image_like(im)
        pswf_gcf.data[...] = 1.0

    return pswf_gcf, cf
def create_vp_generic_numeric(model,
                              pointingcentre=None,
                              diameter=15.0,
                              blockage=0.0,
                              taper='gaussian',
                              edge=0.03162278,
                              zernikes=None,
                              padding=4,
                              use_local=True,
                              rho=0.0,
                              diff=0.0):
    """
    Make an image like model and fill it with an analytical model of the primary beam
    
    The elements of the analytical model are:
    - dish, optionally blocked
    - Gaussian taper, default is -12dB at the edge
    - Offset to pointing centre (optional)
    - zernikes in a list of dictionaries. Each list element is of the form {"coeff":0.1, "noll":5}. See aotools for
    more details
    - Output image can be in RA, DEC coordinates or AZELGEO coordinates (the default). use_local=True means to use
    AZELGEO coordinates centered on 0deg 0deg.
    
    The dish is zero padded according to padding and FFT'ed to get the voltage pattern.
    
    :param model:
    :param pointingcentre: SkyCoord of desired pointing centre
    :param diameter: Diameter of dish in metres
    :param blockage: Blockage of dish in metres
    :param taper: "Gaussian" or None
    :param edge: Value of taper at the end of the dish (default corresponds to -12dB)
    :param zernikes: Zernikes to be applied as phase across the dish (see above)
    :param padding: Pad the image by this amount
    :param use_local: Use local frame (AZELGEO)?
    :return:
    """
    beam = create_empty_image_like(model)
    nchan, npol, ny, nx = beam.shape
    padded_shape = [nchan, npol, padding * ny, padding * nx]
    padded_beam = pad_image(beam, padded_shape)
    padded_beam.data = numpy.zeros(padded_beam.data.shape, dtype='complex')
    _, _, pny, pnx = padded_beam.shape

    xfr = fft_image(padded_beam)
    cx, cy = xfr.wcs.sub(2).wcs.crpix[0] - 1, xfr.wcs.sub(2).wcs.crpix[1] - 1

    for chan in range(nchan):

        # The frequency axis is the second to last in the beam
        frequency = xfr.wcs.sub(['spectral']).wcs_pix2world([chan], 0)[0]
        wavelength = const.c.to('m s^-1').value / frequency

        scalex = xfr.wcs.sub(2).wcs.cdelt[0] * wavelength
        scaley = xfr.wcs.sub(2).wcs.cdelt[1] * wavelength
        # xx, yy in metres
        xx, yy = numpy.meshgrid(scalex * (range(pnx) - cx),
                                scaley * (range(pny) - cy))

        # rr in metres
        rr = numpy.sqrt(xx**2 + yy**2)
        for pol in range(npol):
            xfr.data[chan, pol, ...] = tapered_disk(rr,
                                                    diameter / 2.0,
                                                    blockage=blockage / 2.0,
                                                    edge=edge,
                                                    taper=taper)

        if pointingcentre is not None:
            # Correct for pointing centre
            pcx, pcy = pointingcentre.to_pixel(padded_beam.wcs, origin=0)
            pxx, pyy = numpy.meshgrid((range(pnx) - cx), (range(pny) - cy))
            phase = 2 * numpy.pi * ((pcx - cx) * pxx / float(pnx) +
                                    (pcy - cy) * pyy / float(pny))
            for pol in range(npol):
                xfr.data[chan, pol, ...] *= numpy.exp(1j * phase)

        if isinstance(zernikes, collections.Iterable):
            try:
                import aotools
            except ModuleNotFoundError:
                raise ModuleNotFoundError("aotools is not installed")

            ndisk = numpy.ceil(numpy.abs(diameter / scalex)).astype('int')[0]
            ndisk = 2 * ((ndisk + 1) // 2)
            phase = numpy.zeros([ndisk, ndisk])
            for zernike in zernikes:
                phase = zernike['coeff'] * aotools.functions.zernike(
                    zernike['noll'], ndisk)

            # import matplotlib.pyplot as plt
            # plt.clf()
            # plt.imshow(phase)
            # plt.colorbar()
            # plt.show()
            #
            blc = pnx // 2 - ndisk // 2
            trc = pnx // 2 + ndisk // 2
            for pol in range(npol):
                xfr.data[chan, pol, blc:trc,
                         blc:trc] = xfr.data[chan, pol, blc:trc,
                                             blc:trc] * numpy.exp(1j * phase)

    padded_beam = fft_image(xfr, padded_beam)

    # Undo padding
    beam = create_empty_image_like(model)
    beam.data = padded_beam.data[...,
                                 (pny // 2 - ny // 2):(pny // 2 + ny // 2),
                                 (pnx // 2 - nx // 2):(pnx // 2 + nx // 2)]
    for chan in range(nchan):
        beam.data[chan, ...] /= numpy.max(numpy.abs(beam.data[chan, ...]))

    set_pb_header(beam, use_local=use_local)
    return beam
Example #9
0
    noise_channel = args.noise_channel
    resolution = args.resolution

    plt.clf()
    show_image(im, chan=signal_channel)
    plt.title('Signal image %s' % (basename))
    plt.savefig('simulation_image_channel_%d.png' % signal_channel)
    plt.show()
    plt.clf()
    show_image(im, chan=noise_channel)
    plt.title('Noise image %s' % (basename))
    plt.savefig('simulation_noise_channel_%d.png' % signal_channel)
    plt.show()

    print(im)
    imfft = fft_image(im)
    print(imfft)

    omega = numpy.pi * resolution**2 / (4 * numpy.log(2.0))
    wavelength = consts.c / numpy.average(im.frequency)
    kperjy = 1e-26 * wavelength**2 / (2 * consts.k_B * omega)

    im_spectrum = copy_image(imfft)
    im_spectrum.data = kperjy.value * numpy.abs(imfft.data)
    plt.clf()
    show_image(im_spectrum,
               chan=signal_channel,
               vmax=0.01 * numpy.max(im_spectrum.data[signal_channel, ...]))
    plt.gca().set_title("Amplitude(FFT(image)) %s" % (basename))
    plt.tight_layout()
    plt.savefig('power_spectrum_image_channel_%d.png' % signal_channel)