예제 #1
0
def create_low_test_beam(model: Image) -> Image:
    """Create a test power beam for LOW using an image from OSKAR

    :param model: Template image
    :return: Image
    """

    beam = import_image_from_fits(arl_path('data/models/SKA1_LOW_beam.fits'))

    # Scale the image cellsize to account for the different in frequencies. Eventually we will want to
    # use a frequency cube
    log.info("create_low_test_beam: primary beam is defined at %.3f MHz" %
             (beam.wcs.wcs.crval[2] * 1e-6))

    nchan, npol, ny, nx = model.shape

    # We need to interpolate each frequency channel separately. The beam is assumed to just scale with
    # frequency.

    reprojected_beam = create_empty_image_like(model)

    for chan in range(nchan):

        model2dwcs = model.wcs.sub(2).deepcopy()
        model2dshape = [model.shape[2], model.shape[3]]
        beam2dwcs = beam.wcs.sub(2).deepcopy()

        # The frequency axis is the second to last in the beam
        frequency = model.wcs.sub(['spectral']).wcs_pix2world([chan], 0)[0]
        fscale = beam.wcs.wcs.crval[2] / frequency

        beam2dwcs.wcs.cdelt = fscale * beam.wcs.sub(2).wcs.cdelt
        beam2dwcs.wcs.crpix = beam.wcs.sub(2).wcs.crpix
        beam2dwcs.wcs.crval = model.wcs.sub(2).wcs.crval
        beam2dwcs.wcs.ctype = model.wcs.sub(2).wcs.ctype
        model2dwcs.wcs.crpix = [
            model.shape[2] // 2 + 1, model.shape[3] // 2 + 1
        ]

        beam2d = create_image_from_array(beam.data[0, 0, :, :], beam2dwcs,
                                         model.polarisation_frame)
        reprojected_beam2d, footprint = reproject_image(beam2d,
                                                        model2dwcs,
                                                        shape=model2dshape)
        assert numpy.max(
            footprint.data) > 0.0, "No overlap between beam and model"

        reprojected_beam2d.data *= reprojected_beam2d.data
        reprojected_beam2d.data[footprint.data <= 0.0] = 0.0
        for pol in range(npol):
            reprojected_beam.data[chan,
                                  pol, :, :] = reprojected_beam2d.data[:, :]

    return reprojected_beam
예제 #2
0
    def test_reproject(self):
        # Reproject an image
        cellsize = 1.5 * self.cellsize
        newwcs = self.m31image.wcs.deepcopy()
        newwcs.wcs.cdelt[0] = -cellsize
        newwcs.wcs.cdelt[1] = +cellsize

        newshape = numpy.array(self.m31image.data.shape)
        newshape[2] /= 1.5
        newshape[3] /= 1.5
        newimage, footprint = reproject_image(self.m31image,
                                              newwcs,
                                              shape=newshape)
        checkwcs(newimage.wcs, newwcs)
예제 #3
0
def predict_timeslice_single(vis: Visibility,
                             model: Image,
                             predict=predict_2d,
                             remove=True,
                             gcfcf=None,
                             **kwargs) -> Visibility:
    """ Predict using a single time slices.

    This fits a single plane and corrects the image geometry.

    :param vis: Visibility to be predicted
    :param model: model image
    :param predict:
    :param remove: Remove fitted w (so that wprojection will do the right thing)
    :param gcfcf: (Grid correction function, convolution function)
    :return: resulting visibility (in place works)
    """

    assert isinstance(vis, Visibility), vis

    vis.data['vis'][...] = 0.0

    # Fit and remove best fitting plane for this slice
    uvw = vis.uvw
    avis, p, q = fit_uvwplane(vis, remove=remove)

    # We want to describe work image as distorted. We describe the distortion by putting
    # the olbiquity parameters in the wcs. The input model should be described as having
    # zero olbiquity parameters.
    # Note that this has to be zero relative in first element, one relative in second!!!
    if numpy.abs(p) > 1e-7 or numpy.abs(q) > 1e-7:

        newwcs = model.wcs.deepcopy()
        newwcs.wcs.set_pv([(0, 1, -p), (0, 2, -q)])
        workimage, footprintimage = reproject_image(model,
                                                    newwcs,
                                                    shape=model.shape)
        workimage.data[footprintimage.data <= 0.0] = 0.0
        workimage.wcs.wcs.set_pv([(0, 1, -p), (0, 2, -q)])

        # Now we can do the predict
        vis = predict(avis, workimage, gcfcf=gcfcf, **kwargs)
    else:
        vis = predict(avis, model, gcfcf=gcfcf, **kwargs)

    if remove:
        avis.data['uvw'][...] = uvw

    return vis
예제 #4
0
def invert_timeslice_single(vis: Visibility,
                            im: Image,
                            dopsf,
                            normalize=True,
                            remove=True,
                            gcfcf=None,
                            **kwargs) -> (Image, numpy.ndarray):
    """Process single time slice

    Extracted for re-use in parallel version
    :param vis: Visibility to be inverted
    :param im: image template (not changed)
    :param dopsf: Make the psf instead of the dirty image
    :param gcfcf: (Grid correction function, convolution function)
    :param normalize: Normalize by the sum of weights (True)
    """
    assert isinstance(vis, Visibility), vis

    uvw = vis.uvw
    vis, p, q = fit_uvwplane(vis, remove=remove)

    workimage, sumwt = invert_2d(vis,
                                 im,
                                 dopsf,
                                 normalize=normalize,
                                 gcfcf=gcfcf,
                                 **kwargs)
    # Work image is distorted. We describe the distortion by putting the olbiquity parameters in
    # the wcs. The output image should be described as having zero olbiquity parameters.

    if numpy.abs(p) > 1e-7 or numpy.abs(q) > 1e-7:
        # Note that this has to be zero relative in first element, one relative in second!!!!
        workimage.wcs.wcs.set_pv([(0, 1, -p), (0, 2, -q)])

        finalimage, footprint = reproject_image(workimage, im.wcs, im.shape)
        finalimage.data[footprint.data <= 0.0] = 0.0
        finalimage.wcs.wcs.set_pv([(0, 1, 0.0), (0, 2, 0.0)])

        if remove:
            vis.data['uvw'][...] = uvw

        return finalimage, sumwt
    else:
        if remove:
            vis.data['uvw'][...] = uvw

        return workimage, sumwt
예제 #5
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
예제 #6
0
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