Beispiel #1
0
def init_header_reduced(image):
    '''
    IQWCS = 1 or 0 / Indicates astrometry has been solved for the field
    IQZEROPT =  1 or 0 /indicates if the zero point was calculated for the image    
    SKYBKG = FLOAT / Average sky background given in counts    
    SEEPIX = FLOAT  / Seeing expressed in pixels    
    ZPCAT = 'String' / Catalog used to calculate zero point    
    ZEROPTU = FLOAT  / Zero point uncertainty    
    ZEROPT  = 'FLOAT'  / Zero point by comparison to catalog
    '''
    
    pardic = {"IQWCS" : 0,\
                "IQZEROPT" : 0,\
                "SKYBKG": 0,\
                "SEEPIX": 0,\
                "ZPCAT" : "none",\
                "ZEROPTU" : 0.,\
                "ZEROPT" : 0.,\
                "CRREJ" : 0}
    fitsutils.update_pars(image, pardic)
Beispiel #2
0
def init_header_reduced(image):
    '''
    IQWCS = 1 or 0 / Indicates astrometry has been solved for the field
    IQZEROPT =  1 or 0 /indicates if the zero point was calculated for the image    
    SKYBKG = FLOAT / Average sky background given in counts    
    SEEPIX = FLOAT  / Seeing expressed in pixels    
    ZPCAT = 'String' / Catalog used to calculate zero point    
    ZEROPTU = FLOAT  / Zero point uncertainty    
    ZEROPT  = 'FLOAT'  / Zero point by comparison to catalog
    '''

    pardic = {"IQWCS" : 0,\
                "IQZEROPT" : 0,\
                "SKYBKG": 0,\
                "SEEPIX": 0,\
                "ZPCAT" : "none",\
                "ZEROPTU" : 0.,\
                "ZEROPT" : 0.,\
                "CRREJ" : 0}
    fitsutils.update_pars(image, pardic)
Beispiel #3
0
def reduce_image(image, flatdir=None, biasdir=None, cosmic=False, astrometry=True, channel='rc', target_dir='reduced', overwrite=False):
    '''
    Applies Flat field and bias calibrations to the image.
    
    Steps:
    
    1. - Solve astrometry on the entire image.
    2. - Computes cosmic ray rejectionon the entire image.
    3. - Compute master bias (if it does not exist) and de-bias the image.
    4. - Separate the image into 4 filters.
    5. - Compute flat field for each filter (if it does not exist) and apply flat fielding on the image.
    6. - Compute the image zeropoint.

    '''
    
    logger.info("Reducing image %s"% image)    

    print "Reducing image ", image    

    
    image = os.path.abspath(image)
    imname = os.path.basename(image).replace(".fits", "")
    try:
        objectname = fitsutils.get_par(image, "NAME").replace(" ","")+"_"+fitsutils.get_par(image, "FILTER")
    except:
        logger.error( "ERROR, image "+ image + " does not have a NAME or a FILTER!!!")
        return

    print "For object", objectname
    logger.info( "For object %s"% objectname)


    
    
    #Change to image directory
    mydir = os.path.dirname(image)
    if mydir=="": mydir = "."
    mydir = os.path.abspath(mydir)
    os.chdir(mydir)
    #Create destination directory
    if (not os.path.isdir(target_dir)):
        os.makedirs(target_dir)

    #If we don't want to overwrite the already extracted images, we check wether they exist.
    if (not overwrite):
        existing = True
        for band in ['u', 'g', 'r', 'i']:
            destfile = os.path.join(target_dir, imname + "_f_b_a_%s_%s_0.fits"%(objectname, band))
            logger.info( "Looking if file %s exists: %s"%( destfile, \
                (os.path.isfile(destfile) ) ) )
            existing = existing and (os.path.isfile( destfile ) )
        if existing:
            return []


        
    #Initialize the basic parameters.
    init_header_reduced(image)

    astro = ""
    if (astrometry):
        logger.info( "Solving astometry for the whole image...")
        img = solve_astrometry(image)
        if (os.path.isfile(img)):
            astro="a_"
            fitsutils.update_par(img, "IQWCS", 1)
        else:
            logger.error( "ASTROMETRY DID NOT SOLVE ON IMAGE %s"% image)
            img = image

    #Update noise parameters needed for cosmic reection
    if (fitsutils.get_par(img, "ADCSPEED")==2):
        fitsutils.update_par(img, "RDNOISE", 20.)
    else:
        fitsutils.update_par(img, "RDNOISE", 4.)

    if (cosmic):
        logger.info( "Correcting for cosmic rays...")
        # Correct for cosmics each filter
        cleanimg = clean_cosmic(os.path.join(os.path.abspath(mydir), img))
        img = cleanimg
    
    
    
    #Get basic statistics for the image
    nsrc, fwhm, ellip, bkg = sextractor.get_image_pars(img)
    
    logger.info( "Sextractor statistics: nscr %d, fwhm (pixel) %.2f, ellipticity %.2f"% (nsrc, fwhm, ellip))
    print "Sextractor statistics: nscr %d, fwhm (pixel) %.2f, ellipticity %.2f"% (nsrc, fwhm, ellip)

    
    dic = {"SEEPIX": fwhm/0.394, "NSRC":nsrc, "ELLIP":ellip}
    #Update the seeing information from sextractor
    fitsutils.update_pars(img, dic)
    
    
    #Compute BIAS
    if (biasdir is None or biasdir==""): biasdir = "."
    create_masterbias(biasdir)
    
    bias_slow = os.path.join(biasdir, "Bias_%s_%s.fits"%(channel, 'slow'))
    bias_fast = os.path.join(biasdir, "Bias_%s_%s.fits"%(channel, 'fast'))
    
    # Running IRAF to DE-BIAS
    iraf.noao(_doprint=0)
    iraf.imred(_doprint=0)
    iraf.ccdred(_doprint=0)
    
    #Compute flat field
    if (flatdir is None or flatdir==""): flatdir = "."
    create_masterflat(flatdir, biasdir)
    
    #New names for the object.
    debiased = os.path.join(os.path.dirname(img), "b_" + os.path.basename(img))
    logger.info( "Creating debiased file, %s"%debiased)
    
    if ( (fitsutils.get_par(img, "ADCSPEED")==0.1 and not os.path.isfile(bias_slow)) \
        or (fitsutils.get_par(img, "ADCSPEED")==2 and not os.path.isfile(bias_fast)) ):
        logger.warn( "Master bias not found! Tryting to copy from reference folder...")
        copy_ref_calib(mydir, "Bias")
        if ( (fitsutils.get_par(img, "ADCSPEED")==0.1 and not os.path.isfile(bias_slow)) \
        or (fitsutils.get_par(img, "ADCSPEED")==2 and not os.path.isfile(bias_fast)) ):
            logger.error( "Bias not found in reference folder")
            return


    #Clean first
    if (os.path.isfile(debiased)):
        os.remove(debiased)
        
    #Debias
    if (fitsutils.get_par(img, "ADCSPEED")==2):
        iraf.imarith(img, "-", bias_fast, debiased)
        fitsutils.update_par(debiased, "BIASFILE", bias_fast)
        fitsutils.update_par(debiased, "RDNOISE", 20.)

    else:
        iraf.imarith(img, "-", bias_slow, debiased)
        fitsutils.update_par(debiased, "BIASFILE", bias_slow)
        fitsutils.update_par(debiased, "RDNOISE", 4.)

    #Set negative counts to zero
    hdu = fits.open(debiased)
    header = hdu[0].header
    hdu[0].data[hdu[0].data<0] = 0
    hdu.writeto(debiased, clobber=True)

    #Slicing the image for flats  
    slice_names = slice_rc(debiased)
    print "Creating sliced files, ", slice_names

    
    #Remove un-sliced image
    os.remove(debiased)

    # DE-flat each filter and store under object name
    for i, debiased_f in enumerate(slice_names):
        b = fitsutils.get_par(debiased_f, 'filter')
        
        deflatted = os.path.join(os.path.dirname(image), target_dir, imname + "_f_b_" + astro + objectname + "_%s.fits"%b)

        #Flat to be used for that filter
        flat = os.path.join(flatdir, "Flat_%s_%s_norm.fits"%(channel, b))

        if (not os.path.isfile(flat)):
            logger.warn( "Master flat not found in %s"% flat)
            copy_ref_calib(mydir, "Flat_%s_%s_norm"%(channel, b))
            continue
        else:
            logger.info( "Using flat %s"%flat)
            
        #Cleans the deflatted file if exists
        if (os.path.isfile(deflatted)):
            os.remove(deflatted)

        if (os.path.isfile(debiased_f) and os.path.isfile(flat)):
            logger.info( "Storing de-flatted %s as %s"%(debiased_f, deflatted))
            time.sleep(1)
            iraf.imarith(debiased_f, "/", flat, deflatted)
        else:
            logger.error( "SOMETHING IS WRONG. Error when dividing %s by the flat field %s!"%(debiased_f, flat))
        
        #Removes the de-biased file
        os.remove(debiased_f)
        
        logger.info( "Updating header with original filename and flat field used.")
        fitsutils.update_par(deflatted, "ORIGFILE", os.path.basename(image))
        fitsutils.update_par(deflatted, "FLATFILE", flat)

        slice_names[i] = deflatted
            
                
    #Moving files to the target directory
    for image in slice_names:
        bkg = get_median_bkg(image)
        fitsutils.update_par(image, "SKYBKG", bkg)
        #shutil.move(name, newname)

        
    #Compute the zeropoints
    for image in slice_names:
        zeropoint.calibrate_zeropoint(image)
        
    return slice_names
Beispiel #4
0
def reduce_image(image,
                 flatdir=None,
                 biasdir=None,
                 cosmic=False,
                 astrometry=True,
                 channel='rc',
                 target_dir='reduced',
                 overwrite=False):
    '''
    Applies Flat field and bias calibrations to the image.
    
    Steps:
    
    1. - Solve astrometry on the entire image.
    2. - Computes cosmic ray rejectionon the entire image.
    3. - Compute master bias (if it does not exist) and de-bias the image.
    4. - Separate the image into 4 filters.
    5. - Compute flat field for each filter (if it does not exist) and apply flat fielding on the image.
    6. - Compute the image zeropoint.

    '''

    logger.info("Reducing image %s" % image)

    print "Reducing image ", image

    image = os.path.abspath(image)
    imname = os.path.basename(image).replace(".fits", "")
    try:
        objectname = fitsutils.get_par(image, "NAME").replace(
            " ", "") + "_" + fitsutils.get_par(image, "FILTER")
    except:
        logger.error("ERROR, image " + image +
                     " does not have a NAME or a FILTER!!!")
        return

    print "For object", objectname
    logger.info("For object %s" % objectname)

    #Change to image directory
    mydir = os.path.dirname(image)
    if mydir == "": mydir = "."
    mydir = os.path.abspath(mydir)
    os.chdir(mydir)
    #Create destination directory
    if (not os.path.isdir(target_dir)):
        os.makedirs(target_dir)

    #If we don't want to overwrite the already extracted images, we check wether they exist.
    if (not overwrite):
        existing = True
        for band in ['u', 'g', 'r', 'i']:
            destfile = os.path.join(
                target_dir,
                imname + "_f_b_a_%s_%s_0.fits" % (objectname, band))
            logger.info( "Looking if file %s exists: %s"%( destfile, \
                (os.path.isfile(destfile) ) ) )
            existing = existing and (os.path.isfile(destfile))
        if existing:
            return []

    #Initialize the basic parameters.
    init_header_reduced(image)

    astro = ""
    if (astrometry):
        logger.info("Solving astometry for the whole image...")
        img = solve_astrometry(image)
        if (os.path.isfile(img)):
            astro = "a_"
            fitsutils.update_par(img, "IQWCS", 1)
        else:
            logger.error("ASTROMETRY DID NOT SOLVE ON IMAGE %s" % image)
            img = image

    #Update noise parameters needed for cosmic reection
    if (fitsutils.get_par(img, "ADCSPEED") == 2):
        fitsutils.update_par(img, "RDNOISE", 20.)
    else:
        fitsutils.update_par(img, "RDNOISE", 4.)

    if (cosmic):
        logger.info("Correcting for cosmic rays...")
        # Correct for cosmics each filter
        cleanimg = clean_cosmic(os.path.join(os.path.abspath(mydir), img))
        img = cleanimg

    #Compute BIAS
    if (biasdir is None or biasdir == ""): biasdir = "."
    create_masterbias(biasdir)

    bias_slow = os.path.join(biasdir, "Bias_%s_%s.fits" % (channel, 'slow'))
    bias_fast = os.path.join(biasdir, "Bias_%s_%s.fits" % (channel, 'fast'))

    # Running IRAF to DE-BIAS
    iraf.noao(_doprint=0)
    iraf.imred(_doprint=0)
    iraf.ccdred(_doprint=0)

    #Compute flat field
    if (flatdir is None or flatdir == ""): flatdir = "."
    create_masterflat(flatdir, biasdir)

    #New names for the object.
    debiased = os.path.join(os.path.dirname(img), "b_" + os.path.basename(img))
    logger.info("Creating debiased file, %s" % debiased)

    if ( (fitsutils.get_par(img, "ADCSPEED")==0.1 and not os.path.isfile(bias_slow)) \
        or (fitsutils.get_par(img, "ADCSPEED")==2 and not os.path.isfile(bias_fast)) ):
        logger.warn(
            "Master bias not found! Tryting to copy from reference folder...")
        copy_ref_calib(mydir, "Bias")
        if ( (fitsutils.get_par(img, "ADCSPEED")==0.1 and not os.path.isfile(bias_slow)) \
        or (fitsutils.get_par(img, "ADCSPEED")==2 and not os.path.isfile(bias_fast)) ):
            logger.error("Bias not found in reference folder")
            return

    #Clean first
    if (os.path.isfile(debiased)):
        os.remove(debiased)

    #Debias
    if (fitsutils.get_par(img, "ADCSPEED") == 2):
        iraf.imarith(img, "-", bias_fast, debiased)
        fitsutils.update_par(debiased, "BIASFILE", bias_fast)
        fitsutils.update_par(debiased, "RDNOISE", 20.)

    else:
        iraf.imarith(img, "-", bias_slow, debiased)
        fitsutils.update_par(debiased, "BIASFILE", bias_slow)
        fitsutils.update_par(debiased, "RDNOISE", 4.)

    #Set negative counts to zero
    hdu = fits.open(debiased)
    header = hdu[0].header
    hdu[0].data[hdu[0].data < 0] = 0
    hdu.writeto(debiased, clobber=True)

    #Slicing the image for flats
    slice_names = slice_rc(debiased)
    print "Creating sliced files, ", slice_names

    #Remove un-sliced image
    os.remove(debiased)

    # DE-flat each filter and store under object name
    for i, debiased_f in enumerate(slice_names):
        b = fitsutils.get_par(debiased_f, 'filter')

        deflatted = os.path.join(
            os.path.dirname(image), target_dir,
            imname + "_f_b_" + astro + objectname + "_%s.fits" % b)

        #Flat to be used for that filter
        flat = os.path.join(flatdir, "Flat_%s_%s_norm.fits" % (channel, b))

        if (not os.path.isfile(flat)):
            logger.warn("Master flat not found in %s" % flat)
            copy_ref_calib(mydir, "Flat")
            continue
        else:
            logger.info("Using flat %s" % flat)

        #Cleans the deflatted file if exists
        if (os.path.isfile(deflatted)):
            os.remove(deflatted)

        if (os.path.isfile(debiased_f) and os.path.isfile(flat)):
            logger.info("Storing de-flatted %s as %s" %
                        (debiased_f, deflatted))
            time.sleep(1)
            iraf.imarith(debiased_f, "/", flat, deflatted)
        else:
            logger.error(
                "SOMETHING IS WRONG. Error when dividing %s by the flat field %s!"
                % (debiased_f, flat))

        #Removes the de-biased file
        os.remove(debiased_f)

        logger.info(
            "Updating header with original filename and flat field used.")
        fitsutils.update_par(deflatted, "ORIGFILE", os.path.basename(image))
        fitsutils.update_par(deflatted, "FLATFILE", flat)

        slice_names[i] = deflatted

    #Moving files to the target directory
    for image in slice_names:
        bkg = get_median_bkg(image)
        fitsutils.update_par(image, "SKYBKG", bkg)

        #Get basic statistics for the image
        nsrc, fwhm, ellip, bkg = sextractor.get_image_pars(image)
        plot_image(image)

        logger.info(
            "Sextractor statistics: nscr %d, fwhm (arcsec) %.2f, ellipticity %.2f"
            % (nsrc, fwhm, ellip))
        print "Sextractor statistics: nscr %d, fwhm (arcsec) %.2f, ellipticity %.2f" % (
            nsrc, fwhm, ellip)

        dic = {
            "FWHM": np.round(fwhm, 3),
            "FWHMPIX": np.round(fwhm / 0.394, 3),
            "NSRC": nsrc,
            "ELLIP": np.round(ellip, 3)
        }
        #Update the seeing information from sextractor
        fitsutils.update_pars(image, dic)

    #Compute the zeropoints
    for image in slice_names:
        zeropoint.calibrate_zeropoint(image)

    return slice_names
Beispiel #5
0
def interpolate_zp(reduced, logfile):
    """
    Uses the zeropoint coefficients derived from SDSS fields to interpolate the 
    zeropoint for the images that are outside of SDSS field.
    """
    a = np.genfromtxt(logfile, dtype=None, names=True, delimiter=",")
    a.sort(order=["jd"], axis=0)
    a = a[a["inst"] != 0]
    a = a[a["insterr"] > 0]

    jdmin = np.min(a["jd"])

    jdmax = np.max(a["jd"])

    zpfiles = glob.glob(os.path.join(reduced, "*fits"))

    zpfiles = [
        zf
        for zf in zpfiles
        if fitsutils.has_par(zf, "IQZEROPT")
        and (
            fitsutils.get_par(zf, "IQZEROPT") == 0
            or fitsutils.get_par(zf, "ZEROPT") == 0
            or fitsutils.get_par(zf, "ZPCAT") == "SDSSinterpolated"
        )
    ]

    # Load the coefficients.
    coefs = {}
    for fi in ["u", "g", "r", "i"]:
        coeffile = os.path.join(reduced, "coefs_%s.txt" % fi)
        if os.path.isfile(coeffile):
            coefs[fi] = np.genfromtxt(coeffile)

    # Load the rms.
    rms = {}
    for fi in ["u", "g", "r", "i"]:
        rmsfile = os.path.join(reduced, "rms_%s.txt" % fi)
        if os.path.isfile(rmsfile):
            rms[fi] = np.genfromtxt(os.path.join(reduced, "rms_%s.txt" % fi))

    for image in zpfiles:
        filt = fitsutils.get_par(image, "FILTER")

        # To not extrapolate outside of the valid interval.
        jd = np.maximum(np.percentile(a["jd"] - jdmin, 10), fitsutils.get_par(image, "JD") - jdmin)
        jd = np.minimum(np.percentile(a["jd"] - jdmin, 90), fitsutils.get_par(image, "JD") - jdmin)
        airmass = fitsutils.get_par(image, "AIRMASS")

        # If there are coefficients for that filter, load them and interpolate.
        # Otherwise, skip this file.
        if not coefs.has_key(filt):
            continue

        # est_zp = coef[0] +ab['color']*coef[1] +(ab['airmass']-1.3)*coef[2] + coef[3]*ab['jd'] + coef[4]*ab['jd']**2 + coef[5]*ab['jd']**3 + coef[6]*ab['jd']**4 + coef[7]*ab['jd']**5

        values = np.array([1, 0, airmass - 1.3, jd, jd ** 2])
        est_zp = np.sum(coefs[filt] * values)

        # Update the header with the computed zeropoint.
        pardic = {"IQZEROPT": 1, "ZPCAT": "SDSSinterpolated", "ZEROPTU": float(rms[filt]), "ZEROPT": est_zp}
        fitsutils.update_pars(image, pardic)
Beispiel #6
0
def calibrate_zp_fourshot(logfile, plot=True):
    """
    The field of view is quite small, therefore, all rc shots are used to calibrate the zeropoint.
    This routine retrieves all the stars taken with the same filter when pointing to the science object.
    """

    a = np.genfromtxt(logfile, dtype=None, names=True, delimiter=",")
    a.sort(order=["jd"], axis=0)
    a = a[a["inst"] != 0]

    plotdir = os.path.join(os.path.dirname(os.path.abspath(logfile)), "photometry")

    for name in set(a["object"]):
        for b in set(a["filter"]):
            aib = a[(a["filter"] == b) * (a["object"] == name) * (np.abs(a["color"]) < 1)]

            if len(aib) < 3:
                print "Less than 3 stars found with %s %s" % (name, b)
                continue

            # First fit for the linear and detect the deviations
            coefs, residuals, rank, singular_values, rcond = np.polyfit(
                aib["std"],
                aib["inst"],
                w=1.0 / np.maximum(0.3, np.sqrt(aib["stderr"] ** 2 + aib["insterr"] ** 2)),
                deg=1,
                full=True,
            )
            p = np.poly1d(coefs)

            if plot:
                plt.figure()
                plt.title("%s Filter %s" % (name, b))
                plt.errorbar(aib["std"], aib["inst"], yerr=np.sqrt(aib["stderr"] ** 2 + aib["insterr"] ** 2), fmt="o")
                plt.plot(aib["std"], p(aib["std"]))

            diff = np.abs(aib["inst"] - p(aib["std"]))
            mad = stats.funcs.median_absolute_deviation(diff)
            aib = aib[diff < mad * 5]

            if plot:
                plt.errorbar(aib["std"], aib["inst"], yerr=np.sqrt(aib["stderr"] ** 2 + aib["insterr"] ** 2), fmt="o")
                plt.plot(aib["std"], p(aib["std"]))
                plt.savefig(os.path.join(plotdir, "zp_mag_mag_%s_%s.png" % (name, b)))
                plt.close()

            # Then fit for the colour
            coefs, residuals, rank, singular_values, rcond = np.polyfit(
                aib["color"],
                aib["std"] - aib["inst"],
                w=1.0 / np.maximum(0.15, np.sqrt(aib["stderr"] ** 2 + aib["insterr"] ** 2)),
                deg=1,
                full=True,
            )
            p = np.poly1d(coefs)

            color, zp = coefs

            mad = stats.funcs.median_absolute_deviation(p(aib["color"]) - (aib["std"] - aib["inst"]))

            print coefs, residuals, mad

            for f in aib["filename"]:
                # Add these values to the header.
                pardic = {
                    "IQZEROPT": 1,
                    "ZPCAT": "SDSS4shot",
                    "ZEROPTU": float("%.3f" % mad),
                    "ZEROPT": float("%.3f" % zp),
                    "ZP": float("%.3f" % zp),
                    "ZPERR": float("%.3f" % mad),
                }
                fitsutils.update_pars(f, pardic)

            if plot:
                plt.figure()
                plt.title("%s Filter %s" % (name, b))
                plt.errorbar(
                    aib["color"],
                    aib["std"] - aib["inst"],
                    yerr=np.sqrt(aib["stderr"] ** 2 + aib["insterr"] ** 2),
                    fmt="o",
                )
                plt.plot(aib["color"], p(aib["color"]))
                plt.savefig(os.path.join(plotdir, "zp_col_mag_%s_%s.png" % (name, b)))
                plt.close()
    return
Beispiel #7
0
def calibrate_zeropoint(image, plot=True, plotdir=None, debug=False, refstars=None):
    """
    Calibrates the zeropoint using SDSS catalogue.    
    """

    if plot and plotdir is None:
        plotdir = os.path.join(os.path.dirname(image), "photometry")
        if not os.path.isdir(plotdir):
            os.makedirs(plotdir)

    filt = fitsutils.get_par(image, "filter")
    exptime = fitsutils.get_par(image, "exptime")
    if fitsutils.has_par(image, "JD"):
        date = fitsutils.get_par(image, "JD")
    elif fitsutils.has_par(image, "MJD"):
        date = fitsutils.get_par(image, "MJD")
    elif fitsutils.has_par(image, "MJD-OBS"):
        date = fitsutils.get_par(image, "MJD-OBS")
    else:
        date = 0

    if fitsutils.has_par(image, "AIRMASS"):
        airmass = fitsutils.get_par(image, "AIRMASS")
    else:
        airmass = 1.3
    objname = fitsutils.get_par(image, "OBJECT")
    band = fitsutils.get_par(image, "FILTER")

    logger.info("Starting calibration of ZP for image %s for object %s with filter %s." % (image, objname, band))

    if exptime < 10:
        logger.error("ERROR. Exposure time too short for image (%s) to see anything..." % image)
        return

    extracted = extract_star_sequence(
        os.path.abspath(image), filt, plot=plot, survey="sdss", debug=debug, refstars=refstars, plotdir=plotdir
    )
    if not extracted:
        logger.warn(
            "Field not in SDSS or error when retrieving the catalogue... Skipping. Image %s not zeropoint calibrated."
            % image
        )
        # Add these values to the header.
        pardic = {"IQZEROPT": 0, "ZPCAT": "None", "ZEROPTU": 0, "ZEROPT": 0, "ZP": 0, "ZPERR": 0}
        fitsutils.update_pars(image, pardic)
        return

    # If extraction worked, we can get the FWHM
    fwhm = fitsutils.get_par(image, "fwhm")
    fwhm_as = fwhm * 0.394

    app_phot.get_app_phot("/tmp/sdss_cat_det_%s.txt" % creationdate, image, wcsin="logic", plotdir=plotdir, box=20)

    # Compute the zeropoint for the specific image.
    z, c, err = find_zeropoint_noid("/tmp/sdss_cat_det_%s.txt" % creationdate, image, plot=plot, plotdir=plotdir)

    # Add these values to the header.
    pardic = {"IQZEROPT": 1, "ZPCAT": "SDSS", "ZEROPTU": np.round(err, 3), "ZEROPT": np.round(z, 3)}
    fitsutils.update_pars(image, pardic)

    # Log the current zeropoint for this image
    logname = os.path.join(os.path.dirname(image), "zeropoint.log")

    # Add the data to a later stage zeropoint calibrtion with all-sky data.
    zplogname = os.path.join(os.path.dirname(image), "allstars_zp.log")

    add_to_zp_cal("/tmp/sdss_cat_det_%s.txt" % creationdate, image, zplogname)

    if not os.path.isfile(logname):
        with open(logname, "a") as f:
            f.write("#filename,exptime,filter,date,airmass,fwhm_pix,fwhm_as,zeropoint,color,err\n")
    with open(logname, "a") as f:
        f.write(
            "%s,%.1f,%s,%3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f\n"
            % (image, exptime, filt, date, airmass, fwhm, fwhm_as, z, c, err)
        )

    clean_tmp_files()