Example #1
0
def align_norm(fnlist,uncertlist=None):
    """Aligns a set of images to each other, as well as normalizing the images
    to the same average brightness.
    
    Both the alignment and normalization are accomplished through stellar
    photometry using the IRAF routine 'daophot'. The centroids of a handful
    of stars are found and used to run the IRAF routine 'imalign'. The
    instrumental magnitudes of the stars are used to determine by how much
    each image must be scaled for the photometry to match across images.
    
    The images are simply updated with their rescaled, shifted selves. This
    overwrites the previous images and adds the header keyword 'fpphot' to
    the images.
    
    A handful of temporary files are created during this process, which should
    all be deleted by the routine at the end. But if it is interrupted, they
    might not be.
    
    If the uncertainty images exist, this routine also shifts them by the same
    amounts as the intensity images, as well as updating the uncertainty values
    for both the new normalization and the uncertainties in normalizing the
    images.
    
    Inputs:
    fnlist -> List of strings, each the path to a fits image.
    uncertlist (optional) -> List of paths to uncertainty images.
    
    """
    
    #Fit for the sky background level
    _skyavg, skysig = fit_sky_level(fnlist)
    
    #Get image FWHMs
    fwhm = np.empty(len(fnlist))
    firstimage = openfits(fnlist[0])
    toggle = firstimage[0].header.get("fpfwhm")
    axcen = firstimage[0].header.get("fpaxcen")
    aycen = firstimage[0].header.get("fpaycen")
    arad = firstimage[0].header.get("fparad")
    firstimage.close()
    if axcen == None:
        print "Error! Images have not yet been aperture-masked! Do this first!"
        crash()
    if toggle == None:
        print "Warning: FWHMs have not been measured! Assuming 5 pixel FWHM for all images."
        for i in range(len(fnlist)): fwhm[i] = 5
    else:
        for i in range(len(fnlist)):
            image = openfits(fnlist[i])
            fwhm[i] = image[0].header["fpfwhm"]
            image.close()
    
    #Identify objects in the fields
    coolist = identify_objects(fnlist,skysig,fwhm)
    
    #Match objects between fields
    coofile = match_objects(coolist)
    
    #Do aperture photometry on the matched objects
    photlist = do_phot(fnlist,coofile,fwhm,skysig)
    
    #Read the photometry files
    x, y, mag, dmag = read_phot(photlist)
    
    #Calculate the normalizations
    norm, dnorm = calc_norm(mag,dmag)
    
    #Normalize the images (and optionally, the uncertainty images)
    for i in range(len(fnlist)):
        print "Normalizing image "+fnlist[i]
        image = openfits(fnlist[i],mode="update")
        if not (uncertlist is None):
            uncimage = openfits(uncertlist[i],mode="update")
            uncimage[0].data = np.sqrt(norm[i]**2*uncimage[0].data**2 + dnorm[i]**2*image[0].data**2)
            uncimage.close()
        image[0].data *= norm[i]
        image.close()
    
    #Calculate the shifts
    for i in range(x.shape[1]):
        x[:,i] = -(x[:,i] - x[0,i])
        y[:,i] = -(y[:,i] - y[0,i])
    xshifts = np.average(x,axis=1)
    yshifts = np.average(y,axis=1)
    
    #Shift the images (and optionally, the uncertainty images)
    iraf.images(_doprint=0)
    iraf.immatch(_doprint=0)
    for i in range(len(fnlist)):
        print "Shifting image "+fnlist[i]
        iraf.geotran(input=fnlist[i],
                     output=fnlist[i],
                     geometry="linear",
                     xshift=xshifts[i],
                     yshift=yshifts[i],
                     database="",
                     verbose="no")
        if not (uncertlist is None):
            iraf.geotran(input=uncertlist[i],
                         output=uncertlist[i],
                         geometry="linear",
                         xshift=xshifts[i],
                         yshift=yshifts[i],
                         database="",
                         verbose="no")
    
    #Update the image headers
    for i in range(len(fnlist)):
        image = openfits(fnlist[i],mode="update")
        image[0].header["fpphot"]="True"
        image[0].header["fpxcen"]+=xshifts[i]
        image[0].header["fpycen"]+=yshifts[i]
        image[0].header["fpaxcen"]+=xshifts[i]
        image[0].header["fpaycen"]+=yshifts[i]
        image.close()
    
    #Clean up the coordinate file list
    clean_files(fnlist)
    remove(coofile)
    for i in range(len(photlist)):
        remove(photlist[i])
    
    return