Пример #1
0
def main(image_pre, image_post, res_val, max_factor=0.25):
    """
    Verify subtraction by checking quantities in residual images

    Parameters
    ----------
    image_pre : str
        Filename of image before selfcal
    image_post : str
        Filename of image after selfcal
    res_val : float
        Maximum allowed value of peak residual (Jy/beam)
    max_factor : float
        Factor by which old peak residual must exceed new peak residual

    """
    imgpre = pim.image(image_pre)
    maxvalpre = numpy.max(numpy.abs(imgpre.getdata()))
    imgpost = pim.image(image_post)
    maxvalpost = numpy.max(numpy.abs(imgpost.getdata()))

    if (maxvalpost > res_val) or (maxvalpost * max_factor > maxvalpre):
        return {
            'break': False,
            'maxvalpost': maxvalpost,
            'maxvalpre': maxvalpre
        }
    else:
        return {
            'break': True,
            'maxvalpost': maxvalpost,
            'maxvalpre': maxvalpre
        }
Пример #2
0
def main(image_pre, image_post, res_val, max_factor=0.25):
    """
    Verify subtraction by checking quantities in residual images

    Parameters
    ----------
    image_pre : str
        Filename of image before selfcal
    image_post : str
        Filename of image after selfcal
    res_val : float
        Maximum allowed value of peak residual (Jy/beam)
    max_factor : float
        Factor by which old peak residual must exceed new peak residual

    """
    imgpre = pim.image(image_pre)
    maxvalpre = numpy.max(numpy.abs(imgpre.getdata()))
    imgpost = pim.image(image_post)
    maxvalpost = numpy.max(numpy.abs(imgpost.getdata()))

    if (maxvalpost > res_val) or (maxvalpost*max_factor > maxvalpre):
        return {'break': False, 'maxvalpost': maxvalpost, 'maxvalpre': maxvalpre}
    else:
        return {'break': True, 'maxvalpost': maxvalpost, 'maxvalpre': maxvalpre}
Пример #3
0
def find_imagenoise(imagename):
    """
    Finds noise, dynamic range, and min/max for an image

    Parameters
    ----------
    imagename : str
        Filename of image

    Returns
    -------
    rms : float
        Noise (Jy/beam) of image
    dynamic_range : float
        Dynamic range (max/min) of image
    minmax : float
        Ratio of min/max

    """
    im = pim.image(imagename)
    image = numpy.copy(im.getdata())
    mean, rms = meanclip(image)
    minmax = abs(numpy.min(image) / numpy.max(image))

    return rms, numpy.abs(numpy.max(image) / rms), minmax
Пример #4
0
def find_imagenoise(imagename):
    """
    Finds noise, dynamic range, and min/max for an image

    Parameters
    ----------
    imagename : str
        Filename of image

    Returns
    -------
    rms : float
        Noise (Jy/beam) of image
    dynamic_range : float
        Dynamic range (max/min) of image
    minmax : float
        Ratio of min/max

    """
    im    = pim.image(imagename)
    image = numpy.copy(im.getdata())
    mean, rms =  meanclip(image)
    minmax = abs(numpy.min(image) / numpy.max(image))

    return rms, numpy.abs(numpy.max(image)/rms), minmax
Пример #5
0
def main(fitsimage, outfilename, force_stokes_i=False):
    """
    Convert a fits image to a CASA image

    Parameters
    ----------
    fitsimage : str
        Name of FITS image
    outfilename : str
        Name of output CASA image
    force_stokes_i : bool, optional
        If True, force Stokes axis to be 'I'

    """
    casaimage = pim.image(fitsimage)
    casaimage.saveas(outfilename, overwrite=True)

    if type(force_stokes_i) is str:
        if force_stokes_i.lower() == 'true':
            force_stokes_i = True
        else:
            force_stokes_i = False

    if force_stokes_i:
        coords = casaimage.coordinates().dict()
        coords['stokes1']['stokes'] = ['I']
        freq = coords['spectral2']['wcs']['crval']
        coords['spectral2']['restfreqs'] = np.array([freq])
        outtable = pt.table(outfilename, readonly=False, ack=False)
        outtable.putkeywords({'coords': coords})
        outtable.done()
Пример #6
0
def main(fitsimage, outfilename, force_stokes_i=False):
    """
    Convert a fits image to a CASA image

    Parameters
    ----------
    fitsimage : str
        Name of FITS image
    outfilename : str
        Name of output CASA image
    force_stokes_i : bool, optional
        If True, force Stokes axis to be 'I'

    """
    casaimage = pim.image(fitsimage)
    casaimage.saveas(outfilename, overwrite=True)

    if type(force_stokes_i) is str:
        if force_stokes_i.lower() == 'true':
            force_stokes_i = True
        else:
            force_stokes_i = False

    if force_stokes_i:
        coords = casaimage.coordinates().dict()
        coords['stokes1']['stokes'] = ['I']
        freq = coords['spectral2']['wcs']['crval']
        coords['spectral2']['restfreqs'] = np.array([freq])
        outtable = pt.table(outfilename, readonly=False, ack=False)
        outtable.putkeywords({'coords': coords})
        outtable.done()
Пример #7
0
    def test_CIM_stacking_base(self):
        ds.cim.CIM_stacking_base([self.CIMPathA, self.CIMPathA],
                                 TEST_DIR,
                                 'test_CIM_stacking_base',
                                 overwrite=True)

        assert np.array_equiv(np.multiply(casaimage.image(self.CIMPathA).getdata(),2),casaimage.image('{0:s}/test_CIM_stacking_base'.format(TEST_DIR)).getdata()), \
        'Stacking the same image not equivalent with multiplying with two!'
Пример #8
0
def main(image, output=None, radius=0.5):
    """
    Zero corners of avgpb images

    Parameters
    ----------
    image : str
        avgpb image
    output : str, optional
        Output image name. If None, add a 'z' to the end of the input filename
    radius : float, optional
        Radius beyond which to zero avgpb values (expressed as fraction of
        image width)

    """
    if type(radius) is str:
        radius = float(radius)

    pb = pim.image(image)
    pbdata = pb.getdata()
    (nx, ny) = pbdata.shape[2:]
    pbrad = radius * nx
    cy = ny / 2
    cx = nx / 2
    pbcounter = 0
    for j in range(nx, cx, -1):
        k = ny
        while np.sqrt((j-cx)**2+(k-cy)**2) > pbrad and k > cy:
            pbcounter += 1
            pbdata[:, :, k-1, j-1] = 0.
            pbdata[:, :, k-1, nx-j] = 0.
            pbdata[:, :, ny-k, j-1] = 0.
            pbdata[:, :, ny-k, nx-j] = 0.
            k -= 1
        if k == ny:
            break

    print pbcounter,'x 4 =',pbcounter*4,'zeros replaced'

    if output is None:
        while image[-1] == '/':
            image = image[: -1]
        outim = image + 'z'
    else:
        outim = output
    pout = pim.image(outim, values=pbdata, coordsys=pb.coordinates())
Пример #9
0
def pix2radec(image, i, j):
    """input:  (image, i,j) image name as string, 
                            pixel coordinates as int, (0,0) is lower left (TBC)
       output: (ra, dec) sky coordinates as degree in float"""
    casa_image = images.image(image)
    world_vals = casa_image.toworld((0,0,j,i)) # in: frequency, stokes (0-3), jpixel, ipixel
                                               # out: frequency, stokes (1-4), dec, ra
    ra = degrees(world_vals[3])
    dec = degrees(world_vals[2])
    return (ra, dec) 
Пример #10
0
def radec2pix(image, ra, dec):
    """input:  (image, ra, dec) image name as string, 
                                sky coordinates as degree in float
       output: (i,j) pixel coordinates as int, (0,0) is lower left (TBC)"""
    casa_image = images.image(image)
    ra = radians(ra)
    dec = radians(dec)
    pix_vals = casa_image.topixel((0,1,dec,ra)) # in: frequency, stokes (1-4), dec, ra
                                                # out: frequency, stokes (0-3), jpixel, ipixel
    i = int(floor(pix_vals[3]))
    j = int(floor(pix_vals[2]))
    return (i, j)
Пример #11
0
 def getBeam(self):
     """
     Return the beam size of the image
     """
     this_pim = pim.image(self.imagename)
     info_dict = this_pim.info()['imageinfo']['restoringbeam']
     # get beam info
     bpar_ma = quanta.quantity(info_dict['major']).get_value('arcsec')
     bpar_mi = quanta.quantity(info_dict['minor']).get_value('arcsec')
     bpar_pa = quanta.quantity(info_dict['positionangle']).get_value('deg')
     #print('\n{0} - Beam: maj {1:0.3f} (arcsec), min {2:2.3f} (arcsec), pa {3:0.2f} (deg)'.format(img, bpar_ma, bpar_mi,bpar_pa))
     return (bpar_ma,bpar_mi,bpar_pa)
Пример #12
0
    def test_set_CIM_unit(self):
        test_cim_name = '{0:s}/test_set_CIM_unit'.format(TEST_DIR)
        template_cim = ds.cim.create_CIM_object(self.CIMPathA)
        coordsys = template_cim.coordinates()

        #If shape is given, the data type is automatically set to float!
        test_cim = casaimage.image(test_cim_name,
                                   coordsys=coordsys,
                                   values=template_cim.getdata(),
                                   overwrite=True)

        #Need to give a unit that is known to casacore
        ds.cim.set_CIM_unit(test_cim_name, 'Jy')
        CIM_with_unit = ds.cim.create_CIM_object(
            '{0:s}/test_set_CIM_unit'.format(TEST_DIR))
        assert CIM_with_unit.unit(
        ) == 'Jy', 'Unable to add unit to newly created CASAImage!'
Пример #13
0
def display_image(image):
    """
    Displays image in an external viewer
    """
    global fig, at, selected_direction

    if options['facet_viewer'] == 'casa':
        im2 = pim.image(image)
        im2.view()
    elif options['facet_viewer'] == 'ds9':
        if os.path.isdir(image):
            # Convert casa image to fits
            if not os.path.exists('{0}.fits'.format(image)):
                subprocess.call('image2fits in={0} out={0}.fits'.format(image),
                    shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            image = '{0}.fits'.format(image)
        if not haspyds9:
            os.system('ds9 {} &'.format(image))
        else:
            # use pyds9 if available to re-use an existing ds9
            pyds9.ds9_xpans()
            c = at.get_child()
            info_last = c.get_text()
            info = 'Opening image in ds9...'
            c.set_text(info)
            fig.canvas.draw()
            ds9=pyds9.DS9('checkfactor', wait=120)
            c.set_text(info_last)
            fig.canvas.draw()
            ds9.set('file '+image)
            if options['ds9_limits'] is not None:
                ds9.set('scale limits '+options['ds9_limits'])
            if options['ds9_load_regions']:
                regionfile=os.path.join(selected_direction.working_dir,'regions','facets_ds9.reg')
                ds9.set('regions delete all')
                ds9.set('regions load '+regionfile)
    else:
        info = 'Unknown facet viewer specified in config file!'
        c = at.get_child()
        c.set_text(info)
        fig.canvas.draw()
Пример #14
0
from casacore.images import image

print("creating image named crash")

im = image(imagename='/data/crash', shape=(256, 256))
Пример #15
0
def on_press(event):
    """
    Handle key presses
    """
    global fig, at, selected_direction, choose_from_list

    if event.key == 'u':
        # Update plot
        choose_from_list = False
        update_plot()
        return

    elif event.key == 'c':
        # Open selfcal images (if any)
        choose_from_list = False
        if selected_direction is None:
            return
        selfcal_images = find_selfcal_images(selected_direction)
        if len(selfcal_images) > 0:
            info = 'Opening selfcal images for {}...'.format(selected_direction.name)
            if hasaplpy:
                # Update the text box as the call below takes a few seconds
                c = at.get_child()
                c.set_text(info)
                fig.canvas.draw()
                make_selfcal_images.main(selfcal_images, interactive=True,
                    facet_name=selected_direction.name)
            else:
                if os.path.exists('/tmp/tempimage'):
                    shutil.rmtree('/tmp/tempimage')
                im = pim.image(selfcal_images)
                im.view()
        else:
            info = 'No selfcal images exist for {}'.format(selected_direction.name)

    elif event.key == 'i':
        # Open full facet images (if any)
        if selected_direction is None:
            return
        facet_images, facetimage_ops = find_facet_images(selected_direction)
        if len(facet_images) == 0:
            info = 'No image of facet exists for {}'.format(selected_direction.name)
        else:
            info = 'Load facet image from (choose one):'
            for opindx, (img, fimg_op) in enumerate(zip(facet_images, facetimage_ops)):
                info += '\n  ({0}) {1}'.format(opindx+1, fimg_op)
            choose_from_list = True


    elif event.key == 'v':
        # Open full facet images (if any)
        choose_from_list = False
        if selected_direction is None:
            return
        facet_verify_images = find_facet_verify_images(selected_direction)
        if len(facet_verify_images) == 0:
            info = 'No verify image of facet exists for {}'.format(selected_direction.name)
        else:
            info = 'Opening selfcal verification images for {}...'.format(selected_direction.name)
        display_image(facet_verify_images)

    elif event.key in [str(num+1) for num in range(9)]:
        # Open image (from list given on "i" press)
        if choose_from_list:
            facet_images, facetimage_ops = find_facet_images(selected_direction)
            if int(event.key) <= len(facet_images):
                display_image(facet_images[int(event.key)-1])
                return
        else:
            return

    elif event.key == 't':
        # Open fast TEC selfcal plots (if any)
        choose_from_list = False
        if selected_direction is None:
            return
        selfcal_plots = find_selfcal_tec_plots(selected_direction)
        if len(selfcal_plots) > 0:
            info = 'Opening selfcal TEC solution plots for {}...'.format(selected_direction.name)
            os.system(options['image_display']+' {} &'.format(' '.join(selfcal_plots)))
        else:
            info = 'Final selfcal solutions do not exist for {}'.format(selected_direction.name)

    elif event.key == 'g':
        # Open slow Gain selfcal plots (if any)
        choose_from_list = False
        if selected_direction is None:
            return
        selfcal_plots = find_selfcal_gain_plots(selected_direction)
        if len(selfcal_plots) > 0:
            info = 'Opening selfcal Gain solution plots for {}...'.format(selected_direction.name)
            os.system(options['image_display']+' {} &'.format(' '.join(selfcal_plots)))
        else:
            info = 'Final selfcal solutions do not exist for {}'.format(selected_direction.name)

    elif event.key == 'h':
        choose_from_list = False
        info='Reprinting instructions'
        show_instructions()
        return

    else:
        return

    # Update info box
    c = at.get_child()
    c.set_text(info)
    fig.canvas.draw()
Пример #16
0
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#usage: extractbeam.py imagename

import casacore.images as pim
from casacore import quanta
import sys

for img in sys.argv[1:]:
    this_pim = pim.image(img)
    info_dict = this_pim.info()['imageinfo']['restoringbeam']
    # get beam info
    bpar_ma = quanta.quantity(info_dict['major']).get_value('arcsec')
    bpar_mi = quanta.quantity(info_dict['minor']).get_value('arcsec')
    bpar_pa = quanta.quantity(info_dict['positionangle']).get_value('deg')
    print(
        '\n{0} - Beam: maj {1:0.3f} (arcsec), min {2:2.3f} (arcsec), pa {3:0.2f} (deg)'
        .format(img, bpar_ma, bpar_mi, bpar_pa))
Пример #17
0
def display_image(images):
    """
    Displays images in an external viewer
    """
    global fig, at, selected_direction

    if not isinstance(images, list):
        images = [images]

    if options['facet_viewer'] == 'casa':
        for image in images:
            im2 = pim.image(image)
            im2.view()
    elif options['facet_viewer'] == 'ds9':
        for i in range(len(images)):
            image = images[i]
            if os.path.isdir(image):
                # Convert casa image to fits
                if not os.path.exists('{0}.fits'.format(image)):
                    subprocess.call('image2fits in={0} out={0}.fits'.format(image),
                        shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                images[i] = '{0}.fits'.format(image)
        if not haspyds9:
            os.system('ds9 -tile {} &'.format(' '.join(images)))
        else:
            # use pyds9 if available to re-use an existing ds9
            pyds9.ds9_xpans()
            c = at.get_child()
            info_last = c.get_text()
            info = 'Opening image in ds9...'
            c.set_text(info)
            fig.canvas.draw()
            ds9=pyds9.DS9('checkfactor', wait=120)
            c.set_text(info_last)
            fig.canvas.draw()
            for i in range(len(images)):
                if options['ds9_frames'] == 'current':
                    if len(images) > 1:
                        # For single image, no need to set frame as current one
                        # is used by default. For multiple images, use frame i
                        # for image i
                        ds9.set('frame {:d}'.format(i))
                elif options['ds9_frames'] == 'new':
                    ds9.set('frame new')
                else:
                    log.warning('ds9_frames setting "{}" not understood. Using '
                        '"new" instead'.format(options['ds9_frames']))
                    ds9.set('frame new')
                ds9.set('file '+images[i])
                if options['ds9_limits'] is not None:
                    ds9.set('scale limits '+options['ds9_limits'])
                if options['ds9_load_regions']:
                    regionfile=os.path.join(selected_direction.working_dir,'regions','facets_ds9.reg')
                    ds9.set('regions delete all')
                    ds9.set('regions load '+regionfile)
            if len(images) > 1:
                ds9.set('tile')
                ds9.set('frame match scale and limits')
                ds9.set('frame match colorbar')
                ds9.set('frame match wcs')
    else:
        info = 'Unknown facet viewer specified in config file!'
        c = at.get_child()
        c.set_text(info)
        fig.canvas.draw()
Пример #18
0
def main(images, vertices, outfits, maxwidth=0):
    """
    Creates mosaic

    Parameters
    ----------
    images : str or list of str
        List of filenames of facet images. May be given as a list or as a string
        (e.g., '[image1, image2]'
    vertices : str or list of str
        List of filenames of facet vertices files. May be given as
        a list or as a string (e.g., '[vert1, vert2]'
    outfits : str
        Filename of output FITS mosaic
    maxwidth : int, optional
        Maximum number of pixels to consider for the width of the mosaic
        [default 0 = unlimited] This can be helpful at high declination.

    """
    if type(images) is str:
        images = images.strip('[]').split(',')
        images = [im.strip() for im in images]
    if type(vertices) is str:
        vertices = vertices.strip('[]').split(',')
        vertices = [v.strip() for v in vertices]

    formstr = '{0:45s}  {1:45s} {2:s}  {3:s} {4:s} {5:s}'
    print formstr.format("-----","--------","------------","-------","-------","------")
    print formstr.format("Image", "FC reg","Norm. weight", "Maj(ac)", "Min(ac)","PA(deg)")
    print formstr.format("-----","--------","------------","-------","-------","------")

    psf_fwhm = [] # resolution
    frequency = [] # frequency of images (should be equal?)
    for i in range(len(images)):
        this_pim = pim.image(images[i])
        info_dict = this_pim.info()['imageinfo']['restoringbeam']
        bpar_ma = quanta.quantity(info_dict['major']).get_value('deg')
        bpar_mi = quanta.quantity(info_dict['minor']).get_value('deg')
        bpar_pa = quanta.quantity(info_dict['positionangle']).get_value('deg')
        psf_fwhm.append([bpar_ma, bpar_mi, bpar_pa])
        frequency.append(this_pim.info()['coordinates']['spectral2']['restfreq'])
        print '{0:45.45s}  {1:45.45s} {2:0.2f}          {3:0.2f}    {4:0.2f}    {5:0.2f}'.format(images[i], vertices[i], 0, bpar_ma*60, bpar_mi*60,bpar_pa)

    psf_fwhm = np.array(psf_fwhm)
    frequency = np.array(frequency)
    mean_psf_fwhm = np.mean(psf_fwhm, axis=0)
    mean_frequency = np.mean(frequency)

    # Initialize some vectors
    declims = [] # store the limits of the declination axes
    raleft = []
    raright = []
    rainc = [] # store the r.a. increments in case they differ
    decinc = [] # store the dec increments in case they differ
    pims = [] # stores the casacore images of the data

    # Get image frames for input images
    for im in images:
        image = pim.image(im)
        sptcoords = image.coordinates().get_coordinate('spectral')
        nc = sptcoords.get_axis_size()

        # Get Stokes axis. Ensure we are working with the Stokes parameter requested.
        stkcoords = image.coordinates().get_coordinate('stokes')
        if stkcoords.get_axis_size() == 1:
            assert(stkcoords.get_stokes()[0] == 'I')
        else:
            stks = stkcoords.get_stokes().index('I')
            image = image.subimage(blc=(0, stks), trc=(nc-1, stks), dropdegenerate=False)
        ns = 1

        dircoords = image.coordinates().get_coordinate('direction')
        nx = dircoords.get_axis_size(axis=1)
        ny = dircoords.get_axis_size(axis=0)
        inc = dircoords.get_increment()
        ref = dircoords.get_referencepixel()
        val = dircoords.get_referencevalue()
        # wsclean image header is weird
        if val[1]<0:
            val[1]+=2*np.pi
        ra_axis = (range(nx)-ref[1])*inc[1]+val[1]
        dec_axis = (range(ny)-ref[0])*inc[0]+val[0]
        rainc.append(inc[1])
        decinc.append(inc[0])
        declims.append(min(dec_axis))
        declims.append(max(dec_axis))
        mean_ra = np.mean(ra_axis)
        raleft.append((ra_axis[0]-mean_ra)*np.cos(val[0])+mean_ra)
        raright.append((ra_axis[-1]-mean_ra)*np.cos(val[0])+mean_ra)
        pims.append(image)

    # Generate the mosaic coordinate frame
    master_dec = np.arange(min(declims),max(declims),min(decinc))
    if max(raleft)-min(raright) > 5.*np.pi/3.: # crossed RA=0
        for i in range(len(raright)):
            raright[i] = raright[i]-2.*np.pi
    master_ra = np.arange(max(raleft),min(raright),max(rainc))
    lmra = len(master_ra)
    if maxwidth != 0:
        if lmra > maxwidth:
            xboundary = (lmra-maxwidth)/2
            master_ra = master_ra[xboundary:-xboundary]
    print "Found ra,dec pixel increments (arcsec):"
    print np.array(rainc)*206265.,np.array(decinc)*206265.
    ma = pims[-1].coordinates()
    ma['direction'].set_referencepixel([len(master_dec)/2,len(master_ra)/2])
    ma['direction'].set_increment([decinc[np.argmin(np.abs(decinc))],rainc[np.argmin(np.abs(rainc))]])
    ma['direction'].set_referencevalue([master_dec[len(master_dec)/2],master_ra[len(master_ra)/2]])

    # Initialize the arrays for the output image, sensitivity, and weights
    master_im = np.zeros((len(master_dec),len(master_ra)))
    master_mask = np.zeros((len(master_dec),len(master_ra)))

    # Reproject the images onto the master grid, weight and normalize
    for i, im in enumerate(pims):
        print 'doing image',i
        im, mask = mask_vertices(im, vertices[i])
        im = im.regrid([2,3],ma,outshape=(int(nc),int(ns),len(master_dec),len(master_ra)))
        mask = mask.regrid([2,3],ma,outshape=(int(nc),int(ns),len(master_dec),len(master_ra)))
        master_im += np.squeeze(im.getdata())
        master_mask += np.squeeze(mask.getdata())

    blank=np.ones_like(im)*np.nan
    master_im=np.where(master_mask,master_im,blank)

    # Write fits files
    arrax = np.zeros( (1,1, len(master_im[:,0]), len(master_im[0,:])) )
    arrax[0,0,:,:] = master_im

    # Open new casa image for mosaic
    new_pim = pim.image('',shape=(1,1, len(master_dec),len(master_ra)), coordsys=ma)
    new_pim.putdata(arrax)
    # Write fits
    new_pim.tofits(outfits, overwrite=True)

    # need to add new beam info (not sure if this is possible with casacore)
    hdu = pyfits.open(outfits,mode='update')
    header = hdu[0].header
    header.update('BMAJ',mean_psf_fwhm[0])
    header.update('BMIN',mean_psf_fwhm[1])
    header.update('BPA',mean_psf_fwhm[2])
    header.update('BUNIT',pims[-1].info()['unit'])
    header.update('RESTFRQ',mean_frequency)
    header.update('RESTFREQ',mean_frequency)
    newhdu = pyfits.PrimaryHDU(data=hdu[0].data, header=header)
    newhdu.writeto(outfits,clobber=True)
Пример #19
0
        #Cretae an ARL image from the grids
        sub_grid_real_arlimage = create_ARLimage_from_CASAimage(grid_name_real);
        sub_grid_imag_arlimage = create_ARLimage_from_CASAimage(grid_name_imag);

        #Add it to the combined arlimage
        combined_grid_real_arlimage.data += sub_grid_real_arlimage.data;
        combined_grid_imag_arlimage.data += sub_grid_imag_arlimage.data;

    log.info('Normalise combined grids');
    #Normnalise the combined image
    combined_grid_real_arlimage.data /= N_combination;
    combined_grid_imag_arlimage.data /= N_combination;

    log.info('Write combined grid back to the grids');
    #write this back to the dataset
    combined_grid_real_casaimage = casaimage.image(combined_grid_name_real);
    combined_grid_real_casaimage_data = combined_grid_real_casaimage.getdata();

    combined_grid_imag_casaimage = casaimage.image(combined_grid_name_imag);
    combined_grid_imag_casaimage_data = combined_grid_imag_casaimage.getdata();

    #Put the arl object to the CASAimage object
    combined_grid_real_casaimage_data[...] = combined_grid_real_arlimage.data;
    combined_grid_imag_casaimage_data[...] = combined_grid_imag_arlimage.data;

    #Write it back to the image
    combined_grid_real_casaimage.putdata(combined_grid_real_casaimage_data);
    combined_grid_imag_casaimage.putdata(combined_grid_imag_casaimage_data);
    
    #Deleting the variables closes the image, which release the lock
    #Another soulution would be is to do this inside a function....
Пример #20
0
def display_image(images):
    """
    Displays images in an external viewer
    """
    global fig, at, selected_direction

    if not isinstance(images, list):
        images = [images]

    if options['facet_viewer'] == 'casa':
        for image in images:
            im2 = pim.image(image)
            im2.view()
    elif options['facet_viewer'] == 'ds9':
        for i in range(len(images)):
            image = images[i]
            if os.path.isdir(image):
                # Convert casa image to fits
                if not os.path.exists('{0}.fits'.format(image)):
                    subprocess.call(
                        'image2fits in={0} out={0}.fits'.format(image),
                        shell=True,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)
                images[i] = '{0}.fits'.format(image)
        if not haspyds9:
            os.system('ds9 -tile {} &'.format(' '.join(images)))
        else:
            # use pyds9 if available to re-use an existing ds9
            pyds9.ds9_xpans()
            c = at.get_child()
            info_last = c.get_text()
            info = 'Opening image in ds9...'
            c.set_text(info)
            fig.canvas.draw()
            ds9 = pyds9.DS9('checkfactor', wait=120)
            c.set_text(info_last)
            fig.canvas.draw()
            for i in range(len(images)):
                if options['ds9_frames'] == 'current':
                    if len(images) > 1:
                        # For single image, no need to set frame as current one
                        # is used by default. For multiple images, use frame i
                        # for image i
                        ds9.set('frame {:d}'.format(i))
                elif options['ds9_frames'] == 'new':
                    ds9.set('frame new')
                else:
                    log.warning(
                        'ds9_frames setting "{}" not understood. Using '
                        '"new" instead'.format(options['ds9_frames']))
                    ds9.set('frame new')
                ds9.set('file ' + images[i])
                if options['ds9_limits'] is not None:
                    ds9.set('scale limits ' + options['ds9_limits'])
                if options['ds9_load_regions']:
                    regionfile = os.path.join(selected_direction.working_dir,
                                              'regions', 'facets_ds9.reg')
                    ds9.set('regions delete all')
                    ds9.set('regions load ' + regionfile)
            if len(images) > 1:
                ds9.set('tile')
                ds9.set('frame match scale and limits')
                ds9.set('frame match colorbar')
                ds9.set('frame match wcs')
    else:
        info = 'Unknown facet viewer specified in config file!'
        c = at.get_child()
        c.set_text(info)
        fig.canvas.draw()
Пример #21
0
def main(image_name,
         mask_name,
         atrous_do=False,
         threshisl=0.0,
         threshpix=0.0,
         rmsbox=None,
         rmsbox_bright=(35, 7),
         iterate_threshold=False,
         adaptive_rmsbox=False,
         img_format='fits',
         threshold_format='float',
         trim_by=0.0,
         vertices_file=None,
         atrous_jmax=6,
         pad_to_size=None,
         skip_source_detection=False,
         region_file=None,
         nsig=1.0,
         reference_ra_deg=None,
         reference_dec_deg=None,
         cellsize_deg=0.000417,
         use_adaptive_threshold=False,
         adaptive_thresh=150.0):
    """
    Make a clean mask and return clean threshold

    Parameters
    ----------
    image_name : str
        Filename of input image from which mask will be made. If the image does
        not exist, a template image with center at (reference_ra_deg,
        reference_dec_deg) will be made internally
    mask_name : str
        Filename of output mask image
    atrous_do : bool, optional
        Use wavelet module of PyBDSM?
    threshisl : float, optional
        Value of thresh_isl PyBDSM parameter
    threshpix : float, optional
        Value of thresh_pix PyBDSM parameter
    rmsbox : tuple of floats, optional
        Value of rms_box PyBDSM parameter
    rmsbox_bright : tuple of floats, optional
        Value of rms_box_bright PyBDSM parameter
    iterate_threshold : bool, optional
        If True, threshold will be lower in 20% steps until
        at least one island is found
    adaptive_rmsbox : tuple of floats, optional
        Value of adaptive_rms_box PyBDSM parameter
    img_format : str, optional
        Format of output mask image (one of 'fits' or 'casa')
    threshold_format : str, optional
        Format of output threshold (one of 'float' or 'str_with_units')
    trim_by : float, optional
        Fraction by which the perimeter of the output mask will be
        trimmed (zeroed)
    vertices_file : str, optional
        Filename of file with vertices (must be a pickle file containing
        a dictionary with the vertices in the 'vertices' entry)
    atrous_jmax : int, optional
        Value of atrous_jmax PyBDSM parameter
    pad_to_size : int, optional
        Pad output mask image to a size of pad_to_size x pad_to_size
    skip_source_detection : bool, optional
        If True, source detection is not run on the input image
    region_file : str, optional
        Filename of region file in CASA format. If given, no mask image
        is made (the region file is used as the clean mask)
    nsig : float, optional
        Number of sigma of returned threshold value
    reference_ra_deg : float, optional
        RA for center of output mask image
    reference_dec_deg : float, optional
        Dec for center of output mask image
    cellsize_deg : float, optional
        Size of a pixel in degrees
    use_adaptive_threshold : bool, optional
        If True, use an adaptive threshold estimated from the negative values in
        the image
    adaptive_thresh : float, optional
        If adaptive_rmsbox is True, this value sets the threshold above
        which a source will use the small rms box

    Returns
    -------
    result : dict
        Dict with nsig-sigma rms threshold

    """
    if rmsbox is not None and type(rmsbox) is str:
        rmsbox = eval(rmsbox)

    if type(rmsbox_bright) is str:
        rmsbox_bright = eval(rmsbox_bright)

    if pad_to_size is not None and type(pad_to_size) is str:
        pad_to_size = int(pad_to_size)

    if type(atrous_do) is str:
        if atrous_do.lower() == 'true':
            atrous_do = True
            threshisl = 4.0  # override user setting to ensure proper source fitting
        else:
            atrous_do = False

    if type(iterate_threshold) is str:
        if iterate_threshold.lower() == 'true':
            iterate_threshold = True
        else:
            iterate_threshold = False

    if type(adaptive_rmsbox) is str:
        if adaptive_rmsbox.lower() == 'true':
            adaptive_rmsbox = True
        else:
            adaptive_rmsbox = False

    if type(skip_source_detection) is str:
        if skip_source_detection.lower() == 'true':
            skip_source_detection = True
        else:
            skip_source_detection = False

    if type(use_adaptive_threshold) is str:
        if use_adaptive_threshold.lower() == 'true':
            use_adaptive_threshold = True
        else:
            use_adaptive_threshold = False

    if reference_ra_deg is not None and reference_dec_deg is not None:
        reference_ra_deg = float(reference_ra_deg)
        reference_dec_deg = float(reference_dec_deg)

    if not os.path.exists(image_name):
        print('Input image not found. Making empty image...')
        if not skip_source_detection:
            print('ERROR: Source detection cannot be done on an empty image')
            sys.exit(1)
        if reference_ra_deg is not None and reference_dec_deg is not None:
            image_name = mask_name + '.tmp'
            make_template_image(image_name,
                                reference_ra_deg,
                                reference_dec_deg,
                                cellsize_deg=float(cellsize_deg))
        else:
            print(
                'ERROR: if image not found, a refernce position must be given')
            sys.exit(1)

    trim_by = float(trim_by)
    atrous_jmax = int(atrous_jmax)
    threshpix = float(threshpix)
    threshisl = float(threshisl)
    nsig = float(nsig)
    adaptive_thresh = float(adaptive_thresh)
    threshold = 0.0

    if not skip_source_detection:
        if vertices_file is not None:
            # Modify the input image to blank the regions outside of the polygon
            temp_img = pim.image(image_name)
            image_name += '.blanked'
            temp_img.saveas(image_name, overwrite=True)
            input_img = pim.image(image_name)
            data = input_img.getdata()

            vertices = read_vertices(vertices_file)
            RAverts = vertices[0]
            Decverts = vertices[1]
            xvert = []
            yvert = []
            for RAvert, Decvert in zip(RAverts, Decverts):
                pixels = input_img.topixel(
                    [1, 1, Decvert * np.pi / 180.0, RAvert * np.pi / 180.0])
                xvert.append(pixels[2])  # x -> Dec
                yvert.append(pixels[3])  # y -> RA
            poly = Polygon(xvert, yvert)

            # Find masked regions
            masked_ind = np.where(data[0, 0])

            # Find distance to nearest poly edge and set to NaN those that
            # are outside the facet (dist < 0)
            dist = poly.is_inside(masked_ind[0], masked_ind[1])
            outside_ind = np.where(dist < 0.0)
            if len(outside_ind[0]) > 0:
                data[0, 0, masked_ind[0][outside_ind],
                     masked_ind[1][outside_ind]] = np.nan

            # Save changes
            input_img.putdata(data)

        if use_adaptive_threshold:
            # Get an estimate of the rms
            img = bdsm.process_image(image_name,
                                     mean_map='zero',
                                     rms_box=rmsbox,
                                     thresh_pix=threshpix,
                                     thresh_isl=threshisl,
                                     atrous_do=atrous_do,
                                     ini_method='curvature',
                                     thresh='hard',
                                     adaptive_rms_box=adaptive_rmsbox,
                                     adaptive_thresh=adaptive_thresh,
                                     rms_box_bright=rmsbox_bright,
                                     rms_map=True,
                                     quiet=True,
                                     atrous_jmax=atrous_jmax,
                                     stop_at='isl')

            # Find min and max pixels
            max_neg_val = abs(np.min(img.ch0_arr))
            max_neg_pos = np.where(img.ch0_arr == np.min(img.ch0_arr))
            max_pos_val = abs(np.max(img.ch0_arr))
            max_pos_pos = np.where(img.ch0_arr == np.max(img.ch0_arr))

            # Estimate new thresh_isl from min pixel value's sigma, but don't let
            # it get higher than 1/2 of the peak's sigma
            threshisl_neg = 2.0 * max_neg_val / img.rms_arr[max_neg_pos][0]
            max_sigma = max_pos_val / img.rms_arr[max_pos_pos][0]
            if threshisl_neg > max_sigma / 2.0:
                threshisl_neg = max_sigma / 2.0

            # Use the new threshold only if it is larger than the user-specified one
            if threshisl_neg > threshisl:
                threshisl = threshisl_neg

        if iterate_threshold:
            # Start with given threshold and lower it until we get at least one island
            nisl = 0
            while nisl == 0:
                img = bdsm.process_image(image_name,
                                         mean_map='zero',
                                         rms_box=rmsbox,
                                         thresh_pix=threshpix,
                                         thresh_isl=threshisl,
                                         atrous_do=atrous_do,
                                         ini_method='curvature',
                                         thresh='hard',
                                         adaptive_rms_box=adaptive_rmsbox,
                                         adaptive_thresh=adaptive_thresh,
                                         rms_box_bright=rmsbox_bright,
                                         rms_map=True,
                                         quiet=True,
                                         atrous_jmax=atrous_jmax)
                nisl = img.nisl
                threshpix /= 1.2
                threshisl /= 1.2
                if threshpix < 5.0:
                    break
        else:
            img = bdsm.process_image(image_name,
                                     mean_map='zero',
                                     rms_box=rmsbox,
                                     thresh_pix=threshpix,
                                     thresh_isl=threshisl,
                                     atrous_do=atrous_do,
                                     ini_method='curvature',
                                     thresh='hard',
                                     adaptive_rms_box=adaptive_rmsbox,
                                     adaptive_thresh=adaptive_thresh,
                                     rms_box_bright=rmsbox_bright,
                                     rms_map=True,
                                     quiet=True,
                                     atrous_jmax=atrous_jmax)

        if img.nisl == 0:
            if region_file is None or region_file == '[]':
                print('No islands found. Clean mask cannot be made.')
                sys.exit(1)
            else:
                # Continue on and use user-supplied region file
                skip_source_detection = True
                threshold = nsig * img.clipped_rms

        # Check if there are large islands preset (indicating that multi-scale
        # clean is needed)
        has_large_isl = False
        for isl in img.islands:
            if isl.size_active > 100:
                # Assuming normal sampling, a size of 100 pixels would imply
                # a source of ~ 10 beams
                has_large_isl = True

    if (region_file is not None and region_file != '[]'
            and skip_source_detection):
        # Copy region file and return if source detection was not done
        os.system('cp {0} {1}'.format(region_file.strip('[]"'), mask_name))
        if threshold_format == 'float':
            return {'threshold_5sig': threshold}
        elif threshold_format == 'str_with_units':
            # This is done to get around the need for quotes around strings in casapy scripts
            # 'casastr/' is removed by the generic pipeline
            return {'threshold_5sig': 'casastr/{0}Jy'.format(threshold)}
    elif not skip_source_detection:
        img.export_image(img_type='island_mask',
                         mask_dilation=0,
                         outfile=mask_name,
                         img_format=img_format,
                         clobber=True)

    if (vertices_file is not None or trim_by > 0 or pad_to_size is not None
            or (region_file is not None and region_file != '[]')
            or skip_source_detection):
        # Alter the mask in various ways
        if skip_source_detection:
            # Read the image
            mask_im = pim.image(image_name)
        else:
            # Read the PyBDSM mask
            mask_im = pim.image(mask_name)
        data = mask_im.getdata()
        coordsys = mask_im.coordinates()
        if reference_ra_deg is not None and reference_dec_deg is not None:
            values = coordsys.get_referencevalue()
            values[2][0] = reference_dec_deg / 180.0 * np.pi
            values[2][1] = reference_ra_deg / 180.0 * np.pi
            coordsys.set_referencevalue(values)
        imshape = mask_im.shape()
        del (mask_im)

        if pad_to_size is not None:
            imsize = pad_to_size
            coordsys['direction'].set_referencepixel([imsize / 2, imsize / 2])
            pixmin = (imsize - imshape[2]) / 2
            if pixmin < 0:
                print("The padded size must be larger than the original size.")
                sys.exit(1)
            pixmax = pixmin + imshape[2]
            data_pad = np.zeros((1, 1, imsize, imsize), dtype=np.float32)
            data_pad[0, 0, pixmin:pixmax, pixmin:pixmax] = data[0, 0]
            new_mask = pim.image('',
                                 shape=(1, 1, imsize, imsize),
                                 coordsys=coordsys)
            new_mask.putdata(data_pad)
        else:
            new_mask = pim.image('', shape=imshape, coordsys=coordsys)
            new_mask.putdata(data)

        data = new_mask.getdata()

        if skip_source_detection:
            # Mask all pixels
            data[:] = 1

        if vertices_file is not None:
            # Modify the clean mask to exclude regions outside of the polygon
            vertices = read_vertices(vertices_file)
            RAverts = vertices[0]
            Decverts = vertices[1]
            xvert = []
            yvert = []
            for RAvert, Decvert in zip(RAverts, Decverts):
                try:
                    pixels = new_mask.topixel([
                        0, 1, Decvert * np.pi / 180.0, RAvert * np.pi / 180.0
                    ])
                except:
                    pixels = new_mask.topixel([
                        1, 1, Decvert * np.pi / 180.0, RAvert * np.pi / 180.0
                    ])
                xvert.append(pixels[2])  # x -> Dec
                yvert.append(pixels[3])  # y -> RA
            poly = Polygon(xvert, yvert)

            # Find masked regions
            masked_ind = np.where(data[0, 0])

            # Find distance to nearest poly edge and unmask those that
            # are outside the facet (dist < 0)
            dist = poly.is_inside(masked_ind[0], masked_ind[1])
            outside_ind = np.where(dist < 0.0)
            if len(outside_ind[0]) > 0:
                data[0, 0, masked_ind[0][outside_ind],
                     masked_ind[1][outside_ind]] = 0

        if trim_by > 0.0:
            sh = np.shape(data)
            margin = int(sh[2] * trim_by / 2.0)
            data[0, 0, 0:sh[2], 0:margin] = 0
            data[0, 0, 0:margin, 0:sh[3]] = 0
            data[0, 0, 0:sh[2], sh[3] - margin:sh[3]] = 0
            data[0, 0, sh[2] - margin:sh[2], 0:sh[3]] = 0

        if region_file is not None and region_file != '[]':
            # Merge the CASA regions with the mask
            casa_polys = read_casa_polys(region_file.strip('[]"'), new_mask)
            for poly in casa_polys:
                # Find unmasked regions
                unmasked_ind = np.where(data[0, 0] == 0)

                # Find distance to nearest poly edge and mask those that
                # are inside the casa region (dist > 0)
                dist = poly.is_inside(unmasked_ind[0], unmasked_ind[1])
                inside_ind = np.where(dist > 0.0)
                if len(inside_ind[0]) > 0:
                    data[0, 0, unmasked_ind[0][inside_ind],
                         unmasked_ind[1][inside_ind]] = 1

        # Save changes
        new_mask.putdata(data)
        if img_format == 'fits':
            new_mask.tofits(mask_name, overwrite=True)
        elif img_format == 'casa':
            new_mask.saveas(mask_name, overwrite=True)
        else:
            print(
                'Output image format "{}" not understood.'.format(img_format))
            sys.exit(1)

    if not skip_source_detection:
        if threshold_format == 'float':
            return {
                'threshold_5sig': nsig * img.clipped_rms,
                'multiscale': has_large_isl
            }
        elif threshold_format == 'str_with_units':
            # This is done to get around the need for quotes around strings in casapy scripts
            # 'casastr/' is removed by the generic pipeline
            return {
                'threshold_5sig':
                'casastr/{0}Jy'.format(nsig * img.clipped_rms),
                'multiscale': has_large_isl
            }
    else:
        return {'threshold_5sig': '0.0'}
Пример #22
0
def main(images, outfits, maxwidth=0):
    """
    Creates mosaic

    Parameters
    ----------
    images : str or list of str
        List of filenames of facet images. May be given as a list or as a string
        (e.g., '[image1, image2]'. Each image must be blanked with zeros outside
        of the facet region
    outfits : str
        Filename of output FITS mosaic
    maxwidth : int, optional
        Maximum number of pixels to consider for the width of the mosaic
        [default 0 = unlimited] This can be helpful at high declination.

    """
    if type(images) is str:
        images = images.strip('[]').split(',')
        images = [im.strip() for im in images]

    formstr = '{0:45s}  {1:s}  {2:s} {3:s} {4:s}'
    print formstr.format("-----", "------------", "-------", "-------",
                         "-------")
    print formstr.format("Image", "Norm. weight", "Maj(ac)", "Min(ac)",
                         "PA(deg)")
    print formstr.format("-----", "------------", "-------", "-------",
                         "-------")

    psf_fwhm = []  # resolution
    frequency = []  # frequency of images (should be equal?)
    for i in range(len(images)):
        this_pim = pim.image(images[i])
        info_dict = this_pim.info()['imageinfo']['restoringbeam']
        bpar_ma = quanta.quantity(info_dict['major']).get_value('deg')
        bpar_mi = quanta.quantity(info_dict['minor']).get_value('deg')
        bpar_pa = quanta.quantity(info_dict['positionangle']).get_value('deg')
        psf_fwhm.append([bpar_ma, bpar_mi, bpar_pa])
        frequency.append(
            this_pim.info()['coordinates']['spectral2']['restfreq'])
        print '{0:45.45s}  {1:0.2f}          {2:0.2f}    {3:0.2f}    {4:0.2f}'.format(
            images[i], 0, bpar_ma * 60, bpar_mi * 60, bpar_pa)

    psf_fwhm = np.array(psf_fwhm)
    frequency = np.array(frequency)
    mean_psf_fwhm = np.mean(psf_fwhm, axis=0)
    mean_frequency = np.mean(frequency)

    # Initialize some vectors
    declims = []  # store the limits of the declination axes
    raleft = []
    raright = []
    rainc = []  # store the r.a. increments in case they differ
    decinc = []  # store the dec increments in case they differ
    pims = []  # stores the casacore images of the data

    # Get image frames for input images
    for im in images:
        image = pim.image(im)
        sptcoords = image.coordinates().get_coordinate('spectral')
        nc = sptcoords.get_axis_size()

        # Get Stokes axis. Ensure we are working with the Stokes parameter requested.
        stkcoords = image.coordinates().get_coordinate('stokes')
        if stkcoords.get_axis_size() == 1:
            assert (stkcoords.get_stokes()[0] == 'I')
        else:
            stks = stkcoords.get_stokes().index('I')
            image = image.subimage(blc=(0, stks),
                                   trc=(nc - 1, stks),
                                   dropdegenerate=False)
        ns = 1

        dircoords = image.coordinates().get_coordinate('direction')
        nx = dircoords.get_axis_size(axis=1)
        ny = dircoords.get_axis_size(axis=0)
        inc = dircoords.get_increment()
        ref = dircoords.get_referencepixel()
        val = dircoords.get_referencevalue()
        # wsclean image header is weird
        if val[1] < 0:
            val[1] += 2 * np.pi
        ra_axis = (range(nx) - ref[1]) * inc[1] + val[1]
        dec_axis = (range(ny) - ref[0]) * inc[0] + val[0]
        rainc.append(inc[1])
        decinc.append(inc[0])
        declims.append(min(dec_axis))
        declims.append(max(dec_axis))
        mean_ra = np.mean(ra_axis)
        raleft.append((ra_axis[0] - mean_ra) * np.cos(val[0]) + mean_ra)
        raright.append((ra_axis[-1] - mean_ra) * np.cos(val[0]) + mean_ra)
        pims.append(image)

    # Generate the mosaic coordinate frame
    master_dec = np.arange(min(declims), max(declims), min(decinc))
    if max(raleft) - min(raright) > 5. * np.pi / 3.:  # crossed RA=0
        for i in range(len(raright)):
            raright[i] = raright[i] - 2. * np.pi
    master_ra = np.arange(max(raleft), min(raright), max(rainc))
    lmra = len(master_ra)
    if maxwidth != 0:
        if lmra > maxwidth:
            xboundary = (lmra - maxwidth) / 2
            master_ra = master_ra[xboundary:-xboundary]
    print "Found ra,dec pixel increments (arcsec):"
    print np.array(rainc) * 206265., np.array(decinc) * 206265.
    ma = pims[-1].coordinates()
    ma['direction'].set_referencepixel(
        [len(master_dec) / 2, len(master_ra) / 2])
    ma['direction'].set_increment(
        [decinc[np.argmin(np.abs(decinc))], rainc[np.argmin(np.abs(rainc))]])
    ma['direction'].set_referencevalue(
        [master_dec[len(master_dec) / 2], master_ra[len(master_ra) / 2]])

    # Initialize the arrays for the output image, sensitivity, and weights
    master_im = np.zeros((len(master_dec), len(master_ra)))

    # Reproject the images onto the master grid, weight and normalize
    for im in pims:
        im = im.regrid([2, 3],
                       ma,
                       outshape=(int(nc), int(ns), len(master_dec),
                                 len(master_ra)))
        master_im += np.squeeze(im.getdata())

    blank = np.ones_like(master_im) * np.nan
    master_im = np.where(master_im, master_im, blank)

    # Write fits files
    arrax = np.zeros((1, 1, len(master_im[:, 0]), len(master_im[0, :])))
    arrax[0, 0, :, :] = master_im

    # Open new casa image for mosaic
    new_pim = pim.image('',
                        shape=(1, 1, len(master_dec), len(master_ra)),
                        coordsys=ma)
    new_pim.putdata(arrax)
    # Write fits
    new_pim.tofits(outfits, overwrite=True)

    # need to add new beam info (not sure if this is possible with casacore)
    hdu = pyfits.open(outfits, mode='update', memmap=False)
    header = hdu[0].header
    header['BMAJ'] = mean_psf_fwhm[0]
    header['BMIN'] = mean_psf_fwhm[1]
    header['BPA'] = mean_psf_fwhm[2]
    header['BUNIT'] = pims[-1].info()['unit']
    header['RESTFRQ'] = mean_frequency
    header['RESTFREQ'] = mean_frequency
    newhdu = pyfits.PrimaryHDU(data=hdu[0].data, header=header)
    newhdu.writeto(outfits, clobber=True)
Пример #23
0
def main(input_image_file, vertices_file, output_image_file, blank_value='zero',
    img_format='fits', image_is_casa_model=False, nterms=1):
    """
    Blank a region in an image

    Parameters
    ----------
    input_image_file : str
        Filename of input image from which mask will be made. If the image does
        not exist, a template image with center at (reference_ra_deg,
        reference_dec_deg) will be made internally
    vertices_file : str, optional
        Filename of file with vertices (must be a pickle file containing
        a dictionary with the vertices in the 'vertices' entry)
    output_image_file : str
        Filename of output image
    blank_value : str, optional
        Value for blanks (one of 'zero' or 'nan')
    img_format : str, optional
        Format of output mask image (one of 'fits' or 'casa')
    image_is_casa_model : bool, optional
        If True, the input and output image files are treated as the root name
        of a casa model image (or images)
    nterms : int, optional
        If image_is_casa_model is True, this argument sets the number of nterms
        for the model

    """
    if type(image_is_casa_model) is str:
        if image_is_casa_model.lower() == 'true':
            image_is_casa_model = True
        else:
            image_is_casa_model = False

    if type(nterms) is str:
        nterms = int(nterms)

    if image_is_casa_model:
        if nterms == 1:
            input_image_files = [input_image_file+'.model']
            output_image_files = [output_image_file+'.model']
        if nterms == 2:
            input_image_files = [input_image_file+'.model.tt0',
                input_image_file+'.model.tt1']
            output_image_files = [output_image_file+'.model.tt0',
                output_image_file+'.model.tt1']
        if nterms == 3:
            input_image_files = [input_image_file+'.model.tt0',
                input_image_file+'.model.tt1', input_image_file+'.model.tt2']
            output_image_files = [output_image_file+'.model.tt0',
                output_image_file+'.model.tt1', output_image_file+'.model.tt2']
    else:
        input_image_files = [input_image_file]
        output_image_files = [output_image_file]

    for input_image, output_image in zip(input_image_files, output_image_files):
        im = pim.image(input_image)
        data = im.getdata()
        coordsys = im.coordinates()
        imshape = im.shape()
        new_im = pim.image('', shape=imshape, coordsys=coordsys)

        # Construct polygon
        vertices = read_vertices(vertices_file)
        RAverts = vertices[0]
        Decverts = vertices[1]
        xvert = []
        yvert = []
        for RAvert, Decvert in zip(RAverts, Decverts):
            pixels = new_im.topixel([0, 1, Decvert*np.pi/180.0,
                RAvert*np.pi/180.0])
            xvert.append(pixels[2]) # x -> Dec
            yvert.append(pixels[3]) # y -> RA
        poly = Polygon(xvert, yvert)

        # Find distance to nearest poly edge and blank those that
        # are outside the facet (dist < 0)
        pix_ind = np.indices(data[0, 0].shape)
        dist = poly.is_inside(pix_ind[0], pix_ind[1])
        outside_ind = np.where(dist < 0.0)
        if len(outside_ind[0]) > 0:
            if blank_value == 'zero':
                blank_val = 0.0
            elif blank_value == 'nan':
                blank_val = np.nan
            else:
                print('Blank value type "{}" not understood.'.format(blank_with))
                sys.exit(1)
            data[0, 0, pix_ind[0][outside_ind], pix_ind[1][outside_ind]] = blank_val

        # Save changes
        new_im.putdata(data)
        if img_format == 'fits':
            new_im.tofits(output_image, overwrite=True)
        elif img_format == 'casa':
            new_im.saveas(output_image, overwrite=True)
        else:
            print('Output image format "{}" not understood.'.format(img_format))
            sys.exit(1)
Пример #24
0
 def test_create_CIM_diff_array(self):
     assert np.array_equiv(ds.cim.create_CIM_diff_array(self.CIMPathA,self.CIMPathA),
     np.zeros((np.shape(casaimage.image(self.CIMPathA).getdata())[2],np.shape(casaimage.image(self.CIMPathA).getdata())[3]))) == True, \
     'Failed to produce a difference image of zeros using CIM A!'
Пример #25
0
def main(image_name, mask_name, atrous_do=False, threshisl=0.0, threshpix=0.0, rmsbox=None,
         rmsbox_bright=(35, 7), iterate_threshold=False, adaptive_rmsbox=False, img_format='fits',
         threshold_format='float', trim_by=0.0, vertices_file=None, atrous_jmax=6,
         pad_to_size=None, skip_source_detection=False, region_file=None, nsig=1.0,
         reference_ra_deg=None, reference_dec_deg=None, cellsize_deg=0.000417,
         use_adaptive_threshold=False):
    """
    Make a clean mask and return clean threshold

    Parameters
    ----------
    image_name : str
        Filename of input image from which mask will be made. If the image does
        not exist, a template image with center at (reference_ra_deg,
        reference_dec_deg) will be made internally
    mask_name : str
        Filename of output mask image
    atrous_do : bool, optional
        Use wavelet module of PyBDSM?
    threshisl : float, optional
        Value of thresh_isl PyBDSM parameter
    threshpix : float, optional
        Value of thresh_pix PyBDSM parameter
    rmsbox : tuple of floats, optional
        Value of rms_box PyBDSM parameter
    rmsbox_bright : tuple of floats, optional
        Value of rms_box_bright PyBDSM parameter
    iterate_threshold : bool, optional
        If True, threshold will be lower in 20% steps until
        at least one island is found
    adaptive_rmsbox : tuple of floats, optional
        Value of adaptive_rms_box PyBDSM parameter
    img_format : str, optional
        Format of output mask image (one of 'fits' or 'casa')
    threshold_format : str, optional
        Format of output threshold (one of 'float' or 'str_with_units')
    trim_by : float, optional
        Fraction by which the perimeter of the output mask will be
        trimmed (zeroed)
    vertices_file : str, optional
        Filename of file with vertices (must be a pickle file containing
        a dictionary with the vertices in the 'vertices' entry)
    atrous_jmax : int, optional
        Value of atrous_jmax PyBDSM parameter
    pad_to_size : int, optional
        Pad output mask image to a size of pad_to_size x pad_to_size
    skip_source_detection : bool, optional
        If True, source detection is not run on the input image
    region_file : str, optional
        Filename of region file in CASA format. If given, no mask image
        is made (the region file is used as the clean mask)
    nsig : float, optional
        Number of sigma of returned threshold value
    reference_ra_deg : float, optional
        RA for center of output mask image
    reference_dec_deg : float, optional
        Dec for center of output mask image
    cellsize_deg : float, optional
        Size of a pixel in degrees
    use_adaptive_threshold : bool, optional
        If True, use an adaptive threshold estimated from the negative values in
        the image

    Returns
    -------
    result : dict
        Dict with nsig-sigma rms threshold

    """
    if rmsbox is not None and type(rmsbox) is str:
        rmsbox = eval(rmsbox)

    if type(rmsbox_bright) is str:
        rmsbox_bright = eval(rmsbox_bright)

    if pad_to_size is not None and type(pad_to_size) is str:
        pad_to_size = int(pad_to_size)

    if type(atrous_do) is str:
        if atrous_do.lower() == 'true':
            atrous_do = True
            threshisl = 4.0 # override user setting to ensure proper source fitting
        else:
            atrous_do = False

    if type(iterate_threshold) is str:
        if iterate_threshold.lower() == 'true':
            iterate_threshold = True
        else:
            iterate_threshold = False

    if type(adaptive_rmsbox) is str:
        if adaptive_rmsbox.lower() == 'true':
            adaptive_rmsbox = True
        else:
            adaptive_rmsbox = False

    if type(skip_source_detection) is str:
        if skip_source_detection.lower() == 'true':
            skip_source_detection = True
        else:
            skip_source_detection = False

    if type(use_adaptive_threshold) is str:
        if use_adaptive_threshold.lower() == 'true':
            use_adaptive_threshold = True
        else:
            use_adaptive_threshold = False

    if reference_ra_deg is not None and reference_dec_deg is not None:
        reference_ra_deg = float(reference_ra_deg)
        reference_dec_deg = float(reference_dec_deg)

    if not os.path.exists(image_name):
        print('Input image not found. Making empty image...')
        if not skip_source_detection:
            print('ERROR: Source detection cannot be done on an empty image')
            sys.exit(1)
        if reference_ra_deg is not None and reference_dec_deg is not None:
            image_name = mask_name + '.tmp'
            make_template_image(image_name, reference_ra_deg, reference_dec_deg,
                cellsize_deg=float(cellsize_deg))
        else:
            print('ERROR: if image not found, a refernce position must be given')
            sys.exit(1)

    trim_by = float(trim_by)
    atrous_jmax = int(atrous_jmax)
    threshpix = float(threshpix)
    threshisl = float(threshisl)
    nsig = float(nsig)
    threshold = 0.0

    if not skip_source_detection:
        if vertices_file is not None:
            # Modify the input image to blank the regions outside of the polygon
            temp_img = pim.image(image_name)
            image_name += '.blanked'
            temp_img.saveas(image_name, overwrite=True)
            input_img = pim.image(image_name)
            data = input_img.getdata()

            vertices = read_vertices(vertices_file)
            RAverts = vertices[0]
            Decverts = vertices[1]
            xvert = []
            yvert = []
            for RAvert, Decvert in zip(RAverts, Decverts):
                pixels = input_img.topixel([1, 1, Decvert*np.pi/180.0,
                    RAvert*np.pi/180.0])
                xvert.append(pixels[2]) # x -> Dec
                yvert.append(pixels[3]) # y -> RA
            poly = Polygon(xvert, yvert)

            # Find masked regions
            masked_ind = np.where(data[0, 0])

            # Find distance to nearest poly edge and set to NaN those that
            # are outside the facet (dist < 0)
            dist = poly.is_inside(masked_ind[0], masked_ind[1])
            outside_ind = np.where(dist < 0.0)
            if len(outside_ind[0]) > 0:
                data[0, 0, masked_ind[0][outside_ind], masked_ind[1][outside_ind]] = np.nan

            # Save changes
            input_img.putdata(data)

        if use_adaptive_threshold:
            # Get an estimate of the rms
            img = bdsm.process_image(image_name, mean_map='zero', rms_box=rmsbox,
                                     thresh_pix=threshpix, thresh_isl=threshisl,
                                     atrous_do=atrous_do, ini_method='curvature', thresh='hard',
                                     adaptive_rms_box=adaptive_rmsbox, adaptive_thresh=150,
                                     rms_box_bright=rmsbox_bright, rms_map=True, quiet=True,
                                     atrous_jmax=atrous_jmax, stop_at='isl')

            # Find min and max pixels
            max_neg_val = abs(np.min(img.ch0_arr))
            max_neg_pos = np.where(img.ch0_arr == np.min(img.ch0_arr))
            max_pos_val = abs(np.max(img.ch0_arr))
            max_pos_pos = np.where(img.ch0_arr == np.max(img.ch0_arr))

            # Estimate new thresh_isl from min pixel value's sigma, but don't let
            # it get higher than 1/2 of the peak's sigma
            threshisl_neg = 2.0 * max_neg_val / img.rms_arr[max_neg_pos][0]
            max_sigma = max_pos_val / img.rms_arr[max_pos_pos][0]
            if threshisl_neg > max_sigma / 2.0:
                threshisl_neg = max_sigma / 2.0

            # Use the new threshold only if it is larger than the user-specified one
            if threshisl_neg > threshisl:
                threshisl = threshisl_neg

        if iterate_threshold:
            # Start with given threshold and lower it until we get at least one island
            nisl = 0
            while nisl == 0:
                img = bdsm.process_image(image_name, mean_map='zero', rms_box=rmsbox,
                                         thresh_pix=threshpix, thresh_isl=threshisl,
                                         atrous_do=atrous_do, ini_method='curvature', thresh='hard',
                                         adaptive_rms_box=adaptive_rmsbox, adaptive_thresh=150,
                                         rms_box_bright=rmsbox_bright, rms_map=True, quiet=True,
                                         atrous_jmax=atrous_jmax)
                nisl = img.nisl
                threshpix /= 1.2
                threshisl /= 1.2
                if threshpix < 5.0:
                    break
        else:
            img = bdsm.process_image(image_name, mean_map='zero', rms_box=rmsbox,
                                     thresh_pix=threshpix, thresh_isl=threshisl,
                                     atrous_do=atrous_do, ini_method='curvature', thresh='hard',
                                     adaptive_rms_box=adaptive_rmsbox, adaptive_thresh=150,
                                     rms_box_bright=rmsbox_bright, rms_map=True, quiet=True,
                                     atrous_jmax=atrous_jmax)

        if img.nisl == 0:
            if region_file is None or region_file == '[]':
                print('No islands found. Clean mask cannot be made.')
                sys.exit(1)
            else:
                # Continue on and use user-supplied region file
                skip_source_detection = True
                threshold = nsig * img.clipped_rms

        # Check if there are large islands preset (indicating that multi-scale
        # clean is needed)
        has_large_isl = False
        for isl in img.islands:
            if isl.size_active > 100:
                # Assuming normal sampling, a size of 100 pixels would imply
                # a source of ~ 10 beams
                has_large_isl = True

    if (region_file is not None and region_file != '[]' and skip_source_detection):
        # Copy region file and return if source detection was not done
        os.system('cp {0} {1}'.format(region_file.strip('[]"'), mask_name))
        if threshold_format == 'float':
            return {'threshold_5sig': threshold}
        elif threshold_format == 'str_with_units':
            # This is done to get around the need for quotes around strings in casapy scripts
            # 'casastr/' is removed by the generic pipeline
            return {'threshold_5sig': 'casastr/{0}Jy'.format(threshold)}
    elif not skip_source_detection:
        img.export_image(img_type='island_mask', mask_dilation=0, outfile=mask_name,
                         img_format=img_format, clobber=True)

    if (vertices_file is not None or trim_by > 0 or pad_to_size is not None
        or (region_file is not None and region_file != '[]')
        or skip_source_detection):
        # Alter the mask in various ways
        if skip_source_detection:
            # Read the image
            mask_im = pim.image(image_name)
        else:
            # Read the PyBDSM mask
            mask_im = pim.image(mask_name)
        data = mask_im.getdata()
        coordsys = mask_im.coordinates()
        if reference_ra_deg is not None and reference_dec_deg is not None:
            values = coordsys.get_referencevalue()
            values[2][0] = reference_dec_deg/180.0*np.pi
            values[2][1] = reference_ra_deg/180.0*np.pi
            coordsys.set_referencevalue(values)
        imshape = mask_im.shape()
        del(mask_im)

        if pad_to_size is not None:
            imsize = pad_to_size
            coordsys['direction'].set_referencepixel([imsize/2, imsize/2])
            pixmin = (imsize - imshape[2]) / 2
            if pixmin < 0:
                print("The padded size must be larger than the original size.")
                sys.exit(1)
            pixmax = pixmin + imshape[2]
            data_pad = np.zeros((1, 1, imsize, imsize), dtype=np.float32)
            data_pad[0, 0, pixmin:pixmax, pixmin:pixmax] = data[0, 0]
            new_mask = pim.image('', shape=(1, 1, imsize, imsize), coordsys=coordsys)
            new_mask.putdata(data_pad)
        else:
            new_mask = pim.image('', shape=imshape, coordsys=coordsys)
            new_mask.putdata(data)

        data = new_mask.getdata()

        if skip_source_detection:
            # Mask all pixels
            data[:] = 1

        if vertices_file is not None:
            # Modify the clean mask to exclude regions outside of the polygon
            vertices = read_vertices(vertices_file)
            RAverts = vertices[0]
            Decverts = vertices[1]
            xvert = []
            yvert = []
            for RAvert, Decvert in zip(RAverts, Decverts):
                try:
                    pixels = new_mask.topixel([0, 1, Decvert*np.pi/180.0,
                                               RAvert*np.pi/180.0])
                except:
                    pixels = new_mask.topixel([1, 1, Decvert*np.pi/180.0,
                                               RAvert*np.pi/180.0])
                xvert.append(pixels[2]) # x -> Dec
                yvert.append(pixels[3]) # y -> RA
            poly = Polygon(xvert, yvert)

            # Find masked regions
            masked_ind = np.where(data[0, 0])

            # Find distance to nearest poly edge and unmask those that
            # are outside the facet (dist < 0)
            dist = poly.is_inside(masked_ind[0], masked_ind[1])
            outside_ind = np.where(dist < 0.0)
            if len(outside_ind[0]) > 0:
                data[0, 0, masked_ind[0][outside_ind], masked_ind[1][outside_ind]] = 0

        if trim_by > 0.0:
            sh = np.shape(data)
            margin = int(sh[2] * trim_by / 2.0 )
            data[0, 0, 0:sh[2], 0:margin] = 0
            data[0, 0, 0:margin, 0:sh[3]] = 0
            data[0, 0, 0:sh[2], sh[3]-margin:sh[3]] = 0
            data[0, 0, sh[2]-margin:sh[2], 0:sh[3]] = 0

        if region_file is not None and region_file != '[]':
            # Merge the CASA regions with the mask
            casa_polys = read_casa_polys(region_file.strip('[]"'), new_mask)
            for poly in casa_polys:
                # Find unmasked regions
                unmasked_ind = np.where(data[0, 0] == 0)

                # Find distance to nearest poly edge and mask those that
                # are inside the casa region (dist > 0)
                dist = poly.is_inside(unmasked_ind[0], unmasked_ind[1])
                inside_ind = np.where(dist > 0.0)
                if len(inside_ind[0]) > 0:
                    data[0, 0, unmasked_ind[0][inside_ind], unmasked_ind[1][inside_ind]] = 1

        # Save changes
        new_mask.putdata(data)
        if img_format == 'fits':
            new_mask.tofits(mask_name, overwrite=True)
        elif img_format == 'casa':
            new_mask.saveas(mask_name, overwrite=True)
        else:
            print('Output image format "{}" not understood.'.format(img_format))
            sys.exit(1)

    if not skip_source_detection:
        if threshold_format == 'float':
            return {'threshold_5sig': nsig * img.clipped_rms, 'multiscale': has_large_isl}
        elif threshold_format == 'str_with_units':
            # This is done to get around the need for quotes around strings in casapy scripts
            # 'casastr/' is removed by the generic pipeline
            return {'threshold_5sig': 'casastr/{0}Jy'.format(nsig * img.clipped_rms),
                'multiscale': has_large_isl}
    else:
        return {'threshold_5sig': '0.0'}
Пример #26
0
def on_press(event):
    """
    Handle key presses
    """
    global fig, at, selected_direction, choose_from_list

    if event.key == 'u':
        # Update plot
        choose_from_list = False
        update_plot()
        return

    elif event.key == 'c':
        # Open selfcal images (if any)
        choose_from_list = False
        if selected_direction is None:
            return
        selfcal_images = find_selfcal_images(selected_direction)
        if len(selfcal_images) > 0:
            info = 'Opening selfcal images for {}...'.format(
                selected_direction.name)
            if hasaplpy:
                # Update the text box as the call below takes a few seconds
                c = at.get_child()
                c.set_text(info)
                fig.canvas.draw()
                make_selfcal_images.main(selfcal_images,
                                         interactive=True,
                                         facet_name=selected_direction.name)
            else:
                if os.path.exists('/tmp/tempimage'):
                    shutil.rmtree('/tmp/tempimage')
                im = pim.image(selfcal_images)
                im.view()
        else:
            info = 'No selfcal images exist for {}'.format(
                selected_direction.name)

    elif event.key == 'i':
        # Open full facet images (if any)
        if selected_direction is None:
            return
        facet_images, facetimage_ops = find_facet_images(selected_direction)
        if len(facet_images) == 0:
            info = 'No image of facet exists for {}'.format(
                selected_direction.name)
        else:
            info = 'Load facet image from (choose one):'
            for opindx, (img, fimg_op) in enumerate(
                    zip(facet_images, facetimage_ops)):
                info += '\n  ({0}) {1}'.format(opindx + 1, fimg_op)
            choose_from_list = True

    elif event.key == 'v':
        # Open full facet images (if any)
        choose_from_list = False
        if selected_direction is None:
            return
        facet_verify_images = find_facet_verify_images(selected_direction)
        if len(facet_verify_images) == 0:
            info = 'No verify image of facet exists for {}'.format(
                selected_direction.name)
        else:
            info = 'Opening selfcal verification images for {}...'.format(
                selected_direction.name)
        display_image(facet_verify_images)

    elif event.key in [str(num + 1) for num in range(9)]:
        # Open image (from list given on "i" press)
        if choose_from_list:
            facet_images, facetimage_ops = find_facet_images(
                selected_direction)
            if int(event.key) <= len(facet_images):
                display_image(facet_images[int(event.key) - 1])
                return
        else:
            return

    elif event.key == 't':
        # Open fast TEC selfcal plots (if any)
        choose_from_list = False
        if selected_direction is None:
            return
        selfcal_plots = find_selfcal_tec_plots(selected_direction)
        if len(selfcal_plots) > 0:
            info = 'Opening selfcal TEC solution plots for {}...'.format(
                selected_direction.name)
            os.system(options['image_display'] +
                      ' {} &'.format(' '.join(selfcal_plots)))
        else:
            info = 'Final selfcal solutions do not exist for {}'.format(
                selected_direction.name)

    elif event.key == 'g':
        # Open slow Gain selfcal plots (if any)
        choose_from_list = False
        if selected_direction is None:
            return
        selfcal_plots = find_selfcal_gain_plots(selected_direction)
        if len(selfcal_plots) > 0:
            info = 'Opening selfcal Gain solution plots for {}...'.format(
                selected_direction.name)
            os.system(options['image_display'] +
                      ' {} &'.format(' '.join(selfcal_plots)))
        else:
            info = 'Final selfcal solutions do not exist for {}'.format(
                selected_direction.name)

    elif event.key == 'h':
        choose_from_list = False
        info = 'Reprinting instructions'
        show_instructions()
        return

    else:
        return

    # Update info box
    c = at.get_child()
    c.set_text(info)
    fig.canvas.draw()