Esempio n. 1
0
def _getCircularFraction(image: np.ndarray, centroid: List[float],
                         radius: float, fraction: float) -> float:
    '''Function determines the radius of a circle that encloses a fraction of
       the total light.

    Parameters
    ----------

    image : float, 2d np.ndarray
        Image of galaxy

    centroid : List[float]
        Location of the brightest pixel

    radius : float
        Radius in which to measure galaxy light out to. This is usually Rmax.

    fraction : float
        The fraction of the total galaxy light for the circle to enclose.


    Returns
    -------

    radiusOut : float
        The radius of the circle that encloses fraction of light

    '''

    apeture_total = CircularAperture(centroid, radius)
    totalSum = apeture_total.do_photometry(image, method="exact")[0][0]

    # number of points for grid
    npoints = float(200)

    # grid spacing
    deltaRadius = (radius / npoints) * 2.
    radiusCurrent = radius - deltaRadius
    radiusMin = 0
    radiusMax = 0

    # loop until bracketing values are found for the root at which is
    # our desired radius.
    while True:
        apCur = CircularAperture(centroid, radiusCurrent)
        currentSum = apCur.do_photometry(image, method="exact")[0][0]
        currentFraction = currentSum / totalSum
        if currentFraction <= fraction:
            radiusMin = radiusCurrent
            radiusMax = radiusCurrent + deltaRadius
            break
        radiusCurrent -= deltaRadius

    radiusOut = brentq(_fractionTotalFLuxCircle,
                       radiusMin,
                       radiusMax,
                       args=(image, centroid, totalSum, fraction))

    return radiusOut
Esempio n. 2
0
def measure_source_fwhm(detection, data, rmax=10):
    """
    TO USE CAREFULLY
    Function used to estimate the FWHM of a source.
    It performs aperture photometry with inscreasing radius from the source position, and then, tries to find where half of the maximum of flux is reached.

    Parameters
    ----------
    detection : :class:`~pandas:pandas.Series`
        Row of a DataFrame containing detected sources. Should have columns ``xcentroid`` and ``ycentroid``, in classic convention (not astropy)
    data : 2D :class:`~numpy:numpy.ndarray`
        Flux map used for the photometry
    """
    x, y = np.array(detection[['xcentroid', 'ycentroid']])
    photo_flux = np.zeros(rmax)
    for r in range(rmax):
        if r == 0:
            aper = CircularAperture((x, y), 1.)
        else:
            aper = CircularAnnulus((x, y), r, r + 1)
        photo_flux[r] = aper.do_photometry(data)[0] / aper.area()

    def get_fwhm(flux):
        #We assume max is on 0. If not, source is probably contaminated
        flux = flux - flux.min()
        spline = UnivariateSpline(np.arange(rmax), flux - flux[0] / 2., s=0)
        if spline.roots().shape != (1, ):
            return np.nan
        return spline.roots()[0]

    return (get_fwhm(photo_flux))
Esempio n. 3
0
def snr_astropy(image,sx,sy,r,r_in,r_out):
    """
    Returns signal to noise ratio, signal value, noise value using Astropy's Photutils module
    Args:
        image (2d float array): Image array extracted from fits file
        sx,sy (float): x and y pixel locations for the center of the source
        r (float): radius for aperture
        r_in,r_out (float): inner and outer radii for annulus
    Return:
        snr (float): signal-to-noise ratio
        signal (float): sum of all pixel values within the specified aperture minus sky background
        noise (float): noise in the signal calculated as std deviation of pixels in the sky annulus times sqrt of the area of the
        signal aperture
        poisson_noise (float): snr determined from the poisson noise in the source signal.  Poisson noise = sqrt(counts) [because variance
        of a poisson distribution is the parameter itself].  Poisson snr = Signal/sqrt(signal) = sqrt(signal)
    Written by: Logan Pearce, 2018
    """
    import warnings
    warnings.filterwarnings('ignore')
    from photutils import CircularAperture, CircularAnnulus
    positions = (cx-1,cy-1)
    ap = CircularAperture(positions,r=r)
    skyan = CircularAnnulus(positions,r_in=11,r_out=14)
    apsum = ap.do_photometry(image)[0]
    skysum = skyan.do_photometry(image)[0]
    averagesky = skysum/skyan.area()
    signal = (apsum - ap.area()*averagesky)[0]
    n = ap.area()
    ap_an = aperture_annulus(sx,sy,r,r_in,r_out)
    skyan = ap_an[1]
    poisson_noise = np.sqrt(signal)
    noise = noise = np.std(image[skyan[1],skyan[0]])
    noise = noise*np.sqrt(n)
    snr = signal/noise
    return snr,signal,noise,poisson_noise
Esempio n. 4
0
def estimate_photometric_precision_full(image: np.ndarray, sources: Table, fwhm: float, effective_gain: float = 1):
    """
    Estimate the possible position precision for stars in an image based on the SNR and the PSF FWHM.
    The signal is summed over a circular aperture with radius = fwhm, the error the geometric mean
    within this aperture.
    see. Lindegren, Lennart. “Photoelectric Astrometry - A Comparison of Methods for Precise Image Location.”

    :param image: input exposure
    :param sources: table with 'x' and 'y' columns in pixel coordinates
    :param fwhm: Full width at half maximum for the PSF of the image
    :param effective_gain: gain/quantum_efficiency
    :return: list of computed σ_pos same order as sources in table
    """
    # Idea: use aperture photometry to sum the signal, internally it will perform quadratic mean
    #  of pixel errors, so for each star we have signal and error.
    mean, median, std = sigma_clipped_stats(image, sigma=3.0)
    bkg_error = std
    error_img = calc_total_error(image, bkg_error, effective_gain)

    xy = np.array((sources['x'], sources['y'])).T
    apertures = CircularAperture(xy, r=fwhm)
    signals, errors = apertures.do_photometry(image-median, error_img)

    # sometimes signal is negative over FWHM, avoid negative sigma
    sigma_pos = np.abs(fwhm/(signals/errors))
    return sigma_pos
Esempio n. 5
0
def do_Circ_phot(pos, FWHM, ap_min=3., ap_factor=1.5, rin=None, rout=None, \
                   sky_nsigma=3., sky_iter=10):
    '''
    In rigorous manner, we should use
    error = sqrt (flux / epadu + area * stdev**2 + area**2 * stdev**2 / nsky)
    as in http://stsdas.stsci.edu/cgi-bin/gethelp.cgi?phot .
    Here flux == aperture_sum - sky, i.e., flux from image_reduc.
        stdev should include sky error AND ronoise.
    '''
    if rin == None:
        rin  = 4 * FWHM
    if rout == None:
        rout = 6 * FWHM
    N = len(pos)
    if pos.ndim == 1:
        N = 1
    an       = CircAn(pos, r_in=rin, r_out=rout)
    ap_size  = np.max([ap_min, ap_factor*FWHM])
    aperture = CircAp(pos, r=ap_size)
    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:
#N=len(pos_star_fit)
#an       = CircAn(pos_star_fit, r_in=4*FWHM_moffat, r_out=6*FWHM_moffat)
#ap_size  = 1.5*FWHM_moffat
#aperture = CircAp(pos_star_fit, r=ap_size)
#flux     = aperture.do_photometry(image_reduc, method='exact')[0]
    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 )
# To know rejected number, uncomment the following.
#        plt.imshow(sky_an, cmap='gray_r', vmin=-20)
#        plt.colorbar()
#        plt.show()
#        mask_ap  = (aperture.to_mask(method='exact'))[i]
#        star_ap  = mask_ap.apply(image_reduc)
#        plt.imshow(star_ap)
#        plt.colorbar()
#        plt.show()
#        plt.cla()
        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
Esempio n. 6
0
def starbright(fnstar, fnflat, istar, axs, fg):
    # %% load data
    data = meanstack(fnstar, 100)[0]
    # %% flat field
    flatnorm = readflat(fnflat, fnstar)
    data = (data / flatnorm).round().astype(data.dtype)
    # %% background
    mean, median, std = sigma_clipped_stats(data, sigma=3.0)

    rfact = data.shape[0] // 40
    cfact = data.shape[1] // 40
    bg = Background(data, (rfact, cfact), interp_order=1, sigclip_sigma=3)
    # http://docs.astropy.org/en/stable/units/#module-astropy.units
    # dataphot = (data - bg.background)*u.ph/(1e-4*u.m**2 * u.s * u.sr)
    #   data = (data-0.97*data.min()/bg.background.min()*bg.background) * u.ph/(u.cm**2 * u.s * u.sr)
    data = data * u.ph / (u.cm**2 * u.s * u.sr)
    # %% source extraction
    sources = daofind(data, fwhm=3.0, threshold=5 * std)
    # %% star identification and quantification
    XY = column_stack((sources["xcentroid"], sources["ycentroid"]))
    apertures = CircularAperture(XY, r=4.0)
    norm = ImageNormalize(stretch=SqrtStretch())

    flux = apertures.do_photometry(data, effective_gain=camgain)[0]
    # %% plots
    fg.suptitle("{}".format(fnflat.parent), fontsize="x-large")

    hi = axs[-3].imshow(flatnorm, interpolation="none", origin="lower")
    fg.colorbar(hi, ax=axs[-3])
    axs[-3].set_title("flatfield {}".format(fnflat.name))

    hi = axs[-2].imshow(bg.background, interpolation="none", origin="lower")
    fg.colorbar(hi, ax=axs[-2])
    axs[-2].set_title("background {}".format(fnstar.name))

    hi = axs[-1].imshow(data.value,
                        cmap="Greys",
                        origin="lower",
                        norm=norm,
                        interpolation="none")
    fg.colorbar(hi, ax=axs[-1])
    for i, xy in enumerate(XY):
        axs[-1].text(xy[0],
                     xy[1],
                     str(i),
                     ha="center",
                     va="center",
                     fontsize=16,
                     color="w")
    apertures.plot(ax=axs[-1], color="blue", lw=1.5, alpha=0.5)
    axs[-1].set_title("star {}".format(fnstar.name))

    return flux[istar]
Esempio n. 7
0
def compute_snr(x, y):
    positions = (x - 1, y - 1)
    ap = CircularAperture(positions, r=radius)
    skyan = CircularAnnulus(positions, r_in=11, r_out=14)
    ap = CircularAperture(positions, r=radius)
    skyan = CircularAnnulus(positions, r_in=11, r_out=14)
    apsum = ap.do_photometry(image)[0]
    skysum = skyan.do_photometry(image)[0]
    averagesky = skysum / skyan.area()
    signal = (apsum - ap.area() * averagesky)[0]
    n = ap.area()
    box = image[y + 12:y + 12 + 15, x + 12:x + 12 + 15]
    noise = np.std(box)
    noise = noise * np.sqrt(n)
    snr = signal / noise
    return snr
def starbright(fnstar,fnflat,istar,axs,fg):
    #%% load data
    data = meanstack(fnstar,100)[0]
    #%% flat field
    flatnorm = readflat(fnflat,fnstar)
    data = (data/flatnorm).round().astype(data.dtype)
    #%% background
    mean, median, std = sigma_clipped_stats(data, sigma=3.0)

    rfact=data.shape[0]//40
    cfact=data.shape[1]//40
    bg = Background(data,(rfact,cfact),interp_order=1, sigclip_sigma=3)
# http://docs.astropy.org/en/stable/units/#module-astropy.units
    #dataphot = (data - bg.background)*u.ph/(1e-4*u.m**2 * u.s * u.sr)
 #   data = (data-0.97*data.min()/bg.background.min()*bg.background) * u.ph/(u.cm**2 * u.s * u.sr)
    data = data* u.ph/(u.cm**2 * u.s * u.sr)
    #%% source extraction
    sources = daofind(data, fwhm=3.0, threshold=5*std)
    #%% star identification and quantification
    XY = column_stack((sources['xcentroid'], sources['ycentroid']))
    apertures = CircularAperture(XY, r=4.)
    norm = ImageNormalize(stretch=SqrtStretch())

    flux = apertures.do_photometry(data,effective_gain=camgain)[0]
#%% plots
    fg.suptitle('{}'.format(fnflat.parent),fontsize='x-large')

    hi = axs[-3].imshow(flatnorm,interpolation='none',origin='lower')
    fg.colorbar(hi,ax=axs[-3])
    axs[-3].set_title('flatfield {}'.format(fnflat.name))

    hi = axs[-2].imshow(bg.background,interpolation='none',origin='lower')
    fg.colorbar(hi,ax=axs[-2])
    axs[-2].set_title('background {}'.format(fnstar.name))

    hi = axs[-1].imshow(data.value,
                    cmap='Greys', origin='lower', norm=norm,interpolation='none')
    fg.colorbar(hi,ax=axs[-1])
    for i,xy in enumerate(XY):
        axs[-1].text(xy[0],xy[1], str(i),ha='center',va='center',fontsize=16,color='w')
    apertures.plot(ax=axs[-1], color='blue', lw=1.5, alpha=0.5)
    axs[-1].set_title('star {}'.format(fnstar.name))

    return flux[istar]
Esempio n. 9
0
def _fractionTotalFLuxCircle(radius: float, image: np.ndarray,
                             centroid: List[float], totalSum: float,
                             fraction: float) -> float:
    r'''Helper function to help find the radius of a circle that encloses a
       fraction of the total light in the galaxy of interest.


    Parameters
    ----------

    radius : float
        Radius in which to measure galaxy light out to. This is usually Rmax.

    image : float, 2d np.ndarray
        Image of galaxy

    centroid : List[float]
        Location of the brightest pixel

    totalSum : float
        The total amount of light in the galaxy.

    fraction : float
        The fraction of the total galaxy light for the circle to enclose.


    Returns
    -------

    root : float
        The fraction of light at the current radius minus the fraction,
        so that a root at 0 can be found.

    '''

    apetureCur = CircularAperture(centroid, radius)
    currentSum = apetureCur.do_photometry(image, method="exact")[0][0]

    root = (currentSum / totalSum) - fraction

    return root
Esempio n. 10
0
def tso_aperture_photometry(datamodel, xcenter, ycenter, radius, radius_inner,
                            radius_outer):
    """
    Create a photometric catalog for NIRCam TSO imaging observations.

    Parameters
    ----------
    datamodel : `CubeModel`
        The input `CubeModel` of a NIRCam TSO imaging observation.

    xcenter, ycenter : float
        The ``x`` and ``y`` center of the aperture.

    radius : float
        The radius (in pixels) of the circular aperture.

    radius_inner, radius_outer : float
        The inner and outer radii (in pixels) of the circular-annulus
        aperture, used for local background estimation.

    Returns
    -------
    catalog : `~astropy.table.QTable`
        An astropy QTable (Quantity Table) containing the source
        photometry.
    """

    if not isinstance(datamodel, CubeModel):
        raise ValueError('The input data model must be a CubeModel.')

    # For the SUB64P subarray with the WLP8 pupil, the circular aperture
    # extends beyond the image and the circular annulus does not have any
    # overlap with the image.  In that case, we simply sum all values
    # in the array and skip the background subtraction.
    sub64p_wlp8 = False
    if (datamodel.meta.instrument.pupil == 'WLP8'
            and datamodel.meta.subarray.name == 'SUB64P'):
        sub64p_wlp8 = True

    if not sub64p_wlp8:
        phot_aper = CircularAperture((xcenter, ycenter), r=radius)
        bkg_aper = CircularAnnulus((xcenter, ycenter),
                                   r_in=radius_inner,
                                   r_out=radius_outer)

    # convert the input data and errors from MJy/sr to Jy
    if datamodel.meta.bunit_data != 'MJy/sr':
        raise ValueError('data is expected to be in units of MJy/sr')
    factor = 1.e6 * datamodel.meta.photometry.pixelarea_steradians
    datamodel.data *= factor
    datamodel.err *= factor
    datamodel.meta.bunit_data = 'Jy'
    datamodel.meta.bunit_err = 'Jy'

    aperture_sum = []
    aperture_sum_err = []
    annulus_sum = []
    annulus_sum_err = []

    nimg = datamodel.data.shape[0]

    if sub64p_wlp8:
        info = ('Photometry measured as the sum of all values in the '
                'subarray.  No background subtraction was performed.')

        for i in np.arange(nimg):
            aperture_sum.append(np.sum(datamodel.data[i, :, :]))
            aperture_sum_err.append(np.sqrt(np.sum(datamodel.err[i, :, :]**2)))
    else:
        info = ('Photometry measured in a circular aperture of r={0} '
                'pixels.  Background calculated as the mean in a '
                'circular annulus with r_inner={1} pixels and '
                'r_outer={2} pixels.'.format(radius, radius_inner,
                                             radius_outer))
        for i in np.arange(nimg):
            aper_sum, aper_sum_err = phot_aper.do_photometry(
                datamodel.data[i, :, :], error=datamodel.err[i, :, :])
            ann_sum, ann_sum_err = bkg_aper.do_photometry(
                datamodel.data[i, :, :], error=datamodel.err[i, :, :])

            aperture_sum.append(aper_sum[0])
            aperture_sum_err.append(aper_sum_err[0])
            annulus_sum.append(ann_sum[0])
            annulus_sum_err.append(ann_sum_err[0])

    aperture_sum = np.array(aperture_sum)
    aperture_sum_err = np.array(aperture_sum_err)
    annulus_sum = np.array(annulus_sum)
    annulus_sum_err = np.array(annulus_sum_err)

    # construct metadata for output table
    meta = OrderedDict()
    meta['instrument'] = datamodel.meta.instrument.name
    meta['detector'] = datamodel.meta.instrument.detector
    meta['channel'] = datamodel.meta.instrument.channel
    meta['subarray'] = datamodel.meta.subarray.name
    meta['filter'] = datamodel.meta.instrument.filter
    meta['pupil'] = datamodel.meta.instrument.pupil
    meta['target_name'] = datamodel.meta.target.catalog_name
    meta['xcenter'] = xcenter
    meta['ycenter'] = ycenter
    ra_icrs, dec_icrs = datamodel.meta.wcs(xcenter, ycenter)
    meta['ra_icrs'] = ra_icrs
    meta['dec_icrs'] = dec_icrs
    meta['apertures'] = info

    # initialize the output table
    tbl = QTable(meta=meta)

    # check for the INT_TIMES table extension
    if hasattr(datamodel, 'int_times') and datamodel.int_times is not None:
        nrows = len(datamodel.int_times)
    else:
        nrows = 0
        log.warning("The INT_TIMES table in the input file is missing or "
                    "empty.")

    # load the INT_TIMES table data
    if nrows > 0:
        shape = datamodel.data.shape
        if len(shape) == 2:
            num_integ = 1
        else:  # len(shape) == 3
            num_integ = shape[0]
        int_start = datamodel.meta.exposure.integration_start
        if int_start is None:
            int_start = 1
            log.warning(f"INTSTART not found; assuming a value of {int_start}")

        # Columns of integration numbers & times of integration from the
        # INT_TIMES table.
        int_num = datamodel.int_times['integration_number']
        mid_utc = datamodel.int_times['int_mid_MJD_UTC']
        offset = int_start - int_num[0]  # both are one-indexed
        if offset < 0:
            log.warning("Range of integration numbers in science data extends "
                        "outside the range in INT_TIMES table.")
            log.warning("Can't use INT_TIMES table.")
            del int_num, mid_utc
            nrows = 0  # flag as bad
        else:
            log.debug("Times are from the INT_TIMES table")
            time_arr = mid_utc[offset:offset + num_integ]
            int_times = Time(time_arr, format='mjd', scale='utc')

    # compute integration time stamps on the fly
    if nrows == 0:
        log.debug("Times computed from EXPSTART and EFFINTTM")
        dt = datamodel.meta.exposure.integration_time
        n_dt = (datamodel.meta.exposure.integration_end -
                datamodel.meta.exposure.integration_start + 1)
        dt_arr = (np.arange(1, 1 + n_dt) * dt - (dt / 2.))
        int_dt = TimeDelta(dt_arr, format='sec')
        int_times = (Time(datamodel.meta.exposure.start_time, format='mjd') +
                     int_dt)

    # populate table columns
    unit = u.Unit(datamodel.meta.bunit_data)
    tbl['MJD'] = int_times.mjd
    tbl['aperture_sum'] = aperture_sum << unit
    tbl['aperture_sum_err'] = aperture_sum_err << unit

    if not sub64p_wlp8:
        tbl['annulus_sum'] = annulus_sum << unit
        tbl['annulus_sum_err'] = annulus_sum_err << unit

        if LooseVersion(photutils.__version__) >= '0.7':
            annulus_mean = annulus_sum / bkg_aper.area
            annulus_mean_err = annulus_sum_err / bkg_aper.area

            aperture_bkg = annulus_mean * phot_aper.area
            aperture_bkg_err = annulus_mean_err * phot_aper.area
        else:
            annulus_mean = annulus_sum / bkg_aper.area()
            annulus_mean_err = annulus_sum_err / bkg_aper.area()

            aperture_bkg = annulus_mean * phot_aper.area()
            aperture_bkg_err = annulus_mean_err * phot_aper.area()

        tbl['annulus_mean'] = annulus_mean << unit
        tbl['annulus_mean_err'] = annulus_mean_err << unit

        tbl['aperture_bkg'] = aperture_bkg << unit
        tbl['aperture_bkg_err'] = aperture_bkg_err << unit

        net_aperture_sum = aperture_sum - aperture_bkg
        net_aperture_sum_err = np.sqrt(aperture_sum_err**2 +
                                       aperture_bkg_err**2)
        tbl['net_aperture_sum'] = net_aperture_sum << unit
        tbl['net_aperture_sum_err'] = net_aperture_sum_err << unit
    else:
        colnames = [
            'annulus_sum', 'annulus_sum_err', 'annulus_mean',
            'annulus_mean_err', 'aperture_bkg', 'aperture_bkg_err'
        ]
        for col in colnames:
            tbl[col] = np.full(nimg, np.nan)

        tbl['net_aperture_sum'] = aperture_sum << unit
        tbl['net_aperture_sum_err'] = aperture_sum_err << unit

    return tbl
Esempio n. 11
0
def tso_aperture_photometry(datamodel, xcenter, ycenter, radius, radius_inner,
                            radius_outer):
    """
    Create a photometric catalog for NIRCam TSO imaging observations.

    Parameters
    ----------
    datamodel : `CubeModel`
        The input `CubeModel` of a NIRCam TSO imaging observation.

    xcenter, ycenter : float
        The ``x`` and ``y`` center of the aperture.

    radius : float
        The radius (in pixels) of the circular aperture.

    radius_inner, radius_outer : float
        The inner and outer radii (in pixels) of the circular-annulus
        aperture, used for local background estimation.

    Returns
    -------
    catalog : `~astropy.table.QTable`
        An astropy QTable (Quantity Table) containing the source
        photometry.
    """

    if not isinstance(datamodel, CubeModel):
        raise ValueError('The input data model must be a CubeModel.')

    # For the SUB64P subarray with the WLP8 pupil, the circular aperture
    # extends beyond the image and the circular annulus does not have any
    # overlap with the image.  In that case, we simply sum all values
    # in the array and skip the background subtraction.
    sub64p_wlp8 = False
    if (datamodel.meta.instrument.pupil == 'WLP8' and
            datamodel.meta.subarray.name == 'SUB64P'):
        sub64p_wlp8 = True

    if not sub64p_wlp8:
        phot_aper = CircularAperture((xcenter, ycenter), r=radius)
        bkg_aper = CircularAnnulus((xcenter, ycenter), r_in=radius_inner,
                                   r_out=radius_outer)

    aperture_sum = []
    aperture_sum_err = []
    annulus_sum = []
    annulus_sum_err = []

    nimg = datamodel.data.shape[0]

    if sub64p_wlp8:
        info = ('Photometry measured as the sum of all values in the '
               'subarray.  No background subtraction was performed.')

        for i in np.arange(nimg):
            aperture_sum.append(np.sum(datamodel.data[i, :, :]))
            aperture_sum_err.append(
                np.sqrt(np.sum(datamodel.err[i, :, :]**2)))
    else:
        info = ('Photometry measured in a circular aperture of r={0} '
                'pixels.  Background calculated as the mean in a '
                'circular annulus with r_inner={1} pixels and '
                'r_outer={2} pixels.'.format(radius, radius_inner,
                                                radius_outer))
        for i in np.arange(nimg):
            aper_sum, aper_sum_err = phot_aper.do_photometry(
                datamodel.data[i, :, :], error=datamodel.err[i, :, :])
            ann_sum, ann_sum_err = bkg_aper.do_photometry(
                datamodel.data[i, :, :], error=datamodel.err[i, :, :])

            aperture_sum.append(aper_sum[0])
            aperture_sum_err.append(aper_sum_err[0])
            annulus_sum.append(ann_sum[0])
            annulus_sum_err.append(ann_sum_err[0])

    aperture_sum = np.array(aperture_sum)
    aperture_sum_err = np.array(aperture_sum_err)
    annulus_sum = np.array(annulus_sum)
    annulus_sum_err = np.array(annulus_sum_err)

    # construct metadata for output table
    meta = OrderedDict()
    meta['instrument'] = datamodel.meta.instrument.name
    meta['detector'] = datamodel.meta.instrument.detector
    meta['channel'] = datamodel.meta.instrument.channel
    meta['subarray'] = datamodel.meta.subarray.name
    meta['filter'] = datamodel.meta.instrument.filter
    meta['pupil'] = datamodel.meta.instrument.pupil
    meta['target_name'] = datamodel.meta.target.catalog_name
    meta['xcenter'] = xcenter
    meta['ycenter'] = ycenter
    ra_icrs, dec_icrs = datamodel.meta.wcs(xcenter, ycenter)
    meta['ra_icrs'] = ra_icrs
    meta['dec_icrs'] = dec_icrs
    meta['apertures'] = info

    # initialize the output table
    tbl = QTable(meta=meta)

    if hasattr(datamodel, 'int_times') and datamodel.int_times is not None:
        nrows = len(datamodel.int_times)
    else:
        nrows = 0
    if nrows == 0:
        log.warning("There is no INT_TIMES table in the input file.")

    if nrows > 0:
        shape = datamodel.data.shape
        if len(shape) == 2:
            num_integ = 1
        else:                                   # len(shape) == 3
            num_integ = shape[0]
        int_start = datamodel.meta.exposure.integration_start
        if int_start is None:
            int_start = 1
            log.warning("INTSTART not found; assuming a value of %d",
                        int_start)

        # Columns of integration numbers & times of integration from the
        # INT_TIMES table.
        int_num = datamodel.int_times['integration_number']
        mid_utc = datamodel.int_times['int_mid_MJD_UTC']
        offset = int_start - int_num[0]                 # both are one-indexed
        if offset < 0:
            log.warning("Range of integration numbers in science data extends "
                        "outside the range in INT_TIMES table.")
            log.warning("Can't use INT_TIMES table.")
            del int_num, mid_utc
            nrows = 0                   # flag as bad
        else:
            log.debug("Times are from the INT_TIMES table.")
            time_arr = mid_utc[offset: offset + num_integ]
            int_times = Time(time_arr, format='mjd', scale='utc')
    else:
        log.debug("Times were computed from EXPSTART and TGROUP.")

        dt = (datamodel.meta.exposure.group_time *
              (datamodel.meta.exposure.ngroups + 1))
        dt_arr = (np.arange(1, 1 + datamodel.meta.exposure.nints) *
                  dt - (dt / 2.))
        int_dt = TimeDelta(dt_arr, format='sec')
        int_times = (Time(datamodel.meta.exposure.start_time, format='mjd') +
                     int_dt)

    tbl['MJD'] = int_times.mjd

    tbl['aperture_sum'] = aperture_sum
    tbl['aperture_sum_err'] = aperture_sum_err

    if not sub64p_wlp8:
        tbl['annulus_sum'] = annulus_sum
        tbl['annulus_sum_err'] = annulus_sum_err

        annulus_mean = annulus_sum / bkg_aper.area()
        annulus_mean_err = annulus_sum_err / bkg_aper.area()
        tbl['annulus_mean'] = annulus_mean
        tbl['annulus_mean_err'] = annulus_mean_err

        aperture_bkg = annulus_mean * phot_aper.area()
        aperture_bkg_err = annulus_mean_err * phot_aper.area()
        tbl['aperture_bkg'] = aperture_bkg
        tbl['aperture_bkg_err'] = aperture_bkg_err

        net_aperture_sum = aperture_sum - aperture_bkg
        net_aperture_sum_err = np.sqrt(aperture_sum_err ** 2 +
                                       aperture_bkg_err ** 2)
        tbl['net_aperture_sum'] = net_aperture_sum
        tbl['net_aperture_sum_err'] = net_aperture_sum_err
    else:
        colnames = ['annulus_sum', 'annulus_sum_err', 'annulus_mean',
                    'annulus_mean_err', 'aperture_bkg', 'aperture_bkg_err']
        for col in colnames:
            tbl[col] = np.full(nimg, np.nan)

        tbl['net_aperture_sum'] = aperture_sum
        tbl['net_aperture_sum_err'] = aperture_sum_err

    return tbl
Esempio n. 12
0
######################################### Compute signal to noise ########################################

import photometry

cx, cy = (np.int_(np.mean(xcc)), np.int_(np.mean(ycc)))
sx, sy = (np.int_(np.mean(xcs)), np.int_(np.mean(ycs)))
radius = 5
r_in, r_out = 11, 14

# Companion:
positions = (cx - 1, cy - 1)
ap = CircularAperture(positions, r=radius)
skyan = CircularAnnulus(positions, r_in=11, r_out=14)
ap = CircularAperture(positions, r=radius)
skyan = CircularAnnulus(positions, r_in=11, r_out=14)
apsum = ap.do_photometry(image)[0]
skysum = skyan.do_photometry(image)[0]
averagesky = skysum / skyan.area()
signal = (apsum - ap.area() * averagesky)[0]
n = ap.area()
box = image[cy + 12:cy + 12 + 15, cx + 12:cx + 12 + 15]
noise = np.std(box)
noise = noise * np.sqrt(n)
compsnr = signal / noise

# Star:
positions = (sx - 1, sy - 1)
ap = CircularAperture(positions, r=radius)
skyan = CircularAnnulus(positions, r_in=11, r_out=14)
ap = CircularAperture(positions, r=radius)
skyan = CircularAnnulus(positions, r_in=11, r_out=14)
def analyzeImages(X):
    # create database
    f = open(starDataBases[X], "wb")

    # retrieve data
    hdu = fits.open('./HRData.fits')
    data814 = hdu[0].data[0, :, :]
    data275 = hdu[0].data[2, :, :]
    hdu.close()

    mean814, median814, std814 = sigma_clipped_stats(data814,
                                                     sigma=3.0,
                                                     iters=5)
    daofind814 = DAOStarFinder(fwhm=3.0, threshold=4. * std814)

    mean275, median275, std275 = sigma_clipped_stats(data275,
                                                     sigma=3.0,
                                                     iters=5)
    daofind275 = DAOStarFinder(fwhm=3.0, threshold=4. * std275)

    ## perform photometry analysis
    # both apertures
    if (X == 1):
        print("Find stars from F814W Filter Data")
        sources814 = daofind814(data814 - median814)
        print("Finished F814W Search")

        print("Find stars from F275W Filter Data")
        sources275 = daofind275(data275 - median275)
        print("Finished F275 Search")

        positions814 = (sources814['xcentroid'], sources814['ycentroid'])
        apertures814 = CircularAperture(positions814, r=4.)
        photom814 = apertures814.do_photometry(data814 - median814)

        positions275 = (sources275['xcentroid'], sources275['ycentroid'])
        apertures275 = CircularAperture(positions275, r=4.)
        photom275 = apertures275.do_photometry(data275 - median275)

    # apertures from infrared
    elif (X == 2):
        print("Find stars from F814W Filter Data")
        sources814 = daofind814(data814 - median814)
        print("Finished F814W Search")

        positions814 = (sources814['xcentroid'], sources814['ycentroid'])
        apertures814 = CircularAperture(positions814, r=4.)
        photom814 = apertures814.do_photometry(data814 - median814)

        positions275 = positions814
        photom275 = apertures814.do_photometry(data275 - median275)

    # apertures from ultraviolet
    elif (X == 3):
        print("Find stars from F275W Filter Data")
        sources275 = daofind275(data275 - median275)
        print("Finished F275 Search")

        positions275 = (sources275['xcentroid'], sources275['ycentroid'])
        apertures275 = CircularAperture(positions275, r=4.)
        photom275 = apertures275.do_photometry(data275 - median275)

        positions814 = positions275
        photom814 = apertures275.do_photometry(data814 - median814)

    else:
        print("invalid database selection")
        return

    # store data
    data = (positions814, photom814, positions275, photom275)
    p.dump(data, f)
    f.close()

    return data