Exemplo n.º 1
0
def aperture_photometry_scan(data,
                             x_pos,
                             y_pos,
                             ap_width,
                             ap_length,
                             theta=0.0,
                             show=False,
                             plt_title=None):
    """Aperture photometry on source located on x_pos, y_pos with
    rectangular aperture of dimensions specified by ap_length, ap_width
    is used. Aperture sums are NOT sky subtracted.

    Parameters
    ----------
    data : `np.array`
        2D array of floats
    x_pos : float
        X position of source.
    y_pos : float
        Y position of source
    ap_width : int
        Width (along x axis) of photometric aperture.
    ap_length : int
        Length (along y axis) of photometric aperture.
    theta : float
        Angle of orientation (from x-axis) for aperture, in radians.
        Increases counter-clockwise.
    show : bool, optional
        If true, plot showing aperture(s) on source will pop up. Defaults to F.
    plt_title : str or None, optional
        Only used if `show` is True. Title for plot. Defaults to None.
    Returns
    -------
    phot_tab : `astropy.table`
        Table containing
    """

    copy_data = copy.copy(data)

    rect_ap = RectangularAperture((x_pos, y_pos),
                                  w=ap_width,
                                  h=ap_length,
                                  theta=theta)

    phot_table = aperture_photometry(copy_data, rect_ap, method='exact')
    if show:
        mask = rect_ap.to_mask(method='center')
        data_cutout = mask.cutout(data)
        plt.title(plt_title)
        z1, z2 = (-12.10630989074707, 32.53888328838081)
        plt.imshow(data, origin='lower', vmin=z1, vmax=z2)
        rect_ap.plot(color='white', lw=2)
        plt.show()
        plt.close()

    return phot_table
Exemplo n.º 2
0
def asymmetric_elongated_aperture_photom(scidata, starts, inverted, jpeg='', plot=False, sat_adu = 16383, spectral_band='G'):
    '''
    Compute photometry using rectangular apertures.
    This is a good method to use for "April 2014" de Bruijn encoding
    '''
    logger = logging.getLogger()
    
    logger.debug(f'science image is dimensions: {np.shape(scidata)}')
    
    match, factor = table_matches_image(starts, scidata)
    if not match:
        logger.warning(f'table data does not match image data. Dividing table coordinates by a factor of {factor:.2f} to table data (spectral band is {spectral_band})')
        starts['x_image'] /= factor
        starts['y_image'] /= factor
    
    positions, radii, thetas = aperture_centers_weighted_start_differential(starts)

    # get median pixel value inside the fireball bounding box
    median_bckgnd = np.median(get_bounding_box(scidata, starts))


    if plot:
        plt.close()
        fig = plt.gcf()
        ax = fig.gca()
        plt.imshow(jpeg, cmap=plt.cm.gray)

    starts['aperture_sum'] = np.nan
    starts['bckgng_sub_measurements'] = np.nan
    starts['SNR'] = np.nan
    starts['signal'] = np.nan
    starts['exp_time'] = np.nan
    starts['aperture_sum_err'] = np.nan
    starts['aperture_sum_err_plus'] = np.nan
    starts['aperture_sum_err_minus'] = np.nan
    starts['aperture_saturated'] = False

    for i in range(len(starts)-1):
        starts[i]['exp_time'] = LC_open_time(starts, i, i+1, inverted)

    for el, pos, radius, theta in zip(starts[:-1], positions, radii, thetas):
        
        #zero_order_light = scidata[int(pos[1])][int(pos[0])]
        
        aperture = RectangularAperture(pos, w=radius*2, h=7.*2, theta=theta) # 7
        
        # determine if any of the pixels in the aperture have reached saturation level,
        # flag accordingly
        aperture_mask = aperture.to_mask('center')
        aperture_values = aperture_mask.multiply(scidata)
        if np.any(aperture_values == sat_adu):
            el['aperture_saturated'] = True
        
        
        # do photometry
        aperture_result = aperture_photometry(scidata, aperture, method='subpixel', subpixels=16)
        
        
        el['aperture_sum'] = aperture_result['aperture_sum'].data
        #el['aperture_sum_err'] = aperture_result['aperture_sum_err'].data TODO FIXME
        
        el['bckgng_sub_measurements'] = el['aperture_sum'] -  aperture.area*median_bckgnd
        el['SNR'] = el['aperture_sum'] / np.sqrt(el['aperture_sum'] + aperture.area*median_bckgnd)
        el['aperture_sum_err_plus'] = 1/el['SNR']
        el['aperture_sum_err_minus'] = 1/el['SNR']
        if plot:
            aperture.plot(color='white')


    
    if plot:
        #min_x, min_y, max_x, max_y = get_bounds([p['x_image'] for p in points], pos2)
        ax.set_xlim([np.min(starts['x_image']), np.max(starts['x_image'])])
        ax.set_ylim([np.min(starts['y_image']), np.max(starts['y_image'])])
        
        full_path = starts.meta['self_file_name']
        dirname = os.path.dirname(full_path)
        basename = os.path.basename(full_path).split('.')[0]
        fname = os.path.join(dirname, basename + "_aperture_photometry_"+spectral_band+".jpg")
        plt.savefig(fname, dpi=150)

    return starts
Exemplo n.º 3
0
def do_Rect_phot(pos, FWHM, trail, ap_min=3., ap_factor=1.5, \
                 win=None, wout=None, hout=None,\
                 sky_nsigma=3., sky_iter=10 ):
    if win == None:
        win  = 4 * FWHM + trail
    if wout == None:
        wout = 8 * FWHM + trail
    if hout == None:
        hout = 8 * FWHM
    N = len(pos)
    if pos.ndim == 1:
        N = 1
    theta    = give_theta(number_of_stars=5)
    an       = RectAn(pos, w_in=win, w_out=wout, h_out=hout, theta=theta)
    ap_size  = np.max([ap_min, ap_factor*FWHM])
    aperture = RectAp(pos, w=(trail+ap_size), h=ap_size, theta=theta)
    flux     = aperture.do_photometry(image_reduc, method='exact')[0]
    # do phot and get sum from aperture. [0] is sum and [1] is error.
    #For test:
#FWHM = FWHM_moffat.copy()
#trail=trail_len.copy()
#win  = 4 * FWHM + trail
#wout = 8 * FWHM + trail
#hout = 8 * FWHM
#N=len(pos_star_fit)
#an       = RectAn(pos_star_fit, w_in=win, w_out=wout, h_out=hout, theta=(theta+np.pi/2))
#ap_size  = 1.5*FWHM_moffat
#aperture = RectAp(pos_star_fit, w=(trail+ap_size), h=ap_size, theta=(theta+np.pi/2))
#flux     = aperture.do_photometry(image_reduc, method='exact')[0]
#plt.figure(figsize=(12,12))
#plt.imshow(image_reduc, origin='lower', vmin=-10, vmax=1000)
#an.plot(color='white')
#aperture.plot(color='red')
    flux_ss  = np.zeros(N)
    error    = np.zeros(N)
    for i in range(0, N):
        mask_an    = (an.to_mask(method='center'))[i]
        #   cf: test = mask_an.cutout(image_reduc) <-- will make cutout image.
        sky_an     = mask_an.apply(image_reduc)
        all_sky    = sky_an[np.nonzero(sky_an)]
        # only annulus region will be saved as np.ndarray
        msky, stdev, nsky, nrej = sky_fit(all_sky, method='Mode', mode_option='sex')
        area       = aperture.area()
        flux_ss[i] = flux[i] - msky*area  # sky subtracted flux
        error[i]   = np.sqrt( flux_ss[i]/gain \
                           + area * stdev**2 \
                           + area**2 * stdev**2 / nsky )
        if inputs.star_img_save:
            from matplotlib import pyplot as plt
            mask_ap    = (aperture.to_mask(method='exact'))[i]
            star_ap_ss = mask_ap.apply(image_reduc-msky)
            sky_an_ss  = mask_an.apply(image_reduc-msky)
            plt.suptitle('{0}, Star ID={1} ({nsky:3d} {nrej:3d} {msky:7.2f} {stdev:7.2f})'.format(
                    inputs.filename, i, nsky=nsky, nrej=nrej, msky=msky, stdev=stdev ))
            ax1 = plt.subplot(1,2,1)
            im1 = ax1.imshow(sky_an_ss, origin='lower')
            plt.colorbar(im1, orientation='horizontal')
            ax2 = plt.subplot(1,2,2)
            im2 = ax2.imshow(star_ap_ss, origin='lower')
            plt.colorbar(im2, orientation='horizontal')
            plt.savefig('{0}.star{1}.png'.format(inputs.filename, i))
            plt.clf()
        if pos.ndim > 1:
            print('\t[{x:7.2f}, {y:7.2f}], {nsky:3d} {nrej:3d} {msky:7.2f} {stdev:7.2f} {flux:7.1f} {ferr:3.1f}'.format(\
                          x=pos[i][0], y=pos[i][1], \
                          nsky=nsky, nrej=nrej, msky=msky, stdev=stdev,\
                          flux=flux_ss[i], ferr=error[i]))
    return flux_ss, error
Exemplo n.º 4
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