Пример #1
0
def flatten(filename, channel=0, freqaxis=0):
    """ Flatten a fits file so that it becomes a 2D image. Return new header and data """

    f = pyfits.open(filename)

    naxis = f[0].header['NAXIS']
    if naxis < 2:
        raise RadioError('Can\'t make map from this')
    if naxis == 2:
        pass
        #return f[0].header,f[0].data

    w = pywcs(f[0].header)
    wn = pywcs(naxis=2)

    wn.wcs.crpix[0] = w.wcs.crpix[0]
    wn.wcs.crpix[1] = w.wcs.crpix[1]
    wn.wcs.cdelt = w.wcs.cdelt[0:2]
    wn.wcs.crval = w.wcs.crval[0:2]
    wn.wcs.ctype[0] = w.wcs.ctype[0]
    wn.wcs.ctype[1] = w.wcs.ctype[1]

    header = wn.to_header()
    header["NAXIS"] = 2
    header["NAXIS1"] = f[0].header['NAXIS1']
    header["NAXIS2"] = f[0].header['NAXIS2']
    copy = ('EQUINOX', 'EPOCH')
    for k in copy:
        r = f[0].header.get(k)
        if r:
            header[k] = r

    dataslice = []
    for i in range(naxis, 0, -1):
        if i <= 2:
            dataslice.append(np.s_[:], )
        elif i == freqaxis:
            dataslice.append(channel)
        else:
            dataslice.append(0)

    # add freq
    header["FREQ"] = find_freq(f[0].header)

    # add beam if present
    try:
        header["BMAJ"] = f[0].header['BMAJ']
        header["BMIN"] = f[0].header['BMIN']
        header["BPA"] = f[0].header['BPA']
    except:
        pass

    # slice=(0,)*(naxis-2)+(np.s_[:],)*2
    return header, f[0].data[tuple(dataslice)]
Пример #2
0
    def blank(self, vertices_file=None):
        """
        Blank pixels (NaN) outside of polygon region
        """
        # Construct polygon
        if vertices_file is None:
            vertices_file = self.vertices_file
        vertices = misc.read_vertices(vertices_file)

        w = pywcs(self.header)
        RAind = w.axis_type_names.index('RA')
        Decind = w.axis_type_names.index('DEC')
        RAverts = vertices[0]
        Decverts = vertices[1]
        verts = []
        for RAvert, Decvert in zip(RAverts, Decverts):
            ra_dec = np.array([[0.0, 0.0, 0.0, 0.0]])
            ra_dec[0][RAind] = RAvert
            ra_dec[0][Decind] = Decvert
            verts.append((w.wcs_world2pix(ra_dec, 0)[0][RAind],
                          w.wcs_world2pix(ra_dec, 0)[0][Decind]))
        poly = Polygon(verts)
        poly_padded = poly.buffer(2)
        verts = [(xi, yi)
                 for xi, yi in zip(poly_padded.exterior.coords.xy[0].tolist(),
                                   poly_padded.exterior.coords.xy[1].tolist())]

        # Blank pixels (= NaN) outside of the polygon
        self.img_data = misc.rasterize(verts,
                                       self.img_data,
                                       blank_value=np.nan)
Пример #3
0
def wcs_from_pv_header(hdr):
    '''
    This is mostly for dealing with the Ellerbroek data
    '''
    # Create a WCS object
    mywcs = pywcs(hdr, fix=False)

    # Make sure the WCS info is in [spatial, spectral]
    # order
    if mywcs.wcs.cdelt[0] == 0.2:
        pass
    elif mywcs.wcs.cdelt[1] == 0.2:
        mywcs = mywcs.swapaxes(0, 1)
        #mywcs.pixel_shape = mywcs.pixel_shape[::-1]

    # Is this velocity or wavelength?
    if mywcs.wcs.crval[1] < 1:
        ctype2 = 'VELO'
        cunit2 = u.Unit('km/s').to_string('fits')
    else:
        ctype2 = 'AWAV'
        cunit2 = u.Unit('nm').to_string('fits')

    ctype1 = 'OFFSET'
    cunit1 = u.Unit('arcsec').to_string('fits')

    mywcs.wcs.crpix = np.array([1., 1.])
    mywcs.wcs.ctype = [ctype1, ctype2]
    #mywcs.wcs.cunit = [cunit1, cunit2]

    return mywcs
Пример #4
0
def flatten(filename, channel=0, freqaxis=0):
    """ Flatten a fits file so that it becomes a 2D image. Return new header and data """

    f = pyfits.open(filename)

    naxis=f[0].header['NAXIS']
    if naxis<2:
        raise RadioError('Can\'t make map from this')
    if naxis==2:
        return f[0].header,f[0].data

    w = pywcs(f[0].header)
    wn = pywcs(naxis=2)

    wn.wcs.crpix[0]=w.wcs.crpix[0]
    wn.wcs.crpix[1]=w.wcs.crpix[1]
    wn.wcs.cdelt=w.wcs.cdelt[0:2]
    wn.wcs.crval=w.wcs.crval[0:2]
    wn.wcs.ctype[0]=w.wcs.ctype[0]
    wn.wcs.ctype[1]=w.wcs.ctype[1]

    header = wn.to_header()
    header["NAXIS"]=2
    header["NAXIS1"]=f[0].header['NAXIS1']
    header["NAXIS2"]=f[0].header['NAXIS2']
    copy=('EQUINOX','EPOCH')
    for k in copy:
        r=f[0].header.get(k)
        if r:
            header[k]=r

    dataslice=[]
    for i in range(naxis,0,-1):
        if i<=2:
            dataslice.append(np.s_[:],)
        elif i==freqaxis:
            dataslice.append(channel)
        else:
            dataslice.append(0)

    # add freq
    header["FREQ"] = find_freq(f[0].header)

    # slice=(0,)*(naxis-2)+(np.s_[:],)*2
    return header, f[0].data[dataslice]
Пример #5
0
    def flatten(self):
        """ Flatten a fits file so that it becomes a 2D image. Return new header and data """
        f = pyfits.open(self.imagefile)

        naxis = f[0].header['NAXIS']
        if naxis < 2:
            raise RuntimeError('Can\'t make map from this')
        if naxis == 2:
            self.img_hdr = f[0].header
            self.img_data = f[0].data
        else:
            w = pywcs(f[0].header)
            wn = pywcs(naxis=2)
            wn.wcs.crpix[0] = w.wcs.crpix[0]
            wn.wcs.crpix[1] = w.wcs.crpix[1]
            wn.wcs.cdelt = w.wcs.cdelt[0:2]
            wn.wcs.crval = w.wcs.crval[0:2]
            wn.wcs.ctype[0] = w.wcs.ctype[0]
            wn.wcs.ctype[1] = w.wcs.ctype[1]

            header = wn.to_header()
            header["NAXIS"] = 2
            header["NAXIS1"] = f[0].header['NAXIS1']
            header["NAXIS2"] = f[0].header['NAXIS2']
            header["FREQ"] = self.freq
            header['RESTFREQ'] = self.freq
            header['BMAJ'] = self.beam[0]
            header['BMIN'] = self.beam[1]
            header['BPA'] = self.beam[2]
            copy = ('EQUINOX', 'EPOCH')
            for k in copy:
                r = f[0].header.get(k)
                if r:
                    header[k] = r

            dataslice = []
            for i in range(naxis, 0, -1):
                if i <= 2:
                    dataslice.append(np.s_[:], )
                else:
                    dataslice.append(0)
            self.img_hdr = header
            self.img_data = f[0].data[tuple(dataslice)]
Пример #6
0
def flatten(filename, channel=0, freqaxis=0):
    """ Flatten a fits file so that it becomes a 2D image. Return new header and data """

    f = pyfits.open(filename)

    naxis = f[0].header['NAXIS']
    if naxis < 2:
        raise RadioError('Can\'t make map from this')
    if naxis == 2:
        return f[0].header, f[0].data

    w = pywcs(f[0].header)
    wn = pywcs(naxis=2)

    wn.wcs.crpix[0] = w.wcs.crpix[0]
    wn.wcs.crpix[1] = w.wcs.crpix[1]
    wn.wcs.cdelt = w.wcs.cdelt[0:2]
    wn.wcs.crval = w.wcs.crval[0:2]
    wn.wcs.ctype[0] = w.wcs.ctype[0]
    wn.wcs.ctype[1] = w.wcs.ctype[1]

    header = wn.to_header()
    header["NAXIS"] = 2
    header["NAXIS1"] = f[0].header['NAXIS1']  # Test
    header["NAXIS2"] = f[0].header['NAXIS2']  # Test
    copy = ('EQUINOX', 'EPOCH')
    for k in copy:
        r = f[0].header.get(k)
        if r:
            header[k] = r

    slice = []
    for i in range(naxis, 0, -1):
        if i <= 2:
            slice.append(np.s_[:], )
        elif i == freqaxis:
            slice.append(channel)
        else:
            slice.append(0)

    # slice=(0,)*(naxis-2)+(np.s_[:],)*2
    return header, f[0].data[slice]
Пример #7
0
    def __init__(self,
                 hdr=None,
                 crpix=[1., 1.],
                 crval=[1., 1.],
                 cdelt=[1., 1.],
                 unit1=u.arcsec,
                 unit2=u.dimensionless_unscaled,
                 ctype=['LINEAR', 'AWAV'],
                 shape=None):

        unit1 = u.Unit(unit1).to_string('fits')
        unit2 = u.Unit(unit2)

        self.shape = shape

        #if mode is not None:
        #    print(self.unit)
        if (hdr is not None):
            h = hdr.copy()
            #print(h)
            n = h['NAXIS']
            self.shape = h['NAXIS%d' % n]
            if n == 3:
                self.wcs = wcs_from_cube_header(h)
            elif n == 2:
                self.wcs = wcs_from_pv_header(h)
            print(self.wcs.wcs.cunit)
            if self.wcs.wcs.cunit[0] != '':
                self.spatial_unit = self.wcs.wcs.cunit[0]
            elif self.wcs.wcs.ctype[0] == 'OFFSET':
                self.spatial_unit = u.Unit('arcsec')
            #print(self.wcs.wcs.cunit[1])
            if self.wcs.wcs.cunit[1] == 'm':
                self.spectral_unit = u.Unit('angstrom')
            elif (self.wcs.wcs.cunit[1]
                  == u.Unit('km/s')) or (self.wcs.wcs.ctype[1] == 'VELO'):
                self.spectral_unit = u.Unit('km/s')

        elif hdr is None:
            #if data is not None:
            self.spatial_unit = u.Unit(unit1)
            self.spectral_unit = u.Unit(unit2)
            self.wcs = pywcs(naxis=2)
            #self.shape =

            # set the reference pixel
            self.wcs.wcs.crval = np.array([crval[0], crval[1]])
            self.wcs.wcs.ctype = np.array([ctype[0], ctype[1]])
            self.wcs.wcs.cdelt = np.array([cdelt[0], cdelt[1]])
            self.wcs.wcs.crpix = np.array([crpix[0], crpix[1]])

        #self.wcs.wcs.set()
        self.shape = self.wcs.pixel_shape
Пример #8
0
    if args.shift:
        d.calc_shift(tgss_catalog)


# prepare header for final gridding
if args.header is None:
    logging.warning('Calculate output headers...')
    mra = np.mean( np.array([d.get_wcs().wcs.crval[0] for d in directions]) )
    mdec = np.mean( np.array([d.get_wcs().wcs.crval[1] for d in directions]) )

    logging.info('Will make mosaic at %f %f' % (mra,mdec))
    
    # we make a reference WCS and use it to find the extent in pixels
    # needed for the combined image

    rwcs = pywcs(naxis=2)
    rwcs.wcs.ctype = directions[0].get_wcs().wcs.ctype
    rwcs.wcs.cdelt = directions[0].get_wcs().wcs.cdelt
    rwcs.wcs.crval = [mra,mdec]
    rwcs.wcs.crpix = [1,1]

    xmin=0
    xmax=0
    ymin=0
    ymax=0
    for d in directions:
        w = d.get_wcs()
        ys, xs = np.where(d.img_data)
        axmin = xs.min()
        aymin = ys.min()
        axmax = xs.max()
Пример #9
0
 def get_wcs(self):
     return pywcs(self.img_hdr)
Пример #10
0
    def regrid_common(self,
                      size=None,
                      radec=None,
                      pixscale=None,
                      pix_per_bmin=None,
                      square=False):
        """
        Move all images to a common grid
        Parameters
        ----------
        size: float or array-like of size 2, optional. Default = None
            Size of the new grid in degree. If not a list of size two, is assumed to be square.
            If not provided, automatically determines the largest size that fits all images.
        radec: list of size 2, optional.
            [ra, dec] in degree. If not specified, default to center of first image.
        pixscale: float, optional. Default = use from first image
            Size of a square pixel in arcseconds
        pix_per_bmin: int, optional. How many pixels should there be per BMIN of 1st image?
        square: bool, optional. Default = True
            If False, do not force square image.
        """
        rwcs = pywcs(naxis=2)
        rwcs.wcs.ctype = self.images[0].get_wcs().wcs.ctype
        if pixscale and pix_per_bmin:
            logging.error('Cannot specify both pixscale and pix_per_bmin!')
            sys.exit(1)
        elif pixscale:
            cdelt = pixscale / 3600.
        elif pix_per_bmin:
            cdelt = self.images[0].img_hdr['BMIN'] / pix_per_bmin
            print(self.images[0].img_hdr['BMIN'], cdelt)
        else:
            cdelt = np.mean(np.abs(self.images[0].get_wcs().wcs.cdelt)
                            )  # could also use 1/5 of minor axes (deg)
        logging.info('Pixel scale: %f"' % (cdelt * 3600.))
        rwcs.wcs.cdelt = [-cdelt, cdelt]
        if radec:
            mra, mdec = radec
        else:
            mra = self.images[0].img_hdr['CRVAL1']
            mdec = self.images[0].img_hdr['CRVAL2']
        rwcs.wcs.crval = [mra, mdec]

        # Calculate sizes of all images to find smallest size that fits all images
        sizes = np.empty((len(self.images), 2))
        for i, image in enumerate(self.images):
            sizes[i] = np.array(image.img_data.shape) * image.degperpixel
        if size:
            size = np.array([size])
            if np.any(np.min(sizes, axis=1) < size):
                logging.warning(
                    f'Requested size {size} is larger than smallest image size {np.min(sizes, axis=1)} in at least one dimension. This will result in NaN values in the regridded images.'
                )
        else:
            size = np.min(sizes, axis=0)
            if square:
                size = np.min(size)

        xsize = int(np.rint(np.array([size[0]]) / cdelt))
        ysize = int(np.rint(np.array([size[-1]]) / cdelt))
        if xsize % 2 != 0: xsize += 1
        if ysize % 2 != 0: ysize += 1
        rwcs.wcs.crpix = [xsize / 2, ysize / 2]

        regrid_hdr = rwcs.to_header()
        regrid_hdr['NAXIS'] = 2
        regrid_hdr['NAXIS1'] = xsize
        regrid_hdr['NAXIS2'] = ysize

        logging.info(
            f'Image size: {size} deg ({xsize:.0f},{ysize:.0f} pixels))')
        for image in self.images:
            this_regrid_hdr = regrid_hdr.copy()
            this_regrid_hdr['BMAJ'], this_regrid_hdr['BMIN'], this_regrid_hdr[
                'BPA'] = image.get_beam()
            image.regrid(this_regrid_hdr)
Пример #11
0
 def get_wcs(self):
     return pywcs(self.img_hdr)
Пример #12
0
            
        dra = ref_cat['RA'][idx_matched_ref] - image.cat['RA'][idx_matched_img]
        dra[ dra>180 ] -= 360
        dra[ dra<-180 ] += 360
        ddec = ref_cat['DEC'][idx_matched_ref] - image.cat['DEC'][idx_matched_img]
        flux = ref_cat['Peak_flux'][idx_matched_ref]
        image.apply_shift(np.average(dra, weights=flux), np.average(ddec, weights=flux))

    # clean up
    #for image in all_images:
    #    os.system(rm ...)

 
######################################################
# Generate regrid headers
rwcs = pywcs(naxis=2)
rwcs.wcs.ctype = all_images[0].get_wcs().wcs.ctype
cdelt = target_beam[1]/5. # 1/5 of minor axes (deg)
logging.info('Pixel scale: %f"' % (cdelt*3600.))
rwcs.wcs.cdelt = [-cdelt, cdelt]
if args.radec is not None:
    mra = radec[0]*np.pi/180
    mdec = radec[1]*np.pi/180
else:
    mra = all_images[0].img_hdr['CRVAL1']
    mdec = all_images[0].img_hdr['CRVAL2']
rwcs.wcs.crval = [mra,mdec]

# if size is not give is taken from the mask
if args.size is None:
    if args.region is not None:
Пример #13
0
def wcs_from_cube_header(hdr):
    '''
    Install coordinates for the data. This will have one spatial axis and
    one spectral axis
    '''
    # Don't convert units
    if 'CUNIT3' in hdr:
        unit = u.Unit(hdr.pop('CUNIT3'))

    try:
        naxis = hdr['NAXIS']
    except KeyError:
        naxis = hdr['WCSAXES']

    # generate a WCS object
    mywcs = pywcs(hdr, fix=False)

    # Figure out the spatial limits
    # get the full extent of the data
    nx, ny = mywcs.pixel_shape[:2]
    #print(nx, ny)

    # ideally, crpix should be our centers
    # TODO: add option to pass a center
    xc, yc = mywcs.wcs.crpix[:2]

    # make new WCS object with Spatial and Wavelength axes
    # `wcs.sub()` sets naxis1 to None, so make sure it has
    # the same pixel shape as the parent data
    new_wcs = mywcs.sub([0, WCSSUB_SPECTRAL])
    new_wcs.pixel_shape = mywcs.pixel_shape[1:]

    # get cdelt from CD
    cd = mywcs.wcs.cd
    dy = np.sqrt(cd[0, 1]**2 + cd[1, 1]**2)

    # get dy in arcseconds
    dy = np.round((dy * u.deg).to(u.arcsec).value, 1)
    cdelt1 = dy
    cdelt2 = cd[2, 2]

    # if the WCS header is taken from a cube or a 2D spatial image,
    # get rid of the CD parameter so astropy won't ignore a cdelt value
    if new_wcs.wcs.has_cd():
        del new_wcs.wcs.cd

    # set the WCS info
    new_wcs.wcs.crpix[0] = yc
    new_wcs.wcs.cdelt[0] = cdelt1
    new_wcs.wcs.cdelt[1] = cdelt2
    new_wcs.wcs.crval[0] = 0.  # this is arcsec, so we want the center at 0
    new_wcs.wcs.ctype[0] = 'OFFSET'
    new_wcs.wcs.cunit[0] = u.Unit('arcsec')  #.to_string('fits')
    #new_wcs.wcs.cunit[1] = u.Unit(unit)#.to_string('fits')
    #new_wcs.wcs.set()
    try:
        new_wcs.wcs.pc[1, 0] = new_wcs.wcs.pc[0, 1] = 0
    except AttributeError:
        pass

    return new_wcs
Пример #14
0
def main(input_image_list,
         vertices_file_list,
         output_image,
         skip=False,
         padding=1.1):
    """
    Make a mosaic template image

    Parameters
    ----------
    input_image_list : list
        List of filenames of input images to mosaic
    vertices_file_list : list
        List of filenames of input vertices files
    output_image : str
        Filename of output image
    skip : bool
        If True, skip all processing
    padding : float
        Fraction with which to increase the final mosaic size
    """
    input_image_list = misc.string2list(input_image_list)
    vertices_file_list = misc.string2list(vertices_file_list)
    skip = misc.string2bool(skip)
    if skip:
        return

    # Set up images used in mosaic
    directions = []
    for image_file, vertices_file in zip(input_image_list, vertices_file_list):
        d = FITSImage(image_file)
        d.vertices_file = vertices_file
        d.blank()
        directions.append(d)

    # Prepare header for final gridding
    mra = np.mean(np.array([d.get_wcs().wcs.crval[0] for d in directions]))
    mdec = np.mean(np.array([d.get_wcs().wcs.crval[1] for d in directions]))

    # Make a reference WCS and use it to find the extent in pixels
    # needed for the combined image
    rwcs = pywcs(naxis=2)
    rwcs.wcs.ctype = directions[0].get_wcs().wcs.ctype
    rwcs.wcs.cdelt = directions[0].get_wcs().wcs.cdelt
    rwcs.wcs.crval = [mra, mdec]
    rwcs.wcs.crpix = [1, 1]
    xmin, xmax, ymin, ymax = 0, 0, 0, 0
    for d in directions:
        w = d.get_wcs()
        ys, xs = np.where(d.img_data)
        axmin, aymin, axmax, aymax = xs.min(), ys.min(), xs.max(), ys.max()
        del xs, ys
        for x, y in ((axmin, aymin), (axmax, aymin), (axmin, aymax), (axmax,
                                                                      aymax)):
            ra, dec = [float(f) for f in w.wcs_pix2world(x, y, 0)]
            nx, ny = [float(f) for f in rwcs.wcs_world2pix(ra, dec, 0)]
            xmin, xmax, ymin, ymax = min(nx, xmin), max(nx, xmax), min(
                ny, ymin), max(ny, ymax)
    xsize = int(xmax - xmin)
    ysize = int(ymax - ymin)
    xmax += int(xsize * (padding - 1.0) / 2.0)
    xmin -= int(xsize * (padding - 1.0) / 2.0)
    ymax += int(ysize * (padding - 1.0) / 2.0)
    ymin -= int(ysize * (padding - 1.0) / 2.0)
    xsize = int(xmax - xmin)
    ysize = int(ymax - ymin)
    rwcs.wcs.crpix = [-int(xmin) + 1, -int(ymin) + 1]
    regrid_hdr = rwcs.to_header()
    regrid_hdr['NAXIS'] = 2
    regrid_hdr['NAXIS1'] = xsize
    regrid_hdr['NAXIS2'] = ysize
    for ch in ('BMAJ', 'BMIN', 'BPA', 'FREQ', 'RESTFREQ', 'EQUINOX'):
        regrid_hdr[ch] = directions[0].img_hdr[ch]
    regrid_hdr['ORIGIN'] = 'Raptor'
    regrid_hdr['UNITS'] = 'Jy/beam'
    regrid_hdr['TELESCOP'] = 'LOFAR'

    isum = np.zeros([ysize, xsize])
    hdu = pyfits.PrimaryHDU(header=regrid_hdr, data=isum)
    hdu.writeto(output_image, overwrite=True)
Пример #15
0
def main(input_image, template_image, vertices_file, output_image, skip=False):
    """
    Regrid a FITS image

    Parameters
    ----------
    input_image : str
        Filename of input FITS image to regrid
    template_image : str
        Filename of mosaic template FITS image
    vertices_file : str
        Filename of file with vertices
    output_image : str
        Filename of output FITS image
    skip : bool
        If True, skip all processing
    """
    skip = misc.string2bool(skip)
    if skip:
        if os.path.exists(output_image):
            os.remove(output_image)
        shutil.copyfile(input_image, output_image)
        return

    # Read template header and data
    regrid_hdr = pyfits.open(template_image)[0].header
    isum = pyfits.open(template_image)[0].data
    isum[:] = np.nan
    shape_out = isum.shape
    wcs_out = pywcs(regrid_hdr)

    # Read input image and blank outside its polygon
    d = FITSImage(input_image)
    d.vertices_file = vertices_file
    d.blank()
    wcs_in = d.get_wcs()

    # Define the subarray of the output image that fully encloses the reprojected input
    # image
    ny, nx = d.img_data.shape
    xc = np.array([-0.5, nx - 0.5, nx - 0.5, -0.5])
    yc = np.array([-0.5, -0.5, ny - 0.5, ny - 0.5])
    xc_out, yc_out = wcs_out.world_to_pixel(wcs_in.pixel_to_world(xc, yc))
    imin = max(0, int(np.floor(xc_out.min() + 0.5)))
    imax = min(shape_out[1], int(np.ceil(xc_out.max() + 0.5)))
    jmin = max(0, int(np.floor(yc_out.min() + 0.5)))
    jmax = min(shape_out[0], int(np.ceil(yc_out.max() + 0.5)))

    # Set up output projection
    wcs_out_indiv = wcs_out.deepcopy()
    wcs_out_indiv.wcs.crpix[0] -= imin
    wcs_out_indiv.wcs.crpix[1] -= jmin
    shape_out_indiv = (jmax - jmin, imax - imin)

    # Reproject, place into output image, and write out final FITS file
    ind = slice(jmin, jmax), slice(imin, imax)
    isum[ind] = reproject_interp((d.img_data, wcs_in), output_projection=wcs_out_indiv,
                                 shape_out=shape_out_indiv, return_footprint=False)
    d.img_data = isum
    d.img_hdr = regrid_hdr
    d.write(output_image)