Esempio n. 1
0
def img_data(file_name):
    """Load common image files into a Glue data object"""
    result = Data()

    data = img_loader(file_name)
    data = np.flipud(data)
    shp = data.shape

    comps = []
    labels = []

    # split 3 color images into each color plane
    if len(shp) == 3 and shp[2] in [3, 4]:
        comps.extend([data[:, :, 0], data[:, :, 1], data[:, :, 2]])
        labels.extend(['red', 'green', 'blue'])
        if shp[2] == 4:
            comps.append(data[:, :, 3])
            labels.append('alpha')
    else:
        comps = [data]
        labels = ['PRIMARY']

    # look for AVM coordinate metadata
    try:
        from pyavm import AVM
        avm = AVM(str(file_name))  # avoid unicode
        wcs = avm.to_wcs()
    except:
        pass
    else:
        result.coords = coordinates_from_wcs(wcs)

    for c, l in zip(comps, labels):
        result.add_component(c, l)

    return result
Esempio n. 2
0
def make_rgb_image(data, output, indices=(0, 1, 2), \
                   vmin_r=None, vmax_r=None, pmin_r=0.25, pmax_r=99.75, \
                   stretch_r='linear', vmid_r=None, exponent_r=2, \
                   vmin_g=None, vmax_g=None, pmin_g=0.25, pmax_g=99.75, \
                   stretch_g='linear', vmid_g=None, exponent_g=2, \
                   vmin_b=None, vmax_b=None, pmin_b=0.25, pmax_b=99.75, \
                   stretch_b='linear', vmid_b=None, exponent_b=2, \
                   embed_avm_tags=False):
    '''
    Make an RGB image from a FITS RGB cube or from three FITS files

    Required arguments:

        *data*: [ string | tuple | list ]
            If a string, this is the filename of an RGB FITS cube. If a tuple
            or list, this should give the filename of three files to use for
            the red, green, and blue channel.

        *output*: [ string ]
            The output filename. The image type (e.g. PNG, JPEG, TIFF, ...)
            will be determined from the extension. Any image type supported by
            the Python Imaging Library can be used.

    Optional keyword arguments:

        *indices*: [ tuple ]
            If data is the filename of a FITS cube, these indices are the
            positions in the third dimension to use for red, green, and
            blue respectively. The default is to use the first three
            indices.

        *vmin_r*: [ None | float ]

        *vmin_g*: [ None | float ]

        *vmin_b*: [ None | float ]

            Minimum pixel value to use for the red, green, and blue channels.
            If set to None for a given channel, the minimum pixel value for
            that channel is determined using the corresponding pmin_x argument
            (default).

        *vmax_r*: [ None | float ]

        *vmax_g*: [ None | float ]

        *vmax_b*: [ None | float ]

            Maximum pixel value to use for the red, green, and blue channels.
            If set to None for a given channel, the maximum pixel value for
            that channel is determined using the corresponding pmax_x argument
            (default).

        *pmin_r*: [ float ]

        *pmin_g*: [ float ]

        *pmin_b*: [ float ]

            Percentile values used to determine for a given channel the
            minimum pixel value to use for that channel if the corresponding
            vmin_x is set to None. The default is 0.25% for all channels.

        *pmax_r*: [ float ]

        *pmax_g*: [ float ]

        *pmax_b*: [ float ]

            Percentile values used to determine for a given channel the
            maximum pixel value to use for that channel if the corresponding
            vmax_x is set to None. The default is 99.75% for all channels.

        *stretch_r*: [ 'linear' | 'log' | 'sqrt' | 'arcsinh' | 'power' ]

        *stretch_g*: [ 'linear' | 'log' | 'sqrt' | 'arcsinh' | 'power' ]

        *stretch_b*: [ 'linear' | 'log' | 'sqrt' | 'arcsinh' | 'power' ]

            The stretch function to use for the different channels.

        *vmid_r*: [ None | float ]

        *vmid_g*: [ None | float ]

        *vmid_b*: [ None | float ]

            Baseline values used for the log and arcsinh stretches. If
            set to None, this is set to zero for log stretches and to
            vmin - (vmax - vmin) / 30. for arcsinh stretches

        *exponent_r*: [ float ]

        *exponent_g*: [ float ]

        *exponent_b*: [ float ]

            If stretch_x is set to 'power', this is the exponent to use.
        '''

    if not installed_pil:
        raise Exception(
            "The Python Imaging Library (PIL) is not installed but is required for this function"
        )

    if isinstance(data, basestring):

        image = pyfits.getdata(data)
        image_r = image[indices[0], :, :]
        image_g = image[indices[1], :, :]
        image_b = image[indices[2], :, :]

        # Read in header
        header = pyfits.getheader(data)

        # Remove information about third dimension
        header['NAXIS'] = 2
        for key in [
                'NAXIS', 'CTYPE', 'CRPIX', 'CRVAL', 'CUNIT', 'CDELT', 'CROTA'
        ]:
            for coord in range(3, 6):
                name = key + str(coord)
                if name in header:
                    header.__delitem__(name)

    elif (type(data) == list or type(data) == tuple) and len(data) == 3:

        filename_r, filename_g, filename_b = data
        image_r = pyfits.getdata(filename_r)
        image_g = pyfits.getdata(filename_g)
        image_b = pyfits.getdata(filename_b)

        # Read in header
        header = pyfits.getheader(filename_r)

    else:
        raise Exception(
            "data should either be the filename of a FITS cube or a list/tuple of three images"
        )

    logger.info("Red:")
    image_r = Image.fromarray(_data_stretch(image_r, \
                                            vmin=vmin_r, vmax=vmax_r, \
                                            pmin=pmin_r, pmax=pmax_r, \
                                            stretch=stretch_r, \
                                            vmid=vmid_r, \
                                            exponent=exponent_r))

    logger.info("\nGreen:")
    image_g = Image.fromarray(_data_stretch(image_g, \
                                            vmin=vmin_g, vmax=vmax_g, \
                                            pmin=pmin_g, pmax=pmax_g, \
                                            stretch=stretch_g, \
                                            vmid=vmid_g, \
                                            exponent=exponent_g))

    logger.info("\nBlue:")
    image_b = Image.fromarray(_data_stretch(image_b, \
                                            vmin=vmin_b, vmax=vmax_b, \
                                            pmin=pmin_b, pmax=pmax_b, \
                                            stretch=stretch_b, \
                                            vmid=vmid_b, \
                                            exponent=exponent_b))

    img = Image.merge("RGB", (image_r, image_g, image_b))
    img = img.transpose(Image.FLIP_TOP_BOTTOM)

    img.save(output)

    if embed_avm_tags:
        if not avm_installed:
            raise Exception(
                "PyAVM needs to be installed in order to be able to embed AVM tags into the RGB image"
            )
        else:
            avm = AVM(header)
            avm.embed(output, output)

    return
Esempio n. 3
0
def overlay(
        image,
        bdf,  # basic inputs
        l1=0.0,
        l2=1.0,  # levels
        shift=[0.0, 0.0],  # target shift from reference value 
        radec=[0.0, 0.0],  # target coords, if not ref value (d/s)
        nod=[0, 0],  # shift from default ctr (in asec)
        showGrid=False,  # show coordinate grid?
        stretch='linear',  # 'log', 'linear', etc.     
        invert=False,  # invert a grayscale image?
        hdu=0,  # HDU, if not 0. 
        gray=True,
        readAVM=False):  # plot colour, AVM read
    """ 
    Overlay a SAMI bundle onto a fits image 

    Adapted to astropy input. 

    Inputs 
    -------
      image: fits image used for overlay; 
      bdf:   a 'bundle definition file', generate with the 'bundle_definition' 
             function in this module. 
    """

    import aplpy
    import astropy.wcs as pywcs

    # is the input image a fits file?
    isfits = (image[len(image) - 5:] == '.fits') or (image[len(image) - 4:]
                                                     == '.fit')

    # Use APLPy to read in the FITS file.
    fig = aplpy.FITSFigure(image, north=True, hdu=hdu)
    if (gray == True):
        fig.show_grayscale(vmin=l1, vmax=l2, stretch=stretch, invert=invert)
    else:
        fig.show_rgb()
    if showGrid == True: fig.show_grid()

    # Read the AVM of a jpg or tiff image:
    if readAVM == True:
        from pyavm import AVM
        avm = AVM(image)

    # read BDF
    tab = tab.read(bdf)

    # Get field centre coordinates -- quite messy, clean up.
    ctr = [0., 0.]  # just initiate the field centre (list ok)

    # Input type: image loaded with Astro Visualisation Metadata --
    if (np.mean(radec) == 0.0) and (readAVM != True) and (isfits != True):
        ctr = [0.0, 0.0]  # if cannot find AVM, ctr=0,0
        print("Warning: did not find a valid field centre definition")
    if (np.mean(radec) != 0.0) and (isfits != True):  # respec' user input
        radec = np.array(radec)
        if radec.size > 2:  # if input in sex, not dec
            from SAMI_sdss import ten
            ctr[0] = ten(radec[0], radec[1], radec[2], RA=True)
            ctr[1] = ten(radec[3], radec[4], radec[5])
        else:
            ctr = radec

    if readAVM == True and (np.mean(radec) == 0.0):
        ctr = avm.Spatial.ReferenceValue  # read AVM field centre

    # Input type: fits file --
    if isfits:
        data = pf.open(image)
        wcs = pywcs.WCS(data[0].header)
        ctr = wcs.wcs.crval

    # apply 'nod' (fine positioning shift)
    if (nod[0] != 0) and (nod[1] != 0):
        nod[0] = nod[0] * 15
        nod = np.array(nod) / 3600.
        ctr = np.array(ctr) - nod
        from SAMI_sdss import sixty
        stringer1 = 'Recentering to: ' + str(ctr[0]) + ' ' + str(ctr[1])
        stringer2 = '            ie: ' + str(sixty(ctr[0],RA=True)) + \
            ' ' + str(sixty(ctr[1]))
        print('')
        print(stringer1)
        print(stringer2)

    # shift SAMI bundle into place
    ra = tab['RA'] / np.cos(np.radians(ctr[1])) + ctr[0]
    dec = tab['DEC'] + ctr[1]

    # SAMI bundle (individual fibres)
    fig.show_circles(ra,
                     dec,
                     0.8 / 3600.,
                     edgecolor='cyan',
                     facecolor='cyan',
                     alpha=0.5)

    # Exclusion radius
    fig.show_circles(ctr[0],
                     ctr[1],
                     165. / 3600.,
                     edgecolor='green',
                     facecolor='none',
                     linewidth=3.)