示例#1
0
def pix2world(wcs, x_pix, y_pix):
    if np.isscalar(x_pix) and np.isscalar(y_pix):
        x_world, y_world = wcs.wcs_pix2world(np.array([x_pix]), np.array([y_pix]), 1)
        return x_world[0], y_world[0]
    elif (type(x_pix) == list) and (type(y_pix) == list):
        x_world, y_world = wcs.wcs_pix2world(np.array(x_pix), np.array(y_pix), 1)
        return x_world.tolist(), y_world.tolist()
    elif isinstance(x_pix, np.ndarray) and isinstance(y_pix, np.ndarray):
        return wcs.wcs_pix2world(x_pix, y_pix, 1)
    else:
        raise Exception("pix2world should be provided either with two scalars, two lists, or two numpy arrays")
示例#2
0
文件: utils.py 项目: cdeil/fermipy
def pix_to_skydir(xpix,ypix,wcs):
    """Convert pixel coordinates to a skydir object."""
    
    if 'RA' in wcs.wcs.ctype[0]:    
        ra, dec = wcs.wcs_pix2world(xpix,ypix,0)
        return SkyCoord(ra,dec,unit=u.deg)
    elif 'GLON' in wcs.wcs.ctype[0]:
        glon, glat = wcs.wcs_pix2world(xpix,ypix,0)
        return SkyCoord(glon,glat,unit=u.deg,
                        frame='galactic').transform_to('icrs')
    else:
        raise Exception('Unrecognized WCS coordinate system.')
示例#3
0
def pix2world(wcs, x_pix, y_pix):
    if np.isscalar(x_pix) and np.isscalar(y_pix):
        x_world, y_world = wcs.wcs_pix2world(np.array([x_pix]),
                                             np.array([y_pix]), 1)
        return x_world[0], y_world[0]
    elif (type(x_pix) == list) and (type(y_pix) == list):
        x_world, y_world = wcs.wcs_pix2world(np.array(x_pix), np.array(y_pix),
                                             1)
        return x_world.tolist(), y_world.tolist()
    elif isinstance(x_pix, np.ndarray) and isinstance(y_pix, np.ndarray):
        return wcs.wcs_pix2world(x_pix, y_pix, 1)
    else:
        raise Exception(
            "pix2world should be provided either with two scalars, two lists, or two numpy arrays"
        )
示例#4
0
def get_asteroid_list_from_fitsfile(fitsfile):

    hdulist = astropy.io.fits.open(fitsfile)

    wcs = astropy.wcs.WCS(hdulist[0].header)
    print wcs.wcs.name
    # print wcs.wcs.print_contents()

    # get corner coordinates
    naxis1, naxis2 = hdulist[0].header['NAXIS1'], hdulist[0].header['NAXIS2']

    centerx, centery = naxis1 / 2, naxis2 / 2
    center = numpy.array([[centerx, centery]])
    print center

    center_coord = wcs.wcs_pix2world(center, 1)

    print center_coord

    epoch = hdulist[0].header['MJD-OBS'] + mjd0

    ra = center_coord[0, 0]
    dec = center_coord[0, 1]
    sr = 0.4

    votab = get_minorobjects(epoch, ra, dec, sr)

    hdulist.close()

    return votab
示例#5
0
def query_slice(x0, y0, x1, y1, wcs, shape, width=None):

    nypix, nxpix = shape
    xpix, ypix = np.meshgrid(np.arange(nxpix), np.arange(nypix))
    xpix_world, ypix_world = wcs.wcs_pix2world(xpix.flatten(), ypix.flatten(),
                                               0)

    if isinstance(width, type(None)):
        width = np.abs(wcs.wcs.cdelt[1])

    m = (y1 - y0) / (x1 - x0)
    yvec = m * (xpix_world - x0) + y0

    xmid = (x1 + x0) / 2.
    if x1 != x0:
        xwidth = np.abs(x1 - x0) / 2.
    else:
        xwidth = width
    ymid = (y1 + y0) / 2.
    if y1 != y0:
        ywidth = np.abs(y1 - y0) / 2.
    else:
        ywidth = width

    select = (np.abs(yvec - ypix_world) < width) & (np.abs(
        ypix_world - ymid) < ywidth) & (np.abs(xpix_world - xmid) < xwidth)
    angular_dist = Coordinates.AngularSeperation(x0, y0, xpix_world[select],
                                                 ypix_world[select])
    return select, xpix_world[select], ypix_world[select], angular_dist
示例#6
0
    def get_order_wcs(self):

        # Construct wcs, using each order header for all files
        self.wcs_outer = [[wcs.WCS(header) for header in hdus] for hdus in self.order_header_outer]

        # Construct transposed list to loop through spatial dir
        self.wcs_outer_t = list(map(list, zip(*self.wcs_outer)))

        # Find number of order elements
        self.naxis1_list = [header['NAXIS1'] for header in self.order_header_outer[0]]
        self.naxis2_list = [header['NAXIS2'] for header in self.order_header_outer[0]]

        # Images must have same number of spatial pixels
        if not self.naxis2_list.count(self.naxis2_list[0]) == len(self.naxis2_list):
            raise TypeError("Input image list does not have the same number of spatial pixels.")

        self.naxis2 = self.naxis2_list[0]

        self.cdelt1_list = [header['CDELT1'] for header in self.order_header_outer[0]]
        self.cdelt2_list = [header['CDELT2'] for header in self.order_header_outer[0]]

        # Images must have same sampling in both directions
        if not self.cdelt1_list.count(self.cdelt1_list[0]) == len(self.cdelt1_list):
            raise TypeError("Input image list does not have the same wavelength sampling.")
        if not self.cdelt2_list.count(self.cdelt2_list[0]) == len(self.cdelt2_list):
            raise TypeError("Input image list does not have the same spatial sampling.")

        self.cdelt1 = self.cdelt1_list[0]
        self.cdelt2 = self.cdelt2_list[0]


        # Get CRVAL1 for orders
        self.crval1_list = [header['CRVAL1'] for header in self.order_header_outer[0]]

        # Get wavelength extent of orders in nm
        self.start_wave_list = [wcs.wcs_pix2world(1, 1, 1)[0] + 0 for wcs in self.wcs_outer[0]]
        self.end_wave_list = [wcs.wcs_pix2world(naxis1, 1, 1)[0] + 0 for wcs, naxis1 in zip(self.wcs_outer[0], self.naxis1_list)]

        # Spatial offset of individual images in arcsec
        self.cumoff = [header['HIERARCH ESO SEQ CUMOFF Y'] for header in self.order_header_outer_t[0]]

        # Get spatial extent of orders by looping over the transposed list
        self.start_size_list = [wcs.wcs_pix2world(1, 1, 1)[1] + self.cumoff[elem] for elem, wcs in enumerate(self.wcs_outer_t[0])]
        self.end_size_list = [wcs.wcs_pix2world(1, naxis2, 1)[1] + self.cumoff[elem] for elem, (wcs, naxis2) in enumerate(zip(self.wcs_outer_t[0], self.naxis2_list))]

        # Construct merged wavelength array
        self.waveaxis_merged = (((np.arange(self.header['NAXIS1'])) + 1 - self.header['CRPIX1'])*self.header['CDELT1']+self.header['CRVAL1'])
示例#7
0
 def astrometry(self, name, scale):
     subprocess.call(["/usr/local/astrometry/bin/solve-field", "--cpulimit", "10", "--downsample", "2", "--tweak-order", "2", "--scale-units", "arcsecperpix", "--scale-low", str(numpy.floor(scale*100)/100), "--scale-high", str(numpy.ceil(scale*100)/100), "--no-plots", "--overwrite", name+".ppm"])
     if os.path.isfile(name+'.solved'):
        self.is_solved = True
        wcs = astropy.wcs.WCS(astropy.io.fits.open(name+'.new')[0].header)
        self.RA, self.Dec = wcs.wcs_pix2world(self.center_x, self.center_y, 1)
     else:
        self.is_solved = False
示例#8
0
def make_host(subject, wcs, cache_name, consensus):
    """Returns an RGZ and SWIRE name for the host, and the location.

    subject: RGZ subject dict.
    wcs: World coordinate system (from Astropy).
    cache_name: Name of Gator cache.
    consensus: Consensus dict from database.
    -> (str: RGZ_JHHMMSS-DDMMSS, SWIRE name, RA, DEC)
    """
    # We want RGZ_JHHMMSS-DDMMSS and an associated SWIRE result. Let's start
    # with the SWIRE result so that the coordinates we get are accurate and
    # reproducible. Convert pixel coordinates into RA/DEC.
    x = consensus['source_x']
    # Pretty much following willettk's rgz-analysis code here.
    raise NotImplementedError('Scales have been changed and code not updated.')
    y = config.get('fits_image_height') - consensus['source_y']
    x, y = wcs.wcs_pix2world([x], [y], 1)

    # Get the closest SWIRE object.
    p_hosts = data.get_potential_hosts(subject, cache_name,
                                       convert_to_px=False)
    dist_func = distance_from((x, y))
    nearest = min(p_hosts, key=dist_func)

    # Cutoff is in degrees.
    if not dist_func(nearest) < config.get('swire_distance_cutoff'):
        raise CatalogueError(
            'Closest SWIRE object is not nearby for {}. '
            'Distance: {:.02} degrees'.format(
                    subject['zooniverse_id'],
                    float(dist_func(nearest))))

    swire_name = p_hosts[nearest]['name'].decode('ascii')

    # This provides our coordinates. Separate out HHMMSS/DDMMSS. We can do this
    # using astropy.coordinates.SkyCoord. Note that I'm using the clon/clat
    # values returned by Gator; this helps keep us lined up with the SWIRE
    # coordinates since if you use the RA/DEC raw you get rounding errors.
    clon = p_hosts[nearest]['clon'].decode('ascii')
    clat = p_hosts[nearest]['clat'].decode('ascii')
    coords = astropy.coordinates.SkyCoord(clon + ' ' + clat, unit='deg')
    ra = coords.ra.hms
    dec = coords.dec.signed_dms

    # Construct the name.
    rgz_name = ('RGZ_J{ra_h:02}{ra_m:02}{ra_s:04.01f}{sign}'
                '{dec_d:02}{dec_m:02}{dec_s:02}').format(
                ra_h=int(ra[0]),
                ra_m=int(ra[1]),
                ra_s=ra[2],
                sign='-' if dec[0] < 0 else '+',
                dec_d=int(dec[1]),
                dec_m=int(dec[2]),
                dec_s=int(round(dec[3])))

    return rgz_name, swire_name, clon, clat, consensus['location_agreement']
示例#9
0
def make_host(subject, wcs, cache_name, consensus):
    """Returns an RGZ and SWIRE name for the host, and the location.

    subject: RGZ subject dict.
    wcs: World coordinate system (from Astropy).
    cache_name: Name of Gator cache.
    consensus: Consensus dict from database.
    -> (str: RGZ_JHHMMSS-DDMMSS, SWIRE name, RA, DEC)
    """
    # We want RGZ_JHHMMSS-DDMMSS and an associated SWIRE result. Let's start
    # with the SWIRE result so that the coordinates we get are accurate and
    # reproducible. Convert pixel coordinates into RA/DEC.
    x = consensus['source_x']
    # Pretty much following willettk's rgz-analysis code here.
    raise NotImplementedError('Scales have been changed and code not updated.')
    y = config.get('fits_image_height') - consensus['source_y']
    x, y = wcs.wcs_pix2world([x], [y], 1)

    # Get the closest SWIRE object.
    p_hosts = data.get_potential_hosts(subject,
                                       cache_name,
                                       convert_to_px=False)
    dist_func = distance_from((x, y))
    nearest = min(p_hosts, key=dist_func)

    # Cutoff is in degrees.
    if not dist_func(nearest) < config.get('swire_distance_cutoff'):
        raise CatalogueError('Closest SWIRE object is not nearby for {}. '
                             'Distance: {:.02} degrees'.format(
                                 subject['zooniverse_id'],
                                 float(dist_func(nearest))))

    swire_name = p_hosts[nearest]['name'].decode('ascii')

    # This provides our coordinates. Separate out HHMMSS/DDMMSS. We can do this
    # using astropy.coordinates.SkyCoord. Note that I'm using the clon/clat
    # values returned by Gator; this helps keep us lined up with the SWIRE
    # coordinates since if you use the RA/DEC raw you get rounding errors.
    clon = p_hosts[nearest]['clon'].decode('ascii')
    clat = p_hosts[nearest]['clat'].decode('ascii')
    coords = astropy.coordinates.SkyCoord(clon + ' ' + clat, unit='deg')
    ra = coords.ra.hms
    dec = coords.dec.signed_dms

    # Construct the name.
    rgz_name = ('RGZ_J{ra_h:02}{ra_m:02}{ra_s:04.01f}{sign}'
                '{dec_d:02}{dec_m:02}{dec_s:02}').format(
                    ra_h=int(ra[0]),
                    ra_m=int(ra[1]),
                    ra_s=ra[2],
                    sign='-' if dec[0] < 0 else '+',
                    dec_d=int(dec[1]),
                    dec_m=int(dec[2]),
                    dec_s=int(round(dec[3])))

    return rgz_name, swire_name, clon, clat, consensus['location_agreement']
示例#10
0
    def get_order_information(self):
        # from astropy import wcs

        self.norders = int(len(self.hdul) / 3)

        header_list = [self.hdul[i * 3].header for i in range(self.norders)]
        wcs_list = [wcs.WCS(header) for header in header_list]

        self.cdelt1 = header_list[0]['CDELT1']
        self.naxis1_list = [header['NAXIS1'] for header in header_list]
        self.naxis2 = header_list[0]['NAXIS2']

        self.start_wave_list = [
            wcs.wcs_pix2world(1, 1, 1)[0] for wcs in wcs_list
        ]

        self.end_wave_list = [
            wcs.wcs_pix2world(naxis1, 1, 1)[0]
            for wcs, naxis1 in zip(wcs_list, self.naxis1_list)
        ]
        self.wcs_list, self.header_list = wcs_list, header_list
示例#11
0
def _wcs_toworld (wcs, pixel, wcscale, naxis):
    # TODO: we don't allow the usage of "SIP" or "Paper IV"
    # transformations, let alone a concatenation of these, because
    # they're not invertible.

    pixel = np.asarray (pixel)
    if pixel.shape != (naxis, ):
        raise ValueError ('pixel coordinate must be a %d-element vector', naxis)

    pixel = pixel.reshape ((1, naxis))[:,::-1]
    world = wcs.wcs_pix2world (pixel, 0)
    return world[0,::-1] * wcscale
示例#12
0
文件: astimage.py 项目: vlslv/pwkit
def _wcs_toworld(wcs, pixel, wcscale, naxis):
    # TODO: we don't allow the usage of "SIP" or "Paper IV"
    # transformations, let alone a concatenation of these, because
    # they're not invertible.

    pixel = np.asarray(pixel)
    if pixel.shape != (naxis, ):
        raise ValueError('pixel coordinate must be a %d-element vector', naxis)

    pixel = pixel.reshape((1, naxis))[:, ::-1]
    world = wcs.wcs_pix2world(pixel, 0)
    return world[0, ::-1] * wcscale
示例#13
0
 def _footprint(self, pixel_polygon, target, coordsys="J2000d"):
     """Convert a pixel-space polygon into a sky footprint.""" 
     if coordsys != "J2000d" and coordsys != "Gal":
         raise NotImplementedError("Unknown coordinate system "+coordsys)
     
     # Converts pixel space to WCS-defined sky system
     wcs = self.get_footprint_wcs(target)
     sky = wcs.wcs_pix2world(pixel_polygon, 1)
     # We assume WCS is in J2000d, apply conversion if Galactic is requested
     if coordsys == "Gal":
         for i, coord in enumerate(sky):
             sky[i] = equ2gal(coord)
     return sky
示例#14
0
文件: wcs.py 项目: arlewis/astrogrid
def calc_pixscale(hdr, ref='crpix', units=None):
    """Calculate the x and y pixel scales from the WCS information in a
    FITS header.

    Parameters
    ----------
    hdr : astropy.io.fits.Header
        Header object with WCS keywords. Must have the keys 'naxis1',
        'naxis2', 'crpix1', 'crpix2', 'crval1', and 'crval1'.
    ref : {'crpix', 'center', tuple}, optional
        If 'crpix' (default), the reference pixel is set to CRPIX1,CRPIX2.
        'center' indicates that the central pixel in the image should be
        used. An x,y tuple of floats may be given to use a specific
        reference pixel instead.
    units : tuple, optional
        The units of the longitude and latitude coordinates as a tuple of
        `astropy.units.core.Unit` instances. If None (default), then the
        units will be determined from `hdr`.

    Returns
    -------
    astropy.coordinates.Angle
        An `Angle` instance containing the x and y pixel scales.

    Updates
    -------
    added naxis keyword to astropy.wcs.WCS call to ensure only 2 axes are
    used. - A. R. Lewis 03/30/2015

    """
    wcs = astropy.wcs.WCS(hdr, naxis=2)
    if ref == 'crpix':
        x, y = hdr['crpix1'], hdr['crpix2']
    elif ref == 'center':
        x, y = hdr['naxis1']//2, hdr['naxis2']//2
    else:
        x, y = ref

    if units is None:
        units = wcs.wcs.cunit

    lon, lat = wcs.wcs_pix2world([x, x+1, x], [y, y, y+1], 1)
    if (astropy.version.major < 1) & (astropy.version.minor < 4):
        # Makes no difference whether ICRS, Galactic, AltAz, etc.
        points = astropy.coordinates.ICRS(lon, lat, unit=units)
    else:
        # Makes no difference whether ICRS, Galactic, AltAz, etc.
        points = astropy.coordinates.SkyCoord(lon, lat, frame='icrs', unit=units)
    dxy = astropy.coordinates.Angle([points[0].separation(points[1]),
                                     points[0].separation(points[2])])
    return dxy
示例#15
0
def query_annullus(x0, y0, r0, r1, wcs, shape):
    """
    """
    nypix, nxpix = shape
    xpix, ypix = np.meshgrid(np.arange(nxpix), np.arange(nypix))
    xpix_world, ypix_world = wcs.wcs_pix2world(xpix.flatten(), ypix.flatten(),
                                               0)

    rpix_world = np.sqrt((xpix_world - x0)**2 *
                         np.cos(ypix_world * np.pi / 180.)**2 +
                         (ypix_world - y0)**2)
    select = np.where((rpix_world >= r0) & (rpix_world < r1))[0]

    return select, xpix_world[select], ypix_world[select]
示例#16
0
def query_disc(x0, y0, r, wcs, shape):
    """
    """
    nypix, nxpix = shape
    xpix, ypix = np.meshgrid(np.arange(nxpix), np.arange(nypix))
    xpix_world, ypix_world = wcs.wcs_pix2world(xpix.flatten(), ypix.flatten(),
                                               0)

    rpix_world = np.sqrt((xpix_world - x0)**2 *
                         np.cos(ypix_world * np.pi / 180.)**2 +
                         (ypix_world - y0)**2)
    select = (rpix_world < r)

    return select, xpix_world[select], ypix_world[select]
示例#17
0
def xy_to_radec(wcs, pxy):
    '''
    Convert the x/y coordinates of an image pixel
    into the ra/dec coordinates of a celestial body
    :param wcs: a wcs object, as returned by get_wcs()
    :param pxy: an instance of PixelXY
    :return: an instance of RaDec
    '''

    pixel = np.array([
        [pxy.x, pxy.y],
    ], np.float_)
    sky = wcs.wcs_pix2world(pixel, 0)
    return RaDec(ra=sky[0][0], dec=sky[0][1])
示例#18
0
def get_xlim_ylim(x0, y0, width, wcs, shape):

    nypix, nxpix = shape
    xpix, ypix = np.meshgrid(np.arange(nxpix), np.arange(nypix))
    xpix_world, ypix_world = wcs.wcs_pix2world(xpix, ypix, 0)

    select = (xpix_world < (x0 + width/2.)) & (xpix_world > (x0 - width/2.)) &\
             (ypix_world < (y0 + width/2.)) & (ypix_world > (y0 - width/2.))

    xflat = np.where((np.sum(select, axis=0) > 0))[0]
    yflat = np.where((np.sum(select, axis=1) > 0))[0]

    return (min(xflat),
            max(xflat)), (min(yflat),
                          max(yflat)), np.where(select.flatten())[0]
示例#19
0
    def solver(self, filename):
        name, extension = os.path.splitext(filename)
        if extension != '.CR2' and extension != '.avi':
            self.solve.setEnabled(True)
            return

        self.text_line.setText('Converting file into Tiff')
        if extension == '.CR2':
            raw = rawpy.imread(filename)
            image = raw.postprocess(half_size=True)
            raw.close()
            imageio.imsave(name + '.tif', image)
        if extension == '.avi':
            subprocess.call([
                "/usr/bin/avconv", "-i", filename, "-vframes", "1",
                name + ".jpeg"
            ])
            image = imageio.imread(name + ".jpeg")
            imageio.imsave(name + '.tif', image)
            os.remove(name + '.jpeg')

        center_x = image.shape[1] / 2
        center_y = image.shape[0] / 2

        self.text_line.setText('Solving image...')
        scale = float(self.solve_scale.currentText())
        subprocess.call([
            "/usr/bin/solve-field", "--downsample", "2", "--tweak-order", "2",
            "--no-plots", "--overwrite", name + ".tif"
        ])

        if not os.path.isfile(name + '.solved'):
            self.text_line.setText('Image not solved')
            clean_astrometry(name)
            self.solve.setEnabled(True)
            return

        wcs = astropy.wcs.WCS(astropy.io.fits.open(name + '.new')[0].header)
        RA, Dec = wcs.wcs_pix2world(center_x, center_y, 1)
        self.coords = [RA_to_text(RA), Dec_to_text(Dec)]

        clean_astrometry(name)
        self.solve.setEnabled(True)
        self.mount_ip.setEnabled(True)
        self.mount.setEnabled(True)
        self.ra_label.setText('Ra: ' + self.coords[0])
        self.dec_label.setText('Dec: ' + self.coords[1])
        self.text_line.setText('Done')
示例#20
0
def plotMap(counts, out='tmp.png', cmap=None, roi=None):
    """
This method plots some count map. Inherited from the method plotMaps
above.  

:param counts: FITS file with counts to be plotted
:param cmap: desired colormap for image
:param roi: DS9 region file if present, otherwise leave None
:param out: output filename and format
:returns: image file 'tmp.png' in the source folder.
    """
    import astropy, astropy.io.fits, astropy.wcs
    import aplpy

    def set_hgps_style(f):
        """Set HGPS style for a f = aplpy.FITSFigure"""
        f.ticks.set_xspacing(2)
        f.ticks.set_yspacing(2)
        f.ticks.set_linewidth(1.5)
        f.tick_labels.set_xformat('dd')
        f.tick_labels.set_yformat('dd')
        f.tick_labels.set_style('colons')
        f.axis_labels.set_xtext('Right Ascension (deg)')
        f.axis_labels.set_ytext('Declination (deg)')

    # Determine image center and width / height
    dpi = 2000
    header = astropy.io.fits.getheader(counts)
    wcs = astropy.wcs.WCS(header)
    header['NAXIS1'] / dpi
    header['NAXIS2'] / dpi
    lon, lat = header['NAXIS1'] / 2., header['NAXIS2'] / 2.
    x_center, y_center = wcs.wcs_pix2world(lon, lat, 0)
    radius = header['CDELT2'] * header['NAXIS2'] / 2.

    f = aplpy.FITSFigure(counts)
    f.recenter(x_center, y_center, 0.95 * radius)
    set_hgps_style(f)
    f.show_colorscale(stretch='power', exponent=1, cmap=cmap)
    f.show_colorbar()
    f.show_markers(x_center, y_center, edgecolor='White', s=400.)
    if roi != None: f.show_regions(roi)

    print('Writing {}'.format(out))
    pylab.savefig(out)
示例#21
0
文件: fermi.py 项目: rsnemmen/nemmen
def plotMap(counts,out='tmp.png',cmap=None,roi=None):
    """
This method plots some count map. Inherited from the method plotMaps
above.  

:param counts: FITS file with counts to be plotted
:param cmap: desired colormap for image
:param roi: DS9 region file if present, otherwise leave None
:param out: output filename and format
:returns: image file 'tmp.png' in the source folder.
    """
    import astropy, astropy.io.fits, astropy.wcs
    import aplpy

    def set_hgps_style(f):
        """Set HGPS style for a f = aplpy.FITSFigure"""
        f.ticks.set_xspacing(2)
        f.ticks.set_yspacing(2)
        f.ticks.set_linewidth(1.5)
        f.tick_labels.set_xformat('dd')
        f.tick_labels.set_yformat('dd')
        f.tick_labels.set_style('colons')
        f.axis_labels.set_xtext('Right Ascension (deg)')
        f.axis_labels.set_ytext('Declination (deg)')

    # Determine image center and width / height
    dpi = 2000
    header = astropy.io.fits.getheader(counts)
    wcs = astropy.wcs.WCS(header)
    header['NAXIS1'] / dpi
    header['NAXIS2'] / dpi
    lon, lat = header['NAXIS1'] / 2., header['NAXIS2'] / 2.
    x_center, y_center = wcs.wcs_pix2world(lon, lat, 0)
    radius = header['CDELT2'] * header['NAXIS2'] / 2.

    f = aplpy.FITSFigure(counts)
    f.recenter(x_center, y_center, 0.95 * radius)
    set_hgps_style(f)
    f.show_colorscale(stretch='power', exponent=1, cmap=cmap)
    f.show_colorbar()
    f.show_markers(x_center, y_center, edgecolor='White', s=400.)
    if roi!=None: f.show_regions(roi)
   
    print('Writing {}'.format(out))
    pylab.savefig(out)
示例#22
0
def coordinates(image, world=True, lon_sym=True, radians=False):
    """Get coordinate images for a given image.

    This function is useful if you want to compute
    an image with values that are a function of position.

    Parameters
    ----------
    image : `astropy.io.fits.ImageHDU`
    world : bool
        Use world coordinates (or pixel coordinates)?
    lon_sym : bool
        Use symmetric longitude range `(-180, 180)` (or `(0, 360)`)?

    Returns
    -------
    (lon, lat) : tuple of arrays
        Images as numpy arrays with values
        containing the position of the given pixel.

    Examples
    --------
    >>> l, b = coordinates(image)
    >>> dist = sqrt( (l-42)**2 + (b-43)**2)
    """
    # Create arrays of pixel coordinates
    y, x = np.indices(image.data.shape, dtype='int32') + 1

    if not world:
        return x, y

    from astropy.wcs import WCS
    wcs = WCS(image.header)
    lon, lat = wcs.wcs_pix2world(x, y, 1)
    
    if lon_sym:
        lon = np.where(lon > 180, lon - 360, lon)
    
    if radians:
        lon = np.radians(lon)
        lat = np.radians(lat)

    return lon, lat
示例#23
0
def image_segments(header, n):
    """Generates RA,Dec and yx polygon segments if the image is divided into
    n-by-n square segments.
    """
    wcs = astropy.wcs.WCS(header)
    nx = header['NAXIS1']
    ny = header['NAXIS2']
    dx = int(math.floor(float(nx) / n))
    dy = int(math.floor(float(ny) / n))
    x0, y0 = 0, 0
    for i in xrange(n):
        x0 = 0

        for j in xrange(n):
            x = [x0, x0, x0 + dx, x0 + dx]
            y = [y0, y0 + dx, y0 + dy, y0]
            yx_poly = zip(y, x)
            ra, dec = wcs.wcs_pix2world(np.array(x), np.array(y), 0)
            radec_poly = zip(ra, dec)
            yield radec_poly, yx_poly
            
            x0 += dx

        y0 += dx
示例#24
0
def transient_detection(sextractor_output: str, refcat: str,
                        reffed_image: CCDData):
    image = CCDData.read(reffed_image)
    wcs = image.wcs

    gaia = astropy.table.Table(
        astropy.io.fits.open(refcat)[2].data
    )  # third hdu, get the numpy recarray, convert to astropy table
    sex = astropy.table.Table(astropy.io.fits.open(sextractor_output)[2].data)

    # origin does not seem to really matter...
    gaia_px = wcs.all_world2pix(
        np.array(gaia['X_WORLD', 'Y_WORLD'].to_pandas()), 1)
    gaia['X_IMAGE'] = gaia_px[:, 0]
    gaia['Y_IMAGE'] = gaia_px[:, 1]

    # noinspection PyUnusedLocal
    sex_world = wcs.wcs_pix2world(
        np.array(sex['XWIN_IMAGE', 'YWIN_IMAGE'].to_pandas()), 1)  # noqa

    # Do calculations in image coordinates so we can use error to estimate same-ness of detections

    distinct = []
    ambig = []
    notfound = []
    min_starclassifier = 0.8

    for row in sex[sex['CLASS_STAR'] > 0.8]:
        x, y = row['XWIN_IMAGE'], row['YWIN_IMAGE']
        xerr, yerr = row['ERRX2WIN_IMAGE'], row['ERRY2WIN_IMAGE']

        xcol, ycol = gaia_px[:, 0], gaia_px[:, 1]

        # how far out of the sextractor reported measurement error for the centroid do we want to search
        scale = 100
        candidate_idx = (xcol > x - xerr * scale) * (
            xcol < x + xerr * scale) * (ycol > y - yerr * scale) * (
                ycol < y + yerr * scale)
        n_candidates = sum(candidate_idx)

        if n_candidates == 1:
            # check here for brightness difference. Problem right now is that magnitudes have very different offsets
            distinct.append((row, gaia[candidate_idx]))

        if n_candidates == 0:
            # we found a new star????
            notfound.append(row)

        else:
            ambig.append((row, gaia[candidate_idx]))

    print('N ClassStar>', min_starclassifier, ':',
          len(sex[sex['CLASS_STAR'] > 0.8]))
    print('distinct: ', len(distinct))
    print('notfound: ', len(notfound))
    print('ambiguous: ', len(ambig))

    plt.scatter(gaia_px[:, 0],
                gaia_px[:, 1],
                marker='o',
                color='g',
                label='reference stars')
    plt.scatter(sex['XWIN_IMAGE'],
                sex['YWIN_IMAGE'],
                color='r',
                marker='x',
                label='sextractor')
    plt.legend()

    # plt.figure()
    # plt.scatter([d[0]['XWIN_IMAGE'] for d in distinct], [d[0]['YWIN_IMAGE'] for d in distinct], color='red')
    # plt.scatter([d[1]['X_IMAGE'] for d in distinct], [d[1]['Y_IMAGE'] for d in distinct], color='green')

    # plt.scatter([d['XWIN_IMAGE'] for d in notfound], [d['YWIN_IMAGE'] for d in notfound], color='pink')

    # plt.scatter(gaia['X_WORLD'], gaia['Y_WORLD'])
    # plt.scatter(sex_world[:, 0], sex_world[:, 1])

    plt.show()
    return sex, gaia
    def make_contour_at_level(self,wcs,img,yy,xx,level):
        C = _cntr.Cntr(xx,yy,img)
        paths = [p for p in C.trace(level) if p.ndim==2]

        wcs_paths = [wcs.wcs_pix2world(p,0) for p in paths]
        return(wcs_paths)
示例#26
0
    def load_fits2d(self, filename, xy_unit, **hdus):
        """Load the specified FITS file.

        The data in each image HDU is interpreted with x mapped to columns
        (NAXIS1) and y mapped to rows (NAXIS2).  The x, y coordinates are
        inferred from each image HDUs basic WCS parameters.

        The returned interpolators expect parameter with units and return
        interpolated values with units.  Units for x, y are specified via
        a parameter and assumed to be the same for all HDUs.  Units for
        the interpolated data are taken from the BUNIT header keyword, and
        must be interpretable by astropy.

        Parameters
        ----------
        filename : str
            Name of the file to read using :meth:`astropy.table.Table.read`.
        xy_unit : astropy.units.Unit
            Unit of x, y coordinates.
        hdus : dict
            Dictionary of name, hdu mappings where each hdu is specified by
            its integer offset or its name.

        Returns
        -------
        dict
            Dictionary of 2D linear interpolators corresponding to each hdu,
            with the same keys that appear in the hdus input parameter.
        """
        path = os.path.join(self.abs_base_path, filename)
        hdu_list = astropy.io.fits.open(path, memmap=False)
        interpolators = {}
        for name in hdus:
            hdu = hdu_list[hdus[name]]
            ny, nx = hdu.data.shape
            # Use the header WCS to reconstruct the x,y grids.
            wcs = astropy.wcs.WCS(hdu.header)
            x, _ = wcs.wcs_pix2world(np.arange(nx), [0], 0)
            _, y = wcs.wcs_pix2world([0], np.arange(ny), 0)
            try:
                bunit = hdu.header['BUNIT']
                data_unit = astropy.units.Unit(bunit)
            except KeyError:
                raise KeyError('Missing BUNIT header keyword for HDU {0}.'
                               .format(hdus[name]))
            except ValueError:
                raise ValueError('Invalid BUNIT "{0}" for HDU {1}.'
                                 .format(bunit, hdus[name]))
            dimensionless_interpolator = scipy.interpolate.RectBivariateSpline(
                x, y, hdu.data, kx=1, ky=1, s=0)
            # Note that the default arg values are used to capture the
            # current values of dimensionless_interpolator and data_unit
            # in the closure of this inner function.
            def interpolator(x, y, f=dimensionless_interpolator, u=data_unit):
                return f.ev(x.to(xy_unit).value, y.to(xy_unit).value) * u
            interpolators[name] = interpolator
            if self.verbose:
                print('Loaded {0} from HDU[{1}] of {2}.'
                      .format(name, hdus[name], path))
        hdu_list.close()
        return interpolators
示例#27
0
def parse_classification(classification, subject, atlas_positions, wcs,
                         pix_offset):
    """Converts a raw RGZ classification into a classification dict.

    Scales all positions and flips y axis of clicks.

    classification: RGZ classification dict.
    subject: Associated RGZ subject dict.
    atlas_positions: [[RA, DEC]] NumPy array.
    wcs: World coordinate system of the ATLAS image.
    pix_offset: (x, y) pixel position of this radio subject on the ATLAS image.
    -> dict mapping radio signature to list of corresponding IR host pixel
        locations.
    """
    result = {}

    n_invalid = 0

    for annotation in classification['annotations']:
        if 'radio' not in annotation:
            # This is a metadata annotation and we can ignore it.
            continue

        if annotation['radio'] == 'No Contours':
            # I'm not sure how this occurs. I'm going to ignore it.
            continue

        try:
            radio_signature = make_radio_combination_signature(
                    annotation['radio'], wcs, atlas_positions,
                    subject, pix_offset)
        except CatalogueError:
            # Ignore invalid annotations.
            n_invalid += 1
            logging.debug('Ignoring invalid annotation for %s.',
                          subject['zooniverse_id'])
            continue

        ir_locations = []
        if annotation['ir'] != 'No Sources':
            for ir_click in annotation['ir']:
                ir_x = float(annotation['ir'][ir_click]['x'])
                ir_y = float(annotation['ir'][ir_click]['y'])

                # Rescale to a consistent size.
                ir_x *= config['surveys']['atlas']['click_to_fits_x']
                ir_y *= config['surveys']['atlas']['click_to_fits_y']

                # Ignore out-of-range data.
                if not 0 <= ir_x <= config['surveys']['atlas']['fits_width']:
                    n_invalid += 1
                    continue

                if not 0 <= ir_y <= config['surveys']['atlas']['fits_height']:
                    n_invalid += 1
                    continue

                # Flip the y axis to match other data conventions.
                ir_y = config['surveys']['atlas']['fits_height'] - ir_y

                # Rescale to match the mosaic WCS.
                ir_x *= config['surveys']['atlas']['mosaic_scale_x']
                ir_y *= config['surveys']['atlas']['mosaic_scale_y']

                # Move to the reference location of the radio subject.
                ir_x += pix_offset[0]
                ir_y += pix_offset[1]

                # Convert the location into RA/DEC.
                (ir_x,), (ir_y,) = wcs.wcs_pix2world([ir_x], [ir_y], 1)

                ir_location = (ir_x, ir_y)
                ir_locations.append(ir_location)

            result[radio_signature] = ir_locations

    if n_invalid:
        logging.debug('%d invalid annotations for %s.', n_invalid,
                      subject['zooniverse_id'])

    return result
    def get_contours(self, fitsfile, Ak=None):
        """
        Given a continuum FITS file, return the contours enclosing 
        the source position at a given flux level.
        
        There are a couple complications:
        1) We seek a closed contour
        2) The contour should only extend over the region
            covered by the NIR image (K-band, in this case)
        
        This function could usefully be refactored/simplified
        """
        
        hdulist = fits.open(fitsfile)

        header = hdulist[0].header
        img = hdulist[0].data
        if not Ak:
            contour_level = self.contour_level #10 av in Jy?
            print("Using a contour level of: "+str(round(contour_level,3)))
            
        else:
            contour_level = self.calculate_continuum_level(
                                 cont_survey=self.cont_survey, 
                                 Ak=Ak)
            print("Using a contour level of: "+str(round(contour_level,3)))

        wcs = pywcs.WCS(header)
        yy,xx = np.indices(img.shape)

        img[img!=img] = 0
        
        #Set the borders of an image to be zero (blank) so that all contours close
        img[0,:] = 0.0
        img[-1,:] = 0.0
        img[:,0] = 0.0
        img[:,-1] = 0.0
        
        self.all_contours = []
        
        
        #for contour_level in contour_levels:
        wcs_paths = self.make_contour_at_level(wcs,img,yy,xx,contour_level)
        #    self.all_contours.append(np.array(wcs_paths))

        index = 0
        self.good_contour = False
        
        print(self.glon,self.glat)
        
        if len(wcs_paths) > 1:
            print("More than one contour")
            for i,wcs_path in enumerate(wcs_paths):
                path = Path(wcs_path)
                #print(path)
                if path.contains_point((self.glon,self.glat)):
                    index = i
                    self.good_contour = True
                    print("This was the contour containing the center")
            #index = 1
            #self.good_contour = True
            self.contours = wcs_paths[index]
            #self.contours[:,0] -= 0.02
            #self.contours[:,1] += 0.02
            #print(self.contours[:,1])
            
        else:
            self.good_contour = True
            self.contours =  wcs_paths[0]            
        
        #This selects a contour containing the center
        #Now we trim the contour to the boundaries of the UKIDSS image
        if self.good_contour:
            #And check to see which contour (if any) contains the center
            self.good_contour = False
            #Find the boundaries of the UKIDSS (K-band image) in Galactic coordinates
            h = fits.getheader(self.kim)
            xmin = 0
            xmax = h['NAXIS1']
            ymin = 0
            ymax = h['NAXIS2']
            wcs = pywcs.WCS(h)
            corners = wcs.wcs_pix2world([[xmin,ymin],[xmin,ymax],[xmax,ymax],[xmax,ymin]],0)
            gals = []
            for coord in corners:
                c = coordinates.ICRS(ra=coord[0],dec=coord[1],unit=[u.deg,u.deg])
                gal = c.transform_to(coordinates.Galactic)
                gals.append(gal)
            mycoords = []
            for gal in gals:
                l,b = gal.l.degree,gal.b.degree
                mycoords.append((l,b))
            p1 = shapely.geometry.Polygon(self.contours)
            p1 = p1.buffer(0)
            #print(p1.is_valid)
            p2 = shapely.geometry.Polygon(mycoords)
            p2.buffer(0)
            #print(p2.is_valid)
            ya = p1.intersection(p2)
            #print(ya)
            try:
                mycontours = []
                xx,yy = ya.exterior.coords.xy
                for ix,iy in zip(xx,yy):
                    mycontours.append((ix,iy))
                self.contours = np.array(mycontours)
                self.good_contour = True
            except AttributeError: #MultiPolygon
                mycontours = []
                for j,poly in enumerate(ya):
                    try:
                        #print(poly)
                        yoyo = np.asarray(poly.exterior.coords.xy)
                        #print(yoyo.shape)
                        #print(yoyo)
                        yoyo2 = yoyo.T
                        #print(poly.exterior.coords.xy)
                        #yya = poly.exterior.coords.xy[0]
                        #print(yya.shape)
                        #print(yoyo2)
                        path = Path(yoyo2)
                        if path.contains_point((self.glon,self.glat)):
                            self.good_contour = True
                            index = i
                            print("This was the contour containing the center")
                            xx,yy = poly.exterior.coords.xy
                            for ix,iy in zip(xx,yy):
                                mycontours.append((ix,iy))
                            self.contours = np.array(mycontours)
                    except IOError:
                        pass
                        
        self.contour_area = self.calc_contour_area(self.contours)
        
        if not self.good_contour:
            print("######## No good contour found ########")
            self.contours = None
            self.contour_area = 0
示例#29
0
def parse_classification(classification, subject, atlas_positions, wcs,
                         pix_offset):
    """Converts a raw RGZ classification into a classification dict.

    Scales all positions and flips y axis of clicks.

    classification: RGZ classification dict.
    subject: Associated RGZ subject dict.
    atlas_positions: [[RA, DEC]] NumPy array.
    wcs: World coordinate system of the ATLAS image.
    pix_offset: (x, y) pixel position of this radio subject on the ATLAS image.
    -> dict mapping radio signature to list of corresponding IR host pixel
        locations.
    """
    result = {}

    n_invalid = 0

    for annotation in classification['annotations']:
        if 'radio' not in annotation:
            # This is a metadata annotation and we can ignore it.
            continue

        if annotation['radio'] == 'No Contours':
            # I'm not sure how this occurs. I'm going to ignore it.
            continue

        try:
            radio_signature = make_radio_combination_signature(
                annotation['radio'], wcs, atlas_positions, subject, pix_offset)
        except CatalogueError:
            # Ignore invalid annotations.
            n_invalid += 1
            logging.debug('Ignoring invalid annotation for %s.',
                          subject['zooniverse_id'])
            continue

        ir_locations = []
        if annotation['ir'] != 'No Sources':
            for ir_click in annotation['ir']:
                ir_x = float(annotation['ir'][ir_click]['x'])
                ir_y = float(annotation['ir'][ir_click]['y'])

                # Rescale to a consistent size.
                ir_x *= config['surveys']['atlas']['click_to_fits_x']
                ir_y *= config['surveys']['atlas']['click_to_fits_y']

                # Ignore out-of-range data.
                if not 0 <= ir_x <= config['surveys']['atlas']['fits_width']:
                    n_invalid += 1
                    continue

                if not 0 <= ir_y <= config['surveys']['atlas']['fits_height']:
                    n_invalid += 1
                    continue

                # Flip the y axis to match other data conventions.
                ir_y = config['surveys']['atlas']['fits_height'] - ir_y

                # Rescale to match the mosaic WCS.
                ir_x *= config['surveys']['atlas']['mosaic_scale_x']
                ir_y *= config['surveys']['atlas']['mosaic_scale_y']

                # Move to the reference location of the radio subject.
                ir_x += pix_offset[0]
                ir_y += pix_offset[1]

                # Convert the location into RA/DEC.
                (ir_x, ), (ir_y, ) = wcs.wcs_pix2world([ir_x], [ir_y], 1)

                ir_location = (ir_x, ir_y)
                ir_locations.append(ir_location)

            result[radio_signature] = ir_locations

    if n_invalid:
        logging.debug('%d invalid annotations for %s.', n_invalid,
                      subject['zooniverse_id'])

    return result
https://qiita.com/nishimuraatsushi/items/f422c624027dcd34b820
@author: PC
"""

import numpy
import astropy.coordinates
import astropy.wcs
import astropy.io.fits
fits = astropy.io.fits.open(
    'http://www.astro.s.osakafu-u.ac.jp/~nishimura/Orion/data/Orion.CO1221.Osaka.beam204.mom0.fits.gz'
)
header = fits[0].header
data = fits[0].data

maxind = numpy.unravel_index(numpy.nanargmax(data), data.shape)
wcs = astropy.wcs.WCS(fits[0].header)
maxworld = wcs.wcs_pix2world([maxind[::-1]], 0)
# wcs_pix2world の要求するインデックスの軸の順は x, y(, z)
# fits[0].data の軸の順は、(z,) y, x
# この 2 つの向きが逆なので、maxind[::-1] で反転させている
galx, galy = maxworld[0]
# >>> (208.99999963578261, -19.383371004831144)

# 銀河座標で作成
coord = astropy.coordinates.SkyCoord(galx, galy, frame='galactic', unit='deg')
# >>> <SkyCoord (Galactic): (l, b) in deg
#         (208.99999964, -19.383371)>

# 星座を確認
coord.get_constellation()
示例#31
0
def plotMaps(configfile="analysis.conf", cmap=None):
    """
Given the directory where the results of an Enrico analysis are 
located (enrico_sed), this method plots the different count maps
(observed, model and residuals).

This is the fixed version of the script plotMaps.py from the Enrico
distribution. 

:param configdir: directory with "/" at the end that points to the place
where Enrico output files are located.
:returns: image file SOURCE_Maps.png in the source folder.
    """
    import astropy, astropy.io.fits, astropy.wcs
    import aplpy

    config, c = getconfig(configfile)

    def set_hgps_style(f):
        """Set HGPS style for a f = aplpy.FITSFigure"""
        f.ticks.set_xspacing(2)
        f.ticks.set_yspacing(2)
        f.ticks.set_linewidth(1.5)
        f.tick_labels.set_xformat('dd')
        f.tick_labels.set_yformat('dd')
        f.tick_labels.set_style('colons')
        f.axis_labels.set_xtext('Right Ascension (deg)')
        f.axis_labels.set_ytext('Declination (deg)')

    # Determine image center and width / height
    dpi = 2000
    header = astropy.io.fits.getheader(c['cmapfile'])
    wcs = astropy.wcs.WCS(header)
    header['NAXIS1'] / dpi
    header['NAXIS2'] / dpi
    lon, lat = header['NAXIS1'] / 2., header['NAXIS2'] / 2.
    x_center, y_center = wcs.wcs_pix2world(lon, lat, 0)
    radius = header['CDELT2'] * header['NAXIS2'] / 2.

    # Computing the sub-figure sizes is surprisingly hard
    figsize = (5, 15)
    figure = pylab.figure(figsize=figsize)
    axis_ratio = figsize[0] / float(figsize[1])
    edge_margin_x = 0.12
    edge_margin_y = edge_margin_x * axis_ratio
    edge_margin_x_up = 0.01
    edge_margin_y_up = edge_margin_x_up * axis_ratio
    inner_margin_x = 0.1
    inner_margin_y = inner_margin_x * axis_ratio
    size_x = (1 - edge_margin_x - edge_margin_x_up)
    size_y = (1 - edge_margin_y - edge_margin_y_up - 2 * inner_margin_y) / 3

    for i, image in enumerate(c['images']):
        subplot = [
            edge_margin_x, edge_margin_y + i * (size_y + inner_margin_y),
            size_x, size_y
        ]
        f = aplpy.FITSFigure(image, figure=figure, subplot=subplot)
        f.recenter(x_center, y_center, 0.95 * radius)
        set_hgps_style(f)
        f.show_colorscale(stretch='power', exponent=1, cmap=cmap)
        #f.show_colorbar()
        if i == 0:
            f.show_markers(x_center, y_center, edgecolor='Black', s=400.)
        if i == 1:
            f.show_markers(x_center, y_center, edgecolor='White', s=400.)
            f.show_regions(c['folder'] + '/Roi_model.reg')
        if i == 2:
            f.show_markers(x_center, y_center, edgecolor='Black', s=400.)

    plotfile = c['folder'] + "/" + config['target']['name'] + "_Maps.png"
    print('Writing {}'.format(plotfile))
    figure.savefig(plotfile)
示例#32
0
    def make_contour_at_level(self, wcs, img, yy, xx, level):
        C = _cntr.Cntr(xx, yy, img)
        paths = [p for p in C.trace(level) if p.ndim == 2]

        wcs_paths = [wcs.wcs_pix2world(p, 0) for p in paths]
        return (wcs_paths)
示例#33
0
    def _extract_star_sequence(self, imfile, survey='ps1', minmag=14.5, maxmag=20, plot=True, debug=False):
        '''
        Given a fits image: imfile and a the name of the band which we want to extract the sources from,
        it saves the extracted sources into  '/tmp/sdss_cat_det.txt' file.
        If the band does not match the bands in the survey, a change is performed to adapt to the new band.
        
        If plotting activated, plots the USNOB1 field of stars on top of the star field image.
        Red circles are stars identified from the catalogue in the correct magnitude range.
        Yellow circles are stars that are isolated.
        
        Parameters:
        -----------
        imfile: str
                Name of the file to be calibrated.
        survey: str
                Name of the survey to be used for zeropoint calibration. By default is PS1.
        minmag: int. Default 14.5 mag
                The brightest mangitude that will be retrieved from the catalogues.
        maxmag: int. Default 20.0 mag
                The faintest mangitude that will be retrieved from the catalogues.
        plot: boolean
                Boolean for plotting the zeropoint calibation plots in the plot directory.
        debug: boolean. Default False.
                Boolean to show debug additional plots in the plot directory.
        '''
        
        f = fits.open(imfile)
            
        survey = survey.upper()
            
        
        #Extract the filter
        fheader = f[self.ext].header['FILTER']
        band = self.filter_dic.get(fheader, fheader)
    
        #Extract the WCS
        wcs = astropy.wcs.WCS(f[self.ext].header)
    
        #Extract the pixel scale
        pix2ang = f[self.ext].header[self.pixscale_keyword]
            
        #Extract the data
        img = f[self.ext].data
        #Assume that negative values shall be corrected
        img[img<0] = 0
        
        
        
        #Compute the ra, dec of the centre of the filed and the edges
        ra, dec = wcs.wcs_pix2world(np.array([img.shape[0]/2, img.shape[1]/2], ndmin=2), 1)[0]
        ra0, dec0 = wcs.wcs_pix2world(np.array([img.shape[0], img.shape[1]], ndmin=2), 1)[0]
    
        #Calculate the size of the field --> search radius  . As maximum, it needs to be 0.25 deg.
        sr = 2.1*np.abs(dec-dec0)
        sr = np.minimum(sr, 0.5)
        self.logger.info("Field center: (%.4f %.4f) and FoV: %.4f  [arcmin] "%( ra, dec, sr*60))
        
        #Creates the Query class
        qc = QueryCatalogue.QueryCatalogue(ra, dec, sr/1.8, minmag, maxmag, self.logger)

        
        cat_file = os.path.join(self._tmppath, 'query_result_%s_%.6f_%.6f_%.5f_%.2f_%.2f.txt'%(survey.split("/")[-1], ra, dec, sr, minmag, maxmag) )   
        detected_stars_file = os.path.join(self._tmppath, 'detected_result_%s_%.6f_%.6f_%.5f_%.2f_%.2f.txt'%(survey.split("/")[-1], ra, dec, sr, minmag, maxmag) )   
            
        #Check if the query already exists in our tmp directory,
        #so we do not need to query it again.
        if (os.path.isfile(cat_file)):
            self.logger.info("File %s already exists. Loading it."%cat_file)
            catalog = Table.read(cat_file, format="ascii")
        #If that is not the case, then we check if the catalogue is in one of the lists provided by VO portal
        else:
            self.logger.info("File %s does not exist. Querying it."%cat_file)            
            if (np.any( np.array(['GSC23', 'GSC11', 'GSC12', 'USNOB', 'SDSS', 'FIRST', '2MASS', 'IRAS', 'GALEX', 'GAIA', 'TGAS', 'WISE', \
                   'CAOM_OBSCORE', 'CAOM_OBSPOINTING', 'PS1V3OBJECTS', 'PS1V3DETECTIONS'])==survey)):
                catalog = qc.query_catalogue(catalogue=survey, filtered=True)
            #But it can be a SkyMapper as well (in the south).
            elif (survey == 'SKYMAPPER'):
                catalog = qc.query_sky_mapper(filtered=True)
            #More services can be added here, but at the moment, if the survey is none of the
            # above, the we paunch an error.
            else:
                self.logger.warn("Survey %s not recognized. Trying to query Vizier for that."%survey)

                try:
                    catalog = qc.query_vizier(catalog=survey)

                except:
                    self.logger.error("Unknown survey %s"%survey)
                    return None
    
        if (np.ndim(catalog)==0 or catalog is None):
            return False
        else:
            catalog = Table(data=catalog)
            #if ( np.all(catalog[band].mask )):
            #    self.logger.error( "All magntiudes for filter %s are masked!"% band)
            #    return False
            #else:
            #    catalog = catalog[~catalog[band].mask]
    
        try:
            #Rename the columns, so that the filters match our standard.
            for n in catalog.colnames:
                if n in self.filter_dic.keys():
                    catalog.rename_column(n, self.filter_dic[n])
        except IOError:
            self.logger.error( "Problems with catalogue IO %s"% band)
            return False
        except ValueError:
            self.logger.error( "Problems with the catalogue for the image")
            return False
    
        # Determine the X and Y of all the stars in the query.
        catcoords = astropy.coordinates.SkyCoord( catalog['ra'], catalog['dec'], unit=u.deg)
    
        self.logger.info("Catalogue has %d entries"%len(catcoords))
        
        #Convert ra, dec position of all stars to pixels.
        pixcoord = wcs.all_world2pix( np.array([catalog['ra'],  catalog['dec']]).T, 1)
        x = pixcoord.T[0]
        y = pixcoord.T[1]
        
        #Select only the stars within the image (and within an offset of 15 arcsec (in pixels) from the border.)
        off = math.ceil(15/pix2ang)
        mask1 = (x>off) * (x<img.shape[1]-off)*(y>off) * (y<img.shape[0]-off)
           
        #Select only stars isolated in a radius of ~10 arcsec. Cross match against itself and select the second closest.
        indexes, separations, distances = catcoords.match_to_catalog_sky(catcoords, nthneighbor=2)
        mask2 = (separations >  10 * u.arcsec)
     
        #Select the right magnitude range
        mask3 = (catalog[band]>minmag)*(catalog[band]<maxmag)
    
        #Combine all masks
        mask = mask1 * mask2 * mask3
        
        if (not np.any(mask)):
            self.logger.warn("No good stars left with current conditions.")
            return False
        
        #Otherwise, it means there are good stars left
        catalog = catalog[mask]
        
        self.logger.info("Catalog length after masking: %d"%len(catalog))
    
        self.logger.debug("Left %d stars."%(len(catalog)))
    
        z = np.zeros(len(catalog), dtype=[('xpos', np.float), ('ypos',np.float)])
        
        z['xpos'] = x[mask]
        z['ypos'] = y[mask]
    
        #Iteratively create a header to store catalogue data for selected stars
        #only the relevant fields.
        catalog_det = Table(data=z, names=['xpos', 'ypos'])
        
        for n  in catalog.colnames:
            if ((n in ["objid", "ra", "dec", "u", "g", "r", "i", "z", "y", "du", "dg", "dr", "di", "dz", "dy"]) or
                (n in ['id', 'ra', 'dec', 'U', 'B', 'V', 'R', 'I', 'dU', 'dB', 'dV', 'dR', 'dI'] )):
                    catalog_det.add_column(catalog[n])
    
    
        catalog_det.write(cat_file, format="ascii.csv", overwrite=True)
        self.logger.info( "Saved catalogue stars to %s"%cat_file )
    
        #Find FWHM for this image            
        out = self._find_fwhm(imfile, catalog_det['xpos'], catalog_det['ypos'], plot=debug)
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            mask_valid_fwhm = ( ~np.isnan(out['fwhm']) *  ~np.isnan(out['e']) * out['detected'] * (out['e']>0.6) * (out['fwhm'] < 10))            
    
        self.logger.info("Left %d stars with valid fwhm."%np.count_nonzero(mask_valid_fwhm))
        
        if (np.count_nonzero(mask_valid_fwhm) < 3):
            self.logger.error( "ERROR with FWHM!! Too few points for a valid estimation. %d"% np.count_nonzero(mask_valid_fwhm)+ ") points")
            return False
    
        #Add the FWHM of each detection to the detected stars list
        outd = out[mask_valid_fwhm]
        catalog_det = catalog_det[mask_valid_fwhm]
        fwhm = Column(data=outd['fwhm']*pix2ang, name='fwhm')
        catalog_det.add_column(fwhm)

        #Write it to the header as well        
        fitsutils.update_par(imfile, "FWHM", np.median(outd['fwhm']*pix2ang), ext=self.ext)

        
        catalog_det.write(detected_stars_file, format="ascii", overwrite=True)
        
        self.logger.info( 'Average FWHM %.1f pixels, %.3f arcsec'%(np.median(outd['fwhm']),  np.median(outd['fwhm'])*pix2ang))
        
            
        self.logger.info( "Found %d stars in %s. "%(len(catalog), survey)+ \
            "%d of them are isolated."%np.count_nonzero(mask2)+\
            "%d of them within the FoV. "%np.count_nonzero(mask) +\
            "%d of them with detected stars."%np.count_nonzero(mask_valid_fwhm)) 
        
        
        if (plot):
            #Plot results
            img = img - np.nanmin(img)
            zmin = np.percentile(img, 5)
            zmax = np.percentile(img, 95)
            plt.figure(figsize=(12,12))
                
            im = plt.imshow(img, aspect="equal", origin="lower", cmap=matplotlib.cm.gray_r, vmin=zmin, vmax=zmax)
    
    
            selected_x = catalog_det['xpos']
            selected_y = catalog_det['ypos']
            if (len(selected_x) >0):
                plt.scatter(selected_x, selected_y, marker="o", s=400, \
                    edgecolor="blue", facecolor="none", label="detected")
            
            plt.legend(loc="best", frameon=False, framealpha=0.9)
            plt.title("Selected stars for filter %s"%band)
            extension = os.path.basename(imfile).split(".")[-1]
            figname = os.path.join( self._plotpath, os.path.basename(imfile).replace(extension, 'seqstars.png'))
            plt.savefig( figname)
            self.logger.info( "Saved stars to %s"%figname)        
            plt.clf()
    
        return detected_stars_file
示例#34
0
# -*- coding: utf-8 -*-
"""
Created on Thu May 28 22:44:39 2020

@author: PC
"""

import astropy.wcs
import astropy.io.fits

fits = astropy.io.fits.open(
    'http://www.astro.s.osakafu-u.ac.jp/~nishimura/Orion/data/Orion.CO1221.Osaka.beam204.mom0.fits.gz'
)

wcs = astropy.wcs.WCS(fits[0].header)
print(wcs)

# 画像座標系[pix]→WCS[geg]変換
print(wcs.wcs_pix2world([[0, 0]], 0))
print(wcs.wcs_pix2world([[100, 50]], 0))
print(wcs.wcs_pix2world([[200, 100]], 0))
print(wcs.wcs_pix2world([[300, 150]], 0))
print(wcs.wcs_pix2world([[400, 200]], 0))
print(wcs.wcs_pix2world([[500, 250]], 0))
print(wcs.wcs_pix2world([[600, 300]], 0))
print(wcs.wcs_pix2world([[700, 350]], 0))
示例#35
0
文件: fermi.py 项目: rsnemmen/nemmen
def plotMaps(configfile="analysis.conf",cmap=None):
    """
Given the directory where the results of an Enrico analysis are 
located (enrico_sed), this method plots the different count maps
(observed, model and residuals).

This is the fixed version of the script plotMaps.py from the Enrico
distribution. 

:param configdir: directory with "/" at the end that points to the place
where Enrico output files are located.
:returns: image file SOURCE_Maps.png in the source folder.
    """
    import astropy, astropy.io.fits, astropy.wcs
    import aplpy

    config,c=getconfig(configfile)

    def set_hgps_style(f):
        """Set HGPS style for a f = aplpy.FITSFigure"""
        f.ticks.set_xspacing(2)
        f.ticks.set_yspacing(2)
        f.ticks.set_linewidth(1.5)
        f.tick_labels.set_xformat('dd')
        f.tick_labels.set_yformat('dd')
        f.tick_labels.set_style('colons')
        f.axis_labels.set_xtext('Right Ascension (deg)')
        f.axis_labels.set_ytext('Declination (deg)')

    # Determine image center and width / height
    dpi = 2000
    header = astropy.io.fits.getheader(c['cmapfile'])
    wcs = astropy.wcs.WCS(header)
    header['NAXIS1'] / dpi
    header['NAXIS2'] / dpi
    lon, lat = header['NAXIS1'] / 2., header['NAXIS2'] / 2.
    x_center, y_center = wcs.wcs_pix2world(lon, lat, 0)
    radius = header['CDELT2'] * header['NAXIS2'] / 2.

    # Computing the sub-figure sizes is surprisingly hard
    figsize=(5, 15)
    figure = pylab.figure(figsize=figsize)
    axis_ratio = figsize[0] / float(figsize[1])
    edge_margin_x = 0.12
    edge_margin_y = edge_margin_x * axis_ratio
    edge_margin_x_up = 0.01
    edge_margin_y_up = edge_margin_x_up * axis_ratio
    inner_margin_x = 0.1
    inner_margin_y = inner_margin_x * axis_ratio
    size_x = (1 - edge_margin_x - edge_margin_x_up)
    size_y = (1 - edge_margin_y - edge_margin_y_up - 2 * inner_margin_y) / 3

    for i, image in enumerate(c['images']):
        subplot = [edge_margin_x, edge_margin_y + i * (size_y + inner_margin_y), size_x, size_y]
        f = aplpy.FITSFigure(image, figure=figure, subplot=subplot)
        f.recenter(x_center, y_center, 0.95 * radius)
        set_hgps_style(f)
        f.show_colorscale(stretch='power', exponent=1, cmap=cmap)
        #f.show_colorbar()
        if i==0: f.show_markers(x_center, y_center, edgecolor='Black', s=400.)
        if i==1: 
            f.show_markers(x_center, y_center, edgecolor='White', s=400.)
            f.show_regions(c['folder']+'/Roi_model.reg')
        if i==2: f.show_markers(x_center, y_center, edgecolor='Black', s=400.)

    plotfile =c['folder']+"/"+config['target']['name']+"_Maps.png"
    print('Writing {}'.format(plotfile))
    figure.savefig(plotfile)
示例#36
0
def problem_2(results, **kwargs):
    verbose = kwargs.get('verbose', False)


    # Determine pixel area in arcsec2
    header = results['header']
    wcs = astropy.wcs.WCS(header)
    x, y = np.array([header['crpix1'], header['crpix2']])
    ra, dec = wcs.wcs_pix2world([x, x+1, x], [y, y, y+1], 1)
    points = astropy.coordinates.SkyCoord(ra, dec, 'icrs', unit=wcs.wcs.cunit)
    dxy = astropy.coordinates.Angle([points[0].separation(points[1]),
                                     points[0].separation(points[2])])
    pixel_scales = dxy.arcsec
    pixel_area = pixel_scales[0] * pixel_scales[1]
    results['pixel_scales'], results['pixel_area'] = pixel_scales, pixel_area


    # Photometry
    radius_mult = 1.5  # Size of inner radius wrt aperture (factor)
    dr = 50.0  # Size of outer radius wrt inner (offset in pixels)
    aperture_list = results['apertures_#1']
    image = results['image']
    annulus_list = []
    for aperture in aperture_list:
        xy0 = aperture.xy0
        r1 = radius_mult * aperture.r
        r2 = r1 + dr
        annulus = galaxyphot.CircularAnnulus(xy0, r1, r2, label=aperture.label)
        annulus_list.append(annulus)

    apphot = galaxyphot.apphot(image, aperture_list)
    anphot = galaxyphot.apphot(image, annulus_list)


    # Intensities, counts/pixel
    intensity_tot = apphot['mean']  # Same as total/area
    intensity_bg = anphot['median']
    intensity = intensity_tot - intensity_bg
    err = np.sqrt(intensity_tot * apphot['area'] +
                  intensity_bg * anphot['area']) / apphot['area']


    # Intensities, counts/arcsec2
    intensity /= pixel_area
    err /= pixel_area
    results['intensity_bgannulus'] = intensity_bg / pixel_area

    if verbose:
        print (
            'Photometry:\n'
            '\n'
            '======= ============= ========\n'
            'galaxy  intensity     err\n'
            '        (cnt/arcsec2)\n'
            '======= ============= ========'
            )
        for i, label in enumerate(apphot['label']):
            vals = (label, intensity[i], err[i])
            print '{0:7s} {1:13.2e} {2:8.2e}'.format(*vals)
        print '======= ============= ========\n\n'

    """
    Photometry:

    ======= ============= ========
    galaxy  intensity     err
            (cnt/arcsec2)
    ======= ============= ========
    NGC4875      1.73e+03 7.69e+00
    NGC4869      5.64e+03 1.08e+01
    GMP4277      2.69e+03 5.59e+00
    GMP4350      2.19e+03 5.54e+00
    NGC4860      4.84e+03 7.79e+00
    NGC4881      1.66e+03 2.37e+00
    NGC4921      7.39e+02 4.91e-01
    ======= ============= ========

    """

    return results
示例#37
0
                                                  err=error[freq],
                                                  returnmp=True, rotate=True,
                                                  vheight=True, circle=False,
                                                  returnfitimage=True)
            except:
                mpfits[freq][name] = ()
                gpars[freq][name] = np.array([np.nan]*7)
                gparerrs[freq][name] = np.array([np.nan]*7)
                continue

            mpfits[freq][name] = mp
            gpars[freq][name] = mp.params
            gparerrs[freq][name] = mp.perror
            gfits[freq][name] = fitimg

            wcsX,wcsY = wcs.wcs_pix2world(mp.params[2]+int(xc-3*rp), mp.params[3]+int(yc-3*rp), 0)
            center_coord = coordinates.SkyCoord(wcsX*u.deg, wcsY*u.deg,
                                                frame=wcs.wcs.radesys.lower())
            gpars[freq][name][2] = center_coord.transform_to('fk5').ra.deg
            gpars[freq][name][3] = center_coord.transform_to('fk5').dec.deg
            gpars[freq][name][4] *= pixscale.to(u.deg).value
            gpars[freq][name][5] *= pixscale.to(u.deg).value

            gparerrs[freq][name][2] *= pixscale.to(u.deg).value
            gparerrs[freq][name][3] *= pixscale.to(u.deg).value
            gparerrs[freq][name][4] *= pixscale.to(u.deg).value
            gparerrs[freq][name][5] *= pixscale.to(u.deg).value

        else:
            peaks[freq][name] = np.nan
            valleys[freq][name] = np.nan
示例#38
0
    def get_contours(self, fitsfile, Ak=None):
        """
        Given a continuum FITS file, return the contours enclosing 
        the source position at a given flux level.
        
        There are a couple complications:
        1) We seek a closed contour
        2) The contour should only extend over the region
            covered by the NIR image (K-band, in this case)
        
        This function could usefully be refactored/simplified
        """

        hdulist = fits.open(fitsfile)

        header = hdulist[0].header
        img = hdulist[0].data
        if not Ak:
            contour_level = self.contour_level  #10 av in Jy?
            print("Using a contour level of: " + str(round(contour_level, 3)))

        else:
            contour_level = self.calculate_continuum_level(
                cont_survey=self.cont_survey, Ak=Ak)
            print("Using a contour level of: " + str(round(contour_level, 3)))

        wcs = pywcs.WCS(header)
        yy, xx = np.indices(img.shape)

        img[img != img] = 0

        #Set the borders of an image to be zero (blank) so that all contours close
        img[0, :] = 0.0
        img[-1, :] = 0.0
        img[:, 0] = 0.0
        img[:, -1] = 0.0

        self.all_contours = []

        #for contour_level in contour_levels:
        wcs_paths = self.make_contour_at_level(wcs, img, yy, xx, contour_level)
        #    self.all_contours.append(np.array(wcs_paths))

        index = 0
        self.good_contour = False

        print(self.glon, self.glat)

        if len(wcs_paths) > 1:
            print("More than one contour")
            for i, wcs_path in enumerate(wcs_paths):
                path = Path(wcs_path)
                #print(path)
                if path.contains_point((self.glon, self.glat)):
                    index = i
                    self.good_contour = True
                    print("This was the contour containing the center")
            #index = 1
            #self.good_contour = True
            self.contours = wcs_paths[index]
            #self.contours[:,0] -= 0.02
            #self.contours[:,1] += 0.02
            #print(self.contours[:,1])

        else:
            self.good_contour = True
            self.contours = wcs_paths[0]

        #This selects a contour containing the center
        #Now we trim the contour to the boundaries of the UKIDSS image
        if self.good_contour:
            #And check to see which contour (if any) contains the center
            self.good_contour = False
            #Find the boundaries of the UKIDSS (K-band image) in Galactic coordinates
            h = fits.getheader(self.kim)
            xmin = 0
            xmax = h['NAXIS1']
            ymin = 0
            ymax = h['NAXIS2']
            wcs = pywcs.WCS(h)
            corners = wcs.wcs_pix2world(
                [[xmin, ymin], [xmin, ymax], [xmax, ymax], [xmax, ymin]], 0)
            gals = []
            for coord in corners:
                c = coordinates.ICRS(ra=coord[0],
                                     dec=coord[1],
                                     unit=[u.deg, u.deg])
                gal = c.transform_to(coordinates.Galactic)
                gals.append(gal)
            mycoords = []
            for gal in gals:
                l, b = gal.l.degree, gal.b.degree
                mycoords.append((l, b))
            p1 = shapely.geometry.Polygon(self.contours)
            p1 = p1.buffer(0)
            #print(p1.is_valid)
            p2 = shapely.geometry.Polygon(mycoords)
            p2.buffer(0)
            #print(p2.is_valid)
            ya = p1.intersection(p2)
            #print(ya)
            try:
                mycontours = []
                xx, yy = ya.exterior.coords.xy
                for ix, iy in zip(xx, yy):
                    mycontours.append((ix, iy))
                self.contours = np.array(mycontours)
                self.good_contour = True
            except AttributeError:  #MultiPolygon
                mycontours = []
                for j, poly in enumerate(ya):
                    try:
                        #print(poly)
                        yoyo = np.asarray(poly.exterior.coords.xy)
                        #print(yoyo.shape)
                        #print(yoyo)
                        yoyo2 = yoyo.T
                        #print(poly.exterior.coords.xy)
                        #yya = poly.exterior.coords.xy[0]
                        #print(yya.shape)
                        #print(yoyo2)
                        path = Path(yoyo2)
                        if path.contains_point((self.glon, self.glat)):
                            self.good_contour = True
                            index = i
                            print("This was the contour containing the center")
                            xx, yy = poly.exterior.coords.xy
                            for ix, iy in zip(xx, yy):
                                mycontours.append((ix, iy))
                            self.contours = np.array(mycontours)
                    except IOError:
                        pass

        self.contour_area = self.calc_contour_area(self.contours)

        if not self.good_contour:
            print("######## No good contour found ########")
            self.contours = None
            self.contour_area = 0