processing_components/imaging/primary_beams.py
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

    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:
    
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.
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 .
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):
    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):
        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 = numpy.meshgrid(scalex * (range(pnx) - cx), scaley * (range(pny) - cy))
        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:
            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)
            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
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 ) : 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 ) : 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 = numpy . meshgrid ( scalex * ( range ( pnx ) - cx ) , scaley * ( range ( pny ) - cy ) ) 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 : 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 ) 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 ) 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
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.
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 .
"""
    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:
    """ # The frequency axis is the second to last in the beam # xx, yy in metres # rr in metres # Correct for pointing centre # import matplotlib.pyplot as plt # plt.clf() # plt.imshow(phase) # plt.colorbar() # plt.show() # # Undo padding
None
model
None
pointingcentre
SkyCoord of desired pointing centre
SkyCoord of desired pointing centre
diameter
Diameter of dish in metres
Diameter of dish in metres
blockage
Blockage of dish in metres
Blockage of dish in metres
taper
"Gaussian" or None
" Gaussian " or None
edge
Value of taper at the end of the dish (default corresponds to -12dB)
Value of taper at the end of the dish ( default corresponds to - 12dB )
zernikes
Zernikes to be applied as phase across the dish
Zernikes to be applied as phase across the dish
padding
Pad the image by this amount
Pad the image by this amount
use_local
None
rho
diff