Example #1
0
def fit_pps(hdu=None,
            img=None,
            header=None,
            plot=True,
            figure=pylab.figure(1),
            return_profile=False,
            return_gaussian_profile=False,
            verbose=False):

    if hdu is not None:
        img = hdu[0].data
        header = hdu[0].header
    img[img != img] = 0

    asperpix = -header['CD1_1'] * 3600.0

    xx, yy = numpy.indices(img.shape)

    # Try to fit, make sure fit is successful
    fitloop = 1
    while fitloop:
        if fitloop == 1:
            # this never works for no reason at all
            fitpars = gaussfitter.gaussfit(
                img,
                params=[
                    0,
                    img.max(), img.shape[0] / 2, img.shape[1] / 2, 2, 2, 0
                ],
                minpars=[0, img.max() / 50.0, 0, 0, 1, 1, 0],
                maxpars=[0, 0, 0, 0, 6, 6, 360],
                limitedmin=[False, True, False, False, True, True, True],
                limitedmax=[False, False, False, False, True, True, True],
                fixed=[1, 0, 0, 0, 0, 0, 0])
        elif fitloop == 2:
            if verbose:
                print "Fitloop 1 failed: ", fitpars, ".   Trying fitloop2"
            fitpars = gaussfitter.gaussfit(
                img,
                params=[0, img.max(), 0, 0, 2, 2, 0],
                minpars=[0, img.max() / 10.0, 0, 0, 1, 1, 0],
                maxpars=[0, 0, 0, 0, 6, 6, 360],
                limitedmin=[False, True, False, False, True, True, True],
                limitedmax=[False, False, False, False, True, True, True],
                fixed=[1, 0, 0, 0, 0, 0, 0],
                usemoment=[0, 0, 1, 1, 0, 0, 0])
        elif fitloop == 3:
            if verbose:
                print "Fitloop 2 failed: ", fitpars, ".   Trying fitloop3"
            fitpars = gaussfitter.gaussfit(
                img,
                minpars=[0, img.max() / 10.0, 0, 0, 1, 1, 0],
                maxpars=[0, 0, 0, 0, 6, 6, 360],
                limitedmin=[False, True, False, False, True, True, True],
                limitedmax=[False, False, False, False, True, True, True])
        elif fitloop == 4:
            if verbose:
                print "Fitloop 3 failed: ", fitpars, ".   Trying fitloop4"
            fitpars = gaussfitter.gaussfit(img)
        else:
            fitpars = numpy.array(gaussfitter.moments(img, 0, 1, 1))
            print "Using the parameters you specified: ", fitpars
            fitloop = -1

        gaussim = gaussfitter.twodgaussian(fitpars)(xx, yy)

        wxy = fitpars[4:6] * asperpix * numpy.sqrt(8 * numpy.log(2))
        mean_fwhm = wxy.sum() / 2.0

        if mean_fwhm > 70:
            fitloop += 1
        else:  # there were other conditions before...
            if 1:
                if verbose:
                    print "Success.  Fitpars: ", fitpars
                fitloop = 0
            else:
                fitloop += 1

    wcs = pywcs.WCS(header)
    glon, glat = wcs.wcs_pix2sky(fitpars[2:3], fitpars[3:4], 0)

    if plot:
        ff = aplpy.FITSFigure(hdu, figure=figure)
        ff.show_grayscale()
        ff.show_circles([glon], [glat], [1. / 60.], edgecolor='r')
        ff.show_circles([glon], [glat], [2. / 60.], edgecolor='b')

    if return_gaussian_profile:
        return azimuthalAverage(gaussim, center=fitpars[2:4], returnradii=True)
    elif return_profile:
        return azimuthalAverage(img, center=fitpars[2:4], returnradii=True)
    else:
        return glon, glat
Example #2
0
def cross_correlation_shifts(image1,
                             image2,
                             errim1=None,
                             errim2=None,
                             maxoff=None,
                             verbose=False,
                             gaussfit=False,
                             return_error=False,
                             zeromean=True,
                             **kwargs):
    """ Use cross-correlation and a 2nd order taylor expansion to measure the
    offset between two images
    Given two images, calculate the amount image2 is offset from image1 to
    sub-pixel accuracy using 2nd order taylor expansion.
    Parameters
    ----------
    image1: np.ndarray
        The reference image
    image2: np.ndarray
        The offset image.  Must have the same shape as image1
    errim1: np.ndarray [optional]
        The pixel-by-pixel error on the reference image
    errim2: np.ndarray [optional]
        The pixel-by-pixel error on the offset image.  
    maxoff: int
        Maximum allowed offset (in pixels).  Useful for low s/n images that you
        know are reasonably well-aligned, but might find incorrect offsets due to 
        edge noise
    zeromean : bool
        Subtract the mean from each image before performing cross-correlation?
    verbose: bool
        Print out extra messages?
    gaussfit : bool
        Use a Gaussian fitter to fit the peak of the cross-correlation?
    return_error: bool
        Return an estimate of the error on the shifts.  WARNING: I still don't
        understand how to make these agree with simulations.
        The analytic estimate comes from
        http://adsabs.harvard.edu/abs/2003MNRAS.342.1291Z
        At high signal-to-noise, the analytic version overestimates the error
        by a factor of about 1.8, while the gaussian version overestimates
        error by about 1.15.  At low s/n, they both UNDERestimate the error.
        The transition zone occurs at a *total* S/N ~ 1000 (i.e., the total
        signal in the map divided by the standard deviation of the map - 
        it depends on how many pixels have signal)
    **kwargs are passed to correlate2d, which in turn passes them to convolve.
    The available options include image padding for speed and ignoring NaNs.
    References
    ----------
    From http://solarmuri.ssl.berkeley.edu/~welsch/public/software/cross_cor_taylor.pro
    Examples
    --------
    >>> import numpy as np
    >>> im1 = np.zeros([10,10])
    >>> im2 = np.zeros([10,10])
    >>> im1[4,3] = 1
    >>> im2[5,5] = 1
    >>> import image_registration
    >>> yoff,xoff = image_registration.cross_correlation_shifts(im1,im2)
    >>> im1_aligned_to_im2 = np.roll(np.roll(im1,int(yoff),1),int(xoff),0)
    >>> assert (im1_aligned_to_im2-im2).sum() == 0
    
    """

    if zeromean:
        image1 = image1 - (image1[image1 == image1].mean())
        image2 = image2 - (image2[image2 == image2].mean())

    image1 = np.nan_to_num(image1)
    image2 = np.nan_to_num(image2)

    quiet = kwargs.pop('quiet') if 'quiet' in kwargs else not verbose
    ccorr = (correlate2d(image1, image2, quiet=quiet, **kwargs) / image1.size)
    # allow for NaNs set by convolve (i.e., ignored pixels)
    ccorr[ccorr != ccorr] = 0
    if ccorr.shape != image1.shape:
        raise ValueError(
            "Cross-correlation image must have same shape as input images.  This can only be violated if you pass a strange kwarg to correlate2d."
        )

    ylen, xlen = image1.shape
    xcen = xlen / 2 - (1 - xlen % 2)
    ycen = ylen / 2 - (1 - ylen % 2)

    if ccorr.max() == 0:
        warnings.warn("WARNING: No signal found!  Offset is defaulting to 0,0")
        return 0, 0

    if maxoff is not None:
        if verbose: print("Limiting maximum offset to %i" % maxoff)
        subccorr = ccorr[ycen - maxoff:ycen + maxoff + 1,
                         xcen - maxoff:xcen + maxoff + 1]
        ymax, xmax = np.unravel_index(subccorr.argmax(), subccorr.shape)
        xmax = xmax + xcen - maxoff
        ymax = ymax + ycen - maxoff
    else:
        ymax, xmax = np.unravel_index(ccorr.argmax(), ccorr.shape)
        subccorr = ccorr

    if return_error:
        #if errim1 is None:
        #    errim1 = np.ones(ccorr.shape) * image1[image1==image1].std()
        #if errim2 is None:
        #    errim2 = np.ones(ccorr.shape) * image2[image2==image2].std()
        #eccorr =( (correlate2d(errim1**2, image2**2,quiet=quiet,**kwargs)+
        #correlate2d(errim2**2, image1**2,quiet=quiet,**kwargs))**0.5
        # / image1.size)
        eccorr = (
            (correlate2d(
                (image1 * 0.15)**2, image2**2, quiet=quiet, **kwargs) +
             correlate2d(
                 (image2 * 0.15)**2, image1**2, quiet=quiet, **kwargs))**0.5 /
            image1.size)
        if maxoff is not None:
            subeccorr = eccorr[ycen - maxoff:ycen + maxoff + 1,
                               xcen - maxoff:xcen + maxoff + 1]
        else:
            subeccorr = eccorr

    if gaussfit:
        try:
            from agpy import gaussfitter
        except ImportError:
            raise ImportError(
                "Couldn't import agpy.gaussfitter; try using cross_correlation_shifts with gaussfit=False"
            )
        if return_error:
            pars, epars = gaussfitter.gaussfit(subccorr,
                                               err=subeccorr,
                                               return_all=True)
            exshift = epars[2]
            eyshift = epars[3]
        else:
            pars, epars = gaussfitter.gaussfit(subccorr, return_all=True)
        xshift = maxoff - pars[2] if maxoff is not None else xcen - pars[2]
        yshift = maxoff - pars[3] if maxoff is not None else ycen - pars[3]
        if verbose:
            print("Gaussian fit pars: ", xshift, yshift, epars[2], epars[3],
                  pars[4], pars[5], epars[4], epars[5])

    else:

        xshift_int = xmax - xcen
        yshift_int = ymax - ycen

        local_values = ccorr[ymax - 1:ymax + 2, xmax - 1:xmax + 2]

        d1y, d1x = np.gradient(local_values)
        d2y, d2x, dxy = second_derivative(local_values)

        fx, fy, fxx, fyy, fxy = d1x[1, 1], d1y[1, 1], d2x[1, 1], d2y[1,
                                                                     1], dxy[1,
                                                                             1]

        shiftsubx = (fyy * fx - fy * fxy) / (fxy**2 - fxx * fyy)
        shiftsuby = (fxx * fy - fx * fxy) / (fxy**2 - fxx * fyy)

        xshift = -(xshift_int + shiftsubx)
        yshift = -(yshift_int + shiftsuby)

        # http://adsabs.harvard.edu/abs/2003MNRAS.342.1291Z
        # Zucker error

        if return_error:
            #acorr1 = (correlate2d(image1,image1,quiet=quiet,**kwargs) / image1.size)
            #acorr2 = (correlate2d(image2,image2,quiet=quiet,**kwargs) / image2.size)
            #ccorrn = ccorr / eccorr**2 / ccorr.size #/ (errim1.mean()*errim2.mean()) #/ eccorr**2
            normalization = 1. / ((image1**2).sum() / image1.size) / (
                (image2**2).sum() / image2.size)
            ccorrn = ccorr * normalization
            exshift = (np.abs(
                -1 * ccorrn.size * fxx * normalization / ccorrn[ymax, xmax] *
                (ccorrn[ymax, xmax]**2 / (1 - ccorrn[ymax, xmax]**2)))**-0.5)
            eyshift = (np.abs(
                -1 * ccorrn.size * fyy * normalization / ccorrn[ymax, xmax] *
                (ccorrn[ymax, xmax]**2 / (1 - ccorrn[ymax, xmax]**2)))**-0.5)
            if np.isnan(exshift):
                raise ValueError("Error: NAN error!")

    if return_error:
        return xshift, yshift, exshift, eyshift
    else:
        return xshift, yshift
    ax2.set_xlim(0, 100)
    ax2.set_ylim(0, zzplot[ddplot < 100].max() * 1.1)

    pylab.draw()

    print >> outf, file, wxarr, wyarr, cx, cy, peak, frac20, frac40, frac60, flux20, flux40, flux60, fluxnb20, fluxnb40, fluxnb60, fluxr20, fluxr40, fluxr60, pflux, meandc, stddc
    pylab.savefig(file.replace('fits', 'png'))
    print "Completed loop for file %s in %0.1fs" % (file, time.time() - t0)

outf.close()

if sample in ("notmars", "dec2011notmars"):
    PSF = numpy.median(imstack, axis=2)[100:200, 100:200]
    gf, gg = gaussfitter.gaussfit(PSF,
                                  returnfitimage=True,
                                  limitedmin=[1, 1, 0, 0, 0, 0, 0, 0])
    fitsfile[0].data = PSF
    fitsfile[0].header['CRVAL1'] = 0
    fitsfile[0].header['CRVAL2'] = 0
    fitsfile[0].header['CRPIX1'] = 0
    fitsfile[0].header['CRPIX2'] = 0
    fitsfile[0].header['CD1_1'] = -0.002
    fitsfile[0].header['CD2_2'] = 0.002
    fitsfile[0].header.update('OBJECT', "Uranus & Neptune")
    fitsfile[0].header['BMAJ'] = gf[4] * numpy.sqrt(
        8 * numpy.log(2)) * 7.2 / 3600.0
    fitsfile[0].header['BMIN'] = gf[5] * numpy.sqrt(
        8 * numpy.log(2)) * 7.2 / 3600.0

    for key in [
wxarr, wyarr = numpy.zeros(len(filelist)), numpy.zeros(len(filelist))
frac20, frac40, frac60 = numpy.zeros(len(filelist)), numpy.zeros(
    len(filelist)), numpy.zeros(len(filelist))

for jj, file in enumerate(filelist):
    fitsfile = pyfits.open(file)
    img = fitsfile[0].data
    header = fitsfile[0].header
    img[img != img] = 0

    xx, yy = numpy.indices(img.shape)

    fitpars = gaussfitter.gaussfit(
        img,
        params=[img.max(), img.shape[0] / 2, img.shape[1] / 2, 2, 2, 0],
        minpars=[0, 0, 0, 0, 1, 1, 0],
        vheight=0)
    gaussim = gaussfitter.twodgaussian(fitpars)(xx, yy)

    asperpix = -header['CD1_1'] * 3600.0

    cy, cx = fitpars[2:4]
    wxy = fitpars[4:6] * asperpix * numpy.sqrt(8 * numpy.log(2))
    wxarr[jj], wyarr[jj] = max(wxy), min(wxy)

    rr = (numpy.sqrt((xx - cx)**2 + (yy - cy)**2))
    rrs = numpy.argsort(rr.flat)
    zz = img.flat[rrs]
    zzg = gaussim.flat[rrs]
    #dd = numpy.arange(rr.min(),rr.max())
Example #5
0
def cross_correlation_shifts(image1, image2, errim1=None, errim2=None,
                             maxoff=None, verbose=False, gaussfit=False,
                             return_error=False, zeromean=True, **kwargs):
    """ Use cross-correlation and a 2nd order taylor expansion to measure the
    offset between two images

    Given two images, calculate the amount image2 is offset from image1 to
    sub-pixel accuracy using 2nd order taylor expansion.

    Parameters
    ----------
    image1: np.ndarray
        The reference image
    image2: np.ndarray
        The offset image.  Must have the same shape as image1
    errim1: np.ndarray [optional]
        The pixel-by-pixel error on the reference image
    errim2: np.ndarray [optional]
        The pixel-by-pixel error on the offset image.  
    maxoff: int
        Maximum allowed offset (in pixels).  Useful for low s/n images that you
        know are reasonably well-aligned, but might find incorrect offsets due to 
        edge noise
    zeromean : bool
        Subtract the mean from each image before performing cross-correlation?
    verbose: bool
        Print out extra messages?
    gaussfit : bool
        Use a Gaussian fitter to fit the peak of the cross-correlation?
    return_error: bool
        Return an estimate of the error on the shifts.  WARNING: I still don't
        understand how to make these agree with simulations.
        The analytic estimate comes from
        http://adsabs.harvard.edu/abs/2003MNRAS.342.1291Z
        At high signal-to-noise, the analytic version overestimates the error
        by a factor of about 1.8, while the gaussian version overestimates
        error by about 1.15.  At low s/n, they both UNDERestimate the error.
        The transition zone occurs at a *total* S/N ~ 1000 (i.e., the total
        signal in the map divided by the standard deviation of the map - 
        it depends on how many pixels have signal)

    **kwargs are passed to correlate2d, which in turn passes them to convolve.
    The available options include image padding for speed and ignoring NaNs.

    References
    ----------
    From http://solarmuri.ssl.berkeley.edu/~welsch/public/software/cross_cor_taylor.pro

    Examples
    --------
    >>> import numpy as np
    >>> im1 = np.zeros([10,10])
    >>> im2 = np.zeros([10,10])
    >>> im1[4,3] = 1
    >>> im2[5,5] = 1
    >>> import image_registration
    >>> yoff,xoff = image_registration.cross_correlation_shifts(im1,im2)
    >>> im1_aligned_to_im2 = np.roll(np.roll(im1,int(yoff),1),int(xoff),0)
    >>> assert (im1_aligned_to_im2-im2).sum() == 0
    

    """

    if not image1.shape == image2.shape:
        raise ValueError("Images must have same shape.")

    if zeromean:
        image1 = image1 - (image1[image1==image1].mean())
        image2 = image2 - (image2[image2==image2].mean())

    image1 = np.nan_to_num(image1)
    image2 = np.nan_to_num(image2)

    quiet = kwargs.pop('quiet') if 'quiet' in kwargs else not verbose
    ccorr = (correlate2d(image1,image2,quiet=quiet,**kwargs) / image1.size)
    # allow for NaNs set by convolve (i.e., ignored pixels)
    ccorr[ccorr!=ccorr] = 0
    if ccorr.shape != image1.shape:
        raise ValueError("Cross-correlation image must have same shape as input images.  This can only be violated if you pass a strange kwarg to correlate2d.")

    ylen,xlen = image1.shape
    xcen = xlen/2-(1-xlen%2) 
    ycen = ylen/2-(1-ylen%2) 

    if ccorr.max() == 0:
        warnings.warn("WARNING: No signal found!  Offset is defaulting to 0,0")
        return 0,0

    if maxoff is not None:
        if verbose: print("Limiting maximum offset to %i" % maxoff)
        subccorr = ccorr[ycen-maxoff:ycen+maxoff+1,xcen-maxoff:xcen+maxoff+1]
        ymax,xmax = np.unravel_index(subccorr.argmax(), subccorr.shape)
        xmax = xmax+xcen-maxoff
        ymax = ymax+ycen-maxoff
    else:
        ymax,xmax = np.unravel_index(ccorr.argmax(), ccorr.shape)
        subccorr = ccorr

    if return_error:
        if errim1 is None:
            errim1 = np.ones(ccorr.shape) * image1[image1==image1].std() 
        if errim2 is None:
            errim2 = np.ones(ccorr.shape) * image2[image2==image2].std() 
        eccorr =( (correlate2d(errim1**2, image2**2,quiet=quiet,**kwargs)+
                   correlate2d(errim2**2, image1**2,quiet=quiet,**kwargs))**0.5 
                   / image1.size)
        if maxoff is not None:
            subeccorr = eccorr[ycen-maxoff:ycen+maxoff+1,xcen-maxoff:xcen+maxoff+1]
        else:
            subeccorr = eccorr

    if gaussfit:
        try: 
            from agpy import gaussfitter
        except ImportError:
            raise ImportError("Couldn't import agpy.gaussfitter; try using cross_correlation_shifts with gaussfit=False")
        if return_error:
            pars,epars = gaussfitter.gaussfit(subccorr,err=subeccorr,return_all=True)
            exshift = epars[2]
            eyshift = epars[3]
        else:
            pars,epars = gaussfitter.gaussfit(subccorr,return_all=True)
        xshift = maxoff - pars[2] if maxoff is not None else xcen - pars[2]
        yshift = maxoff - pars[3] if maxoff is not None else ycen - pars[3]
        if verbose: 
            print("Gaussian fit pars: ",xshift,yshift,epars[2],epars[3],pars[4],pars[5],epars[4],epars[5])

    else:

        xshift_int = xmax-xcen
        yshift_int = ymax-ycen

        local_values = ccorr[ymax-1:ymax+2,xmax-1:xmax+2]

        d1y,d1x = np.gradient(local_values)
        d2y,d2x,dxy = second_derivative(local_values)

        fx,fy,fxx,fyy,fxy = d1x[1,1],d1y[1,1],d2x[1,1],d2y[1,1],dxy[1,1]

        shiftsubx=(fyy*fx-fy*fxy)/(fxy**2-fxx*fyy)
        shiftsuby=(fxx*fy-fx*fxy)/(fxy**2-fxx*fyy)

        xshift = -(xshift_int+shiftsubx)
        yshift = -(yshift_int+shiftsuby)

        # http://adsabs.harvard.edu/abs/2003MNRAS.342.1291Z
        # Zucker error

        if return_error:
            #acorr1 = (correlate2d(image1,image1,quiet=quiet,**kwargs) / image1.size)
            #acorr2 = (correlate2d(image2,image2,quiet=quiet,**kwargs) / image2.size)
            #ccorrn = ccorr / eccorr**2 / ccorr.size #/ (errim1.mean()*errim2.mean()) #/ eccorr**2
            normalization = 1. / ((image1**2).sum()/image1.size) / ((image2**2).sum()/image2.size) 
            ccorrn = ccorr * normalization
            exshift = (np.abs(-1 * ccorrn.size * fxx*normalization/ccorrn[ymax,xmax] *
                    (ccorrn[ymax,xmax]**2/(1-ccorrn[ymax,xmax]**2)))**-0.5) 
            eyshift = (np.abs(-1 * ccorrn.size * fyy*normalization/ccorrn[ymax,xmax] *
                    (ccorrn[ymax,xmax]**2/(1-ccorrn[ymax,xmax]**2)))**-0.5) 
            if np.isnan(exshift):
                raise ValueError("Error: NAN error!")

    if return_error:
        return xshift,yshift,exshift,eyshift
    else:
        return xshift,yshift