예제 #1
0
def fit(im, impsf, hpsf, xpos=None, ypos=None, radius=32):

    x = xpos
    y = ypos

    ny, nx = np.shape(im)
    ixlo, iylo = int(x - radius), int(y - radius)
    if ixlo < 0: ixlo = 0
    if iylo < 0: iylo = 0
    ixhi = int(x + radius) + 1
    iyhi = int(y + radius) + 1
    if ixhi > (nx - 1): ixhi = nx - 1
    if iyhi > (ny - 1): iyhi = ny - 1
    ixx = ixhi - ixlo + 1
    iyy = iyhi - iylo + 1
    dx = np.arange(ixx) + ixlo - x
    dy = np.arange(iyy) + iylo - y
    gauss = [
        hpsf['GAUSS1'], hpsf['GAUSS2'], hpsf['GAUSS3'], hpsf['GAUSS4'],
        hpsf['GAUSS5']
    ]
    dx = dx.reshape(1, len(dx))
    dy = dy.reshape(len(dy), 1)
    dx = rebin.rebin(dx, [np.shape(dx)[1], np.shape(dx)[1]])
    dy = rebin.rebin(dy, [len(dy), len(dy)])
    try:
        model = dao_value.dao_value(dx, dy, gauss, impsf, deriv=False)
    except:
        return 1, 1, 0, 0, False, 0, 0, 0

    subim = im[iylo - 1:iyhi, ixlo - 1:ixhi]

    model = model / 10**(-0.4 * (hpsf['PSFMAG'] - 25))

    return model, subim
예제 #2
0
def fit(im, impsf,hpsf,xpos=None, ypos=None, radius=32):

    x = xpos
    y = ypos

    ny, nx = np.shape(im)
    ixlo, iylo = int(x - radius), int(y - radius)
    if ixlo < 0: ixlo = 0
    if iylo < 0: iylo = 0
    ixhi = int(x + radius) + 1
    iyhi = int(y + radius) + 1
    if ixhi > (nx - 1): ixhi = nx - 1
    if iyhi > (ny - 1): iyhi = ny - 1
    ixx = ixhi - ixlo + 1
    iyy = iyhi - iylo + 1
    dx = np.arange(ixx) + ixlo - x
    dy = np.arange(iyy) + iylo - y
    gauss = [hpsf['GAUSS1'], hpsf['GAUSS2'], hpsf['GAUSS3'],
             hpsf['GAUSS4'], hpsf['GAUSS5']]
    dx = dx.reshape(1, len(dx))
    dy = dy.reshape(len(dy), 1)
    dx = rebin.rebin(dx, [np.shape(dx)[1], np.shape(dx)[1]])
    dy = rebin.rebin(dy, [len(dy), len(dy)])
    try:
        model = dao_value.dao_value(dx, dy, gauss, impsf, deriv=False)
    except:
        return 1, 1, 0, 0, False, 0, 0, 0

    subim = im[iylo - 1:iyhi, ixlo - 1:ixhi]

    model = model/ 10 ** (-0.4 * (hpsf['PSFMAG'] - 25))

    return model,subim
예제 #3
0
파일: rdpsf.py 프로젝트: djbrout/pysmp
def rdpsf(psfname):
    """Read the FITS file created by GETPSF in the DAOPHOT sequence

    Combines the Gaussian with the residuals to create an output PSF array.
    
    psf,hpsf = rdpsf.rdpsf( PSFname )
    
    INPUTS:
         PSFname - string giving the name of the FITS file containing the PSF
                    residuals
     
    RETURNS:
         psf - array containing the actual PSF
         hpsf - header associated with psf
     
    PROCEDURES CALLED:
         DAO_VALUE()
    REVISION HISTORY:
         Written                          W. Landsman              December,  1988
         Checked for IDL Version 2        J. Isensee & J. Hill     December,  1990
         Converted to IDL V5.0            W. Landsman              September, 1997
         Converted to Python              D. Jones                 January,   2014
    """

    resid = pyfits.getdata(psfname)
    hpsf = pyfits.getheader(psfname)

    gauss1 = hpsf['GAUSS1']  #Get Gaussian parameters (5)
    gauss2 = hpsf['GAUSS2']  #
    gauss3 = hpsf['GAUSS3']  #
    gauss4 = hpsf['GAUSS4']  #
    gauss5 = hpsf['GAUSS5']  #
    gauss = [gauss1, gauss2, gauss3, gauss4, gauss5]

    psfrad = hpsf['PSFRAD']  # Get PSF radius
    npsf = 2 * psfrad + 1  #hpsf['NAXIS1']            # Width of output array containing PSF
    psf = np.zeros([npsf, npsf])  # Create output array
    dx = np.arange(
        npsf,
        dtype='int') - psfrad  # Vector gives X distance from center of array
    dy = np.arange(npsf, dtype='int') - psfrad  # Ditto for dy

    ny = len(dy)
    nx = len(dx)
    dx = dx.reshape(1, nx)
    dy = dy.reshape(ny, 1)

    dx = rebin(dx, [ny, nx])
    dy = rebin(dy, [ny, nx])

    psf = psf + dao_value.dao_value(
        dx, dy, gauss, resid,
        deriv=False)  #Compute DAOPHOT value at each point

    hpsf['NAXIS1'] = npsf
    hpsf['NAXIS2'] = npsf

    return (psf, hpsf)
예제 #4
0
def rdpsf(psfname):
    """Read the FITS file created by GETPSF in the DAOPHOT sequence

    Combines the Gaussian with the residuals to create an output PSF array.
    
    psf,hpsf = rdpsf.rdpsf( PSFname )
    
    INPUTS:
         PSFname - string giving the name of the FITS file containing the PSF
                    residuals
     
    RETURNS:
         psf - array containing the actual PSF
         hpsf - header associated with psf
     
    PROCEDURES CALLED:
         DAO_VALUE()
    REVISION HISTORY:
         Written                          W. Landsman              December,  1988
         Checked for IDL Version 2        J. Isensee & J. Hill     December,  1990
         Converted to IDL V5.0            W. Landsman              September, 1997
         Converted to Python              D. Jones                 January,   2014
    """

    resid=pyfits.getdata(psfname)
    hpsf = pyfits.getheader(psfname)

    gauss1 = hpsf['GAUSS1']  #Get Gaussian parameters (5)
    gauss2 = hpsf['GAUSS2']  #
    gauss3 = hpsf['GAUSS3']  #
    gauss4 = hpsf['GAUSS4']  #
    gauss5 = hpsf['GAUSS5']  #
    gauss=[gauss1,gauss2,gauss3,gauss4,gauss5]

    psfrad = hpsf['PSFRAD'] # Get PSF radius
    npsf = 2*psfrad + 1 #hpsf['NAXIS1']            # Width of output array containing PSF

    psf = np.zeros([npsf,npsf])       # Create output array
    dx = np.arange(npsf,dtype='int') - psfrad    # Vector gives X distance from center of array
    dy = np.arange(npsf,dtype='int') - psfrad                       # Ditto for dy


    ny = len(dy)
    nx = len(dx)
    dx = dx.reshape(1,nx)
    dy = dy.reshape(ny,1)

    dx = rebin(dx, [ny, nx])
    dy = rebin(dy, [ny, nx])

    psf = psf + dao_value.dao_value(dx,dy,gauss,resid,deriv=False) #Compute DAOPHOT value at each point

    hpsf['NAXIS1'] = npsf
    hpsf['NAXIS2'] = npsf

    return(psf,hpsf)
예제 #5
0
def mkpsfimage(psfmodel, x, y, size, fluxscale=1):
    """  Construct a numpy array with the psf model appropriately scaled,
    using the gaussian parameters from the header and the residual components
    from the image array of the given fits file

    :param psfmodel: the psf model, provided as either
       (a) a fits file containing the psf model with gaussian parameters in
       the header and a lookup table of residual values in the data array, or
       (b) a tuple with the list of gaussian parameters as the first value and
       the lookup table in the second, as returned by getpsfmodel
    :param x,y: float values in the range [0,1) giving the sub-pixel position
       for the desired center of the psf in the output image
    :param size: width and height in pixels for the output image showing the
       psf realization
    :param fluxscale: scale the output psf image to have this total value for
       the flux, summed across all pixels in the output image
    :return: a numpy array holding the psf image realization
    """

    # require stampsize to be odd, so the central pixel contains
    # the peak of the psf. Define dx,dy as the half-width of the stamp on
    # either side of the central row/column
    assert isinstance(size, int)
    if size % 2 == 0:
        size += 1
    dx = dy = (size - 1) / 2

    gaussparam, lookuptable, psfmag, psfzpt = rdpsfmodel(psfmodel)

    # make a 2D data array with the realized psf image (gaussian+residuals)
    xx = np.tile(np.arange(-dx, dx + 1, 1, float), (size, 1))
    yy = np.tile(np.arange(-dy, dy + 1, 1, float), (size, 1)).T

    psfimage = dao_value(xx - x, yy - y, gaussparam, lookuptable, deriv=False)
    psfstarflux = 10 ** (-0.4 * (psfmag - psfzpt))
    psfimage *= fluxscale / psfstarflux

    return psfimage
    def pkfit(self,
              scale,
              x,
              y,
              sky,
              radius,
              debug=False,
              xyout=False,
              maxiter=25,
              recenter=True):
        f = self.f
        gauss = self.gauss
        psf = self.psf
        fnoise = self.fnoise
        fmask = self.fmask

        if f.dtype != 'float64': f = f.astype('float64')
        #        psf1d = psf.reshape(shape(psf)[0]**2.)
        s = shape(f)  #Get array dimensions
        nx = s[1]
        ny = s[0]  #Initialize a few things for the solution

        redo = 0
        pkerr = 0.027 / (gauss[3] * gauss[4])**2.
        clamp = zeros(3) + 1.
        dtold = zeros(3)
        niter = 0
        chiold = 1.

        if debug:
            print('PKFIT: ITER  X      Y      SCALE    ERRMAG   CHI     SHARP')

        loop = True
        while loop:  #Begin the big least-squares loop
            niter = niter + 1

            if isnan(x) or isnan(y):
                scale = np.nan
                errmag = np.nan
                chi = np.nan
                sharp = np.nan
                if xyout:
                    return (errmag, chi, sharp, niter, scale, x, y)
                else:
                    return (errmag, chi, sharp, niter, scale)

            ixlo = int(x - radius)
            if ixlo < 0: ixlo = 0  #Choose boundaries of subarray containing
            iylo = int(y - radius)
            if iylo < 0: iylo = 0  # 3points inside the fitting radius
            ixhi = int(x + radius) + 1
            if ixhi > (nx - 1): ixhi = nx - 1
            iyhi = int(y + radius) + 1
            if iyhi > ny - 1: iyhi = ny - 1
            ixx = ixhi - ixlo + 1
            iyy = iyhi - iylo + 1
            dy = arange(
                iyy) + iylo - y  #X distance vector from stellar centroid
            dysq = dy**2.
            dx = arange(ixx) + ixlo - x
            dxsq = dx**2.
            rsq = zeros([iyy, ixx])  #RSQ - array of squared

            rsq = array([(dxsq + dysqj) / radius**2 for dysqj in dysq])

            # The fitting equation is of the form
            #
            # Observed brightness =
            #      SCALE + delta(SCALE)  *  PSF + delta(Xcen)*d(PSF)/d(Xcen) +
            #                                           delta(Ycen)*d(PSF)/d(Ycen)
            #
            # and is solved for the unknowns delta(SCALE) ( = the correction to
            # the brightness ratio between the program star and the PSF) and
            # delta(Xcen) and delta(Ycen) ( = corrections to the program star's
            # centroid).
            #
            # The point-spread function is equal to the sum of the integral under
            # a two-dimensional Gaussian profile plus a value interpolated from
            # a look-up table.

            good = where(rsq < 1.)
            if fnoise:
                good = good[where(fnoise[iylo:iyhi + 1, ixlo:ixhi + 1] > 0)]
            if fmask:
                good = good[where(fmask[iylo:iyhi + 1, ixlo:ixhi + 1] == 0)]

            ngood = len(good[0])
            if ngood < 1: ngood = 1

            t = zeros([3, ngood])

            if not len(good[0]):
                scale = np.nan
                errmag = np.nan
                chi = np.nan
                sharp = np.nan
                if xyout:
                    return (errmag, chi, sharp, niter, scale, x, y)
                else:
                    return (errmag, chi, sharp, niter, scale)

            dx = dx[good[1]]
            dy = dy[good[0]]

            model, dvdx, dvdy = dao_value.dao_value(
                dx,
                dy,
                gauss,
                psf,  #psf1d=psf1d,
                deriv=True)  #,ps1d=True)

            if debug:
                print('model created ')
                if xyout:
                    return (errmag, chi, sharp, niter, scale, x, y)
                else:
                    return (errmag, chi, sharp, niter, scale)

            t[0, :] = model
            sa = shape(dvdx)
            if sa[0] > ngood or len(sa) == 0:
                scale = 0
                if xyout:
                    return (errmag, chi, sharp, niter, scale, x, y)
                else:
                    return (errmag, chi, sharp, niter, scale)

            t[1, :] = -scale * dvdx
            t[2, :] = -scale * dvdy
            fsub = f[iylo:iyhi + 1, ixlo:ixhi + 1]

            fsub = fsub[good[0], good[1]]
            if fnoise:
                # D. Jones - noise addition from Scolnic
                fsubnoise = fnoise[iylo:iyhi + 1, ixlo:ixhi + 1]
                fsubnoise = fsubnoise[good[0], good[1]]
                sig = fsubnoise[:]
                sigsq = fsubnoise**2.

            rsq = rsq[good[0], good[1]]
            # Scolnic Added!!!
            #
            yx = zeros(1)
            yx[0] = sky
            skys = yx[0]
            sky = skys
            df = fsub - scale * model - sky  #Residual of the brightness from the PSF fit

            # The expected random error in the pixel is the quadratic sum of
            # the Poisson statistics, plus the readout noise, plus an estimated
            # error of 0.75% of the total brightness for the difficulty of flat-
            # fielding and bias-correcting the chip, plus an estimated error of
            # of some fraction of the fourth derivative at the peak of the profile,
            # to account for the difficulty of accurately interpolating within the
            # point-spread function.  The fourth derivative of the PSF is
            # proportional to H/sigma**4 (sigma is the Gaussian width parameter for
            # the stellar core); using the geometric mean of sigma(x) and sigma(y),
            # this becomes H/ sigma(x)*sigma(y) **2.  The ratio of the fitting
            # error to this quantity is estimated from a good-seeing CTIO frame to
            # be approximately 0.027 (see definition of PKERR above.)

            if not fnoise:
                fpos = (fsub - df
                        )  #Raw data - residual = model predicted intensity
                fposrow = where(fpos < 0.)[0]
                if len(fposrow): fpos[fposrow] = 0
                sigsq = fpos / self.phpadu + self.ronois + (
                    0.0075 * fpos)**2 + (pkerr * (fpos - skys))**2
                sig = sqrt(sigsq)
            relerr = df / sig

            # SIG is the anticipated standard error of the intensity
            # including readout noise, Poisson photon statistics, and an estimate
            # of the standard error of interpolating within the PSF.

            rhosq = zeros([iyy, ixx])

            rhosq = array([dxsq / gauss[3]**2 + j / gauss[4]**2 for j in dysq])

            rhosq = rhosq[good[0], good[1]]

            if niter >= 2:  #Reject any pixel with 10 sigma residual
                badpix = where(abs(relerr / chiold) >= 10.)[0]
                nbad = len(badpix)
                # scolnic added
                sbd = shape(badpix)
                sdf = shape(df)
                if sbd[0] == sdf[0]:
                    scale = np.nan
                    errmag = np.nan
                    if xyout:
                        return (errmag, chi, sharp, niter, scale, x, y)
                    else:
                        return (errmag, chi, sharp, niter, scale)

                if nbad > 0:
                    fsub = item_remove(badpix, fsub)
                    if fnoise:
                        fsubnoise = item_remove(badpix, fsubnoise)
                    df = item_remove(badpix, df)
                    sigsq = item_remove(badpix, sigsq)
                    sig = item_remove(badpix, sig)
                    relerr = item_remove(badpix, relerr)
                    rsq = item_remove(badpix, rsq)
                    rhosq = item_remove(badpix, rhosq)

                    ngood = ngood - badpix

            wt = 5. / (5. + rsq / (1. - rsq))
            lilrho = where(rhosq <= 36.)[
                0]  #Include only pixels within 6 sigma of centroid
            if not len(lilrho):
                scale = np.nan
                errmag = np.nan
                chi = np.nan
                sharp = np.nan
                if xyout:
                    return (errmag, chi, sharp, niter, scale, x, y)
                else:
                    return (errmag, chi, sharp, niter, scale)

            rhosq[lilrho] = 0.5 * rhosq[lilrho]
            dfdsig = exp(-rhosq[lilrho]) * (rhosq[lilrho] - 1.)

            if not fnoise:
                # FPOS-SKY = raw data minus sky = estimated value of the stellar
                # intensity (which presumably is non-negative).
                fpos = fsub[lilrho]
                fposrow = where(fsub[lilrho] - sky < 0.)[0]
                fpos[fposrow] = sky
                sig = fpos / self.phpadu + self.ronois + (0.0075 * fpos)**2 + (
                    pkerr * (fpos - sky))**2
            else:
                sig = fsubnoise[lilrho[0]]**2.

            numer = sum(dfdsig * df[0:len(lilrho)] / sig)
            denom = sum(dfdsig**2 / sig)

            # Derive the weight of this pixel.  First of all, the weight depends
            # upon the distance of the pixel from the centroid of the star-- it
            # is determined from a function which is very nearly unity for radii
            # much smaller than the fitting radius, and which goes to zero for
            #  radii very near the fitting radius.

            chi = sum(wt * abs(relerr))
            sumwt = sum(wt)

            wt = wt / sigsq  #Scale weight to inverse square of expected mean error
            if niter >= 2:  #Reduce weight of a bad pixel
                wt = wt / (1. + (0.4 * relerr / chiold)**8)

            v = zeros(3)  #Compute vector of residuals and the normal matrix.
            c = zeros([3, 3])

            lenwt = len(wt)
            for kk in range(3):
                v[kk] = sum(df * t[kk, 0:lenwt] * wt)
                for ll in range(3):
                    c[ll, kk] = sum(t[kk, 0:lenwt] * t[ll, 0:lenwt] * wt)

            # Compute the (robust) goodness-of-fit index CHI.
            # CHI is pulled toward its expected value of unity before being stored
            # in CHIOLD to keep the statistics of a small number of pixels from
            # completely dominating the error analysis.

            if sumwt > 3.0:
                chi = 1.2533 * chi * sqrt(1. / (sumwt * (sumwt - 3.)))
                chiold = ((sumwt - 3.) * chi + 3.) / sumwt

            if not isnan(sum(c)) and not isinf(sum(c)):
                try:
                    c = linalg.inv(c)  #Invert the normal matrix
                except:
                    print('singular matrix')
                    scale = np.nan
                    errmag = np.nan
                    chi = np.nan
                    sharp = np.nan
                    if xyout:
                        return (errmag, chi, sharp, niter, scale, x, y)
                    else:
                        return (errmag, chi, sharp, niter, scale)
            else:
                print('infinite matrix')
                scale = np.nan
                errmag = np.nan
                chi = np.nan
                sharp = np.nan
                if xyout:
                    return (errmag, chi, sharp, niter, scale, x, y)
                else:
                    return (errmag, chi, sharp, niter, scale)

            dt = matrix(v) * c  #Compute parameter corrections
            dt = array(dt)[0]

            # In the beginning, the brightness of the star will not be permitted
            # to change by more than two magnitudes per iteration (that is to say,
            # if the estimate is getting brighter, it may not get brighter by
            # more than 525% per iteration, and if it is getting fainter, it may
            # not get fainter by more than 84% per iteration).  The x and y
            # coordinates of the centroid will be allowed to change by no more
            # than one-half pixel per iteration.  Any time that a parameter
            # correction changes sign, the maximum permissible change in that
            # parameter will be reduced by a factor of 2.

            div = where(dtold * dt < -1.e-38)[0]
            nbad = len(div)
            if nbad > 0: clamp[div] = clamp[div] / 2.
            dtold = dt
            adt = abs(dt)

            denom2 = (dt[0] / (5.25 * scale))
            if denom2 < (-1 * dt[0] / (0.84 * scale)):
                denom2 = (-1 * dt[0] / (0.84 * scale))
            scale = scale + dt[0] / (1 + denom2 / clamp[0])
            if recenter:
                x = x + dt[1] / (1. + adt[1] / (0.5 * clamp[1]))
                y = y + dt[2] / (1. + adt[2] / (0.5 * clamp[2]))
            redo = 0

            # Convergence criteria:  if the most recent computed correction to the
            # brightness is larger than 0.1% or than 0.05 * sigma(brightness),
            # whichever is larger, OR if the absolute change in X or Y is
            # greater than 0.01 pixels, convergence has not been achieved.

            sharp = 2. * gauss[3] * gauss[4] * numer / (gauss[0] * scale *
                                                        denom)
            errmag = chiold * sqrt(c[0, 0])
            if (adt[0] > max(0.05 * errmag, 0.001 * scale)): redo = 1
            if (adt[1] > 0.01) or (adt[2] > 0.01): redo = 1

            if debug: print(niter, x, y, scale, errmag, chiold, sharp)

            if niter >= 3: loop = False  #At least 3 iterations required

            # If the solution has gone 25 iterations, OR if the standard error of
            # the brightness is greater than 200%, give up.

            if (redo and (errmag <= 1.9995) and (niter < maxiter)): loop = True
            #        if sharp < -99.999: sharp = -99.999
            #        elif sharp > 99.999: sharp = 99.999

        if xyout:
            return (errmag, chi, sharp, niter, scale, x, y)
        else:
            return (errmag, chi, sharp, niter, scale)
예제 #7
0
    def pkfit(self,scale,x,y,sky,radius,
              debug=False,
              xyout=False,
              maxiter=25):
        f = self.f; gauss = self.gauss; psf = self.psf

        if f.dtype != 'float64': f = f.astype('float64')
#        psf1d = psf.reshape(shape(psf)[0]**2.)
        s = shape(f) #Get array dimensions
        nx = s[1] ; ny = s[0] #Initialize a few things for the solution

        redo = 0
        pkerr = 0.027/(gauss[3]*gauss[4])**2.
        clamp = zeros(3) + 1.
        dtold = zeros(3)
        niter = 0
        chiold = 1.

        if debug:
            print('PKFIT: ITER  X      Y      SCALE    ERRMAG   CHI     SHARP')

        loop=True
        while loop:                        #Begin the big least-squares loop
            niter = niter+1

            if isnan(x) or isnan(y):
                scale=1000000.0;
                errmag=100000
                chi=100000
                sharp=100000
                if xyout:
                    return(errmag,chi,sharp,niter,scale,x,y)
                else:
                    return(errmag,chi,sharp,niter,scale)
        
            ixlo = int(x-radius)
            if ixlo < 0: ixlo = 0       #Choose boundaries of subarray containing
            iylo = int(y-radius)
            if iylo < 0: iylo = 0       # 3points inside the fitting radius
            ixhi = int(x+radius) +1 
            if ixhi > (nx-1): ixhi = nx-1
            iyhi = int(y+radius) +1
            if iyhi > ny-1: iyhi = ny-1
            ixx  = ixhi-ixlo+1
            iyy  = iyhi-iylo+1
            dy   = arange(iyy) + iylo - y    #X distance vector from stellar centroid
            dysq = dy**2.
            dx   = arange(ixx) + ixlo - x
            dxsq = dx**2.
            rsq  = zeros([iyy,ixx])  #RSQ - array of squared

            rsq = array([(dxsq+dysqj)/radius**2 for dysqj in dysq])

            # The fitting equation is of the form
            #
            # Observed brightness =
            #      SCALE + delta(SCALE)  *  PSF + delta(Xcen)*d(PSF)/d(Xcen) +
            #                                           delta(Ycen)*d(PSF)/d(Ycen)
            #
            # and is solved for the unknowns delta(SCALE) ( = the correction to
            # the brightness ratio between the program star and the PSF) and
            # delta(Xcen) and delta(Ycen) ( = corrections to the program star's
            # centroid).
            #
            # The point-spread function is equal to the sum of the integral under
            # a two-dimensional Gaussian profile plus a value interpolated from
            # a look-up table.

            good = where(rsq < 1.)

            ngood = len(good[0])
            if ngood < 1: ngood = 1
        
            t = zeros([3,ngood])

            if not len(good[0]):
                scale=1000000.0;
                errmag=100000
                chi=100000
                sharp=100000
                if xyout:
                    return(errmag,chi,sharp,niter,scale,x,y)
                else:
                    return(errmag,chi,sharp,niter,scale)
            
            dx = dx[good[1]]
            dy = dy[good[0]]

            model,dvdx,dvdy = dao_value.dao_value(dx, dy, gauss,
                                                  psf, #psf1d=psf1d,
                                                  deriv=True)#,ps1d=True)

            if debug: 
                print('model created ')
                if xyout:
                    return(errmag,chi,sharp,niter,scale,x,y)
                else:
                    return(errmag,chi,sharp,niter,scale)

            t[0,:] = model
            sa=shape(dvdx)
            if sa[0] > ngood or len(sa) == 0:
                scale=0
                if xyout:
                    return(errmag,chi,sharp,niter,scale,x,y)
                else:
                    return(errmag,chi,sharp,niter,scale)

            t[1,:] = -scale*dvdx
            t[2,:] = -scale*dvdy
            fsub = f[iylo:iyhi+1,ixlo:ixhi+1]

            fsub = fsub[good[0],good[1]]
            rsq = rsq[good[0],good[1]]
            # Scolnic Added!!!
            #
            yx=zeros(1)
            yx[0]=sky
            skys=yx[0]
            sky=skys
            df = fsub - scale*model - sky     #Residual of the brightness from the PSF fit
        
            # The expected random error in the pixel is the quadratic sum of
            # the Poisson statistics, plus the readout noise, plus an estimated
            # error of 0.75% of the total brightness for the difficulty of flat-
            # fielding and bias-correcting the chip, plus an estimated error of
            # of some fraction of the fourth derivative at the peak of the profile,
            # to account for the difficulty of accurately interpolating within the
            # point-spread function.  The fourth derivative of the PSF is
            # proportional to H/sigma**4 (sigma is the Gaussian width parameter for
            # the stellar core); using the geometric mean of sigma(x) and sigma(y),
            # this becomes H/ sigma(x)*sigma(y) **2.  The ratio of the fitting
            # error to this quantity is estimated from a good-seeing CTIO frame to
            # be approximately 0.027 (see definition of PKERR above.)
        
            fpos = (fsub-df)   #Raw data - residual = model predicted intensity
            fposrow = where(fpos < 0.)[0]
            if len(fposrow): fpos[fposrow] = 0
            sigsq = fpos/self.phpadu + self.ronois + (0.0075*fpos)**2 + (pkerr*(fpos-skys))**2

            sig = sqrt(sigsq)
            relerr = df/sig
        
            # SIG is the anticipated standard error of the intensity
            # including readout noise, Poisson photon statistics, and an estimate
            # of the standard error of interpolating within the PSF.
        
            rhosq = zeros([iyy,ixx])
        
            rhosq = array([dxsq/gauss[3]**2+j/gauss[4]**2 for j in dysq])

            rhosq = rhosq[good[0],good[1]]

            if niter >= 2:    #Reject any pixel with 10 sigma residual
                badpix = where( abs(relerr/chiold) >= 10. )[0]
                nbad = len(badpix)
                # scolnic added
                sbd=shape(badpix)
                sdf=shape(df)
                if sbd[0] == sdf[0]:
                    scale=1000000.0
                    errmag=100000
                    if xyout:
                        return(errmag,chi,sharp,niter,scale,x,y)
                    else:
                        return(errmag,chi,sharp,niter,scale)

                if nbad > 0:
                    fsub = item_remove(badpix, fsub)
                    df = item_remove(badpix,df)
                    sigsq = item_remove(badpix,sigsq)
                    sig = item_remove(badpix,sig)
                    relerr = item_remove(badpix,relerr)
                    rsq = item_remove(badpix,rsq)
                    rhosq = item_remove(badpix,rhosq)

                    ngood = ngood-badpix

            wt = 5./(5.+rsq/(1.-rsq))
            lilrho = where(rhosq <= 36.)[0]   #Include only pixels within 6 sigma of centroid
            if not len(lilrho):
                scale=1000000.0
                errmag=100000
                chi=100000
                sharp=100000
                if xyout:
                    return(errmag,chi,sharp,niter,scale,x,y)
                else:
                    return(errmag,chi,sharp,niter,scale)

            rhosq[lilrho] = 0.5*rhosq[lilrho]
            dfdsig = exp(-rhosq[lilrho])*(rhosq[lilrho]-1.)
            fpos = fsub[lilrho]
            fposrow = where(fsub[lilrho]-sky < 0.)[0]
            fpos[fposrow] = sky

            # FPOS-SKY = raw data minus sky = estimated value of the stellar
            # intensity (which presumably is non-negative).

            sig  = fpos/self.phpadu + self.ronois + (0.0075*fpos)**2 + (pkerr*(fpos-sky))**2
            numer = sum(dfdsig*df[0:len(lilrho)]/sig)
            denom = sum(dfdsig**2/sig)
        
            # Derive the weight of this pixel.  First of all, the weight depends
            # upon the distance of the pixel from the centroid of the star-- it
            # is determined from a function which is very nearly unity for radii
            # much smaller than the fitting radius, and which goes to zero for
            #  radii very near the fitting radius.

            chi = sum(wt*abs(relerr))
            sumwt = sum(wt)

            wt = wt/sigsq   #Scale weight to inverse square of expected mean error
            if niter >= 2: #Reduce weight of a bad pixel
                wt = wt/(1.+(0.4*relerr/chiold)**8)

            v = zeros(3)       #Compute vector of residuals and the normal matrix.
            c = zeros([3,3])

            lenwt = len(wt)
            for kk in xrange(3):
                v[kk] = sum(df*t[kk,0:lenwt]*wt)
                for ll in xrange(3): c[ll,kk] = sum(t[kk,0:lenwt]*t[ll,0:lenwt]*wt)

            # Compute the (robust) goodness-of-fit index CHI.
            # CHI is pulled toward its expected value of unity before being stored
            # in CHIOLD to keep the statistics of a small number of pixels from
            # completely dominating the error analysis.

            if sumwt > 3.0:
                chi = 1.2533*chi*sqrt(1./(sumwt*(sumwt-3.)))
                chiold = ((sumwt-3.)*chi+3.)/sumwt

            if not isnan(sum(c)) and not isinf(sum(c)):
                try:
                    c = linalg.inv(c)  #Invert the normal matrix
                except:
                    print('singular matrix')
                    scale=1000000.0
                    errmag=100000
                    chi=100000
                    sharp=100000
                    if xyout:
                        return(errmag,chi,sharp,niter,scale,x,y)
                    else:
                        return(errmag,chi,sharp,niter,scale)
            else:
                print('infinite matrix')
                scale=1000000.0
                errmag=100000
                chi=100000
                sharp=100000
                if xyout:
                    return(errmag,chi,sharp,niter,scale,x,y)
                else:
                    return(errmag,chi,sharp,niter,scale)
            
            dt = matrix(v)*c       #Compute parameter corrections
            dt = array(dt)[0]

            # In the beginning, the brightness of the star will not be permitted
            # to change by more than two magnitudes per iteration (that is to say,
            # if the estimate is getting brighter, it may not get brighter by
            # more than 525% per iteration, and if it is getting fainter, it may
            # not get fainter by more than 84% per iteration).  The x and y
            # coordinates of the centroid will be allowed to change by no more
            # than one-half pixel per iteration.  Any time that a parameter
            # correction changes sign, the maximum permissible change in that
            # parameter will be reduced by a factor of 2.
    
            div = where( dtold*dt < -1.e-38)[0]
            nbad = len(div)
            if nbad > 0: clamp[div] = clamp[div]/2.
            dtold = dt
            adt = abs(dt)

            denom2 = ( dt[0]/(5.25*scale))
            if denom2 < (-1*dt[0]/(0.84*scale)): denom2 = (-1*dt[0]/(0.84*scale))
            scale = scale+dt[0]/(1 + denom2/clamp[0])
            x = x + dt[1]/(1.+adt[1]/(0.5*clamp[1]))
            y = y + dt[2]/(1.+adt[2]/(0.5*clamp[2]))
            redo = 0

            # Convergence criteria:  if the most recent computed correction to the
            # brightness is larger than 0.1% or than 0.05 * sigma(brightness),
            # whichever is larger, OR if the absolute change in X or Y is
            # greater than 0.01 pixels, convergence has not been achieved.
        
            sharp = 2.*gauss[3]*gauss[4]*numer/(gauss[0]*scale*denom)
            errmag = chiold*sqrt(c[0,0])
            if ( adt[0] > max(0.05*errmag,0.001*scale)): redo = 1
            if (adt[1] > 0.01) or (adt[2] > 0.01): redo = 1

            if debug: print niter,x,y,scale,errmag,chiold,sharp
        
            if niter >= 3: loop=False        #At least 3 iterations required

            # If the solution has gone 25 iterations, OR if the standard error of
            # the brightness is greater than 200%, give up.

            if (redo and (errmag <= 1.9995) and (niter < maxiter) ): loop=True
            #        if sharp < -99.999: sharp = -99.999
            #        elif sharp > 99.999: sharp = 99.999

        if xyout:
            return(errmag,chi,sharp,niter,scale,x,y)
        else:
            return(errmag,chi,sharp,niter,scale)
예제 #8
0
    def pkfit_fast_norecenter(self, scale, x, y, sky, radius,
                              debug=False, maxiter=25, sigclip=4):
        """ Fit the target star with a psf model, using quick numpy-based
        least squares fitting, with iterative sigma clipping.

        :param scale: initial guess of the optimized psf scale
        :param x: x position of the target in the data array
        :param y: y position of the target in the data array
        :param sky: fixed value of the background sky flux
        :param radius: fitting radius in pixels
        :param maxiter: max number of sigma clipping iterations
        :param sigclip: after each fitting iteration, clip pixels that have
                residuals discrepant by more than sigclip times the
                expected random flux error
        :param debug: enter the pdb debugger. Set >1 for diagnostic plots.
        :return: The best-fit scale factor that matches the PSF to the target
           star, without any recentering.
        """
        # TODO : better checking for valid input data, with exceptions
        assert not (isnan(x) or isnan(y))

        f = self.f
        gauss = self.gauss
        psf = self.psf

        # psf1d = psf.reshape(shape(psf)[0]**2.)
        s = shape(f)  # Get array dimensions
        nx = s[1]
        ny = s[0]  # Initialize a few things for the solution

        redo = 0
        pkerr = 0.027 / (gauss[3] * gauss[4]) ** 2.
        clamp = zeros(3) + 1.
        dtold = zeros(3)
        niter = 0
        chiold = 1.

        if debug:
            import time
            tstart = time.time()
            print('PKFIT: ITER  X      Y      SCALE    ERRMAG   CHI     SHARP')
            import pdb
            pdb.set_trace()

        # Set the x,y pixel position boundaries for a subarray
        # containing all pixels that fall within the fitting radius
        # NOTE: in this version, with no recentering, the x,y position
        # never changes, so we can define this subarray outside the loop
        ixlo = int(x - radius)
        if ixlo < 0:
            ixlo = 0
        iylo = int(y - radius)
        if iylo < 0:
            iylo = 0
        ixhi = int(x + radius) + 1
        if ixhi > (nx - 1):
            ixhi = nx - 1
        iyhi = int(y + radius) + 1
        if iyhi > ny - 1:
            iyhi = ny - 1
        ixx = ixhi - ixlo + 1
        iyy = iyhi - iylo + 1
        dy = arange(iyy) + iylo - y  # Y dist. vector from stellar centroid
        dysq = dy ** 2
        dx = arange(ixx) + ixlo - x
        dxsq = dx ** 2

        # construct rsq as an array giving the square of the radial distance
        # of each pixel from the center of the target star, in units of the
        # user-defined fitting radius (i.e. rsq=1 is the circle at the
        # fitting radius)
        rsq = zeros([iyy, ixx])
        for j in range(iyy):
            rsq[j, :] = (dxsq + dysq[j]) / radius ** 2

        # define a list of indices in the subarray for those pixels that
        # are within the fitting radius from the stellar center
        i_tofit = where(rsq.reshape(shape(rsq)[0] * shape(rsq)[1]) < 1)[0]
        n_tofit = len(i_tofit)
        if n_tofit < 1:
            n_tofit = 1

        # Extract a subarray with the observed flux for all pixels within the
        # fitting radius of the center of the target star
        flux_observed_tofit = (
            f[iylo:iyhi + 1, ixlo:ixhi + 1].ravel()[[i_tofit]])

        # Call the function dao_value to generate realized flux values
        # from the given psf model for each pixel position in the image
        # subarray that is within the fitting radius
        dx = dx[i_tofit % ixx]
        dy = dy[i_tofit / ixx]
        flux_model_tofit = dao_value.dao_value(dx, dy, gauss, psf, deriv=False)

        # Set the weight of each pixel for the least squares fitter based on
        # its distance from the fixed center of the target star:
        # weight ~ 1 at the center, and diminishes rapidly to ~0 at the edge
        # of the fitting radius.
        weight_tofit = (5. / (5. + rsq / (1. - rsq))).ravel()[i_tofit]

        flux_observed_tofit_weighted_minussky = \
            flux_observed_tofit * weight_tofit - sky
        flux_model_tofit_weighted = flux_model_tofit * weight_tofit

        # Since we are not allowing the PSF to be recentered in this version,
        # the error function to minimize has only one free variable, SCALE:
        #    err = sum(flux_observed * weight - SCALE * flux_model * weight)
        def errfunc(psf_scale, goodpixmask=1):
            """ Error function to minimize
            :param psf_scale: the psf scaling factor
            :param goodpixmask: set to 1 if all pixels are good;
                   or set to an array of with 1 for good pixels and 0 for bad
            :return: vector of pixel residuals
            """
            fobs = flux_observed_tofit_weighted_minussky * goodpixmask
            fmod = flux_model_tofit_weighted * goodpixmask
            error_vector = fobs - psf_scale * fmod
            return error_vector

        # The expected random error in the pixel is the quadratic sum of
        # the Poisson statistics, plus the readout noise, plus an estimated
        # error of 0.75% of the total brightness for the difficulty of flat
        # fielding and bias-correcting the chip, plus an estimated error
        #  of some fraction of the fourth derivative at the peak of the
        # profile, to account for the difficulty of accurately
        # interpolating within the point-spread function.  The fourth
        # derivative of the PSF is proportional to H/sigma**4 (sigma is
        # the Gaussian width parameter for the stellar core); using the
        # geometric mean of sigma(x) and sigma(y), this becomes
        # H/ sigma(x)*sigma(y) **2.  The ratio of the fitting error to
        # this quantity is estimated to be approximately 0.027
        # (see definition of PKERR above.)
        flux_observed_tofit_noneg = where(flux_observed_tofit - sky < 0,
                                          abs(sky), flux_observed_tofit)
        fluxerr2 = (flux_observed_tofit_noneg / self.phpadu +
                    self.ronois +
                    (0.0075 * flux_observed_tofit_noneg) ** 2 +
                    (pkerr * (flux_observed_tofit_noneg - sky)) ** 2)
        fluxerr = sqrt(fluxerr2)

        # Solve for the SCALE factor using least squares minimization,
        # iteratively rejecting bad pixels that are more than 'sigclip'
        # sigma discrepant from the model, where sigma is the expected
        # random error (fluxerr above), separately defined for each pixel
        goodpix_mask = 1
        n_badpix_beforefit = 0
        for iteration in xrange(maxiter):
            bestfit_scale, cov = leastsq(errfunc, scale, args=goodpix_mask)
            scale = bestfit_scale[0]
            flux_resid_tofit = (flux_observed_tofit -
                                scale * flux_model_tofit - sky)
            goodpix_mask = abs(flux_resid_tofit / fluxerr) < sigclip
            n_badpix_afterfit = n_tofit - sum(goodpix_mask)
            if n_badpix_afterfit <= n_badpix_beforefit:
                break
            if n_badpix_afterfit > 0.5 * n_tofit:
                #raise RuntimeWarning(
                print(
                    ">50pct of pixels >%.1f sigma discrepant.  " % sigclip +
                    "Disabling badpix masking in iteration %i." % iteration)
                goodpix_mask = 1

        if iteration == maxiter - 1:
            raise RuntimeWarning("Max # of iterations exceeded")

        if not debug:
            return scale
        elif debug > 1:
            # Serious debugging:
            # collect the full output from the least squares fitting
            # routine, plot the observed, model and residual fluxes,
            # and enter the pdb debugger.

            flux_obs_subarray = f[iylo:iyhi + 1, ixlo:ixhi + 1]
            flux_model_subarray = np.zeros(flux_obs_subarray.shape).ravel()
            flux_model_subarray[i_tofit] = flux_model_tofit * scale + sky
            flux_model_subarray = flux_model_subarray.reshape(
                flux_obs_subarray.shape)
            flux_resid_subarray = np.zeros(flux_obs_subarray.shape).ravel()
            flux_resid_subarray[i_tofit] = (flux_observed_tofit -
                                            scale * flux_model_tofit - sky)
            flux_resid_subarray = flux_resid_subarray.reshape(
                flux_obs_subarray.shape)

            from matplotlib import pyplot as pl, cm
            pl.figure(2, figsize=[10, 3.5])
            pl.clf()
            fig = pl.gcf()
            fig.subplots_adjust(left=0.05, right=0.95, bottom=0.1, top=0.95)
            ax1 = fig.add_subplot(1, 3, 1)
            ax2 = fig.add_subplot(1, 3, 2)
            ax3 = fig.add_subplot(1, 3, 3)
            im1 = ax1.imshow(flux_obs_subarray, interpolation='nearest',
                             aspect='equal', cmap=cm.Greys_r)
            cb1 = pl.colorbar(im1, ax=ax1, use_gridspec=True,
                              orientation='horizontal')
            im2 = ax2.imshow(flux_model_subarray, interpolation='nearest',
                             aspect='equal', cmap=cm.Greys_r)
            cb2 = pl.colorbar(im2, ax=ax2, use_gridspec=True,
                              orientation='horizontal')
            im3 = ax3.imshow(flux_resid_subarray, interpolation='nearest',
                             aspect='equal', cmap=cm.Greys_r)
            cb3 = pl.colorbar(im3, ax=ax3, use_gridspec=True,
                              orientation='horizontal')

        return scale
예제 #9
0
파일: chkpsf.py 프로젝트: djbrout/pysmp
def fit(
        fileroot='/export/scratch0/ps1sn1/data/v10.0/GPC1v3/eventsv1/workspace/PSc560121/g/PSc560121.md01s043.g.ut090831e.1917665_14.sw',
        xpos=None, ypos=None, radius=10, pdf_pages=None, ra=None, dec=None, title='', returnstamps = False, maskfile=None, mysky=None,mysig=None):
    # xpos = xpos +1
    # ypos = ypos +1
    # from matplotlib.backends.backend_pdf import PdfPages
    #pdf_pages = PdfPages('daophot_resid.pdf')
    dofcmp = False
    good = False

    im = pyfits.getdata('%s.fits' % fileroot)
    mask = pyfits.getdata(maskfile)
    impsf = pyfits.getdata('%s.dao.psf.fits' % fileroot)
    fullpsf, hpsf = rdpsf.rdpsf('%s.dao.psf.fits' % fileroot)
    imhdr = pyfits.getheader('%s.fits' % fileroot)

    if dofcmp:
        p = pyfits.open('%s.fcmp' % fileroot)
        p.verify("fix")


        if os.path.exists('test.fcmp'):
            os.remove('test.fcmp')
        p.writeto('test.fcmp', output_verify='fix')
        # fcmp = p[0].header
        # print p[1]

        fcmp = txtobj('test.fcmp', cmpheader=True)
        # print fcmp.__dict__['class']
        # print fcmp['class']
        # raw_input()


        w = wcs.WCS('%s.fits' % fileroot)
        #results2 = w.wcs_world2pix(np.array([[ra, dec]]), 0)
        # xpos,ypos =results2[0][0], results2[0][1]


        psfsize = np.shape(impsf)[0]

        fcmp.Xpos = fcmp.Xpos[1:].astype(float)
        fcmp.Ypos = fcmp.Ypos[1:].astype(float)
        fcmp.__dict__['class'] = fcmp.__dict__['class'][1:].astype(float)

        fcmp.flux = fcmp.flux[1:].astype(float)
        fcmp.dflux = fcmp.dflux[1:].astype(float)
        # for x,y,flux,fluxerr in zip(fcmp.Xpos,fcmp.Ypos,
        #                            fcmp.flux,fcmp.dflux):


        # print fcmp.Xpos-xpos
        # print fcmp.Ypos-ypos
        # raw_input()
        #print fcmp.__dict__['class']
        #print fcmp.Xpos
        #print xpos
        #raw_input()
        ww = (abs(fcmp.Xpos - xpos) < 1.) & (abs(fcmp.Ypos - ypos) < 1.)
        thisclass = fcmp.__dict__['class'][ww]
        #print 'THIS CLASS IS', thisclass
        #print 'all classes', fcmp.__dict__['class']
        # flux = fcmp.flux
        # fluxerr = fcmp.dflux

        if len(thisclass) == 1:
            if thisclass[0] == 1:
                good = True

    fluxerr = 100.
    chisq = 1.
    dms = 1.

    x = xpos
    y = ypos

    ny, nx = np.shape(im)
    psfy, psfx = np.shape(impsf)
    ixlo, iylo = int(x - radius), int(y - radius)
    if ixlo < 0: ixlo = 0
    if iylo < 0: iylo = 0
    ixhi = int(x + radius) + 1
    iyhi = int(y + radius) + 1
    if ixhi > (nx - 1): ixhi = nx - 1
    if iyhi > (ny - 1): iyhi = ny - 1
    ixx = ixhi - ixlo + 1
    iyy = iyhi - iylo + 1
    dx = np.arange(ixx) + ixlo - x
    dy = np.arange(iyy) + iylo - y
    psf1d = impsf.reshape(np.shape(impsf)[0] ** 2.)
    gauss = [hpsf['GAUSS1'], hpsf['GAUSS2'], hpsf['GAUSS3'],
             hpsf['GAUSS4'], hpsf['GAUSS5']]
    dx = dx.reshape(1, len(dx))
    dy = dy.reshape(len(dy), 1)
    dx = rebin.rebin(dx, [np.shape(dx)[1], np.shape(dx)[1]])
    dy = rebin.rebin(dy, [len(dy), len(dy)])
    try:
        model = dao_value.dao_value(dx, dy, gauss,
                                    impsf,  # psf1d=psf1d,
                                    deriv=False)  # ,ps1d=False)
    except:
        return 1, 1, 0, 0, False, 0, 0, 0


    subim = im[iylo - 1:iyhi, ixlo - 1:ixhi]
    #print 'modelshape', model.shape, 'imshape', subim.shape
    #raw_input()
    submask = mask[iylo - 1:iyhi, ixlo - 1:ixhi]
    submask[submask != 0] = 9
    submask[submask == 0 ] = 1
    submask[submask == 9 ] = 0
    # scaledpsf = model+impsf[psfy/2+1-radius:psfy/2+1+radius+1,
    #                        psfx/2+1-radius:psfx/2+1+radius+1]
    # print model.shape
    # print flux.shape
    # print hpsf['PSFMAG']
    # print imhdr['SKYADU']
    chisqvec = []
    fluxvec = []
    substamp = model.shape[0]
    fitrad = np.zeros([substamp, substamp])
    radius = 4
    for x in np.arange(substamp):
        for y in np.arange(substamp):
            if np.sqrt((substamp / 2. - x) ** 2 + (substamp / 2. - y) ** 2) < radius:
                fitrad[int(x), int(y)] = 1.
    '''
    for flux in range(1,500000,200):
        scaledpsf = model*flux/10**(-0.4*(hpsf['PSFMAG']-25)) + imhdr['SKYADU']
        chisq = np.sum(fitrad*(subim-scaledpsf)**2/imhdr['SKYSIG']**2)
        chisqvec.append(chisq)
        fluxvec.append(flux)

    chisqvec = np.array(chisqvec)
    fluxvec = np.array(fluxvec)
    flux = fluxvec[np.argmin(chisqvec)]
    scaledpsf = model*flux/10**(-0.4*(hpsf['PSFMAG']-25)) + imhdr['SKYADU']

    #resid(param,psf,im,sigma,fitrad,sky,psfmag)

    #print model, subim, imhdr['SKYSIG']
    '''
    # fluxls, cov = opti.leastsq(resid, 100000,
    #                            args=(model, subim, imhdr['SKYSIG'], fitrad, imhdr['SKYADU'], hpsf['PSFMAG']),full_output=False)

    fluxls, cov = opti.leastsq(resid, 100000,args=(model, subim, mysig, fitrad, mysky, hpsf['PSFMAG']),full_output=False)

    #print cov.shape
    #print fluxls, cov
    #raw_input('covshape')
    # print 'flux fit comparo',flux,fluxls,
    scaledpsf = model*fluxls/10**(-0.4*(hpsf['PSFMAG']-25)) + imhdr['SKYADU']



    dontplot = False
    if not pdf_pages is None:
        if not dontplot:
            print 'plottingggg'
            fig = plt.figure()
            plt.clf()
            axim = plt.subplot(131)
            axpsf = plt.subplot(132)
            axdiff = plt.subplot(133)
            for ax,title in zip([axim,axpsf,axdiff],['image','model','difference']):
                ax.set_title(title)
                axim.imshow(subim,
                cmap='gray',interpolation='nearest')
                axpsf.imshow(model,cmap='gray',interpolation='nearest')
                axdiff.imshow(subim-scaledpsf,cmap='gray',interpolation='nearest')
                #plt.colorbar()
                axim = plt.subplot(131)
                axpsf = plt.subplot(132)
                axdiff = plt.subplot(133)
            #for ax,title in zip([axim,axpsf,axdiff],['image','model','difference']):
                if good:
                    ax.set_title(title + 'GOOD')
                else:
                    ax.set_title(title + 'BADD')
                #ax.set_title(title)
            axim.imshow(subim,cmap='gray',interpolation='nearest')
            axpsf.imshow(scaledpsf,cmap='gray',interpolation='nearest')
            ax = axdiff.imshow(subim-scaledpsf,cmap='gray',interpolation='nearest')
            cbar = fig.colorbar(ax)
            #plt.imshow((subim-scaledpsf)/imhdr['SKYSIG'],cmap='gray',interpolation='nearest')
            #plt.colorbar()
            if good:
                plt.title(title + 'GOOD' )
            else:
                plt.title(title + 'BADD' )
            pdf_pages.savefig(fig)

            #pdf_pages.close()
    #plt.savefig('')




    if returnstamps:
        rpsf = model
        good = True#we know this wont be in the starcat file so set to good is true
        #print 'fluxls', fluxls
        #print 'maxpsf', np.max(rpsf)
        return fluxls,fluxerr,chisq,dms,good,subim, rpsf, imhdr['SKYSIG'], fitrad, imhdr['SKYADU'], hpsf['PSFMAG'], submask
    #print fluxls
    #print np.max(model)
    #raw_input('fluxls')
    sstamp = simstamp(fluxls,model, subim, imhdr['SKYSIG'], fitrad, imhdr['SKYADU'], hpsf['PSFMAG'])

    return fluxls, fluxerr, chisq, dms, good, subim, sstamp, model