Пример #1
0
    def _create_apertures(self, image, image_stars_coordinates, data_shape):
        self.info('Creating apertures started')
        apertures = []
        sigma_values_table = []
        sigma_value = namedtuple('sigma_value', ['mean', 'median', 'std'])

        masks = [
            self._create_mask(star_coo, data_shape)
            for star_coo in image_stars_coordinates
        ]

        for i, mask in enumerate(masks):
            mean, median, std = sigma_clipped_stats(
                image.data,
                mask=mask,
                sigma=self.config_section.get('sigma_clipped_sigma'),
                iters=self.config_section.get('sigma_clipped_iters'))

            self.info('Sigma clipped stats: mean={}, median={}, std={}'.format(
                mean, median, std))

            if (self.config_section.get('calculate_center')
                    or self.config_section.get('calculate_aperture')):

                star_properties = self._find_star_properties(
                    np.copy(image.data), median, mask,
                    image_stars_coordinates[i])

            if self.config_section.get('calculate_center'):
                position = (star_properties['xcentroid'].value,
                            star_properties['ycentroid'].value)
            else:
                position = image_stars_coordinates[i]
                self.info(
                    'Calculate center is off, original coordinates have been used'
                )
                self.info('Coordinates={}'.format(position))

            if self.config_section.get('calculate_aperture'):
                self.info('Calculating apertures has been started')
                a = star_properties[
                    'semimajor_axis_sigma'] * self.config_section.get(
                        'r_aperture_multi')
                b = star_properties[
                    'semiminor_axis_sigma'] * self.config_section.get(
                        'r_aperture_multi')
                theta = star_properties['orientation']
                self.info(
                    'Found aperture parameters: a={}, b={}, theta={}'.format(
                        a, b, theta))
                aperture = EllipticalAperture(position,
                                              a=a.value,
                                              b=b.value,
                                              theta=theta.value)
                annulus = EllipticalAnnulus(
                    position,
                    a_in=a.value + self.config_section.get('r_annulus_in'),
                    a_out=a.value + self.config_section.get('r_annulus_out'),
                    b_out=b.value + self.config_section.get('r_annulus_out'),
                    theta=theta.value)
            else:
                self.info('Aperture calculate is off')
                self.info(
                    'Aperture paratmeters from configuration file have been used'
                )

                aperture = CircularAperture(
                    position, r=self.config_section.get('r_aperture'))
                annulus = CircularAnnulus(
                    position,
                    r_in=self.config_section.get('r_aperture') +
                    self.config_section.get('r_annulus_in'),
                    r_out=self.config_section.get('r_aperture') +
                    self.config_section.get('r_annulus_out'))

            apertures.append([aperture, annulus, std])
            sigma_values_table.append(sigma_value(mean, median, std))

        return apertures, sigma_values_table
Пример #2
0
import numpy as np

from photutils.datasets import make_noise_image
from photutils.isophote import EllipseGeometry, Ellipse
from photutils import EllipticalAperture

g = Gaussian2D(100., 75, 75, 20, 12, theta=40. * np.pi / 180.)
ny = nx = 150
y, x = np.mgrid[0:ny, 0:nx]

noise = make_noise_image((ny, nx),
                         distribution='gaussian',
                         mean=0.,
                         stddev=2.,
                         random_state=12345)
data = g(x, y) + noise

#==========================================

geometry = EllipseGeometry(x0=75, y0=75, sma=20, eps=0.5, pa=20. * np.pi / 180)

aper = EllipticalAperture((geometry.x0, geometry.y0), geometry.sma,
                          geometry.sma * (1 - geometry.eps), geometry.pa)

plt.imshow(data, origin='lower')
aper.plot(color='white')
plt.show()

ellipse = Ellipse(data, geometry)
isolist = ellipse.fit_image()
Пример #3
0
def ap_phot(image, sources, radius, aperture='circular', coords='xy', theta=0,
            centroid=False, show_plot=False, **kargs):
    """Performs circular aperture fotometry on a background substracted image, given a table with the
    coordinates (x,y) or (ra,dec) of the sources.

    Input:
        image:      (str) name of the .fits file with the image
        sources:    table with the Positions of the sources in the image.
        radius:     Radius of the circular aperture in pixels.
                    If aperture = 'elliptical' the semi axes of the ellipese
                    (a,b) should be given.
        aperture:   (str) Shape of the aperture to use. 'circular' or
                    'elliptical'
        theta:      Rotation angle for elliptical aperture in radians, optional
        centroid:   (Boolean) if True the source position centroid are
                    recalculated.
        sky_coord   (str) type of coordinates to use, either xy or radec.
                    If xy sources table must have 'x' and 'y' cols.
                    If ra dec sources table must to have 'ra' and 'dec' cols.
        show_plot:  (Boolean) If True a plot of the aperture is displayed.
    Output:
        phot_table: Table with the resulting photometry
    """

    data = fits.getdata(image)
    x, y = sources.colnames

    if coords == 'radec':
        sources = SkyCoord(sources[x], sources[y], **kargs)
        # convert to pixel coordinates
        header = fits.getheader(image)
        wcs = WCS(header)
        sources = Table(sources.to_pixel(wcs), names=[x, y])
    elif coords == 'xy':
        warnings.warn('Image pixels start at 1 while python index stats at 0',
                      AstropyUserWarning)
        # Check if the following correction is necessary
        # sources[x] -= 1
        # sources[y] -= 1

    if centroid:
        sources = centroid_sources(data, sources[x], sources[y], box_size=30)
        sources = Table(sources, names=[x, y])

    # create apertures
    sources = [(a, b) for a, b in zip(sources[x], sources[y])]
    if aperture == 'circular':
        source_aperture = CircularAperture(sources, r=radius)
    elif aperture == 'elliptical':
        source_aperture = EllipticalAperture(sources, a=radius[0], b=radius[1],
                                           theta=theta)

    if show_plot:
        index = [str(i+1) for i in range(len(sources))]
        norm = simple_norm(data, 'sqrt', percent=99)
        plt.figure()
        plt.imshow(data, norm=norm)
        source_aperture.plot(color='white', lw=2)
        for a, b in sources:
            plt.text(a, b, index, color="purple", fontsize=12)
        plt.show()

    phot_table = aperture_photometry(data, source_aperture)

    return phot_table
Пример #4
0
def std1dspec(infile, startz=2000, nsigma=5, overwrite=False):
    print('\n#############################')
    print('Making 1D spectrum')
                              
    hdl = fits.open(infile)
    hdr = hdl[0].header
    basename = hdr['FRAMEID']
    outfile = basename + '.1dspec.fits'
    if os.path.isfile(outfile) and not overwrite:
        print('\t 1D data already exits. '+outfile)
        print('\t This procedure is skipped.')
        return outfile, True
    
    scidata = hdl[0].data
    binfac1 = hdr['BIN-FCT1']

    # Showing the image 
    aspect = 0.43/(0.104*binfac1)
    fig=plt.figure()
    plt.title('Click on the star. ')
    plt.imshow(scidata[startz,:,:], aspect=aspect, \
               interpolation='nearest', origin='lower')

    global xc,yc
    xc = 0.0
    yc = 0.0

    def star_center(event):
        global xc,yc
        xc= event.xdata
        yc = event.ydata
        plt.close()
        return

    
    cid = fig.canvas.mpl_connect('button_press_event', star_center)
    print('\n\t Click near the star center.')
    plt.show()

    print('\t Initial star location: (%.2f, %.2f)'%(xc,yc))
    initc = np.array((xc,yc))
    cutdata, initp = cutout(scidata[startz,:,:], initc ,w=10)
    g_init = Gaussian2D(amplitude=np.max(cutdata),
                         x_mean=initc[0]-initp[0],
                         y_mean=initc[1]-initp[1],
                         x_stddev=2.0,
                         y_stddev=1.0,
                         theta=3.1416/2)
    g_init.theta.fixed = True
    fitter = LevMarLSQFitter()
    y, x = np.indices(cutdata.shape)
    gfit = fitter(g_init, x, y, cutdata)
    print('\t Initial 2D Gaussian fitting result:')
    print(gfit)
    position0 = np.array([gfit.x_mean.value, gfit.y_mean.value])
    position0 = position0 + initp
    position = position0

    a = gfit.x_stddev.value * nsigma
    b = gfit.y_stddev.value * nsigma
    theta = gfit.theta.value

    plt.imshow(scidata[startz,:,:], aspect=aspect, \
               interpolation='nearest', origin='lower')
    apertures = EllipticalAperture(position, a=a ,b=b,theta=theta)
    apertures.plot()
    print('\n\t Check the aperture, and close the plot window.')
    plt.title('Check the aperture')
    plt.show()

    global coords, ii, std1ddata, lam

    std1ddata = np.zeros(scidata.shape[0], dtype=np.float32)

    # Aperture photometry with incleasing wavelength pix from startz 
    for i in range(startz,scidata.shape[0]):
        cutdata, initp = cutout(scidata[i,:,:],position)
        if np.min(cutdata) == np.max(cutdata):
            print('\t Cutdata is empty at '+str(i)+' pix.')
            break
        position_pre = position
        position = centroid_com(cutdata)
        position = position + initp
        if np.linalg.norm(position-position_pre) > 2.:
            print('\t Cetroid is not good at '+str(i)+' pix.')
            break
        apertures = EllipticalAperture(position, a=a ,b=b,theta=theta)
        phot_table = aperture_photometry(scidata[i,:,:], apertures)   
        std1ddata[i] = phot_table['aperture_sum'].data[0]

    # Aperture photometry with decreasing wavelength pix from startz 
    position = position0
    for i in range(startz-1,0,-1):
        cutdata, initp = cutout(scidata[i,:,:],position)
        if np.min(cutdata) == np.max(cutdata):
            print('\t Cutdata is empty! at ' + str(i) + ' pix.')
            break
        position_pre = position
        position = centroid_com(cutdata)
        position = position + initp
        if np.linalg.norm(position-position_pre) > 2.:
            print('\t Cetroid is not good at ' + str(i) + ' pix.')
            break
        apertures = EllipticalAperture(position, a=a ,b=b,theta=theta)
        phot_table = aperture_photometry(scidata[i,:,:], apertures)   
        std1ddata[i] = phot_table['aperture_sum'].data[0]


    # Plotting the 1D data & selecting the spectral range.
    crpix = hdr['CRPIX3']
    crval = hdr['CRVAL3']
    #cdelt = hdr['CDELT3']
    cdelt = hdr['CD3_3']
    object_name = hdr['OBJECT']

    npix = len(std1ddata)
    start = crval - (crpix-1)*cdelt
    stop = crval + (npix - crpix + 0.5)*cdelt
    lam = np.arange(start ,stop, cdelt)
    
    coords = np.zeros((2,2))
    ii=0

    print('\n\t Press any key except \'q\' to specify a required range')
    
    def select_range(event):
        global coords, ii, std1ddata, lam
        if event.key == 'q':
            plt.close()
        elif ii == 0:
            coords[0,0] = event.xdata
            coords[0,1] = event.ydata
            ii = 1
            print('\t Press any key again except \'q\'')            
        elif ii == 1:
            coords[1,0] = event.xdata
            coords[1,1] = coords[0,1] 
            plt.plot(coords[:,0], coords[:,1])
            plt.draw()
            ii = 2
            print('\t Press \'q\' to quit, or any other key to redo.')
        elif ii == 2:
            plt.cla()
            plt.plot(lam, std1ddata)
            plt.draw()
            coords[0,0] = event.xdata
            coords[0,1] = event.ydata
            ii = 1
            print('\t Press any key except \'q\' to specify a required range')
        return

    fig=plt.figure()
    cid = fig.canvas.mpl_connect('key_press_event', select_range)
    plt.plot(lam,std1ddata)
    plt.title(object_name)
    plt.xlabel('Lambda (Angstrom)')
    plt.ylabel('Count')
    plt.show()

    num = 0
    while coords[0,0] > lam[num]:
        num += 1
    x1 = num
    crval = lam[num]

    while coords[1,0]> lam[num]:
        num += 1
    x2 = num

    if x1 > x2:
        temp = x1
        x1 = x2
        x2 = temp

    # Saving the output fits file
    outhdu = fits.PrimaryHDU(data=std1ddata[x1:x2+1])
    outhdl = fits.HDUList([outhdu])
    
    outhdr = hdl[0].header
    outhdr['CTYPE1']  = hdl[0].header['CTYPE3'] 
    outhdr['CRVAL1']  = crval
    outhdr['CRPIX1']  = 1
    #outhdr['CDELT1']  = hdl[0].header['CDELT3']
    outhdr['CD1_1'] = hdl[0].header['CD3_3']
    outhdr['DISPAXIS'] = 1
    outhdr['WCSDIM'] = 1
    
    outhdr['XSTDDEV'] = (gfit.x_stddev.value, \
                         'X stddev of the star radial profile')
    outhdr['YSTDDEV'] = (gfit.y_stddev.value, \
                         'Y stddev of the star radial profile')
    outhdr['APNSIG'] = (nsigma, 'Number of sigmas for integration aperture')
    
    outhdr.remove('CTYPE2')
    outhdr.remove('CRVAL2') 
    outhdr.remove('CRPIX2') 
    #outhdr.remove('CDELT2') 
    outhdr.remove('CD2_2')
    outhdr.remove('LTM2_2')
    #outhdr.remove('CD1_1')
    outhdr.remove('LTM1_1')
    outhdr.remove('CTYPE3')
    outhdr.remove('CRVAL3') 
    outhdr.remove('CRPIX3') 
    #outhdr.remove('CDELT3') 
    outhdr.remove('CD3_3')
    outhdr.remove('LTM3_3')
    
    outhdl[0].header = outhdr
    outhdl.writeto(outfile, overwrite=overwrite)
    print('\t 1D data file: '+outfile)

    outhdl.close()
    hdl.close()
    return outfile, True
Пример #5
0
def segmentation_photometry(path_file_abs,
                            bkg_sigma=3.0,
                            source_snr=3.0,
                            fwhm_kernel=2.0,
                            x_size_kernel=3,
                            y_size_kernel=3,
                            save_fig_pdf=True,
                            clobber=False):
    """

    given a fits file (master image), this function calculates
    aperture photometry by source segmentation.

    make_source_mask not yet available in photutils v0.2.2, this version
    manually creates a source mask for determining background.

    """

    import os
    import copy
    import glob
    import pickle
    import numpy as np
    from scipy import ndimage
    import matplotlib
    import matplotlib.pyplot as plt
    from astropy.io import fits, ascii
    from astropy.convolution import Gaussian2DKernel
    from astropy.stats import sigma_clipped_stats, gaussian_fwhm_to_sigma
    #    from astropy.table import Table
    from astropy.visualization import (LogStretch, mpl_normalize)
    #    from astropy.extern.six.moves import StringIO
    from photutils import (detect_threshold, EllipticalAperture,
                           source_properties, properties_table)
    from photutils.detection import detect_sources
    from photutils.utils import random_cmap

    # create preliminary mask
    #from photutils import make_source_mask
    #masterMask = make_source_mask(master, snr=2, npixels=5, dilate_size=11)

    #        if LEDoff was used, get threshold from LEDoff/background
    #        path_dataset = os.path.dirname(path_file_abs) + os.path.sep
    #        filenameCombined = '\t'.join(
    #            os.listdir(os.path.join(datasetDirLocal, 'master')))
    #        if 'master_ledoff_subtracted' in filename:
    #            print('Using master_ledoff')
    #            # path_file_abs = os.path.join(datasetDir, 'master', filename)
    #            hdu = fits.open(path_file_abs)[0]
    #            data_subtracted = hdu.data
    #            # calculate threadhold
    #            ledoff_pred = np.mean(data_subtracted) * \
    #                np.ones(data_subtracted.shape)
    #            mse = mean_squared_error(data_subtracted, ledoff_pred)
    #            rmse = np.sqrt(mse)
    #            threshold = 7.0 * rmse
    #            threshold_value = threshold
    #         if no LEDoff was used, background subtraction is needed
    #         there should exist no file named "subtracted"
    #         if 'master.fit' in filenameCombined \
    #             or 'master_normalised.fit' in filenameCombined:

    filename = os.path.basename(path_file_abs)
    dir_save = os.path.dirname(path_file_abs)
    filenames_combined = '\t'.join(os.listdir(os.path.dirname(path_file_abs)))

    if clobber == False \
        and 'segm.obj' in filenames_combined  \
        and 'props.obj' in filenames_combined \
        and 'props.csv' in filenames_combined\
        and 'props.ecsv' in filenames_combined:
        print('Photometry properties table already exists. Reading objects...')
        segm = pickle.load(
            open(glob.glob(os.path.join(dir_save, '*segm.obj*'))[0], 'rb'))
        props = pickle.load(
            open(glob.glob(os.path.join(dir_save, '*props.obj*'))[0], 'rb'))

        return [segm, props]

    if 'master' in path_file_abs:
        if 'normalised' in path_file_abs:
            print('Performing photometry to ' +
                  'normalised master object image {}...'.format(path_file_abs))
        else:
            print('Performing photometry to ' +
                  'un-normalised master image {}...'.format(path_file_abs))
    else:
        print('Warning: Photometry being performed to ' +
              'a single exposure {}...'.format(path_file_abs))

    hdu = fits.open(path_file_abs)[0]
    data = hdu.data
    header = hdu.header

    if 'EXPREQ' in header:
        exptime = header['EXPREQ']
    elif 'EXPTIME' in header:
        exptime = header['EXPTIME']
    else:
        print('Exposure time not found in header. Cannot determine magnitude.')
        exptime = np.nan

    # === Iteratively determine background level ===

    # assuming background is homogenous, estimate background by sigma clipping
    # if background noise varies across image, generate 2D background instead
    print('Determining background noise level...' '')
    [mean, median, std] = sigma_clipped_stats(data, sigma=bkg_sigma, iters=5)
    threshold = median + (std * 2.0)
    segm = detect_sources(data, threshold, npixels=5)
    # turn segm into a mask
    mask = segm.data.astype(np.bool)
    # dilate the source mask to ensure complete masking of detected sources
    dilate_structure = np.ones((5, 5))
    mask_dilated = ndimage.binary_dilation(mask, structure=dilate_structure)
    # get sigma clipping stats of background, without sources that are masekd
    [bkg_mean, bkg_median, bkg_std] = sigma_clipped_stats(data,
                                                          sigma=bkg_sigma,
                                                          mask=mask_dilated,
                                                          iters=3)

    # === Detect sources by segmentation ===

    print('Determining threshold for source detection...')
    # determine threshold for source detection
    # in current implementation, if all inputs are present, the formula is
    # threshold = background + (background_error * snr)
    threshold = detect_threshold(data,
                                 background=bkg_median,
                                 error=bkg_std,
                                 snr=source_snr)
    print('Preparing 2D Gaussian kernal...')
    sigma_kernel = fwhm_kernel * gaussian_fwhm_to_sigma
    kernel = Gaussian2DKernel(sigma_kernel,
                              x_size=x_size_kernel,
                              y_size=y_size_kernel)
    # normalise kernel
    # The kernel models are normalized per default, ∫∞−∞f(x)dx=1∫−∞∞f(x)dx=1.
    # But because of the limited kernel array size, the normalization
    # for kernels with an infinite response can differ from one.
    kernel.normalize()
    # obtain a  SegmentationImage object with the same shape as the data,
    # where sources are labeled by different positive integer values.
    # A value of zero is always reserved for the background.
    # if the threshold includes the background level as above, then the image
    # input into detect_sources() should not be background subtracted.
    print('Segmentation processing...')
    segm = detect_sources(data, threshold, npixels=5, filter_kernel=kernel)
    print('Segmentation labels are: ', repr(segm.labels))

    # === Measure regional source properties ===

    # source_properties() assumes that the data have been background-subtracted.
    # Background is the background level that was previously present
    # in the input data.
    # The input background does not get subtracted from the input data,
    # which should already be background-subtracted.
    print('Extracting source properties...')
    props = source_properties(data - bkg_median, segm, background=bkg_median)
    # add flux and instrumental magnitude to properties
    # flux = source_sum / exptime
    # instrumental magnitude = -2.5 * log10(flux)
    for i in range(len(props)):
        # source_sum is by definition background-subtracted already
        props[i].flux = props[i].source_sum / exptime
        props[i].mag_instr = -2.5 * np.log10(props[i].flux)
    # make plots and save to images
    # define approximate isophotal ellipses for each object
    apertures = []
    r = 2.8  # approximate isophotal extent
    for prop in props:
        position = (prop.xcentroid.value, prop.ycentroid.value)
        a = prop.semimajor_axis_sigma.value * r
        b = prop.semiminor_axis_sigma.value * r
        theta = prop.orientation.value
        apertures.append(EllipticalAperture(position, a, b, theta=theta))

    # create a table of properties
    try:
        props_table = properties_table(props)
    except:
        print('No source detected in {}'.format(path_file_abs))
        return [None, None]

    props_table['flux'] = [props[i].flux for i in range(len(props))]
    props_table['mag_instr'] = [props[i].mag_instr for i in range(len(props))]
    # add custom columns to the table: mag_instru and flux

    # plot centroid and segmentation using approximate elliptical apertures
    norm = mpl_normalize.ImageNormalize(stretch=LogStretch())
    rand_cmap = random_cmap(segm.max + 1, random_state=12345)
    [fig1, (ax1, ax2)] = plt.subplots(1, 2, figsize=(12, 6))
    ax1.imshow(data, origin='lower', cmap=plt.cm.gray, norm=norm)
    ax1.plot(props_table['xcentroid'],
             props_table['ycentroid'],
             ls='none',
             color='blue',
             marker='+',
             ms=10,
             lw=1.5)
    ax2.imshow(segm, origin='lower', cmap=rand_cmap)
    for aperture in apertures:
        aperture.plot(ax=ax1, lw=1.0, alpha=1.0, color='red')
        aperture.plot(ax=ax2, lw=1.0, alpha=1.0, color='red')
    # plot using actual segmentation outlines (to be improved)
    [fig2, ax3] = plt.subplots(figsize=(6, 6))
    ax3.imshow(data, origin='lower', cmap=plt.cm.gray, norm=norm)
    segm_outline = np.array(segm.outline_segments(), dtype=float)
    segm_outline[segm_outline < 1] = np.nan
    # get a copy of the gray color map
    segm_outline_cmap = copy.copy(plt.cm.get_cmap('autumn'))
    # set how the colormap handles 'bad' values
    segm_outline_cmap.set_bad(alpha=0)
    ax3.imshow(segm_outline, origin='lower', cmap=segm_outline_cmap)

    # === save ===
    # Save segm, porps to object files, and also save props to table file.
    print(
        'Saving segmentation and source properties to {}...'.format(dir_save))
    try:
        # if filename ends with fits, remove it in the  filename
        if filename[-5:] == '.fits':
            dir_save_prefix = os.path.join(dir_save, filename[0:-5])
        else:
            dir_save_prefix = os.path.join(dir_save, filename)
        # Enhanced CSV allows preserving table meta-data such as
        # column data types and units.
        # In this way a data table can be stored and read back as ASCII
        # with no loss of information.
        ascii.write(props_table,
                    dir_save_prefix + '-phot_props.ecsv',
                    format='ecsv')
        # csv for readability in MS excel
        ascii.write(props_table,
                    dir_save_prefix + '-phot_props.csv',
                    format='csv')

        # dump segmentation and properties to object files in binary mode
        file_segm = open(dir_save_prefix + '-phot_segm.obj', 'wb')
        pickle.dump(segm, file_segm)
        file_props = open(dir_save_prefix + '-phot_props.obj', 'wb')
        pickle.dump(props, file_props)

        # save figures
        fig1.savefig(dir_save_prefix + '-phot_segm_fig1.png', dpi=600)

        fig2.savefig(dir_save_prefix + '-phot_segm_fig2.png', dpi=600)

        if save_fig_pdf:

            matplotlib.rcParams['text.usetex'] = True
            matplotlib.rcParams['text.latex.unicode'] = True
            from matplotlib.backends.backend_pdf import PdfPages

            pp1 = PdfPages(dir_save_prefix + '-phot_segm_fig1.pdf')
            pp1.savefig(fig1)
            pp1.close()

            pp2 = PdfPages(dir_save_prefix + '-phot_segm_fig2.pdf')
            pp2.savefig(fig2)
            pp2.close()

        print('Segmentation, properties objects, tables, and images saved to',
              dir_save)
    except:
        print('Unable to write to disk, check permissions.')

    return [segm, props]
def ellip_ap_an(positions,
                fwhm,
                theta=0.,
                f_ap=(1.5, 1.5),
                f_in=(4., 4.),
                f_out=(6., 6.)):
    ''' A convenience function for pixel elliptical aperture/annulus
    Parameters
    ----------
    positions : array_like or `~astropy.units.Quantity`
        The pixel coordinates of the aperture center(s) in one of the
        following formats:

        * single ``(x, y)`` pair as a tuple, list, or `~numpy.ndarray`
        * tuple, list, or `~numpy.ndarray` of ``(x, y)`` pairs
        * `~astropy.units.Quantity` instance of ``(x, y)`` pairs in
            pixel units

    fwhm : float
        The FWHM in pixel unit.

    theta : float, optional
        The rotation angle in radians of the ellipse semimajor axis from
        the positive ``x`` axis.  The rotation angle increases
        counterclockwise.  The default is 0.

    f_ap, f_in, f_out: int or float, list or tuple of such, optional
        The factors multiplied to ``fwhm`` to set the aperture ``a`` and
        ``b``, inner sky ``a`` and ``b``, and outer sky ``a`` and ``b``,
        respectively. If scalar, it is assumed to be identical for both
        ``a`` and ``b`` parameters. Defaults are ``(1.5, 1.5)``, ``(4.0,
        4.0)``, and ``(6.0, 6.0)``, respectively, which are de facto
        standard values used by classical IRAF users.

    Returns
    -------
    ap, an : `~photutils.EllipticalAperture` and `~photutils.EllipticalAnnulus`
        The object aperture and sky annulus.
    '''
    if np.isscalar(fwhm):
        fwhm = np.repeat(fwhm, 2)

    if np.isscalar(f_ap):
        f_ap = np.repeat(f_ap, 2)

    if np.isscalar(f_in):
        f_in = np.repeat(f_in, 2)

    if np.isscalar(f_out):
        f_out = np.repeat(f_out, 2)

    a_ap = f_ap[0] * fwhm[0]
    b_ap = f_ap[1] * fwhm[1]
    a_in = f_in[0] * fwhm[0]
    a_out = f_out[0] * fwhm[0]
    b_out = f_out[1] * fwhm[1]

    ap = EllipticalAperture(positions=positions, a=a_ap, b=b_ap, theta=theta)
    an = EllipticalAnnulus(positions=positions,
                           a_in=a_in,
                           a_out=a_out,
                           b_out=b_out,
                           theta=theta)

    return ap, an
    def _prepare_mask(bbox, ap_r, ap_1, ap_2, method, subpixels, min_mask=0):
        """ Make the pill box mask array.
        Note
        ----
        To make an ndarray to represent the overlapping mask, the three
        (a rectangular and two elliptical) apertures are generated, but
        parallely shifted such that the bounding box has ``ixmin`` and
        ``iymin`` both zero. Then proper mask is generated as an
        ndarray. It is then used by ``PillBoxMaskMixin.to_mask`` to make
        an ``ApertureMask`` object by combining this mask with the
        original bounding box.

        Parameters
        ----------
        bbox : `~photutils.BoundingBox`
            The bounding box of the original aperture.

        ap_r : `~photutils.RectangularAperture`
            The rectangular aperture of a pill box.

        ap_1, ap_2 : `~photutils.EllipticalAperture`
            The elliptical apertures of a pill box. The order of
            left/right ellipses is not important for this method.

        method : See `~photutils.PillBoxMaskMixin.to_mask`

        subpixels : See `~photutils.PillBoxMaskMixin.to_mask`

        min_mask : float, optional
            The mask values smaller than this value is ignored (set to
            0). This is required because the subtraction of elliptical
            and rectangular masks give some negative values. One can set
            it to be ``1/subpixels**2`` because ``RectangularAperture``
            does not support ``method='exact'`` yet.

        Returns
        -------
        mask_pill : ndarray
            The mask of the pill box.
        """
        aps = []
        for ap in [ap_r, ap_1, ap_2]:
            pos_cent = ap.positions
            tmp_cent = pos_cent - np.array([bbox.ixmin, bbox.iymin])
            if hasattr(ap, 'w'):
                tmp_ap = RectangularAperture(positions=tmp_cent,
                                             w=ap.w,
                                             h=ap.h,
                                             theta=ap.theta)
            else:
                tmp_ap = EllipticalAperture(positions=tmp_cent,
                                            a=ap.a,
                                            b=ap.b,
                                            theta=ap.theta)
            aps.append(tmp_ap)

        bbox_shape = bbox.shape

        mask_kw = dict(method=method, subpixels=subpixels)
        mask_r = (aps[0].to_mask(**mask_kw).to_image(bbox_shape))
        mask_1 = (aps[1].to_mask(**mask_kw).to_image(bbox_shape))
        mask_2 = (aps[2].to_mask(**mask_kw).to_image(bbox_shape))

        # Remove both machine epsilon artifact & negative mask values:
        mask_pill_1 = mask_1 - mask_r
        mask_pill_1[mask_pill_1 < min_mask] = 0
        mask_pill_2 = mask_2 - mask_r
        mask_pill_2[mask_pill_2 < min_mask] = 0

        mask_pill = mask_r + mask_pill_1 + mask_pill_2

        # Overlap of elliptical parts may make value > 1:
        mask_pill[mask_pill > 1] = 1

        return mask_pill
Пример #8
0
def surface_phot(label, center_ra, center_dec, major_diam, minor_diam, pos_angle,
                     ann_width, zeropoint, zeropoint_err=0.0,
                     aperture_factor=1.0, sky_aperture_factor=1.0,
                     mask_file=None, offset_file=False,
                     verbose=False):
    """
    Do surface brightness photometry within annuli

    Parameters
    ----------
    label : string
        label associated with the galaxy, both for finding image files and
        saving results (e.g., 'ngc24_offset_w2_')

    center_ra, center_dec : float
        coordinates of the center of the galaxy (degrees)

    major_diam, minor_diam : float
        major and minor axes for the galaxy ellipse (arcsec)

    pos_angle : float
        position angle of the galaxy ellipse ("position angle increases
        counterclockwise from North (PA=0)")

    ann_width : float
        width of annuli (arcsec)

    zeropoint : float
        conversion from counts/sec into magnitude units
        AB_mag = -2.5*log10(counts/sec) + zeropoint

    zeropoint_err : float (default=0)
        uncertainty for the zeropoint

    aperture_factor : float (default=1.0)
        make the aperture larger by a factor of N (useful to quickly adjust
        aperture if, e.g., you know R25 is too small for your UV galaxy)

    sky_aperture_factor : float (default=1.0)
        choose whether the sky aperture starts at the edge of the photometry
        aperture (1.0) or some factor N larger

    mask_file : string (default=None)
        path+name of ds9 region file with masks

    offset_file : boolean (default=False)
        if True, the file label+'sk_off.fits' is used to show what offsets (in
        counts) have already been added to the counts images

    verbose : boolean (default=False)
        if True, print progress

    """

    # read in the images
    counts_im = label + 'sk.fits'
    exp_im = label + 'ex.fits'
    offset_im = label + 'sk_off.fits'

    # if files don't exist, return NaN
    if (not os.path.isfile(counts_im)) or (not os.path.isfile(exp_im)):
        print('surface_phot: image(s) not found')
        return np.nan
    

    with fits.open(counts_im) as hdu_counts, fits.open(exp_im) as hdu_ex:

        # if mask region file is provided, make a mask image
        if mask_file is not None:
            mask_image = make_mask_image(hdu_counts[1], mask_file)
        # otherwise mask is all 1s
        else:
            mask_image = np.ones(hdu_counts[1].data.shape)

        # mask any areas where exposure time is 0
        mask_image[np.where(hdu_ex[1].data < 1e-5)] = 0
            
        # for some unknown reason (uvotimsum bug?), counts file could have NaNs
        # -> mask them
        mask_image[np.where(np.isfinite(hdu_counts[1].data) == 0)] = 0


        # if offset file is set, save it into an array
        if offset_file == True:
            with fits.open(label+'sk_off.fits') as hdu_off:
                counts_off_array = hdu_off[1].data

            # mask any NaNs
            mask_image[np.where(np.isfinite(counts_off_array) == 0)] = 0

        else:
            counts_off_array = None


        # WCS for the images
        wcs_counts = wcs.WCS(hdu_counts[1].header)
        arcsec_per_pix = wcs_counts.wcs.cdelt[1] * 3600
        
        # ellipse center
        #ellipse_center = SkyCoord(ra=center_ra*u.deg, dec=center_dec*u.deg)
        ellipse_center = wcs_counts.wcs_world2pix([[center_ra,center_dec]], 0)[0]
        
        # array of annuli over which to do photometry
        annulus_array = np.arange(0, major_diam*aperture_factor, ann_width)# * u.arcsec 


        # -------------------------
        # sky background and variation
        # -------------------------

        # size of sky annulus
        sky_in = annulus_array[-1] * sky_aperture_factor
        sky_ann_width = ann_width * 10
        sky_out = sky_in + sky_ann_width

        sky_phot, sky_seg_phot, sky_seg_phot_err = calc_sky(hdu_counts[1], hdu_ex[1],
                                                                ellipse_center, major_diam, minor_diam, pos_angle,
                                                                sky_in, sky_out,
                                                                mask_image=mask_image,
                                                                counts_off_array=counts_off_array)
        

        # -------------------------
        # photometry for each annulus
        # -------------------------

        # initialize a table (or, rather, the rows... turn into table later)
        cols_ann = ['radius','count_rate','count_rate_err',
                    'count_rate_err_poisson','count_rate_err_bg',
                    'mu','mu_err','n_pix']
        units_ann = ['arcsec','cts/sec','cts/sec',
                     'cts/sec','cts/sec',
                     'ABmag/arcsec2','ABmag/arcsec2','']
        dtypes = ['%9.3f','%9f','%9f',
                      '%9f','%9f',
                      '%9f','%9f','%9f']
        phot_dict_ann = {key:np.zeros(len(annulus_array)-1) for key in cols_ann}

        for i in range(len(annulus_array)-1):
        #for i in range(0,5):

            # save radius
            phot_dict_ann['radius'][i] = annulus_array[i+1]

            # define aperture object
            aperture = EllipticalAnnulus(tuple(ellipse_center),
                                             a_in=annulus_array[i]/arcsec_per_pix,
                                             a_out=annulus_array[i+1]/arcsec_per_pix,
                                             b_out=annulus_array[i+1]/arcsec_per_pix * minor_diam/major_diam,
                                             theta=(90+pos_angle)*np.pi/180)
            # make an ApertureMask object with the aperture
            annulus_mask = aperture.to_mask(method='exact')
            # turn aperture into an image
            annulus_im = annulus_mask[0].to_image(hdu_counts[1].data.shape)

            # get total number of pixels (using ellipse areas, in case some of the aperture is off the image)
            #tot_pix = np.sum(annulus_im)
            area_out = np.pi * annulus_array[i+1]/arcsec_per_pix * annulus_array[i+1]/arcsec_per_pix * minor_diam/major_diam
            area_in = np.pi * annulus_array[i]/arcsec_per_pix * annulus_array[i]/arcsec_per_pix * minor_diam/major_diam
            tot_pix = area_out - area_in
            tot_arcsec2 = tot_pix * arcsec_per_pix**2
            phot_dict_ann['n_pix'][i] = tot_pix
            
            # make masked version
            annulus_im = annulus_im * mask_image

            # plot things
            #annulus_data = annulus_mask[0].multiply(hdu_counts[1].data)
            #plt.imshow(annulus_mask[0])
            #plt.imshow(annulus_data, origin='lower')
            #plt.imshow(annulus_im, origin='lower')
            #plt.colorbar()

            # list of values within aperture
            nonzero_annulus = np.where(annulus_im > 1e-5)
            annulus_list = annulus_im[nonzero_annulus]
            counts_list = hdu_counts[1].data[nonzero_annulus]
            exp_list = hdu_ex[1].data[nonzero_annulus]
            if offset_file == True:
                counts_off_list = counts_off_array[nonzero_annulus]

            # do photometry
            if offset_file == True:
                ann_temp = do_phot(annulus_list, counts_list, exp_list, offset_list=counts_off_list)
            else:
                ann_temp = do_phot(annulus_list, counts_list, exp_list)

            # subtract background
            ann_phot_per_pix = ann_temp['count_rate_per_pix'] - sky_phot['count_rate_per_pix']
            ann_phot_per_pix_err = np.sqrt(ann_temp['count_rate_err_per_pix']**2 +
                                            sky_phot['count_rate_err_per_pix']**2 +
                                            np.nanstd(sky_seg_phot)**2 )
            ann_phot_per_pix_pois_err = ann_temp['count_rate_pois_err_per_pix']
            ann_phot_per_pix_bg_err = np.sqrt(ann_temp['count_rate_off_err_per_pix']**2 +
                                                sky_phot['count_rate_err_per_pix']**2 +
                                                np.nanstd(sky_seg_phot)**2 )

            # multiply by the number of pixels in the annulus to get the total count rate
            ann_phot = ann_phot_per_pix * tot_pix
            ann_phot_err = ann_phot_per_pix_err * tot_pix
            ann_phot_pois_err = ann_phot_per_pix_pois_err * tot_pix
            ann_phot_bg_err = ann_phot_per_pix_bg_err * tot_pix

            phot_dict_ann['count_rate'][i] = ann_phot
            phot_dict_ann['count_rate_err'][i] = ann_phot_err
            phot_dict_ann['count_rate_err_poisson'][i] = ann_phot_pois_err
            phot_dict_ann['count_rate_err_bg'][i] = ann_phot_bg_err

            # convert to surface brightness
            # - counts/sec/arcsec2
            ann_phot_arcsec2 = ann_phot / tot_arcsec2
            ann_phot_arcsec2_err = ann_phot_err / tot_arcsec2
            # - mag/arcsec2
            mag_arcsec2 = -2.5 * np.log10(ann_phot_arcsec2) + zeropoint
            mag_arcsec2_err = np.sqrt( ( 2.5/np.log(10) * ann_phot_arcsec2_err/ann_phot_arcsec2 )**2 +
                                           zeropoint_err**2 )

            phot_dict_ann['mu'][i] = mag_arcsec2
            phot_dict_ann['mu_err'][i] = mag_arcsec2_err

            
            #[print(k+': ', phot_dict_ann[k][i]) for k in cols_ann]
            #pdb.set_trace()


        # make big numpy array
        data_array = np.column_stack(tuple([phot_dict_ann[key] for key in cols_ann]))
        # save it to a file
        np.savetxt(label+'phot_annprofile.dat', data_array,
                       header=' '.join(cols_ann) + '\n' + ' '.join(units_ann),
                       delimiter='  ', fmt=dtypes)


        # -------------------------
        # total photometry within each radius
        # -------------------------

        # initialize a table (or, rather, the rows... turn into table later)
        cols_tot = ['radius','count_rate','count_rate_err',
                    'count_rate_err_poisson','count_rate_err_bg',
                    'mag','mag_err','n_pix']
        units_tot = ['arcsec','cts/sec','cts/sec',
                     'cts/sec','cts/sec',
                     'ABmag','ABmag','']
        dtypes = ['%9.3f','%9f','%9f',
                      '%9f','%9f',
                      '%9f','%9f','%9f']
        phot_dict_tot = {key:np.zeros(len(annulus_array)-1) for key in cols_tot}

        for i in range(len(annulus_array)-1):
        #for i in range(0,5):

            # save radius
            phot_dict_tot['radius'][i] = annulus_array[i+1]

            # define aperture object
            aperture = EllipticalAperture(tuple(ellipse_center),
                                             a=annulus_array[i+1]/arcsec_per_pix,
                                             b=annulus_array[i+1]/arcsec_per_pix * minor_diam/major_diam,
                                             theta=(90+pos_angle)*np.pi/180)
            # make an ApertureMask object with the aperture
            annulus_mask = aperture.to_mask(method='exact')
            # turn aperture into an image
            annulus_im = annulus_mask[0].to_image(hdu_counts[1].data.shape)
            
            # get total number of pixels (using ellipse areas, in case some of the aperture is off the image)
            #tot_pix = np.sum(annulus_im)
            tot_pix = np.pi * annulus_array[i+1]/arcsec_per_pix * annulus_array[i+1]/arcsec_per_pix * minor_diam/major_diam
            tot_arcsec2 = tot_pix * arcsec_per_pix**2
            phot_dict_tot['n_pix'][i] = tot_pix
            
            # make masked version
            annulus_im = annulus_im * mask_image

            # plot things
            #annulus_data = annulus_mask[0].multiply(hdu_counts[1].data)
            #plt.imshow(annulus_mask[0])
            #plt.imshow(annulus_data, origin='lower')
            #plt.imshow(annulus_im, origin='lower')
            #plt.colorbar()

            # list of values within aperture
            nonzero_annulus = np.where(annulus_im > 1e-5)
            annulus_list = annulus_im[nonzero_annulus]
            counts_list = hdu_counts[1].data[nonzero_annulus]
            exp_list = hdu_ex[1].data[nonzero_annulus]
            if offset_file == True:
                counts_off_list = counts_off_array[nonzero_annulus]

            # do photometry
            if offset_file == True:
                tot_temp = do_phot(annulus_list, counts_list, exp_list, offset_list=counts_off_list)
            else:
                tot_temp = do_phot(annulus_list, counts_list, exp_list)

            # subtract background
            tot_phot_per_pix = tot_temp['count_rate_per_pix'] - sky_phot['count_rate_per_pix']
            tot_phot_per_pix_err = np.sqrt(tot_temp['count_rate_err_per_pix']**2 +
                                            sky_phot['count_rate_err_per_pix']**2 +
                                            np.nanstd(sky_seg_phot)**2 )
            tot_phot_per_pix_pois_err = tot_temp['count_rate_pois_err_per_pix']
            tot_phot_per_pix_bg_err = np.sqrt(tot_temp['count_rate_off_err_per_pix']**2 +
                                                sky_phot['count_rate_err_per_pix']**2 +
                                                np.nanstd(sky_seg_phot)**2 )

            # multiply by the number of pixels in the annulus to get the total count rate
            tot_phot = tot_phot_per_pix * tot_pix
            tot_phot_err = tot_phot_per_pix_err * tot_pix
            tot_phot_pois_err = tot_phot_per_pix_pois_err * tot_pix
            tot_phot_bg_err = tot_phot_per_pix_bg_err * tot_pix

            phot_dict_tot['count_rate'][i] = tot_phot
            phot_dict_tot['count_rate_err'][i] = tot_phot_err
            phot_dict_tot['count_rate_err_poisson'][i] = tot_phot_pois_err
            phot_dict_tot['count_rate_err_bg'][i] = tot_phot_bg_err

            # convert to magnitudes
            mag = -2.5 * np.log10(tot_phot) + zeropoint
            mag_err = np.sqrt( ( 2.5/np.log(10) * tot_phot_err/tot_phot )**2 +
                                           zeropoint_err**2 )

            phot_dict_tot['mag'][i] = mag
            phot_dict_tot['mag_err'][i] = mag_err

            
            #[print(k+': ', phot_dict_tot[k][i]) for k in cols_tot]
            #pdb.set_trace()


        # make big numpy array
        data_array = np.column_stack(tuple([phot_dict_tot[key] for key in cols_tot]))
        # save it to a file
        np.savetxt(label+'phot_totprofile.dat', data_array,
                       header=' '.join(cols_tot) + '\n' + ' '.join(units_tot),
                       delimiter='  ', fmt=dtypes)



        # -------------------------
        # calculate magnitudes
        # -------------------------

        # asymptotic: plot accumulated flux vs gradient of accumulated flux, then get y-intercept
        # (see Gil de Paz et al 2007, section 4.3)
        
        # - grab points with the last part of flux accumulation
        use_ind = np.where(phot_dict_tot['count_rate'] >= 0.9 * np.max(phot_dict_tot['count_rate']))
        use_rad = phot_dict_tot['radius'][use_ind]
        use_cr = phot_dict_tot['count_rate'][use_ind]
        use_cr_err = phot_dict_tot['count_rate_err'][use_ind]
        grad = np.diff(use_cr) / np.diff(use_rad)
        
        # - bootstrap linear fit
        fit_boot = boot_lin_fit(grad, use_cr[1:], use_cr_err[1:])

        # - convert flux to mags
        asym_mag = -2.5 * np.log10(fit_boot['int']) + zeropoint
        asym_mag_err = np.sqrt( ( 2.5/np.log(10) * fit_boot['int_err']/fit_boot['int'] )**2 +
                                    zeropoint_err**2 )

        # - save it
        np.savetxt(label+'phot_asymmag.dat',
                       np.array([[fit_boot['int'], fit_boot['int_err'], asym_mag, asym_mag_err]]),
                       header='count_rate count_rate_err mag mag_err\ncts/sec cts/sec ABmag ABmag',
                       delimiter='  ', fmt=['%9f','%9f','%9f','%9f'])


        # - make plots
        if False:
            fig = plt.figure(figsize=(6,5), num='flux gradient stuff')
            plt.errorbar(grad, use_cr[1:],
                         yerr=use_cr_err[1:],
                         marker='.', color='black', ms=5, mew=0,
                         linestyle='-', ecolor='black', capsize=0)
            plt.plot(np.linspace(0,np.max(grad),50),
                     fit_boot['slope']*np.linspace(0,np.max(grad),50) + fit_boot['int'],
                     marker='.', ms=0, mew=0,
                     color='dodgerblue', linestyle='-')
            ax = plt.gca()
            ax.set_ylabel('Accumulated Flux (counts/sec)')
            ax.set_xlabel('Gradient of Accumulated Flux')
            plt.tight_layout()
            pdb.set_trace()
        
            fig = plt.figure(figsize=(6,5), num='flux stuff')
            plt.errorbar(use_rad/60, use_cr,
                         yerr=use_cr_err,
                         marker='.', color='black', ms=5, mew=0,
                         linestyle='-', ecolor='black', capsize=0)
            ax = plt.gca()
            ax.set_ylabel('Accumulated Flux (counts/sec)')
            ax.set_xlabel('Radius (arcmin)')
            plt.tight_layout()
            pdb.set_trace()



        # total: outermost annular point with S/N > 2 -> get accumulated flux within that radius
        sn = phot_dict_ann['count_rate'] / phot_dict_ann['count_rate_err']
        ind = np.nonzero(sn > 2)[0][-1]
        max_radius = phot_dict_tot['radius'][ind]
        tot_mag = phot_dict_tot['mag'][ind]
        tot_mag_err = phot_dict_tot['mag_err'][ind]
        # save it
        np.savetxt(label+'phot_totmag.dat',
                       np.array([[phot_dict_tot['count_rate'][ind], phot_dict_tot['count_rate_err'][ind], tot_mag, tot_mag_err]]),
                       header='count_rate count_rate_err mag mag_err\ncts/sec cts/sec ABmag ABmag',
                       delimiter='  ', fmt=['%9f','%9f','%9f','%9f'])
        

        # return various useful info
        return {'phot_dict_ann':phot_dict_ann, 'cols_ann':cols_ann, 'units_ann':units_ann,
                    'phot_dict_tot':phot_dict_tot, 'cols_tot':cols_tot, 'units_tot':units_tot,
                    'sky_phot':sky_phot,
                    'sky_seg_phot':sky_seg_phot, 'sky_seg_phot_err':sky_seg_phot_err,
                    'asym_mag':asym_mag, 'asym_mag_err':asym_mag_err,
                    'tot_mag':tot_mag, 'tot_mag_err':tot_mag_err}
Пример #9
0
def A_photometry(image_data, bg_err, factor = 1, ape_sum = [], ape_sum_err = [],
	cx = 15, cy = 15, r = 2.5, a = 5, b = 5, w_r = 5, h_r = 5, 
	theta = 0, shape = 'Circular', method='center'):
	'''
	Performs aperture photometry, first by creating the aperture (Circular,
	Rectangular or Elliptical), then it sums up the flux that falls into the 
	aperture.

    Parameters
    ==========

    image_data: 3D array 
    	Data cube of images (2D arrays of pixel values).

    bg_err   : 1D array
    	Array of uncertainties on pixel value.

    factor   : float (optional)
    	Electron count to photon count factor. Default is 1 if none given.

    ape_sum  : 1D array (optional)
    	Array of flux to append new flux values to. If 'None', the new values
    	will be appended to an empty array

    ape_sum_err: 1D array (optional)
    	Array of flux uncertainty to append new flux uncertainty values to. If 
    	'None', the new values will be appended to an empty array.

    cx       : int (optional)
    	x-coordinate of the center of the aperture. Default is 15.

    cy       : int (optional)
    	y-coordinate of the center of the aperture. Default is 15.

    r        : int (optional)
    	If phot_meth is 'Aperture' and ap_shape is 'Circular', c_radius is 
    	the radius for the circular aperture. Default is 2.5.

	a        : int (optional)
		If phot_meth is 'Aperture' and ap_shape is 'Elliptical', e_semix is
		the semi-major axis for elliptical aperture (x-axis). Default is 5.

	b        : int (optional)
		If phot_meth is 'Aperture' and ap_shape is 'Elliptical', e_semiy is
		the semi-major axis for elliptical aperture (y-axis). Default is 5.

	w_r      : int (optional)
		If phot_meth is 'Aperture' and ap_shape is 'Rectangular', r_widthx is
		the full width for rectangular aperture (x-axis). Default is 5.

	h_r      : int (optional)
		If phot_meth is 'Aperture' and ap_shape is 'Rectangular', r_widthy is
		the full height for rectangular aperture (y-axis). Default is 5.

    theta    : int (optional)
    	If phot_meth is 'Aperture' and ap_shape is 'Elliptical' or
    	'Rectangular', theta is the angle of the rotation angle in radians 
    	of the semimajor axis from the positive x axis. The rotation angle 
    	increases counterclockwise. Default is 0.

	shape    : string object (optional)
    	If phot_meth is 'Aperture', ap_shape is the shape of the aperture. 
    	Possible aperture shapes are 'Circular', 'Elliptical', 'Rectangular'. 
    	Default is 'Circular'.

    method   : string object (optional)
    	If phot_meth is 'Aperture', apemethod is the method used to 
    	determine the overlap of the aperture on the pixel grid. Possible 
    	methods are 'exact', 'subpixel', 'center'. Default is 'exact'.

    Returns
    -------
    ape_sum  : 1D array
    	Array of flux with new flux appended.

    ape_sum_err: 1D array
    	Array of flux uncertainties with new flux uncertainties appended.

	'''
	l, h, w = image_data.shape
	position=[cx, cy]
	if   (shape == 'Circular'):
		aperture = CircularAperture(position, r=r)
	elif (shape == 'Elliptical'):
		aperture = EllipticalAperture(position, a=a, b=b, theta=theta)
	elif (shape == 'Rectangular'):
		aperture = RectangularAperture(position, w=w_r, h=h_r, theta=theta)
	for i in range(l):
		data_error = calc_total_error(image_data[i,:,:], bg_err[i], effective_gain=1)
		phot_table = aperture_photometry(image_data[i,:,:],aperture, error=data_error, pixelwise_error=False)
		ape_sum.extend(phot_table['aperture_sum']*factor)
		ape_sum_err.extend(phot_table['aperture_sum_err']*factor)
	return ape_sum, ape_sum_err
Пример #10
0
def mask_obj(img,
             snr=3.0,
             exp_sz=1.2,
             pltshow=0,
             npixels=20,
             return_deblend=False):
    threshold = detect_threshold(img, snr=snr)
    sigma = 3.0 * gaussian_fwhm_to_sigma  # FWHM = 3.
    kernel = Gaussian2DKernel(sigma, x_size=npixels / 4, y_size=npixels / 4)
    kernel.normalize()
    segm = detect_sources(img,
                          threshold,
                          npixels=npixels,
                          filter_kernel=kernel)
    npixels = npixels
    segm_deblend = deblend_sources(img,
                                   segm,
                                   npixels=npixels,
                                   filter_kernel=kernel,
                                   nlevels=15,
                                   contrast=0.001)
    columns = ['id', 'xcentroid', 'ycentroid', 'source_sum', 'area']
    cat = source_properties(img, segm_deblend)
    tbl = cat.to_table(columns=columns)
    tbl['xcentroid'].info.format = '.2f'  # optional format
    tbl['ycentroid'].info.format = '.2f'
    print(tbl)
    #Number of objects segm_deblend.data.max()
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12.5, 10))
    import copy, matplotlib
    my_cmap = copy.copy(
        matplotlib.cm.get_cmap('gist_heat'))  # copy the default cmap
    my_cmap.set_bad('black')
    vmin = 1.e-3
    vmax = 2.1
    ax1.imshow(img,
               origin='lower',
               cmap=my_cmap,
               norm=LogNorm(),
               vmin=vmin,
               vmax=vmax)
    ax1.set_title('Data')
    ax2.imshow(segm_deblend,
               origin='lower',
               cmap=segm_deblend.cmap(random_state=12345))
    for obj in cat:
        ax2.text(obj.xcentroid.value,
                 obj.ycentroid.value,
                 'ID{0}'.format(obj.id - 1),
                 fontsize=20,
                 color='white')
    ax2.set_title('Segmentation Image')
    if return_deblend == True:
        plt.show()

    from photutils import EllipticalAperture
    segm_deblend_size = segm_deblend.areas
    apertures = []
    for obj in cat:
        size = segm_deblend_size[obj.id]
        position = (obj.xcentroid.value, obj.ycentroid.value)
        a_o = obj.semimajor_axis_sigma.value
        b_o = obj.semiminor_axis_sigma.value
        size_o = np.pi * a_o * b_o
        r = np.sqrt(size / size_o) * exp_sz
        a, b = a_o * r, b_o * r
        theta = obj.orientation.value
        apertures.append(EllipticalAperture(position, a, b, theta=theta))
    center_img = len(img) / 2
    dis_sq = [
        np.sqrt((apertures[i].positions[0][0] - center_img)**2 +
                (apertures[i].positions[0][1] - center_img)**2)
        for i in range(len(apertures))
    ]
    dis_sq = np.asarray(dis_sq)
    c_index = np.where(dis_sq == dis_sq.min())[0][0]
    #from astropy.visualization.mpl_normalize import ImageNormalize
    #norm = ImageNormalize(stretch=SqrtStretch())
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12.5, 10))
    ax1.imshow(img,
               origin='lower',
               cmap=my_cmap,
               norm=LogNorm(),
               vmin=vmin,
               vmax=vmax)
    ax1.set_title('Data')
    ax2.imshow(segm_deblend,
               origin='lower',
               cmap=segm_deblend.cmap(random_state=12345))
    ax2.set_title('Segmentation Image')
    for i in range(len(apertures)):
        aperture = apertures[i]
        aperture.plot(color='white', lw=1.5, ax=ax1)
        aperture.plot(color='white', lw=1.5, ax=ax2)
    if pltshow == 0 or return_deblend == True:
        plt.close()
    else:
        plt.show()
    from regions import PixCoord, EllipsePixelRegion
    from astropy.coordinates import Angle
    obj_masks = []  # In the script, the objects are 1, emptys are 0.
    for i in range(len(apertures)):
        aperture = apertures[i]
        x, y = aperture.positions[0]
        center = PixCoord(x=x, y=y)
        theta = Angle(aperture.theta / np.pi * 180., 'deg')
        reg = EllipsePixelRegion(center=center,
                                 width=aperture.a * 2,
                                 height=aperture.b * 2,
                                 angle=theta)
        patch = reg.as_artist(facecolor='none', edgecolor='red', lw=2)
        fig, axi = plt.subplots(1, 1, figsize=(10, 12.5))
        axi.add_patch(patch)
        mask_set = reg.to_mask(mode='center')
        mask = mask_set.to_image((len(img), len(img)))
        axi.imshow(mask, origin='lower')
        plt.close()
        if i != c_index:
            obj_masks.append(mask)
        elif i == c_index:
            target_mask = mask
    if obj_masks == []:
        obj_masks.append(np.zeros_like(img))
    if return_deblend == False:
        return target_mask, obj_masks
    else:
        return target_mask, obj_masks, segm_deblend
Пример #11
0
kernel = Gaussian2DKernel(sigma, x_size=3, y_size=3)
kernel.normalize()
segm = detect_sources(green_avg, threshold, npixels=5, filter_kernel=kernel)
npixels = 5

segm_deblend = deblend_sources(green_avg, segm, npixels=npixels,
                                filter_kernel=kernel, nlevels=32,
                                contrast=0.001)
cat = source_properties(green_avg, segm)
r=3
apertures = []
for obj in cat:
    position = (obj.xcentroid.value, obj.ycentroid.value)
    a = obj.semimajor_axis_sigma.value * rastro_peaks.py
    b = obj.semiminor_axis_sigma.value * r
    theta = obj.orientation.value
    apertures.append(EllipticalAperture(position, a, b, theta=theta))


norm = ImageNormalize(stretch=SqrtStretch())
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 12.5))
ax1.imshow(green_avg, origin='lower', cmap='Greys_r', norm=norm)
ax1.set_title('Data')
ax2.imshow(segm, origin='lower', cmap=segm.cmap(random_state=12345))
ax2.set_title('Segmentation Image')

for aperture in apertures:
    aperture.plot(color='white', lw=1.5, ax=ax1)
    aperture.plot(color='white', lw=1.5, ax=ax2)

plt.show()
Пример #12
0
def measure_flux(fitsimage,
                 detections=None,
                 pixel_coords=None,
                 skycoords=None,
                 method='single-aperture',
                 a=None,
                 b=None,
                 theta=None,
                 n_boostrap=100,
                 minimal_aperture_size=1,
                 aperture_size=None,
                 aperture_scale=6.0,
                 gaussian_segment_scale=4.0,
                 plot=False,
                 ax=None,
                 color='white',
                 debug=False):
    """Accurate flux measure

    Args:
        fitsimage: the FitsImage class
        detections: astropy.table, including all source position and shapes
        pixel_coords: the pixel coordinates of the detections
        skycoords: the sky coordinates of the detections.
        aperture_size: the fixed size of the aperture, in arcsec
        a,b,theta: the size of the source, in arcsec and deg
        minimal_aperture_size: if the aperture_size is None, this can control the
            minial aperture_size for the fain source, where the adaptive aperture 
            could not be securely measured
        aperture_scale: the source shape determined aperture, lower priority than
                        aperture_size
    Note:
        When several coordinates parameters are provided, detections has the
        higher priority
    """
    pixel2arcsec = fitsimage.pixel2deg_ra * 3600
    arcsec2pixel = 1 / pixel2arcsec
    if detections is not None:
        if len(detections) < 1:
            print('No source founded...')
            return None, None
        dets_colnames = detections.colnames
        # if ('x' in dets_colnames) and ('y' in dets_colnames):
        # pixel_coords = np.array(list(zip(detections['x'], detections['y'])))
        if ('ra' in dets_colnames) and ('dec' in dets_colnames):
            ra = np.array([detections['ra']])
            dec = np.array([detections['dec']])
            skycoords = SkyCoord(ra.flatten(), dec.flatten(), unit='deg')
            pixel_coords = np.array(
                list(zip(*skycoord_to_pixel(skycoords, fitsimage.wcs))))
        if aperture_scale is not None:
            if a is None:  # in arcsec
                if 'a' in detections.colnames:
                    a = detections['a']
                else:
                    a = fitsimage.bmaj * 0.5 * 3600
            if b is None:
                if 'b' in detections.colnames:
                    b = detections['b']
                else:
                    b = fitsimage.bmin * 0.5 * 3600
            if theta is None:  # in deg
                if 'theta' in detections.colnames:
                    theta = detections['theta']
                else:
                    theta = fitsimage.bpa
    elif skycoords is not None:
        pixel_coords = np.array(
            list(zip(*skycoord_to_pixel(skycoords, fitsimage.wcs))))
        if a is None:
            a = fitsimage.bmaj * 0.5 * 3600
        if b is None:
            b = fitsimage.bmin * 0.5 * 3600
        if theta is None:
            theta = fitsimage.bpa  # in deg
    elif pixel_coords is not None:
        if a is None:
            a = fitsimage.bmaj * 0.5 * 3600
        if b is None:
            b = fitsimage.bmin * 0.5 * 3600
        if theta is None:
            theta = fitsimage.bpa  # in deg
    else:
        print("Nothing to do...")
        return None, None
    n_sources = len(pixel_coords)

    # define aperture for all the detections
    if aperture_scale is not None:
        if isinstance(a, (tuple, list, np.ndarray)):
            a_aper = aperture_scale * a * arcsec2pixel
            # a_aper = aperture_scale*a*u.arcsec
        else:
            a_aper = np.full(n_sources, aperture_scale * a * arcsec2pixel)
        if isinstance(b, (tuple, list, np.ndarray)):
            b_aper = aperture_scale * b * arcsec2pixel
            # b_aper = aperture_scale*b*u.arcsec
        else:
            b_aper = np.full(n_sources, aperture_scale * b * arcsec2pixel)
        if minimal_aperture_size is not None:
            minimal_aperture_size_in_pixel = minimal_aperture_size * arcsec2pixel
            a_aper[
                a_aper <
                minimal_aperture_size_in_pixel] = minimal_aperture_size_in_pixel
            b_aper[
                b_aper <
                minimal_aperture_size_in_pixel] = minimal_aperture_size_in_pixel
        if not isinstance(theta, (tuple, list, np.ndarray)):
            theta = np.full(n_sources, theta)
    if aperture_size is not None:
        aperture_size_pixel = aperture_size * arcsec2pixel
        a_aper = np.full(n_sources, aperture_size_pixel)
        b_aper = np.full(n_sources, aperture_size_pixel)
        theta = np.full(n_sources, 0)
    apertures = []
    for i, coord in enumerate(pixel_coords):
        apertures.append(
            EllipticalAperture(coord, a_aper[i], b_aper[i], theta[i]))
        # apertures.append(SkyEllipticalAperture(skycoords, a_aper[i], b_aper[i], theta[i]))
    detections_mask = np.zeros(fitsimage.imagesize, dtype=bool)
    for mask in apertures:
        image_aper_mask = mask.to_mask().to_image(shape=fitsimage.imagesize)
        if image_aper_mask is not None:
            detections_mask = detections_mask + image_aper_mask
        else:
            continue
    detections_mask = (detections_mask > 0) | fitsimage.imagemask

    detections_apers = []
    flux = np.zeros(n_sources)
    fluxerr = np.zeros(n_sources)
    if method == 'single-aperture':
        # measuring flux density
        for i, aper in enumerate(apertures):
            x, y = pixel_coords[i]
            pixel_fluxscale = 1. / (fitsimage.beamsize)
            detections_apers.append(
                EllipticalAperture([x, y], a_aper[i], b_aper[i], theta[i]))
            if fitsimage.has_pbcor:
                phot_table = aperture_photometry(fitsimage.image_pbcor,
                                                 aper,
                                                 mask=fitsimage.imagemask)
            else:
                phot_table = aperture_photometry(fitsimage.image,
                                                 aper,
                                                 mask=fitsimage.imagemask)
            flux[i] = phot_table['aperture_sum'].value * pixel_fluxscale
            # measuring the error of flux density
            # run the boostrap for random aperture with the image
            pixel_x = np.random.random(n_boostrap) * fitsimage.imagesize[
                1]  # 1 for x axis
            pixel_y = np.random.random(n_boostrap) * fitsimage.imagesize[
                0]  # 0 for y axis
            # points_select = (pixel_x**2 + pixel_y**2) < (np.min(fitsimage.imagesize)-np.max([a,b]))**2
            # points_select = (pixel_x-**2 + pixel_y**2) > (np.max([a,b]))**2
            # pixel_coords_boostrap = np.vstack([pixel_x[points_select], pixel_y[points_select]]).T
            pixel_coords_boostrap = np.vstack([pixel_x, pixel_y]).T
            apertures_boostrap = EllipticalAperture(pixel_coords_boostrap,
                                                    a_aper[i], b_aper[i],
                                                    theta[i])
            noise_boostrap = aperture_photometry(fitsimage.image,
                                                 apertures_boostrap,
                                                 mask=detections_mask)
            fluxerr[i] = np.std(
                np.ma.masked_invalid(
                    noise_boostrap['aperture_sum'])) * pixel_fluxscale
            # fluxerr[i] = np.std(noise_boostrap['aperture_sum']) * pixel_fluxscale
            if fitsimage.has_pbcor:
                pixel_pbcor = 1. / fitsimage.image_pb[int(np.round(x)),
                                                      int(np.round(y))]
                fluxerr[i] = fluxerr[i] * pixel_pbcor
    if method == 'gaussian':
        seg_size = gaussian_segment_scale * np.int(fitsimage.bmaj_pixel)
        segments = RectangularAperture(pixel_coords,
                                       seg_size,
                                       seg_size,
                                       theta=0)
        segments_mask = segments.to_mask(method='center')
        for i, s in enumerate(segments_mask):
            x, y = pixel_coords[i]
            pixel_fluxscale = 1 / (fitsimage.beamsize)
            image_cutout = s.cutout(fitsimage.image)
            gaussian_fitting = gaussian_2Dfitting(image_cutout, debug=debug)
            flux[i] = gaussian_fitting['flux'] * pixel_fluxscale
            # boostrap for noise measurement
            a_fitted_aper = 1.0 * 2.355 * gaussian_fitting[
                'x_stddev']  # 2xFWHM of gaussian
            b_fitted_aper = 1.0 * 2.355 * gaussian_fitting['y_stddev']
            theta_fitted = gaussian_fitting['theta']
            detections_apers.append(
                EllipticalAperture([x, y], a_fitted_aper, b_fitted_aper,
                                   theta_fitted))
            pixel_x = np.random.random(n_boostrap) * fitsimage.imagesize[
                1]  # 1 for x axis
            pixel_y = np.random.random(n_boostrap) * fitsimage.imagesize[
                0]  # 0 for y axis
            pixel_coords_boostrap = np.vstack([pixel_x, pixel_y]).T
            apertures_boostrap = EllipticalAperture(pixel_coords_boostrap,
                                                    a_fitted_aper,
                                                    b_fitted_aper,
                                                    theta_fitted)
            noise_boostrap = aperture_photometry(fitsimage.image,
                                                 apertures_boostrap,
                                                 mask=detections_mask)
            fluxerr[i] = np.std(
                np.ma.masked_invalid(
                    noise_boostrap['aperture_sum'])) * pixel_fluxscale

            if fitsimage.has_pbcor:
                pixel_pbcor = 1. / fitsimage.image_pb[int(np.round(x)),
                                                      int(np.round(y))]
                flux[i] = flux[i] * pixel_pbcor
                fluxerr[i] = fluxerr[i] * pixel_pbcor

    if plot:
        if ax is None:
            fig, ax = plt.subplots(figsize=(8, 6))
        im = ax.imshow(fitsimage.image,
                       interpolation='nearest',
                       vmin=-0.2 * fitsimage.std,
                       vmax=10.0 * fitsimage.std,
                       origin='lower')
        plt.colorbar(im, fraction=0.046, pad=0.04)

        for i in range(n_sources):
            obj = pixel_coords[i]
            im = detections_apers[i].plot(color=color, lw=1, alpha=0.8)
            ax.text(
                obj[0],
                (1.0 - 2.0 * detections_apers[i].a / fitsimage.imagesize[0]) *
                obj[1],
                "{:.2f}mJy".format(flux[i] * 1e3),
                color=color,
                horizontalalignment='center',
                verticalalignment='top',
            )
        # # only for test
        # for ap in apertures_boostrap:
        # im = ap.plot(color='gray', lw=2, alpha=0.2)

    return flux, fluxerr
Пример #13
0
    def mask_detections(self,
                        detections=None,
                        aperture_scale=6,
                        aperture_size=None,
                        sky_coords=None,
                        pixel_coords=None,
                        a=None,
                        b=None,
                        theta=None,
                        minimal_aperture_size=None):
        # generate mask around all the detections

        if detections is not None:
            if len(detections) < 1:
                print('No source founded...')
                return None, None
            dets_colnames = detections.colnames
            if ('x' in dets_colnames) and ('y' in dets_colnames):
                pixel_coords = np.array(
                    list(zip(detections['x'], detections['y'])))
            elif ('ra' in dets_colnames) and ('dec' in dets_colnames):
                ra = np.array([detections['ra']])
                dec = np.array([detections['dec']])
                skycoords = SkyCoord(ra.flatten(), dec.flatten(), unit='deg')
                pixel_coords = np.array(
                    list(zip(*skycoord_to_pixel(skycoords, fitsimage.wcs))))
            if aperture_scale is not None:
                if a is None:
                    if 'a' in detections.colnames:
                        a = detections['a']
                    else:
                        a = self.bmaj_pixel
                if b is None:
                    if 'b' in detections.colnames:
                        b = detections['b']
                    else:
                        b = self.bmin_pixel
                if theta is None:
                    if 'theta' in detections.colnames:
                        theta = detections['theta']
                    else:
                        theta = self.bpa  # in deg
        elif sky_coords is not None:
            pixel_coords = np.array(
                list(zip(*skycoord_to_pixel(sky_coords, self.wcs))))
            if a is None:
                a = self.bmaj_pixel
            if b is None:
                b = self.bmin_pixel
            if theta is None:
                theta = self.bpa  # in deg
        elif pixel_coords is not None:
            if a is None:
                a = self.bmaj_pixel
            if b is None:
                b = self.bmin_pixel
            if theta is None:
                theta = self.bpa  # in deg
        else:
            print("Nothing to do...")
            return None, None
        n_sources = len(pixel_coords)

        # define aperture for all the detections
        if aperture_scale is not None:
            if isinstance(a, (tuple, list, np.ndarray)):
                a_aper = aperture_scale * a
            else:
                a_aper = np.full(n_sources, aperture_scale * a)
            if isinstance(b, (tuple, list, np.ndarray)):
                b_aper = aperture_scale * b
            else:
                b_aper = np.full(n_sources, aperture_scale * b)
            if minimal_aperture_size is not None:
                minimal_aperture_size_in_pixel = minimal_aperture_size / (
                    self.pixel2deg_ra * 3600)
                a_aper[
                    a_aper <
                    minimal_aperture_size_in_pixel] = minimal_aperture_size_in_pixel
                b_aper[
                    b_aper <
                    minimal_aperture_size_in_pixel] = minimal_aperture_size_in_pixel
            if not isinstance(theta, (tuple, list, np.ndarray)):
                theta = np.full(n_sources, theta)
        if aperture_size is not None:
            aperture_size_pixel = aperture_size / (3600 * self.pixel2deg_ra)
            a_aper = np.full(n_sources, aperture_size_pixel)
            b_aper = np.full(n_sources, aperture_size_pixel)
            theta = np.full(n_sources, 0)
        apertures = []
        for i, coord in enumerate(pixel_coords):
            apertures.append(
                EllipticalAperture(coord, a_aper[i], b_aper[i], theta[i]))
        detections_mask = np.zeros(self.imagesize, dtype=bool)
        for mask in apertures:
            image_aper_mask = mask.to_mask().to_image(shape=self.imagesize)
            if image_aper_mask is not None:
                detections_mask = detections_mask + image_aper_mask
            else:
                continue
        return detections_mask > 0
Пример #14
0
def prepare_data(file, data_dir, folder):
    """
    prepare_data picks a file with the image of the galaxy, detect the central object, rotate it to the major axis, and returns 
    the data and errors ready to fit a warp curve, along with the maximum distance from the center 

    """

    # check if there is a folder for the figures, if not create it

    if not os.path.isdir('../figs/' + str(folder)):
        os.mkdir('../figs/' + str(folder))

    # check if there is a folder for the text output, if not create it

    if not os.path.isdir('../output/' + str(folder)):
        os.mkdir('../output/' + str(folder))

    print(data_dir + '/' + str(file))

    hdu = fits.open(data_dir + '/' + str(file[:-1]))[
        0]  #fits.open(data_dir+'/'+str(file[:-1]))[0]
    wcs = WCS(hdu.header)

    data = hdu.data

    sigma_clip = SigmaClip(sigma=3., iters=10)
    bkg_estimator = MedianBackground()
    bkg = Background2D(data, (25, 25),
                       filter_size=(3, 3),
                       sigma_clip=sigma_clip,
                       bkg_estimator=bkg_estimator)

    if (cfg.DATA_TYPE == 'REAL'):
        weight = fits.open(data_dir + '/' + str(file[:-1]))[1].data
    else:
        weight = bkg.background_rms

    threshold = bkg.background + (3. * bkg.background_rms)

    sigma = 2.0 * gaussian_fwhm_to_sigma  # FWHM = 2.
    kernel = Gaussian2DKernel(sigma, x_size=3, y_size=3)
    kernel.normalize()
    segm = detect_sources(data, threshold, npixels=5, filter_kernel=kernel)

    rand_cmap = random_cmap(segm.max + 1, random_state=12345)
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 8))
    ax1.imshow(data, origin='lower', cmap='Greys_r')
    ax2.imshow(segm, origin='lower', cmap=rand_cmap)
    plt.savefig('../figs/' + str(folder) + '/' + str(file[:-5]) + 'fig2.png')
    plt.close()

    props = source_properties(data, segm)
    tbl = properties_table(props)

    my_min = 100000.

    x_shape = np.float(data.shape[0])
    y_shape = np.float(data.shape[1])

    r = 3.  # approximate isophotal extent
    apertures = []
    for prop in props:
        position = (prop.xcentroid.value, prop.ycentroid.value)
        a = prop.semimajor_axis_sigma.value * r
        b = prop.semiminor_axis_sigma.value * r
        theta = prop.orientation.value
        apertures.append(EllipticalAperture(position, a, b, theta=theta))
        my_dist = np.sqrt((prop.xcentroid.value - x_shape / 2.)**2 +
                          (prop.ycentroid.value - y_shape / 2.)**2)
        if (my_dist < my_min):
            my_label = prop.id - 1
            my_min = my_dist

    mytheta = props[my_label].orientation.value
    mysize = np.int(np.round(r * props[my_label].semimajor_axis_sigma.value))
    my_x = props[my_label].xcentroid.value
    my_y = props[my_label].ycentroid.value

    mask_obj = np.ones(data.shape, dtype='bool')
    mask_obj[(segm.data != 0) * (segm.data != props[my_label].id)] = 0

    weigth = weight[mask_obj]

    rand_cmap = random_cmap(segm.max + 1, random_state=12345)
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 8))
    ax1.imshow(data, origin='lower', cmap='Greys_r')
    ax2.imshow(segm, origin='lower', cmap=rand_cmap)
    for aperture in apertures:
        aperture.plot(color='blue', lw=1.5, alpha=0.5, ax=ax1)
        aperture.plot(color='white', lw=1.5, alpha=1.0, ax=ax2)
    plt.savefig('../figs/' + str(folder) + '/' + str(file[:-5]) + 'fig3.png')
    plt.close()

    data_rot = rotate(data, np.rad2deg(mytheta))
    data_rot = data_rot[data_rot.shape[0] / 2 - 100:data_rot.shape[0] / 2 +
                        100, data_rot.shape[1] / 2 -
                        100:data_rot.shape[1] / 2 + 100]

    w_rot = rotate(weight, np.rad2deg(mytheta))
    w = w_rot[w_rot.shape[0] / 2 - 100:w_rot.shape[0] / 2 + 100,
              w_rot.shape[1] / 2 - 100:w_rot.shape[1] / 2 + 100]

    plt.figure()
    plt.imshow(data_rot, origin='lower', cmap='Greys_r')
    plt.savefig('../figs/' + str(folder) + '/' + str(file[:-5]) + 'fig4.png')
    plt.close()

    newx, newy, newtheta, newsize = find_centroid(data_rot)
    print('old center = ', my_x, my_y, mysize)
    print('new center = ', newx, newy, np.rad2deg(newtheta), newsize)

    x_shape2 = np.float(data_rot.shape[0])
    y_shape2 = np.float(data_rot.shape[1])

    np.savetxt(
        '../output/' + str(folder) + '/' + str(file[:-5]) +
        '_size_xcent_ycent_xy_shape.txt',
        np.array([newsize, newx, newy, x_shape2, y_shape2]))

    return data_rot, w, newsize, newx, newy, x_shape2, y_shape2
     string=lines[l2[trust]].split('model_Sersic_result: ')[1])
 galaxy_mag = [
     galaxy_dic[i]['magnitude'] for i in range(len(galaxy_dic))
 ]
 host_mag_list[i] = galaxy_mag
 galaxy_pos = np.array(
     [[-1 * galaxy_dic[i]['center_x'], galaxy_dic[i]['center_y']]
      for i in range(len(galaxy_dic))])
 galaxy_pos = galaxy_pos / 0.168 + radius
 apertures = []
 for j in range(len(galaxy_dic)):
     a = galaxy_dic[j]['R_sersic'] / 0.168
     b = galaxy_dic[j]['R_sersic'] / 0.168 * galaxy_dic[j]['q']
     theta = galaxy_dic[j]['phi_G']
     apertures.append(
         EllipticalAperture(galaxy_pos[j], a, b, theta=theta))
 np.random.seed(seed=4)
 for j in range(len(AGN_pos)):
     label = None
     if i == 0:
         label = 'PS {0}'.format(j)
     axs[i].scatter(AGN_pos[j][0],
                    AGN_pos[j][1],
                    color=(np.random.uniform(0, 1),
                           np.random.uniform(0, 1),
                           np.random.uniform(0, 1)),
                    s=180,
                    marker=".",
                    label=label)
 np.random.seed(seed=3)
 for j in range(len(apertures)):
Пример #16
0
def std1dspec(infile, startz=2000, nsigma=5, overwrite=False):
    print('\n#############################')
    print('Making 1D spectrum')
                              
    hdl = fits.open(infile)
    hdr = hdl[0].header
    
    scidata = hdl[0].data
    binfac1 = hdr['BIN-FCT1']

    # Showing the image 
    aspect = 0.43/(0.104*binfac1)
    fig=plt.figure()
    plt.title('Click on the star. ')
    plt.imshow(scidata[startz,:,:], aspect=aspect, \
               interpolation='nearest', origin='lower')

    global xc,yc
    xc = 0.0
    yc = 0.0

    def star_center(event):
        global xc,yc
        xc= event.xdata
        yc = event.ydata
        plt.close()
        return

    
    cid = fig.canvas.mpl_connect('button_press_event', star_center)
    print('\n\t Click near the star center.')
    plt.show()

    print('\t Initial star location: (%.2f, %.2f)'%(xc,yc))
    initc = np.array((xc,yc))
    cutdata, initp = cutout(scidata[startz,:,:], initc ,w=10)
    g_init = Gaussian2D(amplitude=np.max(cutdata),
                         x_mean=initc[0]-initp[0],
                         y_mean=initc[1]-initp[1],
                         x_stddev=2.0,
                         y_stddev=1.0,
                         theta=3.1416/2)
    g_init.theta.fixed = True
    fitter = LevMarLSQFitter()
    y, x = np.indices(cutdata.shape)
    gfit = fitter(g_init, x, y, cutdata)
    print('\t Initial 2D Gaussian fitting result:')
    print(gfit)
    position0 = np.array([gfit.x_mean.value, gfit.y_mean.value])
    position0 = position0 + initp
    position = position0

    a = gfit.x_stddev.value * nsigma
    b = gfit.y_stddev.value * nsigma
    theta = gfit.theta.value

    plt.imshow(scidata[startz,:,:], aspect=aspect, \
               interpolation='nearest', origin='lower')
    apertures = EllipticalAperture(position, a=a ,b=b,theta=theta)
    apertures.plot()
    print('\n\t Check the aperture, and close the plot window.')
    plt.title('Check the aperture')
    plt.show()

    global coords, ii, std1ddata, lam

    std1ddata = np.zeros(scidata.shape[0], dtype=np.float32)
    positions = np.zeros((scidata.shape[0], 2), dtype=np.float)

    # Aperture photometry with incleasing wavelength pix from startz 
    for i in range(startz,scidata.shape[0]):
        cutdata, initp = cutout(scidata[i,:,:],position)
        if np.min(cutdata) == np.max(cutdata):
            print('\t Cutdata is empty at '+str(i)+' pix.')
            break
        position_pre = position
        position = centroid_com(cutdata)
        position = position + initp
        if np.linalg.norm(position-position_pre) > 2.:
            print('\t Cetroid is not good at '+str(i)+' pix.')
            break
        positions[i,:] = position
        #apertures = EllipticalAperture(position, a=a ,b=b,theta=theta)
        #phot_table = aperture_photometry(scidata[i,:,:], apertures)   
        #std1ddata[i] = phot_table['aperture_sum'].data[0]

    # Aperture photometry with decreasing wavelength pix from startz 
    position = position0
    for i in range(startz-1,0,-1):
        cutdata, initp = cutout(scidata[i,:,:],position)
        if np.min(cutdata) == np.max(cutdata):
            print('\t Cutdata is empty! at ' + str(i) + ' pix.')
            break
        position_pre = position
        position = centroid_com(cutdata)
        position = position + initp
        if np.linalg.norm(position-position_pre) > 2.:
            print('\t Cetroid is not good at ' + str(i) + ' pix.')
            break
        positions[i,:] = position
        #apertures = EllipticalAperture(position, a=a ,b=b,theta=theta)
        #phot_table = aperture_photometry(scidata[i,:,:], apertures)   
        #std1ddata[i] = phot_table['aperture_sum'].data[0]


    # Plotting the 1D data & selecting the spectral range.
    crpix = hdr['CRPIX3']
    crval = hdr['CRVAL3']
    #cdelt = hdr['CDELT3']
    cdelt = hdr['CD3_3']
    object_name = hdr['OBJECT']

    npix = len(std1ddata)
    start = crval - (crpix-1)*cdelt
    stop = crval + (npix - crpix + 0.5)*cdelt
    lam = np.arange(start ,stop, cdelt)
    
    plt.plot(lam,positions[:,0])
    plt.title(object_name)
    plt.xlabel('Lambda (Angstrom)')
    plt.ylabel('X (pix)')
    plt.grid()
    plt.show()

    plt.plot(lam,positions[:,1])
    plt.title(object_name)
    plt.xlabel('Lambda (Angstrom)')
    plt.ylabel('Y (pix)')
    plt.grid()
    plt.show()
    
    return