Example #1
0
def test_pyregion_subset():
    header = dict(naxis=2, crpix1=15, crpix2=15, crval1=0.1, crval2=0.1,
                  cdelt1=-1. / 3600, cdelt2=1. / 3600., ctype1='GLON-CAR',
                  ctype2='GLAT-CAR')
    mywcs = wcs.WCS(header)
    # circle with radius 10" at 0.1, 0.1
    shape = Shape('circle', (0.1, 0.1, 10. / 3600.))
    shape.coord_format = 'galactic'
    shape.coord_list = (0.1, 0.1, 10. / 3600.)
    shape.attr = ([], {})
    data = np.ones([40, 40])

    # The following line raises a DeprecationWarning from pyregion, ignore it
    with warnings.catch_warnings():
        warnings.filterwarnings('ignore')
        (xlo, xhi, ylo, yhi), d = utils.pyregion_subset(shape, data, mywcs)

    # sticky note over check-engine light solution... but this problem is too
    # large in scope to address here.  See
    # https://github.com/astropy/astropy/pull/3992
    assert d.sum() >= 313 & d.sum() <= 315  # VERY approximately pi
    np.testing.assert_almost_equal(xlo,
                                   data.shape[0] / 2 - mywcs.wcs.crpix[0] - 1)
    np.testing.assert_almost_equal(xhi,
                                   data.shape[0] - mywcs.wcs.crpix[0] - 1)
    np.testing.assert_almost_equal(ylo,
                                   data.shape[1] / 2 - mywcs.wcs.crpix[1] - 1)
    np.testing.assert_almost_equal(yhi,
                                   data.shape[1] - mywcs.wcs.crpix[1] - 1)
def footprint_to_reg(footprint):
    """
    ALMA footprints have the form:
    'Polygon ICRS 266.519781 -28.724666 266.524678 -28.731930 266.536683
    -28.737784 266.543860 -28.737586 266.549277 -28.733370 266.558133
    -28.729545 266.560136 -28.724666 266.558845 -28.719605 266.560133
    -28.694332 266.555234 -28.687069 266.543232 -28.681216 266.536058
    -28.681414 266.530644 -28.685630 266.521788 -28.689453 266.519784
    -28.694332 266.521332 -28.699778'
    Some of them have *additional* polygons
    """
    if footprint[:7] != 'Polygon':
        raise ValueError("Unrecognized footprint type")

    from pyregion.parser_helper import Shape

    entries = footprint.split()
    polygons = [ii for ii, xx in enumerate(entries) if xx == 'Polygon']

    reglist = []
    for start, stop in zip(polygons, polygons[1:]+[None]):
        reg = Shape('polygon', [float(x) for x in entries[start+2:stop]])
        reg.coord_format = footprint.split()[1].lower()
        reg.coord_list = reg.params  # the coord_list attribute is needed somewhere
        reg.attr = ([], {'color': 'green', 'dash': '0 ', 'dashlist': '8 3',
                         'delete': '1 ', 'edit': '1 ', 'fixed': '0 ', 'font':
                         '"helvetica 10 normal roman"', 'highlite': '1 ',
                         'include': '1 ', 'move': '1 ', 'select': '1',
                         'source': '1', 'text': '', 'width': '1 '})
        reglist.append(reg)

    return reglist
Example #3
0
def footprint_to_reg(footprint):
    """
    ALMA footprints have the form:
    'Polygon ICRS 266.519781 -28.724666 266.524678 -28.731930 266.536683
    -28.737784 266.543860 -28.737586 266.549277 -28.733370 266.558133
    -28.729545 266.560136 -28.724666 266.558845 -28.719605 266.560133
    -28.694332 266.555234 -28.687069 266.543232 -28.681216 266.536058
    -28.681414 266.530644 -28.685630 266.521788 -28.689453 266.519784
    -28.694332 266.521332 -28.699778'
    Some of them have *additional* polygons
    """
    if footprint[:7] != 'Polygon':
        raise ValueError("Unrecognized footprint type")

    from pyregion.parser_helper import Shape

    entries = footprint.split()
    polygons = [ii for ii, xx in enumerate(entries) if xx == 'Polygon']

    reglist = []
    for start, stop in zip(polygons, polygons[1:]+[None]):
        reg = Shape('polygon', [float(x) for x in entries[start+2:stop]])
        reg.coord_format = footprint.split()[1].lower()
        reg.coord_list = reg.params  # the coord_list attribute is needed somewhere
        reg.attr = ([], {'color': 'green', 'dash': '0 ', 'dashlist': '8 3',
                         'delete': '1 ', 'edit': '1 ', 'fixed': '0 ', 'font':
                         '"helvetica 10 normal roman"', 'highlite': '1 ',
                         'include': '1 ', 'move': '1 ', 'select': '1',
                         'source': '1', 'text': '', 'width': '1 '})
        reglist.append(reg)

    return reglist
Example #4
0
def test_pyregion_subset():
    header = dict(naxis=2,
                  crpix1=15,
                  crpix2=15,
                  crval1=0.1,
                  crval2=0.1,
                  cdelt1=-1. / 3600,
                  cdelt2=1. / 3600.,
                  ctype1='GLON-CAR',
                  ctype2='GLAT-CAR')
    mywcs = wcs.WCS(header)
    # circle with radius 10" at 0.1, 0.1
    shape = Shape('circle', (0.1, 0.1, 10. / 3600.))
    shape.coord_format = 'galactic'
    shape.coord_list = (0.1, 0.1, 10. / 3600.)
    shape.attr = ([], {})
    data = np.ones([40, 40])
    (xlo, xhi, ylo, yhi), d = utils.pyregion_subset(shape, data, mywcs)

    assert d.sum() == 314  # approximately pi
    np.testing.assert_almost_equal(xlo,
                                   data.shape[0] / 2 - mywcs.wcs.crpix[0] - 1)
    np.testing.assert_almost_equal(xhi, data.shape[0] - mywcs.wcs.crpix[0] - 1)
    np.testing.assert_almost_equal(ylo,
                                   data.shape[1] / 2 - mywcs.wcs.crpix[1] - 1)
    np.testing.assert_almost_equal(yhi, data.shape[1] - mywcs.wcs.crpix[1] - 1)
Example #5
0
def test_pyregion_subset():
    header = dict(naxis=2,
                  crpix1=15,
                  crpix2=15,
                  crval1=0.1,
                  crval2=0.1,
                  cdelt1=-1. / 3600,
                  cdelt2=1. / 3600.,
                  ctype1='GLON-CAR',
                  ctype2='GLAT-CAR')
    mywcs = wcs.WCS(header)
    # circle with radius 10" at 0.1, 0.1
    shape = Shape('circle', (0.1, 0.1, 10. / 3600.))
    shape.coord_format = 'galactic'
    shape.coord_list = (0.1, 0.1, 10. / 3600.)
    shape.attr = ([], {})
    data = np.ones([40, 40])
    (xlo, xhi, ylo, yhi), d = utils.pyregion_subset(shape, data, mywcs)

    # sticky note over check-engine light solution... but this problem is too
    # large in scope to address here.  See
    # https://github.com/astropy/astropy/pull/3992
    assert d.sum() >= 313 & d.sum() <= 315  # VERY approximately pi
    np.testing.assert_almost_equal(xlo,
                                   data.shape[0] / 2 - mywcs.wcs.crpix[0] - 1)
    np.testing.assert_almost_equal(xhi, data.shape[0] - mywcs.wcs.crpix[0] - 1)
    np.testing.assert_almost_equal(ylo,
                                   data.shape[1] / 2 - mywcs.wcs.crpix[1] - 1)
    np.testing.assert_almost_equal(yhi, data.shape[1] - mywcs.wcs.crpix[1] - 1)
Example #6
0
def table_to_circ_region(table,
                         outfile,
                         racol='RA',
                         deccol='DEC',
                         sizecol='size',
                         color='red',
                         label=True):
    """
    Get a table with ra, dec, size and generate a circular ds9 region 
    TODO: if cat is given, add a small circle around all sources on the edge
    """

    regions = []
    for i, r in enumerate(table):
        s = Shape('circle', None)
        s.coord_format = 'fk5'
        s.coord_list = [r[racol], r[deccol], r[sizecol]]  # ra, dec, radius
        s.coord_format = 'fk5'
        s.attr = ([], {
            'width': '2',
            'point': 'cross',
            'font': '"helvetica 16 normal roman"'
        })
        if label: s.comment = 'color={} text="{}"'.format(color, str(i))
        else: s.comment = 'color={}'.format(color)
        regions.append(s)

    regions = pyregion.ShapeList(regions)
    check_rm(outfile)
    regions.write(outfile)
Example #7
0
    def makeBeamReg(self, outfile, pb_cut=None, to_null=False, freq='mid'):
        """
        Create a ds9 region of the beam
        outfile : str
            output file
        pb_cut : float, optional
            diameter of the beam
        to_null : bool, optional
            arrive to the first null, not the FWHM
        freq: min,max,med 
            which frequency to use to estimate the beam size
        """
        logger.debug('Making PB region: '+outfile)
        ra, dec = self.getPhaseCentre()

        if pb_cut is None:
            radius = self.getFWHM(freq=freq)/2.
        else:
            radius = pb_cut/2.

        if to_null: radius *= 2 # rough estimation

        s = Shape('circle', None)
        s.coord_format = 'fk5'
        s.coord_list = [ ra, dec, radius ] # ra, dec, radius
        s.coord_format = 'fk5'
        s.attr = ([], {'width': '2', 'point': 'cross',
                       'font': '"helvetica 16 normal roman"'})
        s.comment = 'color=red text="beam"'

        regions = pyregion.ShapeList([s])
        lib_util.check_rm(outfile)
        regions.write(outfile)
def test_pyregion_subset():
    header = dict(naxis=2, crpix1=15, crpix2=15, crval1=0.1, crval2=0.1,
                  cdelt1=-1./3600, cdelt2=1./3600., ctype1='GLON-CAR',
                  ctype2='GLAT-CAR')
    mywcs = wcs.WCS(header)
    # circle with radius 10" at 0.1, 0.1
    shape = Shape('circle', (0.1, 0.1, 10./3600.))
    shape.coord_format = 'galactic'
    shape.coord_list = (0.1, 0.1, 10./3600.)
    shape.attr = ([], {})
    data = np.ones([40,40])
    (xlo,xhi,ylo,yhi), d = utils.pyregion_subset(shape, data, mywcs)

    assert d.sum() == 314 # approximately pi
    np.testing.assert_almost_equal(xlo, data.shape[0]/2-mywcs.wcs.crpix[0]-1)
    np.testing.assert_almost_equal(xhi, data.shape[0]-mywcs.wcs.crpix[0]-1)
    np.testing.assert_almost_equal(ylo, data.shape[1]/2-mywcs.wcs.crpix[1]-1)
    np.testing.assert_almost_equal(yhi, data.shape[1]-mywcs.wcs.crpix[1]-1)
Example #9
0
    def set_region(self, loc):
        """
        Creates a ds9 regionfile that covers the DD-cal model
        """
        assert self.size is not None and self.position is not None  # we need this to be already set

        self.region_file = loc+'/'+self.name+'.reg'
        s = Shape('circle', None)
        s.coord_format = 'fk5'
        s.coord_list = [ self.position[0], self.position[1], self.size/2. ]  # ra, dec, radius
        s.coord_format = 'fk5'
        s.attr = ([], {'width': '2', 'point': 'cross',
                       'font': '"helvetica 16 normal roman"'})
        if not self.peel_off: s.comment = 'color=red text="%s"' % self.name
        else: s.comment = 'color=blue text="%s"' % self.name

        regions = pyregion.ShapeList([s])
        lib_util.check_rm(self.region_file)
        regions.write(self.region_file)
Example #10
0
    def makeBeamReg(self, outfile, pb_cut=None, to_null=False):
        """
        Create a ds9 region of the beam
        outfile : str
            output file
        pb_cut : float, optional
            diameter of the beam
        to_null : bool, optional
            arrive to the first null, not the FWHM
        """
        logger.debug('Making PB region: ' + outfile)
        ra, dec = self.getPhaseCentre()

        if pb_cut is None:
            if 'OUTER' in self.getObsMode():
                size = 8. / 2.
            elif 'SPARSE' in self.getObsMode():
                size = 12. / 2.
            elif 'INNER' in self.getObsMode():
                size = 16. / 2.
            else:
                logger.error(
                    'Cannot find beam size, only LBA_OUTER or LBA_SPARSE_* are implemented. Assuming beam diameter = 8 deg.'
                )
                size = 8. / 2.
        else:
            size = pb_cut / 2.

        if to_null: size *= 1.7  # rough estimation

        s = Shape('circle', None)
        s.coord_format = 'fk5'
        s.coord_list = [ra, dec, size]  # ra, dec, radius
        s.coord_format = 'fk5'
        s.attr = ([], {
            'width': '2',
            'point': 'cross',
            'font': '"helvetica 16 normal roman"'
        })
        s.comment = 'color=red text="beam"'

        regions = pyregion.ShapeList([s])
        lib_util.check_rm(outfile)
        regions.write(outfile)
Example #11
0
def make_voronoi_reg(directions,
                     fitsfile,
                     outdir_reg='regions',
                     out_mask='facet.fits',
                     beam_reg=None,
                     png=None):
    """
    Take a list of coordinates and an image and voronoi tesselate the sky.
    It saves ds9 regions + fits mask of the facets

    directions : dict with {'Dir_0':[ra,dec], 'Dir_1':[ra,dec]...} - note that the "Dir_##" naming is important
    firsfile : mask fits file to tassellate (used for coordinates and to avoid splitting islands)
    outdir* : dir where to save regions/masks
    beam_reg : a ds9 region showing the the primary beam, exclude directions outside it
    """
    def closest_node(node, nodes):
        """
        Return closest values to node from nodes
        """
        nodes = np.asarray(nodes)
        dist_2 = np.sum((nodes - node)**2, axis=1)
        return np.argmin(dist_2)

    import lib_img
    logger.debug("Image used for tasselation reference: " + fitsfile)
    fits = pyfits.open(fitsfile)
    hdr, data = lib_img.flatten(fits)
    w = pywcs.WCS(hdr)
    pixsize = np.abs(hdr['CDELT1'])

    # Get facets central pixels
    ras = np.array([directions[d][0].degree for d in directions])
    decs = np.array([directions[d][1].degree for d in directions])
    x_fs, y_fs = w.all_world2pix(ras, decs, 0, ra_dec_order=True)
    # keep trak of numbers in the direction names to name correctly patches in the fits files
    # in this way Dir_12 will have "12" into the fits for that patch.
    nums = [int(d.split('_')[1]) for d in directions.keys()]

    x_c = data.shape[0] / 2.
    y_c = data.shape[1] / 2.

    if beam_reg is None:
        # no beam, use all directions for facets
        idx_for_facet = range(len(directions))
    else:
        r = pyregion.open(beam_reg)
        beam_mask = r.get_mask(header=hdr, shape=data.shape)
        beamradius_pix = r[0].coord_list[2] / pixsize
        idx_for_facet = []
        for i, dd in enumerate(t):
            if beam_mask[t['x'][i], t['y'][i]] == True:
                idx_for_facet.append(i)

    # convert to pixel space (voronoi must be in eucledian space)
    x1 = 0
    y1 = 0
    x2 = data.shape[0]
    y2 = data.shape[1]

    # do tasselization
    vor = Voronoi(
        np.array((x_fs[idx_for_facet], y_fs[idx_for_facet])).transpose())
    box = np.array([[x1, y1], [x2, y2]])
    impoly = voronoi_finite_polygons_2d_box(vor, box)

    # create fits mask (each region one number)
    x, y = np.meshgrid(np.arange(x2),
                       np.arange(y2))  # make a canvas with coordinates
    x, y = x.flatten(), y.flatten()
    pixels = np.vstack((x, y)).T
    data_facet = np.zeros(shape=data.shape)
    for num, poly in zip(nums, impoly):
        p = Path(poly)
        pixels_region = p.contains_points(pixels)
        # iterate through direction centres and find which one belongs to this region, then use the dir name to set the number
        # this is important as the vornoi tassellation has to have the same names of the original tassellation
        #for x,y,d in zip(x_fs, y_fs, directions.keys()):
        #    if pixels_region.reshape(x2,y2)[int(np.rint(x)),int(np.rint(y))] == True:
        #        num = int(d.split('_')[1])
        #        print num,x,y,d
        data_facet[pixels_region.reshape(x2, y2)] = num

    # put all values in each island equal to the closest region
    struct = generate_binary_structure(2, 2)
    data = binary_dilation(data, structure=struct,
                           iterations=3).astype(data.dtype)  # expand masks
    blobs, number_of_blobs = label(data.astype(int).squeeze(),
                                   structure=[[1, 1, 1], [1, 1, 1], [1, 1, 1]])
    center_of_masses = center_of_mass(data, blobs, range(number_of_blobs + 1))
    for blob in xrange(1, number_of_blobs + 1):
        # get closer facet
        facet_num = closest_node(center_of_masses[blob],
                                 np.array([y_fs, x_fs]).T)
        # put all pixel of that mask to that facet value
        data_facet[blobs == blob] = nums[facet_num]

    # save fits mask
    pyfits.writeto(out_mask, data_facet, hdr, overwrite=True)

    # save regions
    all_s = []
    for i, poly in enumerate(impoly):
        ra, dec = w.all_pix2world(poly[:, 0], poly[:, 1], 0, ra_dec_order=True)
        coords = np.array([ra, dec]).T.flatten()

        s = Shape('Polygon', None)
        s.coord_format = 'fk5'
        s.coord_list = coords  # ra, dec, radius
        s.coord_format = 'fk5'
        s.attr = ([], {
            'width': '2',
            'point': 'cross',
            'font': '"helvetica 16 normal roman"'
        })
        s.comment = 'color=red'
        all_s.append(s)

        regions = pyregion.ShapeList([s])
        regionfile = outdir_reg + '/' + directions.keys()[
            idx_for_facet[i]] + '.reg'
        regions.write(regionfile)

    # add names for all.reg
    for d_name, d_coord in directions.iteritems():
        s = Shape('circle', None)
        s.coord_format = 'fk5'
        s.coord_list = [d_coord[0].degree, d_coord[1].degree,
                        0.01]  # ra, dec, radius
        s.coord_format = 'fk5'
        s.attr = ([], {
            'width': '1',
            'point': 'cross',
            'font': '"helvetica 16 normal roman"'
        })
        s.comment = 'color=white text="%s"' % d_name
        all_s.append(s)

    regions = pyregion.ShapeList(all_s)
    regionfile = outdir_reg + '/all.reg'
    regions.write(regionfile)
    logger.debug(
        'There are %i regions within the PB and %i outside (no facet).' %
        (len(idx_for_facet), len(directions) - len(idx_for_facet)))

    # plot tesselization
    if png is not None:
        import matplotlib.pyplot as pl
        pl.figure(figsize=(8, 8))
        ax1 = pl.gca()
        voronoi_plot_2d(vor,
                        ax1,
                        show_vertices=True,
                        line_colors='black',
                        line_width=2,
                        point_size=4)
        for i, d in enumerate(directions):
            ax1.text(x_fs[i], y_fs[i], d, fontsize=15)
        if not beam_reg is None:
            c1 = pl.Circle((x_c, y_c), beamradius_pix, color='g', fill=False)
            ax1.add_artist(c1)
        ax1.plot([x1, x1, x2, x2, x1], [y1, y2, y2, y1, y1])
        ax1.set_xlabel('RA (pixel)')
        ax1.set_ylabel('Dec (pixel)')
        ax1.set_xlim(x1, x2)
        ax1.set_ylim(y1, y2)
        logger.debug('Save plot: %s' % png)
        pl.savefig(png)
Example #12
0
def make_finder_chart_from_image_and_catalog(
    image,
    catalog,
    save_prefix,
    alma_kwargs={
        'public': False,
        'science': False
    },
    bands=(3, 4, 5, 6, 7, 8, 9),
    private_band_colors=('maroon', 'red', 'orange', 'coral', 'brown', 'yellow',
                         'mediumorchid'),
    public_band_colors=('blue', 'cyan', 'green', 'turquoise', 'teal',
                        'darkslategrey', 'chartreuse'),
    integration_time_contour_levels=np.logspace(0, 5, base=2, num=6),
    save_masks=False,
    use_saved_masks=False,
):
    """
    Create a "finder chart" showing where ALMA has pointed in various bands,
    including different color coding for public/private data and each band.

    Contours are set at various integration times.

    Parameters
    ----------
    image : fits.PrimaryHDU or fits.ImageHDU object
        The image to overlay onto
    catalog : astropy.Table object
        The catalog of ALMA observations
    save_prefix : str
        The prefix for the output files.  Both .reg and .png files will be
        written.  The .reg files will have the band numbers and
        public/private appended, while the .png file will be named
        prefix_almafinderchart.png
    alma_kwargs : dict
        Keywords to pass to the ALMA archive when querying.
    private_band_colors / public_band_colors : tuple
        A tuple or list of colors to be associated with private/public
        observations in the various bands
    integration_time_contour_levels : list or np.array
        The levels at which to draw contours in units of seconds.  Default is
        log-spaced (2^n) seconds: [  1.,   2.,   4.,   8.,  16.,  32.])
    """
    import aplpy

    import pyregion
    from pyregion.parser_helper import Shape

    primary_beam_radii = [
        approximate_primary_beam_sizes(row['Frequency support'])
        for row in catalog
    ]

    all_bands = bands
    bands = used_bands = np.unique(catalog['Band'])
    log.info("The bands used include: {0}".format(used_bands))
    band_colors_priv = dict(zip(all_bands, private_band_colors))
    band_colors_pub = dict(zip(all_bands, public_band_colors))
    log.info("Color map private: {0}".format(band_colors_priv))
    log.info("Color map public: {0}".format(band_colors_pub))

    if use_saved_masks:
        hit_mask_public = {}
        hit_mask_private = {}

        for band in bands:
            pubfile = '{0}_band{1}_public.fits'.format(save_prefix, band)
            if os.path.exists(pubfile):
                hit_mask_public[band] = fits.getdata(pubfile)
            privfile = '{0}_band{1}_private.fits'.format(save_prefix, band)
            if os.path.exists(privfile):
                hit_mask_private[band] = fits.getdata(privfile)

    else:
        today = np.datetime64('today')

        private_circle_parameters = {
            band: [(row['RA'], row['Dec'], np.mean(rad).to(u.deg).value)
                   for row, rad in zip(catalog, primary_beam_radii)
                   if not row['Release date'] or (np.datetime64(
                       row['Release date']) > today and row['Band'] == band)]
            for band in bands
        }

        public_circle_parameters = {
            band: [(row['RA'], row['Dec'], np.mean(rad).to(u.deg).value)
                   for row, rad in zip(catalog, primary_beam_radii)
                   if row['Release date'] and (np.datetime64(
                       row['Release date']) <= today and row['Band'] == band)]
            for band in bands
        }

        unique_private_circle_parameters = {
            band: np.array(list(set(private_circle_parameters[band])))
            for band in bands
        }
        unique_public_circle_parameters = {
            band: np.array(list(set(public_circle_parameters[band])))
            for band in bands
        }

        release_dates = np.array(catalog['Release date'], dtype=np.datetime64)

        for band in bands:
            log.info("BAND {0}".format(band))
            privrows = sum((catalog['Band'] == band) & (release_dates > today))
            pubrows = sum((catalog['Band'] == band) & (release_dates <= today))
            log.info("PUBLIC:  Number of rows: {0}.  Unique pointings: "
                     "{1}".format(pubrows,
                                  len(unique_public_circle_parameters[band])))
            log.info("PRIVATE: Number of rows: {0}.  Unique pointings: "
                     "{1}".format(privrows,
                                  len(unique_private_circle_parameters[band])))

        prv_regions = {
            band: pyregion.ShapeList([
                Shape('circle', [x, y, r])
                for x, y, r in private_circle_parameters[band]
            ])
            for band in bands
        }
        pub_regions = {
            band: pyregion.ShapeList([
                Shape('circle', [x, y, r])
                for x, y, r in public_circle_parameters[band]
            ])
            for band in bands
        }
        for band in bands:
            circle_pars = np.vstack([
                x for x in (private_circle_parameters[band],
                            public_circle_parameters[band]) if any(x)
            ])
            for r, (x, y, c) in zip(prv_regions[band] + pub_regions[band],
                                    circle_pars):
                r.coord_format = 'fk5'
                r.coord_list = [x, y, c]
                r.attr = ([], {
                    'color': 'green',
                    'dash': '0 ',
                    'dashlist': '8 3',
                    'delete': '1 ',
                    'edit': '1 ',
                    'fixed': '0 ',
                    'font': '"helvetica 10 normal roman"',
                    'highlite': '1 ',
                    'include': '1 ',
                    'move': '1 ',
                    'select': '1',
                    'source': '1',
                    'text': '',
                    'width': '1 '
                })

            if prv_regions[band]:
                prv_regions[band].write('{0}_band{1}_private.reg'.format(
                    save_prefix, band))
            if pub_regions[band]:
                pub_regions[band].write('{0}_band{1}_public.reg'.format(
                    save_prefix, band))

        prv_mask = {
            band:
            fits.PrimaryHDU(prv_regions[band].get_mask(image).astype('int'),
                            header=image.header)
            for band in bands if prv_regions[band]
        }
        pub_mask = {
            band:
            fits.PrimaryHDU(pub_regions[band].get_mask(image).astype('int'),
                            header=image.header)
            for band in bands if pub_regions[band]
        }

        hit_mask_public = {
            band: np.zeros_like(image.data)
            for band in pub_mask
        }
        hit_mask_private = {
            band: np.zeros_like(image.data)
            for band in prv_mask
        }
        mywcs = wcs.WCS(image.header)

        for band in bands:
            log.debug('Band: {0}'.format(band))
            for row, rad in ProgressBar(list(zip(catalog,
                                                 primary_beam_radii))):
                shape = Shape(
                    'circle',
                    (row['RA'], row['Dec'], np.mean(rad).to(u.deg).value))
                shape.coord_format = 'fk5'
                shape.coord_list = (row['RA'], row['Dec'],
                                    np.mean(rad).to(u.deg).value)
                shape.attr = ([], {
                    'color': 'green',
                    'dash': '0 ',
                    'dashlist': '8 3 ',
                    'delete': '1 ',
                    'edit': '1 ',
                    'fixed': '0 ',
                    'font': '"helvetica 10 normal roman"',
                    'highlite': '1 ',
                    'include': '1 ',
                    'move': '1 ',
                    'select': '1 ',
                    'source': '1',
                    'text': '',
                    'width': '1 '
                })
                log.debug('{1} {2}: {0}'.format(shape, row['Release date'],
                                                row['Band']))

                if not row['Release date']:
                    reldate = False
                else:
                    reldate = np.datetime64(row['Release date'])

                if (((not reldate) or (reldate > today))
                        and (row['Band'] == band) and (band in prv_mask)):
                    # private: release_date = 'sometime' says when it will be released
                    (xlo, xhi, ylo,
                     yhi), mask = pyregion_subset(shape,
                                                  hit_mask_private[band],
                                                  mywcs)
                    log.debug("{0},{1},{2},{3}: {4}".format(
                        xlo, xhi, ylo, yhi, mask.sum()))
                    hit_mask_private[band][
                        ylo:yhi, xlo:xhi] += row['Integration'] * mask
                elif (reldate and (reldate <= today) and (row['Band'] == band)
                      and (band in pub_mask)):
                    # public: release_date = '' should mean already released
                    (xlo, xhi, ylo,
                     yhi), mask = pyregion_subset(shape, hit_mask_public[band],
                                                  mywcs)
                    log.debug("{0},{1},{2},{3}: {4}".format(
                        xlo, xhi, ylo, yhi, mask.sum()))
                    hit_mask_public[band][ylo:yhi,
                                          xlo:xhi] += row['Integration'] * mask

        if save_masks:
            for band in bands:
                if band in hit_mask_public:
                    hdu = fits.PrimaryHDU(data=hit_mask_public[band],
                                          header=image.header)
                    hdu.writeto('{0}_band{1}_public.fits'.format(
                        save_prefix, band),
                                clobber=True)
                if band in hit_mask_private:
                    hdu = fits.PrimaryHDU(data=hit_mask_private[band],
                                          header=image.header)
                    hdu.writeto('{0}_band{1}_private.fits'.format(
                        save_prefix, band),
                                clobber=True)

    fig = aplpy.FITSFigure(fits.HDUList(image), convention='calabretta')
    fig.show_grayscale(stretch='arcsinh')
    for band in bands:
        if band in hit_mask_public:
            fig.show_contour(fits.PrimaryHDU(data=hit_mask_public[band],
                                             header=image.header),
                             levels=integration_time_contour_levels,
                             colors=[band_colors_pub[int(band)]] *
                             len(integration_time_contour_levels),
                             convention='calabretta')
        if band in hit_mask_private:
            fig.show_contour(fits.PrimaryHDU(data=hit_mask_private[band],
                                             header=image.header),
                             levels=integration_time_contour_levels,
                             colors=[band_colors_priv[int(band)]] *
                             len(integration_time_contour_levels),
                             convention='calabretta')

    fig.save('{0}_almafinderchart.png'.format(save_prefix))

    return image, catalog, hit_mask_public, hit_mask_private
def writeRegionFile(outname, catalog, matches, color='blue', width=2,
                    fonttype='helvetica', fontsize=10, fontweight='normal',
                    fontfamily='roman'):
    '''
    Writes the region file.

    Keywords:
        outname -- A string containing the name of the output file.
        gParam -- A dictionary of global setup parameters.
        catalog -- A dictionary containing the different region.
        matches -- A list containing the indices matching the search keyword(s).

    '''

    fontpars = dict(fontweight=fontweight, fonttype=fonttype,
                    fontfamily=fontfamily, fontsize=fontsize)

    shapeList = []

    for row in matches:

        name = row['name']
        stype = row['stype']
        coords = row['coord']
        epoch = row['epoch']
        shape = row['shape']
        sunit = row['sunit']
        text = row['text']

 
        #
        # do some coordinate system conversion, if necessary

        if 'equatorial' in row['ctype']:
            if epoch == 1950:
                frame = coord.FK4
                pos = coord.SkyCoord(coords, frame=frame, unit=(u.hourangle, u.deg))
                pos_fk5 = pos.fk5

            elif epoch == 2000:
                frame = coord.FK5
                pos_fk5 = coord.SkyCoord(coords, frame=frame, unit=(u.hourangle, u.deg))

            else:
                print("Cannot read epoch and/or ctype. Skipping index %i" % index)
                continue


        if 'ellipse' in stype:

            shape_list = shape.split(',')

            rmaj = u.Quantity(float(shape_list[0].strip()), sunit)
            rmin = u.Quantity(float(shape_list[1].strip()), sunit)
            rpa = shape_list[2].strip()

            shape = Shape(stype,
                          (pyregion.region_numbers.SimpleNumber(pos_fk5.ra.deg),
                           pyregion.region_numbers.SimpleNumber(pos_fk5.dec.deg),
                           pyregion.region_numbers.AngularDistance('{0}"'.format(rmaj.to(u.arcsec).value)),
                           pyregion.region_numbers.AngularDistance('{0}"'.format(rmin.to(u.arcsec).value)),
                           pyregion.region_numbers.AngularDistance(rpa),))
            shape.coord_format = 'fk5'
            shape.attr = ([],{})
            shape.attr[1].update({'color': color,
                                  'text': "{0}{2}{1}".format(name,text, ", " if text else ""),
                                  'width': str(width),
                                  'font': "{fonttype} {fontsize} {fontweight} {fontfamily}".format(**fontpars),
                                 })
            shape.coord_list = [pos_fk5.ra.deg, pos_fk5.dec.deg,
                                rmaj.to(u.deg).value, rmin.to(u.deg).value,
                                float(rpa)]
            shape.comment = "text={{{text}}}".format(**shape.attr[1])
            print(shape, shape.attr)





        shapeList.append(shape)

    SL = pyregion.ShapeList(shapeList)
    SL.write(outname)

    return SL
Example #14
0
fig = aplpy.FITSFigure(m83_images[0])
fig.show_grayscale(stretch='arcsinh', vmid=0.1)
fig.show_circles(unique_public_circle_parameters[:, 0],
                 unique_public_circle_parameters[:, 1],
                 unique_public_circle_parameters[:, 2],
                 color='b',
                 alpha=0.2)

# Use pyregion to write the observed regions to disk.  Pyregion has a very
# awkward API; there is (in principle) work in progress to improve that
# situation but for now one must do all this extra work.

import pyregion
from pyregion.parser_helper import Shape
prv_regions = pyregion.ShapeList(
    [Shape('circle', [x, y, r]) for x, y, r in private_circle_parameters])
pub_regions = pyregion.ShapeList(
    [Shape('circle', [x, y, r]) for x, y, r in public_circle_parameters])
for r, (x, y, c) in zip(
        prv_regions + pub_regions,
        np.vstack([private_circle_parameters, public_circle_parameters])):
    r.coord_format = 'fk5'
    r.coord_list = [x, y, c]
    r.attr = ([], {
        'color': 'green',
        'dash': '0 ',
        'dashlist': '8 3 ',
        'delete': '1 ',
        'edit': '1 ',
        'fixed': '0 ',
        'font': '"helvetica 10 normal roman"',
Example #15
0
def make_voronoi_reg(directions,
                     fitsfile,
                     outdir='regions/',
                     beam_reg='',
                     png=None):
    """
    Take a list of coordinates and an image and voronoi tesselate the sky.
    It saves ds9 regions of the facets and and return facet sizes

    directions : dict with {'dir0':[ra,dec], 'dir1':[ra,dec]...}
    firsfile : model fits file to tassellate (used for coordinates)
    outdir : dir where to save regions
    beam_reg : a ds9 region showing the the primary beam, exclude directions outside it
    """

    logger.debug("Image used for tasselation reference: " + fitsfile)
    fits = pyfits.open(fitsfile)
    hdr, data = flatten(fits)
    w = pywcs.WCS(hdr)
    pixsize = np.abs(hdr['CDELT1'])

    # Add facet size column
    ras = np.array([directions[d][0].degree for d in directions])
    decs = np.array([directions[d][1].degree for d in directions])
    x, y = w.all_world2pix(ras, decs, 0, ra_dec_order=True)

    x_c = data.shape[0] / 2.
    y_c = data.shape[1] / 2.

    if beam_reg == '':
        # no beam, use all directions for facets
        idx_for_facet = range(len(directions))
    else:
        r = pyregion.open(beam_reg)
        beam_mask = r.get_mask(header=hdr, shape=data.shape)
        beamradius_pix = r[0].coord_list[2] / pixsize
        idx_for_facet = []
        for i, dd in enumerate(t):
            if beam_mask[t['x'][i], t['y'][i]] == True:
                idx_for_facet.append(i)

    # convert to pixel space (voronoi must be in eucledian space)
    x1 = 0
    y1 = 0
    x2 = data.shape[0]
    y2 = data.shape[1]

    # do tasselization
    vor = Voronoi(np.array((x[idx_for_facet], y[idx_for_facet])).transpose())
    box = np.array([[x1, y1], [x2, y2]])
    impoly = voronoi_finite_polygons_2d_box(vor, box)

    # save regions
    all_s = []
    for i, poly in enumerate(impoly):
        ra, dec = w.all_pix2world(poly[:, 0], poly[:, 1], 0, ra_dec_order=True)
        coords = np.array([ra, dec]).T.flatten()

        s = Shape('Polygon', None)
        s.coord_format = 'fk5'
        s.coord_list = coords  # ra, dec, radius
        s.coord_format = 'fk5'
        s.attr = ([], {
            'width': '2',
            'point': 'cross',
            'font': '"helvetica 16 normal roman"'
        })
        s.comment = 'color=red'
        all_s.append(s)

        regions = pyregion.ShapeList([s])
        regionfile = outdir + directions.keys()[idx_for_facet[i]] + '.reg'
        regions.write(regionfile)

        #if beam_reg != '': npix = size_from_reg(fitsfile, [regionfile, beam_reg], [ras[idx_for_facet[i]], decs[idx_for_facet[i]]])
        #else: npix = size_from_reg(fitsfile, [regionfile], [ras[idx_for_facet[i]], decs[idx_for_facet[i]]])

    # add names for all.reg
    for d_name, d_coord in directions.iteritems():
        s = Shape('circle', None)
        s.coord_format = 'fk5'
        s.coord_list = [d_coord[0].degree, d_coord[1].degree,
                        0.01]  # ra, dec, radius
        s.coord_format = 'fk5'
        s.attr = ([], {
            'width': '1',
            'point': 'cross',
            'font': '"helvetica 16 normal roman"'
        })
        s.comment = 'color=white text="%s"' % d_name
        all_s.append(s)

    regions = pyregion.ShapeList(all_s)
    regionfile = outdir + 'all.reg'
    regions.write(regionfile)
    logger.debug(
        'There are %i calibrator within the PB and %i outside (no facet).' %
        (len(idx_for_facet), len(directions) - len(idx_for_facet)))

    # plot tesselization
    if png is not None:
        import matplotlib.pyplot as pl
        pl.figure(figsize=(8, 8))
        ax1 = pl.gca()
        ax1.plot(x, y, '*', color='red')
        for i, d in enumerate(directions):
            ax1.text(x[i], y[i], d, fontsize=15)
        if beam_reg != '':
            c1 = pl.Circle((x_c, y_c), beamradius_pix, color='g', fill=False)
            ax1.add_artist(c1)
        ax1.plot([x1, x1, x2, x2, x1], [y1, y2, y2, y1, y1])
        for p in impoly:
            pp = p.transpose()
            ax1.plot(pp[0], pp[1])
        ax1.set_xlabel('RA (pixel)')
        ax1.set_ylabel('Dec (pixel)')
        logger.debug('Save plot: %s' % png)
        pl.savefig(png)
Example #16
0
                                                                  xhi=xhi,
                                                                  yhi=yhi))


    subwcs = mywcs[ylo:yhi, xlo:xhi]
    subhdr = subwcs.sub([wcs.WCSSUB_CELESTIAL]).to_header()
    subdata = data[ylo:yhi, xlo:xhi]

    mask = shapelist.get_mask(header=subhdr,
                              shape=subdata.shape)
    log.debug("Shapes: data={0}, subdata={2}, mask={1}".format(data.shape, mask.shape, subdata.shape))
    return (xlo, xhi, ylo, yhi), mask


for row, rad in zip(m83, primary_beam_radii):
    shape = Shape('circle', (row['RA'], row['Dec'], np.mean(rad).to(u.deg).value))
    shape.coord_format = 'fk5'
    shape.coord_list = (row['RA'], row['Dec'], np.mean(rad).to(u.deg).value)
    shape.attr = ([], {'color': 'green',  'dash': '0 ',  'dashlist': '8 3 ',
                       'delete': '1 ',  'edit': '1 ', 'fixed': '0 ',
                       'font': '"helvetica 10 normal roman"',  'highlite': '1 ',
                       'include': '1 ',  'move': '1 ',  'select': '1 ',
                       'source': '1',  'text': '', 'width': '1 '})
    if row['Release date']==b'' and row['Band']==3:
        (xlo, xhi, ylo, yhi), mask = pyregion_subset(shape, hit_mask_band3_private, mywcs)
        hit_mask_band3_private[ylo:yhi, xlo:xhi] += row['Integration']*mask
    elif row['Release date'] and row['Band']==3:
        (xlo, xhi, ylo, yhi), mask = pyregion_subset(shape, hit_mask_band3_public, mywcs)
        hit_mask_band3_public[ylo:yhi, xlo:xhi] += row['Integration']*mask
    elif row['Release date'] and row['Band']==6:
        (xlo, xhi, ylo, yhi), mask = pyregion_subset(shape, hit_mask_band6_public, mywcs)
Example #17
0
def make_finder_chart(target, radius, save_prefix, service=SkyView.get_images,
                      service_kwargs={'survey': ['2MASS-K'], 'pixels': 500},
                      alma_kwargs={'public': False, 'science': False},
                      private_band_colors=('red', 'darkred', 'orange',
                                           'brown', 'maroon'),
                      public_band_colors=('blue', 'cyan', 'green',
                                          'turquoise', 'teal'),
                      integration_time_contour_levels=np.logspace(0, 5, base=2,
                                                                  num=6),
                      ):
    """
    Create a "finder chart" showing where ALMA has pointed in various bands,
    including different color coding for public/private data and each band.

    Contours are set at various integration times.

    Parameters
    ----------
    target : `astropy.coordinates` or str
        A legitimate target name
    radius : `astropy.units.Quantity`
        A degree-equivalent radius
    save_prefix : str
        The prefix for the output files.  Both .reg and .png files will be
        written.  The .reg files will have the band numbers and
        public/private appended, while the .png file will be named
        prefix_almafinderchart.png
    service : function
        The `get_images` function of an astroquery service, e.g. SkyView.
    service_kwargs : dict
        The keyword arguments to pass to the specified service.  For example,
        for SkyView, you can give it the survey ID (e.g., 2MASS-K) and the
        number of pixels in the resulting image.  See the documentation for the
        individual services for more details.
    alma_kwargs : dict
        Keywords to pass to the ALMA archive when querying.
    private_band_colors / public_band_colors : tuple
        A tuple or list of colors to be associated with private/public
        observations in the various bands
    integration_time_contour_levels : list or np.array
        The levels at which to draw contours in units of seconds.  Default is
        log-spaced (2^n) seconds: [  1.,   2.,   4.,   8.,  16.,  32.])
    """
    import aplpy

    import pyregion
    from pyregion.parser_helper import Shape

    log.info("Querying {0} for images".format(service))
    images = service(target, radius=radius, **service_kwargs)

    log.info("Querying ALMA around {0}".format(target))
    catalog = Alma.query_region(coordinate=target, radius=radius,
                                **alma_kwargs)

    primary_beam_radii = [
        approximate_primary_beam_sizes(row['Frequency support'])
        for row in catalog]

    bands = np.unique(catalog['Band'])
    log.info("The bands used include: {0}".format(bands))
    band_colors_priv = dict(zip(bands, private_band_colors))
    band_colors_pub = dict(zip(bands, public_band_colors))

    private_circle_parameters = {
        band: [(row['RA'], row['Dec'], np.mean(rad).to(u.deg).value)
               for row, rad in zip(catalog, primary_beam_radii)
               if row['Release date'] != '' and row['Band'] == band]
        for band in bands}

    public_circle_parameters = {
        band: [(row['RA'], row['Dec'], np.mean(rad).to(u.deg).value)
               for row, rad in zip(catalog, primary_beam_radii)
               if row['Release date'] == '' and row['Band'] == band]
        for band in bands}

    unique_private_circle_parameters = {
        band: np.array(list(set(private_circle_parameters[band])))
        for band in bands}
    unique_public_circle_parameters = {
        band: np.array(list(set(public_circle_parameters[band])))
        for band in bands}

    for band in bands:
        log.info("BAND {0}".format(band))
        privrows = sum((catalog['Band'] == band) &
                       (catalog['Release date'] != ''))
        pubrows = sum((catalog['Band'] == band) &
                      (catalog['Release date'] == ''))
        log.info("PUBLIC:  Number of rows: {0}.  Unique pointings: "
                 "{1}".format(pubrows,
                              len(unique_public_circle_parameters[band])))
        log.info("PRIVATE: Number of rows: {0}.  Unique pointings: "
                 "{1}".format(privrows,
                              len(unique_private_circle_parameters[band])))

    prv_regions = {
        band: pyregion.ShapeList([Shape('circle', [x, y, r]) for x, y, r
                                  in private_circle_parameters[band]])
        for band in bands}
    pub_regions = {
        band: pyregion.ShapeList([Shape('circle', [x, y, r]) for x, y, r
                                  in public_circle_parameters[band]])
        for band in bands}
    for band in bands:
        circle_pars = np.vstack(
            [x for x in (private_circle_parameters[band],
                         public_circle_parameters[band]) if any(x)])
        for r, (x, y, c) in zip(prv_regions[band] + pub_regions[band],
                                circle_pars):
            r.coord_format = 'fk5'
            r.coord_list = [x, y, c]
            r.attr = ([], {'color': 'green', 'dash': '0 ', 'dashlist': '8 3',
                           'delete': '1 ', 'edit': '1 ', 'fixed': '0 ',
                           'font': '"helvetica 10 normal roman"', 'highlite':
                           '1 ', 'include': '1 ', 'move': '1 ', 'select': '1',
                           'source': '1', 'text': '', 'width': '1 '})

        if prv_regions[band]:
            prv_regions[band].write(
                '{0}_band{1}_private.reg'.format(save_prefix, band))
        if pub_regions[band]:
            pub_regions[band].write(
                '{0}_band{1}_public.reg'.format(save_prefix, band))

    prv_mask = {
        band: fits.PrimaryHDU(
            prv_regions[band].get_mask(images[0][0]).astype('int'),
            header=images[0][0].header) for band in bands if prv_regions[band]}
    pub_mask = {
        band: fits.PrimaryHDU(
            pub_regions[band].get_mask(images[0][0]).astype('int'),
            header=images[0][0].header) for band in bands if pub_regions[band]}

    hit_mask_public = {band: np.zeros_like(images[0][0].data)
                       for band in pub_mask}
    hit_mask_private = {band: np.zeros_like(images[0][0].data)
                        for band in prv_mask}
    mywcs = wcs.WCS(images[0][0].header)

    for band in bands:
        log.debug('Band: {0}'.format(band))
        for row, rad in zip(catalog, primary_beam_radii):
            shape = Shape('circle', (row['RA'], row['Dec'],
                                     np.mean(rad).to(u.deg).value))
            shape.coord_format = 'fk5'
            shape.coord_list = (row['RA'], row['Dec'],
                                np.mean(rad).to(u.deg).value)
            shape.attr = ([], {'color': 'green', 'dash': '0 ',
                               'dashlist': '8 3 ',
                               'delete': '1 ', 'edit': '1 ', 'fixed': '0 ',
                               'font': '"helvetica 10 normal roman"',
                               'highlite': '1 ', 'include': '1 ', 'move': '1 ',
                               'select': '1 ', 'source': '1', 'text': '',
                               'width': '1 '})
            log.debug('{1} {2}: {0}'
                      .format(shape, row['Release date'], row['Band']))
            if (row['Release date'] != '' and row['Band'] == band and
                    band in prv_mask):
                (xlo, xhi, ylo, yhi), mask = pyregion_subset(
                    shape, hit_mask_private[band], mywcs)
                log.debug("{0},{1},{2},{3}: {4}"
                          .format(xlo, xhi, ylo, yhi, mask.sum()))
                hit_mask_private[band][ylo:yhi, xlo:xhi] += row['Integration']*mask
            if (row['Release date'] == '' and row['Band'] == band and
                    band in pub_mask):
                (xlo, xhi, ylo, yhi), mask = pyregion_subset(
                    shape, hit_mask_public[band], mywcs)
                log.debug("{0},{1},{2},{3}: {4}"
                          .format(xlo, xhi, ylo, yhi, mask.sum()))
                hit_mask_public[band][ylo:yhi, xlo:xhi] += row['Integration']*mask

    fig = aplpy.FITSFigure(images[0])
    fig.show_grayscale(stretch='arcsinh')
    for band in bands:
        if band in pub_mask:
            fig.show_contour(fits.PrimaryHDU(data=hit_mask_public[band],
                                             header=images[0][0].header),
                             levels=integration_time_contour_levels,
                             colors=[band_colors_pub[band]] * 6)
        if band in prv_mask:
            fig.show_contour(fits.PrimaryHDU(data=hit_mask_private[band],
                                             header=images[0][0].header),
                             levels=integration_time_contour_levels,
                             colors=[band_colors_priv[band]] * 6)

    fig.save('{0}_almafinderchart.png'.format(save_prefix))

    return images, catalog, hit_mask_public, hit_mask_private
Example #18
0
            dist = lib_util.distanceOnSphere(phasecentre[0], phasecentre[1],
                                             peelsou['RA'], peelsou['DEC'])
            if dist < 0.5:
                continue

            logger.info('Peeling %s (%.1f Jy)' % (name, peelsou['Total_flux']))

            with w.if_todo('peel-%s' % name):
                lib_util.check_rm('peel-%s' % name)
                os.system('mkdir peel-%s' % name)

                # make a region
                from pyregion.parser_helper import Shape
                import pyregion
                peel_region_file = 'peel-' + name + '/' + name + '.reg'
                sh = Shape('circle', None)
                sh.coord_format = 'fk5'
                sh.coord_list = [peelsou['RA'], peelsou['DEC'],
                                 0.1]  # ra, dec, diam
                sh.coord_format = 'fk5'
                sh.attr = ([], {
                    'width': '2',
                    'point': 'cross',
                    'font': '"helvetica 16 normal roman"'
                })
                sh.comment = 'color=red text="%s"' % (name + '.reg')
                regions = pyregion.ShapeList([sh])
                lib_util.check_rm(peel_region_file)
                regions.write(peel_region_file)

                # copy and blank models
Example #19
0
def make_voronoi_reg(directions,
                     fitsfile,
                     outdir_reg='regions',
                     out_mask='facet.fits',
                     png=None):
    """
    Take a list of coordinates and an image and voronoi tesselate the sky.
    It saves ds9 regions + fits mask of the facets

    directions : array of Direction objects
    firsfile : mask fits file to tassellate (used for coordinates and as template for the out_mask)
    outdir_reg : dir where to save regions
    out_mask : output mask with different numbers in each facet
    png : output png file that shows the tassellation
    """
    def closest_node(node, nodes):
        """
        Return closest values to node from nodes
        """
        nodes = np.asarray(nodes)
        dist_2 = np.sum((nodes - node)**2, axis=1)
        return np.argmin(dist_2)

    logger.debug("Image used for tasselation reference: " + fitsfile)
    fits = pyfits.open(fitsfile)
    hdr, data = lib_img.flatten(fits)
    w = pywcs.WCS(hdr)
    pixsize = np.abs(hdr['CDELT1'])

    # Get facets central pixels
    ras = np.array([d.position_cal[0] for d in directions])
    decs = np.array([d.position_cal[1] for d in directions])
    x_fs, y_fs = w.all_world2pix(ras, decs, 0, ra_dec_order=True)
    # keep trak of numbers in the direction names to name correctly patches in the fits files
    # in this way Isl_patch_12 will have "12" into the fits for that patch.
    nums = [d.isl_num for d in directions]

    x_c = data.shape[0] / 2.
    y_c = data.shape[1] / 2.

    # Check if dir is in img, otherwise drop
    idx_for_facet = []
    for i, direction in enumerate(directions):
        x, y = w.all_world2pix(ras[i], decs[i], 0, ra_dec_order=True)
        if x < 0 or x > data.shape[0] or y < 0 or y > data.shape[1]:
            logger.info(
                'Direction %s is outside the primary beam and will not have a facet (it will still be a calibrator).'
                % direction.name)
        else:
            idx_for_facet.append(i)

    # convert to pixel space (voronoi must be in eucledian space)
    x1 = 0
    y1 = 0
    x2 = data.shape[1]  # note that y is before x in fits.data
    y2 = data.shape[0]

    # do tasselization
    vor = Voronoi(
        np.array((x_fs[idx_for_facet], y_fs[idx_for_facet])).transpose())
    box = np.array([[x1, y1], [x2, y2]])
    impoly = voronoi_finite_polygons_2d_box(vor, box)

    # create fits mask (each region one number)
    x, y = np.meshgrid(np.arange(x2),
                       np.arange(y2))  # make a canvas with coordinates
    x, y = x.flatten(), y.flatten()
    pixels = np.vstack((x, y)).T
    data_facet = np.zeros(shape=data.shape)
    for num, poly in zip(nums, impoly):
        p = Path(poly)
        pixels_region = p.contains_points(pixels)
        data_facet[pixels_region.reshape(y2, x2)] = num

    # put all values in each island equal to the closest region
    struct = generate_binary_structure(2, 2)
    data = binary_dilation(data, structure=struct,
                           iterations=3).astype(data.dtype)  # expand masks
    blobs, number_of_blobs = label(data.astype(int).squeeze(),
                                   structure=[[1, 1, 1], [1, 1, 1], [1, 1, 1]])
    center_of_masses = center_of_mass(data, blobs,
                                      list(range(number_of_blobs + 1)))
    for blob in range(1, number_of_blobs + 1):
        # get closer facet
        facet_num = closest_node(
            center_of_masses[blob],
            np.array([y_fs[idx_for_facet], x_fs[idx_for_facet]]).T)
        # put all pixel of that mask to that facet value
        data_facet[blobs == blob] = nums[facet_num]

    # save fits mask
    pyfits.writeto(out_mask, data_facet, hdr, overwrite=True)

    # save regions
    if not os.path.isdir(outdir_reg): os.makedirs(outdir_reg)

    all_s = []
    for i, poly in enumerate(impoly):
        ra, dec = w.all_pix2world(poly[:, 0], poly[:, 1], 0, ra_dec_order=True)
        coords = np.array([ra, dec]).T.flatten()

        s = Shape('Polygon', None)
        s.coord_format = 'fk5'
        s.coord_list = coords  # ra, dec, radius
        s.coord_format = 'fk5'
        s.attr = ([], {
            'width': '2',
            'point': 'cross',
            'font': '"helvetica 16 normal roman"'
        })
        s.comment = 'color=red'
        all_s.append(s)

        regions = pyregion.ShapeList([s])
        regionfile = outdir_reg + '/' + directions[
            idx_for_facet[i]].name + '.reg'
        regions.write(regionfile)

    # add names for all.reg
    for d in directions:
        s = Shape('circle', None)
        s.coord_format = 'fk5'
        s.coord_list = [d.position_cal[0], d.position_cal[1],
                        0.01]  # ra, dec, radius
        s.coord_format = 'fk5'
        s.attr = ([], {
            'width': '1',
            'point': 'cross',
            'font': '"helvetica 16 normal roman"'
        })
        s.comment = 'color=white text="%s"' % d.name
        all_s.append(s)

    regions = pyregion.ShapeList(all_s)
    regionfile = outdir_reg + '/all.reg'
    regions.write(regionfile)
    logger.debug(
        'There are %i regions within the PB and %i outside (no facet).' %
        (len(idx_for_facet), len(directions) - len(idx_for_facet)))

    # plot tesselization
    if png is not None:
        import matplotlib.pyplot as pl
        pl.figure(figsize=(8, 8))
        ax1 = pl.gca()
        voronoi_plot_2d(vor,
                        ax1,
                        show_vertices=True,
                        line_colors='black',
                        line_width=2,
                        point_size=4)
        for i, d in enumerate(directions):
            ax1.text(x_fs[i], y_fs[i], d.name, fontsize=15)
        ax1.plot([x1, x1, x2, x2, x1], [y1, y2, y2, y1, y1])
        ax1.set_xlabel('RA (pixel)')
        ax1.set_ylabel('Dec (pixel)')
        ax1.set_xlim(x1, x2)
        ax1.set_ylim(y1, y2)
        logger.debug('Save plot: %s' % png)
        pl.savefig(png)
Example #20
0
def make_finder_chart(target, radius, save_prefix, service=SkyView.get_images,
                      service_kwargs={'survey':['2MASS-K'], 'pixels':500},
                      alma_kwargs={'public':False, 'science':False},
                      private_band_colors=('red','darkred','orange','brown','maroon'),
                      public_band_colors=('blue','cyan','green','turquoise','teal'),
                      integration_time_contour_levels=np.logspace(0,5,base=2, num=6),
                     ):
    """
    Create a "finder chart" showing where ALMA has pointed in various bands,
    including different color coding for public/private data and each band.

    Contours are set at various integration times.

    Parameters
    ----------
    target : `astropy.coordinates` or str
        A legitimate target name
    radius : `astropy.units.Quantity`
        A degree-equivalent radius
    save_prefix : str
        The prefix for the output files.  Both .reg and .png files will be written.
        The .reg files will have the band numbers and public/private appended,
        while the .png file will be named prefix_almafinderchart.png
    service : function
        The `get_images` function of an astroquery service, e.g. SkyView.
    service_kwargs : dict
        The keyword arguments to pass to the specified service.  For example,
        for SkyView, you can give it the survey ID (e.g., 2MASS-K) and the
        number of pixels in the resulting image.  See the documentation for the
        individual services for more details.
    alma_kwargs : dict
        Keywords to pass to the ALMA archive when querying.  
    private_band_colors / public_band_colors : tuple
        A tuple or list of colors to be associated with private/public observations
        in the various bands
    integration_time_contour_levels : list or np.array
        The levels at which to draw contours in units of seconds.  Default is
        log-spaced (2^n) seconds: [  1.,   2.,   4.,   8.,  16.,  32.])
    """
    import aplpy

    import pyregion
    from pyregion.parser_helper import Shape

    log.info("Querying {0} for images".format(service))
    images = service(target, radius=radius, **service_kwargs)

    log.info("Querying ALMA around {0}".format(target))
    catalog = Alma.query_region(coordinate=target, radius=radius,
                                **alma_kwargs)

    primary_beam_radii = [approximate_primary_beam_sizes(row['Frequency support'])
                          for row in catalog]

    bands = np.unique(catalog['Band'])
    log.info("The bands used include: {0}".format(bands))
    band_colors_priv = dict(zip(bands, private_band_colors))
    band_colors_pub = dict(zip(bands, public_band_colors))

    private_circle_parameters = {band: [(row['RA'],row['Dec'],np.mean(rad).to(u.deg).value)
                                 for row,rad in zip(catalog, primary_beam_radii)
                                 if row['Release date']!='' and row['Band']==band]
                                 for band in bands}
    public_circle_parameters = {band: [(row['RA'],row['Dec'],np.mean(rad).to(u.deg).value)
                                 for row,rad in zip(catalog, primary_beam_radii)
                                 if row['Release date']=='' and row['Band']==band]
                                 for band in bands}

    unique_private_circle_parameters = {band:
                                        np.array(list(set(private_circle_parameters[band])))
                                        for band in bands}
    unique_public_circle_parameters = {band:
                                       np.array(list(set(public_circle_parameters[band])))
                                       for band in bands}

    for band in bands:
        log.info( "BAND {0}".format(band) )
        privrows = sum((catalog['Band']==band) & (catalog['Release date'] != ''))
        pubrows  = sum((catalog['Band']==band) & (catalog['Release date'] == ''))
        log.info("PUBLIC:  Number of rows: {0}.  Unique pointings: "
                 "{1}".format(pubrows,
                 len(unique_public_circle_parameters[band])))
        log.info( "PRIVATE: Number of rows: {0}.  Unique pointings: "
                 "{1}".format(privrows,
                 len(unique_private_circle_parameters[band])))

    prv_regions = {band: pyregion.ShapeList([Shape('circle',[x,y,r]) for x,y,r
                                             in
                                             private_circle_parameters[band]])
                   for band in bands}
    pub_regions = {band: pyregion.ShapeList([Shape('circle',[x,y,r]) for x,y,r
                                             in
                                             public_circle_parameters[band]])
                   for band in bands}
    for band in bands:
        circle_pars = np.vstack([x for x in (private_circle_parameters[band],
                                        public_circle_parameters[band]) if any(x)])
        for r,(x,y,c) in zip(prv_regions[band]+pub_regions[band],
                             circle_pars):
            r.coord_format = 'fk5'
            r.coord_list = [x,y,c]
            r.attr = ([], {'color': 'green',  'dash': '0 ',  'dashlist': '8 3',
                           'delete': '1 ',  'edit': '1 ', 'fixed': '0 ',
                           'font': '"helvetica 10 normal roman"',  'highlite':
                           '1 ', 'include': '1 ',  'move': '1 ',  'select': '1',
                           'source': '1',  'text': '', 'width': '1 '})
            
        if prv_regions[band]:
            prv_regions[band].write('{0}_band{1}_private.reg'.format(save_prefix, band))
        if pub_regions[band]:
            pub_regions[band].write('{0}_band{1}_public.reg'.format(save_prefix, band))

    prv_mask = {band: fits.PrimaryHDU(prv_regions[band].get_mask(images[0][0]).astype('int'),
                               header=images[0][0].header) for band in bands
                if prv_regions[band]}
    pub_mask = {band: fits.PrimaryHDU(pub_regions[band].get_mask(images[0][0]).astype('int'),
                               header=images[0][0].header) for band in bands
                if pub_regions[band]}

    hit_mask_public = {band: np.zeros_like(images[0][0].data) for band in pub_mask}
    hit_mask_private = {band: np.zeros_like(images[0][0].data) for band in prv_mask}
    mywcs = wcs.WCS(images[0][0].header)

    for band in bands:
        log.debug('Band: {0}'.format(band))
        for row,rad in zip(catalog, primary_beam_radii):
            shape = Shape('circle', (row['RA'], row['Dec'],np.mean(rad).to(u.deg).value))
            shape.coord_format = 'fk5'
            shape.coord_list = (row['RA'], row['Dec'],np.mean(rad).to(u.deg).value)
            shape.attr = ([], {'color': 'green',  'dash': '0 ',  'dashlist': '8 3 ',
                               'delete': '1 ',  'edit': '1 ', 'fixed': '0 ',
                               'font': '"helvetica 10 normal roman"',
                               'highlite': '1 ', 'include': '1 ',  'move': '1 ',
                               'select': '1 ',  'source': '1',  'text': '',
                               'width': '1 '})
            log.debug('{1} {2}: {0}'.format(shape, row['Release date'], row['Band']))
            if row['Release date']!='' and row['Band']==band and band in prv_mask:
                (xlo,xhi,ylo,yhi),mask = pyregion_subset(shape,
                                                         hit_mask_private[band],
                                                         mywcs) 
                log.debug("{0},{1},{2},{3}: {4}".format(xlo,xhi,ylo,yhi,mask.sum()))
                hit_mask_private[band][ylo:yhi,xlo:xhi] += row['Integration']*mask
            if row['Release date']=='' and row['Band']==band and band in pub_mask:
                (xlo,xhi,ylo,yhi),mask = pyregion_subset(shape,
                                                         hit_mask_public[band],
                                                         mywcs) 
                log.debug("{0},{1},{2},{3}: {4}".format(xlo,xhi,ylo,yhi,mask.sum()))
                hit_mask_public[band][ylo:yhi,xlo:xhi] += row['Integration']*mask



    fig = aplpy.FITSFigure(images[0])
    fig.show_grayscale(stretch='arcsinh')
    for band in bands:
        if band in pub_mask:
            fig.show_contour(fits.PrimaryHDU(data=hit_mask_public[band],
                                             header=images[0][0].header),
                             levels=integration_time_contour_levels,
                             colors=[band_colors_pub[band]]*6)
        if band in prv_mask:
            fig.show_contour(fits.PrimaryHDU(data=hit_mask_private[band],
                                             header=images[0][0].header),
                             levels=integration_time_contour_levels,
                             colors=[band_colors_priv[band]]*6)

    fig.save('{0}_almafinderchart.png'.format(save_prefix))

    return images, catalog, hit_mask_public, hit_mask_private
Example #21
0
def make_finder_chart_from_image_and_catalog(image, catalog, save_prefix,
                                             alma_kwargs={'public': False,
                                                          'science': False},
                                             bands=(3,4,5,6,7,8,9),
                                             private_band_colors=('maroon',
                                                                  'red',
                                                                  'orange',
                                                                  'coral',
                                                                  'brown',
                                                                  'yellow',
                                                                  'mediumorchid'),
                                             public_band_colors=('blue',
                                                                 'cyan',
                                                                 'green',
                                                                 'turquoise',
                                                                 'teal',
                                                                 'darkslategrey',
                                                                 'chartreuse'),
                                             integration_time_contour_levels=np.logspace(0,
                                                                                         5,
                                                                                         base=2,
                                                                                         num=6),
                                             save_masks=False,
                                             use_saved_masks=False,
                                            ):
    """
    Create a "finder chart" showing where ALMA has pointed in various bands,
    including different color coding for public/private data and each band.

    Contours are set at various integration times.

    Parameters
    ----------
    image : fits.PrimaryHDU or fits.ImageHDU object
        The image to overlay onto
    catalog : astropy.Table object
        The catalog of ALMA observations
    save_prefix : str
        The prefix for the output files.  Both .reg and .png files will be
        written.  The .reg files will have the band numbers and
        public/private appended, while the .png file will be named
        prefix_almafinderchart.png
    alma_kwargs : dict
        Keywords to pass to the ALMA archive when querying.
    private_band_colors / public_band_colors : tuple
        A tuple or list of colors to be associated with private/public
        observations in the various bands
    integration_time_contour_levels : list or np.array
        The levels at which to draw contours in units of seconds.  Default is
        log-spaced (2^n) seconds: [  1.,   2.,   4.,   8.,  16.,  32.])
    """
    import aplpy

    import pyregion
    from pyregion.parser_helper import Shape



    primary_beam_radii = [
        approximate_primary_beam_sizes(row['Frequency support'])
        for row in catalog]

    all_bands = bands
    bands = used_bands = np.unique(catalog['Band'])
    log.info("The bands used include: {0}".format(used_bands))
    band_colors_priv = dict(zip(all_bands, private_band_colors))
    band_colors_pub = dict(zip(all_bands, public_band_colors))
    log.info("Color map private: {0}".format(band_colors_priv))
    log.info("Color map public: {0}".format(band_colors_pub))

    if use_saved_masks:
        hit_mask_public = {}
        hit_mask_private = {}

        for band in bands:
            pubfile = '{0}_band{1}_public.fits'.format(save_prefix, band)
            if os.path.exists(pubfile):
                hit_mask_public[band] = fits.getdata(pubfile)
            privfile = '{0}_band{1}_private.fits'.format(save_prefix, band)
            if os.path.exists(privfile):
                hit_mask_private[band] = fits.getdata(privfile)

    else:
        today = np.datetime64('today')

        private_circle_parameters = {
            band: [(row['RA'], row['Dec'], np.mean(rad).to(u.deg).value)
                   for row, rad in zip(catalog, primary_beam_radii)
                   if not row['Release date'] or
                   (np.datetime64(row['Release date']) > today and row['Band'] == band)]
            for band in bands}

        public_circle_parameters = {
            band: [(row['RA'], row['Dec'], np.mean(rad).to(u.deg).value)
                   for row, rad in zip(catalog, primary_beam_radii)
                   if row['Release date'] and
                   (np.datetime64(row['Release date']) <= today and row['Band'] == band)]
            for band in bands}

        unique_private_circle_parameters = {
            band: np.array(list(set(private_circle_parameters[band])))
            for band in bands}
        unique_public_circle_parameters = {
            band: np.array(list(set(public_circle_parameters[band])))
            for band in bands}

        release_dates = np.array(catalog['Release date'], dtype=np.datetime64)

        for band in bands:
            log.info("BAND {0}".format(band))
            privrows = sum((catalog['Band'] == band) &
                           (release_dates > today))
            pubrows = sum((catalog['Band'] == band) &
                          (release_dates <= today))
            log.info("PUBLIC:  Number of rows: {0}.  Unique pointings: "
                     "{1}".format(pubrows,
                                  len(unique_public_circle_parameters[band])))
            log.info("PRIVATE: Number of rows: {0}.  Unique pointings: "
                     "{1}".format(privrows,
                                  len(unique_private_circle_parameters[band])))

        prv_regions = {
            band: pyregion.ShapeList([Shape('circle', [x, y, r]) for x, y, r
                                      in private_circle_parameters[band]])
            for band in bands}
        pub_regions = {
            band: pyregion.ShapeList([Shape('circle', [x, y, r]) for x, y, r
                                      in public_circle_parameters[band]])
            for band in bands}
        for band in bands:
            circle_pars = np.vstack(
                [x for x in (private_circle_parameters[band],
                             public_circle_parameters[band]) if any(x)])
            for r, (x, y, c) in zip(prv_regions[band] + pub_regions[band],
                                    circle_pars):
                r.coord_format = 'fk5'
                r.coord_list = [x, y, c]
                r.attr = ([], {'color': 'green', 'dash': '0 ', 'dashlist': '8 3',
                               'delete': '1 ', 'edit': '1 ', 'fixed': '0 ',
                               'font': '"helvetica 10 normal roman"', 'highlite':
                               '1 ', 'include': '1 ', 'move': '1 ', 'select': '1',
                               'source': '1', 'text': '', 'width': '1 '})

            if prv_regions[band]:
                prv_regions[band].write(
                    '{0}_band{1}_private.reg'.format(save_prefix, band))
            if pub_regions[band]:
                pub_regions[band].write(
                    '{0}_band{1}_public.reg'.format(save_prefix, band))

        prv_mask = {
            band: fits.PrimaryHDU(
                prv_regions[band].get_mask(image).astype('int'),
                header=image.header) for band in bands if prv_regions[band]}
        pub_mask = {
            band: fits.PrimaryHDU(
                pub_regions[band].get_mask(image).astype('int'),
                header=image.header) for band in bands if pub_regions[band]}

        hit_mask_public = {band: np.zeros_like(image.data)
                           for band in pub_mask}
        hit_mask_private = {band: np.zeros_like(image.data)
                            for band in prv_mask}
        mywcs = wcs.WCS(image.header)

        for band in bands:
            log.debug('Band: {0}'.format(band))
            for row, rad in ProgressBar(list(zip(catalog, primary_beam_radii))):
                shape = Shape('circle', (row['RA'], row['Dec'],
                                         np.mean(rad).to(u.deg).value))
                shape.coord_format = 'fk5'
                shape.coord_list = (row['RA'], row['Dec'],
                                    np.mean(rad).to(u.deg).value)
                shape.attr = ([], {'color': 'green', 'dash': '0 ',
                                   'dashlist': '8 3 ',
                                   'delete': '1 ', 'edit': '1 ', 'fixed': '0 ',
                                   'font': '"helvetica 10 normal roman"',
                                   'highlite': '1 ', 'include': '1 ', 'move': '1 ',
                                   'select': '1 ', 'source': '1', 'text': '',
                                   'width': '1 '})
                log.debug('{1} {2}: {0}'
                          .format(shape, row['Release date'], row['Band']))

                if not row['Release date']:
                    reldate = False
                else:
                    reldate = np.datetime64(row['Release date'])

                if (((not reldate) or (reldate > today)) and
                    (row['Band'] == band) and
                    (band in prv_mask)
                   ):
                    # private: release_date = 'sometime' says when it will be released
                    (xlo, xhi, ylo, yhi), mask = pyregion_subset(
                        shape, hit_mask_private[band], mywcs)
                    log.debug("{0},{1},{2},{3}: {4}"
                              .format(xlo, xhi, ylo, yhi, mask.sum()))
                    hit_mask_private[band][ylo:yhi, xlo:xhi] += row['Integration']*mask
                elif (reldate and (reldate <= today) and (row['Band'] == band) and
                      (band in pub_mask)):
                    # public: release_date = '' should mean already released
                    (xlo, xhi, ylo, yhi), mask = pyregion_subset(
                        shape, hit_mask_public[band], mywcs)
                    log.debug("{0},{1},{2},{3}: {4}"
                              .format(xlo, xhi, ylo, yhi, mask.sum()))
                    hit_mask_public[band][ylo:yhi, xlo:xhi] += row['Integration']*mask

        if save_masks:
            for band in bands:
                if band in hit_mask_public:
                    hdu = fits.PrimaryHDU(data=hit_mask_public[band],
                                          header=image.header)
                    hdu.writeto('{0}_band{1}_public.fits'.format(save_prefix, band),
                                clobber=True)
                if band in hit_mask_private:
                    hdu = fits.PrimaryHDU(data=hit_mask_private[band],
                                          header=image.header)
                    hdu.writeto('{0}_band{1}_private.fits'.format(save_prefix, band),
                                clobber=True)

    fig = aplpy.FITSFigure(fits.HDUList(image), convention='calabretta')
    fig.show_grayscale(stretch='arcsinh')
    for band in bands:
        if band in hit_mask_public:
            fig.show_contour(fits.PrimaryHDU(data=hit_mask_public[band],
                                             header=image.header),
                             levels=integration_time_contour_levels,
                             colors=[band_colors_pub[band]] * len(integration_time_contour_levels),
                             convention='calabretta')
        if band in hit_mask_private:
            fig.show_contour(fits.PrimaryHDU(data=hit_mask_private[band],
                                             header=image.header),
                             levels=integration_time_contour_levels,
                             colors=[band_colors_priv[band]] * len(integration_time_contour_levels),
                             convention='calabretta')

    fig.save('{0}_almafinderchart.png'.format(save_prefix))

    return image, catalog, hit_mask_public, hit_mask_private