Index: /branches/eam_branches/ipp-20130307/pswarp/src/Makefile.am
===================================================================
--- /branches/eam_branches/ipp-20130307/pswarp/src/Makefile.am	(revision 35372)
+++ /branches/eam_branches/ipp-20130307/pswarp/src/Makefile.am	(revision 35373)
@@ -28,7 +28,11 @@
 	pswarp.c			\
 	pswarpArguments.c		\
-	pswarpExit.c			\
+	pswarpExitCode.c		\
 	pswarpLoop.c			\
+	pswarpLoopBackground.c		\
+	pswarpCleanup.c			\
+	pswarpStatsFile.c		\
 	pswarpDefine.c			\
+	pswarpDefineBackground.c	\
 	pswarpDefineSkycell.c		\
 	pswarpErrorCodes.c		\
Index: /branches/eam_branches/ipp-20130307/pswarp/src/pswarp.c
===================================================================
--- /branches/eam_branches/ipp-20130307/pswarp/src/pswarp.c	(revision 35372)
+++ /branches/eam_branches/ipp-20130307/pswarp/src/pswarp.c	(revision 35373)
@@ -12,5 +12,4 @@
 
 #include "pswarp.h"
-#include "pswarpFileNames.h"
 
 int main (int argc, char **argv)
@@ -22,12 +21,10 @@
     psphotInit();
 
-    const char *statsName = NULL;       // Filename for statistics
-    psMetadata *stats = NULL;           // Container for statistics
-    FILE *statsFile = NULL;             // File stream for statistics
-
     pmConfig *config = pswarpArguments(argc, argv);
     if (!config) {
-        goto DIE;
+        pswarpCleanup(config, NULL);
     }
+
+    pswarpStatsFile *statsFile = pswarpStatsFileOpen (config);
 
     pswarpVersionPrint();
@@ -35,111 +32,31 @@
     // load identify the data sources
     if (!pswarpParseCamera(config)) {
-        goto DIE;
+        pswarpCleanup(config, statsFile);
     }
 
     if (!pswarpOptions(config)) {
-        goto DIE;
+        pswarpCleanup(config, statsFile);
     }
 
     // load the skycell layout information
     if (!pswarpDefine(config)) {
-        goto DIE;
+        pswarpCleanup(config, statsFile);
     }
-    if (psMetadataLookupBool(NULL,config->arguments,"BACKGROUND.MODEL")) {
-      if (!pswarpDefineBackground(config)) {
-	goto DIE;
-      }
-    }
-
-    // Open the statistics file
-    bool mdok;                          ///< Status of MD lookup
-    statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS"); ///< Filename for statistics
-    if (mdok && statsName && strlen(statsName) > 0) {
-        psString resolved = pmConfigConvertFilename(statsName, config, true, true);
-        statsFile = fopen(resolved, "w");
-        if (!statsFile) {
-            psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.\n", resolved);
-            psFree(resolved);
-            goto DIE;
-        }
-        psFree(resolved);
-        stats = psMetadataAlloc();
-        psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", 0, "No problems", 0);
+    if (!pswarpDefineBackground(config)) {
+        pswarpCleanup(config, statsFile);
     }
 
     // load and warp
-    if (!pswarpLoop(config, stats)) {
-        goto DIE;
+    if (!pswarpLoop(config, statsFile->md)) {
+        pswarpCleanup(config, statsFile);
     }
-    if (psMetadataLookupBool(NULL,config->arguments,"BACKGROUND.MODEL")) {
-      if (!pswarpLoopBackground(config, stats)) {
+    if (!pswarpLoopBackground(config, statsFile->md)) {
 	fprintf(stderr,"Dying!\n");
-        goto DIE;
-      }
+        pswarpCleanup(config, statsFile);
     }
 
     psLogMsg("pswarp", PS_LOG_INFO, "complete pswarp run: %f sec\n", psTimerMark("pswarp"));
+    pswarpCleanup(config, statsFile);
+}
 
-DIE:
-    {
-        psExit exitValue = pswarpExitCode(PS_EXIT_SUCCESS); // Exit code
-
-        // Ensure everything is written out, at every level
-        pswarpFileActivation(config, detectorFiles, true);
-        pswarpFileActivation(config, skycellFiles, true);
-        pswarpFileActivation(config, photFiles, true);
-        pswarpFileActivation(config, independentFiles, true);
-        if (!pswarpIOChecksAfter(config)) {
-            psError(psErrorCodeLast(), false, "Unable to write files.");
-            exitValue = pswarpExitCode(exitValue);
-            pmFPAfileFreeSetStrict(false);
-        }
-
-        // Write out summary statistics
-        if (stats && statsFile) {
-            psMetadataAddF32(stats, PS_LIST_TAIL, "DT_WARP", 0, "Time for warp completion",
-                             psTimerMark("pswarp"));
-
-            const char *statsMDC = psMetadataConfigFormat(stats);
-            if (!statsMDC) {
-                psError(psErrorCodeLast(), false, "Unable to get statistics file.");
-                exitValue = pswarpExitCode(exitValue);
-            }
-            psFree(stats);
-            if (fprintf(statsFile, "%s", statsMDC) != strlen(statsMDC)) {
-                psError(PSWARP_ERR_IO, true, "Unable to write statistics file.");
-                exitValue = pswarpExitCode(exitValue);
-            }
-            psFree(statsMDC);
-            if (fclose(statsFile) == EOF) {
-                psError(PSWARP_ERR_IO, true, "Unable to close statistics file.");
-                exitValue = pswarpExitCode(exitValue);
-            }
-            pmConfigRunFilenameAddWrite(config, "STATS", statsName);
-        }
-
-        // Dump configuration
-        psString dump_file = psMetadataLookupStr(&mdok, config->arguments, "DUMP_CONFIG");
-        if (dump_file) {
-            if (!pmConfigDump(config, dump_file)) {
-                psError(psErrorCodeLast(), false, "Unable to dump configuration");
-                exitValue = pswarpExitCode(exitValue);
-            }
-        }
-
-        psThreadPoolFinalize();
-        psMemCheckCorruption(stderr, true);
-
-        psFree(config);
-
-        psTimerStop();
-        pmVisualClose();
-        pmModelClassCleanup();
-        pmConceptsDone();
-        pmConfigDone();
-        psLibFinalize();
-
-        exitValue = pswarpExitCode(exitValue);
-        return exitValue;
-    }
-}
+// NOTE: pswarpCleanup calls exit
Index: /branches/eam_branches/ipp-20130307/pswarp/src/pswarp.h
===================================================================
--- /branches/eam_branches/ipp-20130307/pswarp/src/pswarp.h	(revision 35372)
+++ /branches/eam_branches/ipp-20130307/pswarp/src/pswarp.h	(revision 35373)
@@ -77,4 +77,10 @@
     double jacobian;                    ///< (Square root of) local Jacobian
 } pswarpTransformTileArgs;
+
+typedef struct {
+    FILE *f;				// File stream for statistics
+    char *name;				// Filename for statistics
+    psMetadata *md;			// Container for statistics
+} pswarpStatsFile;
 
 pswarpTransformTileArgs *pswarpTransformTileArgsAlloc(void);
@@ -160,2 +166,8 @@
     );
 
+pswarpStatsFile *pswarpStatsFileAlloc ();
+pswarpStatsFile *pswarpStatsFileOpen (pmConfig *config);
+bool pswarpStatsFileSave (pmConfig *config, pswarpStatsFile *statsFile);
+
+// cleanup memory and exit
+void pswarpCleanup (pmConfig *config, pswarpStatsFile *statsFile) PS_ATTR_NORETURN;
Index: /branches/eam_branches/ipp-20130307/pswarp/src/pswarpCleanup.c
===================================================================
--- /branches/eam_branches/ipp-20130307/pswarp/src/pswarpCleanup.c	(revision 35373)
+++ /branches/eam_branches/ipp-20130307/pswarp/src/pswarpCleanup.c	(revision 35373)
@@ -0,0 +1,60 @@
+/** @file pswarp.c
+ *
+ *  @brief cleanup the open files & memory then exit
+ *  @ingroup pswarp
+ *
+ *  @author IfA
+ *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-11 23:27:58 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+# include "pswarp.h"
+# include "pswarpFileNames.h"
+
+void pswarpCleanup (pmConfig *config, pswarpStatsFile *statsFile)
+{
+    psExit exitValue = pswarpExitCode(PS_EXIT_SUCCESS); // Exit code
+
+    // Ensure everything is written out, at every level
+    pswarpFileActivation(config, detectorFiles, true);
+    pswarpFileActivation(config, skycellFiles, true);
+    pswarpFileActivation(config, photFiles, true);
+    pswarpFileActivation(config, independentFiles, true);
+
+    if (!pswarpIOChecksAfter(config)) {
+	psError(psErrorCodeLast(), false, "Unable to write files.");
+	exitValue = pswarpExitCode(exitValue);
+	pmFPAfileFreeSetStrict(false);
+    }
+
+    if (!pswarpStatsFileSave (config, statsFile)) {
+	psError(psErrorCodeLast(), false, "Unable to save stats file.");
+	exitValue = pswarpExitCode(exitValue);
+    }
+
+    // Dump configuration
+    bool mdok = false;
+    psString dump_file = psMetadataLookupStr(&mdok, config->arguments, "DUMP_CONFIG");
+    if (dump_file) {
+	if (!pmConfigDump(config, dump_file)) {
+	    psError(psErrorCodeLast(), false, "Unable to dump configuration");
+	    exitValue = pswarpExitCode(exitValue);
+	}
+    }
+
+    psThreadPoolFinalize();
+    psMemCheckCorruption(stderr, true);
+
+    psFree(config);
+
+    psTimerStop();
+    pmVisualClose();
+    pmModelClassCleanup();
+    pmConceptsDone();
+    pmConfigDone();
+    psLibFinalize();
+
+    exitValue = pswarpExitCode(exitValue);
+    exit (exitValue);
+}
Index: /branches/eam_branches/ipp-20130307/pswarp/src/pswarpDefine.c
===================================================================
--- /branches/eam_branches/ipp-20130307/pswarp/src/pswarpDefine.c	(revision 35372)
+++ /branches/eam_branches/ipp-20130307/pswarp/src/pswarpDefine.c	(revision 35373)
@@ -1,6 +1,5 @@
 /** @file pswarpDefine.c
  *
- *  @brief
- *
+ *  @brief generates the output images
  *  @ingroup pswarp
  *
@@ -13,7 +12,4 @@
 # include "pswarp.h"
 
-/**
- * loads the skycell metadata
- */
 bool pswarpDefine (pmConfig *config) {
 
@@ -132,144 +128,2 @@
 }
 
-bool pswarpDefineBackground (pmConfig *config) {
-
-    // load the PSWARP recipe
-    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
-    if (!recipe) {
-        psError(PSWARP_ERR_CONFIG, true, "Can't find PSWARP recipe!\n");
-        return false;
-    }
-
-    // select the input data sources
-    pmFPAfile *skycell = psMetadataLookupPtr (NULL, config->files, "PSWARP.SKYCELL");
-    if (!skycell) {
-        psError(PSWARP_ERR_CONFIG, false, "Can't find skycell data!\n");
-        return false;
-    }
-    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PSWARP.OUTPUT.BKGMODEL");
-    if (!output) {
-        psError(PSWARP_ERR_CONFIG, false, "Can't find output data!\n");
-        return false;
-    }
-    pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PSWARP.INPUT");
-    if (!input) {
-        psError(PSWARP_ERR_CONFIG, false, "Can't find input data!\n");
-        return false;
-    }
-    
-    // open the full skycell file; no need to defer different depths. only load the header data
-    pmFPAview *view = pmFPAviewAlloc (0);
-    pmFPAfileOpen (skycell, view, config);
-
-    // Read header and create target
-    {
-        if (!pmFPAReadHeaderSet(skycell->fpa, skycell->fits, config)) {
-            psError(psErrorCodeLast(), false, "Unable to read headers for skycell.");
-            psFree(view);
-            return false;
-        }
-        view->chip = 0;
-        view->cell = 0;
-        view->readout = 0;
-        pmCell *source = pmFPAfileThisCell(config->files, view, "PSWARP.SKYCELL"); ///< Source cell
-        pmHDU *hdu = pmHDUFromCell(source); ///< HDU for source
-        if (!hdu || !hdu->header) {
-            psError(PM_ERR_PROG, false, "Unable to find header for sky cell.");
-            psFree(view);
-            return false;
-        }
-        int numCols = psMetadataLookupS32(NULL, hdu->header, "NAXIS1"); ///< Number of columns
-        int numRows = psMetadataLookupS32(NULL, hdu->header, "NAXIS2"); ///< Number of rows
-        if ((numCols == 0) || (numRows == 0)) {
-            psError(PSWARP_ERR_DATA, false, "skycell has invalid dimensions %d x %d", numCols, numRows);
-            psFree(view);
-            return false;
-        }
-
-        pmCell *target = pmFPAviewThisCell(view, output->fpa); ///< Target cell
-        pmReadout *readout = pmReadoutAlloc(target); ///< Target readout
-        readout->image = psImageAlloc(numCols / output->xBin, numRows / output->yBin, PS_TYPE_F32);
-        psImageInit(readout->image, NAN);
-        psFree(readout);                // Drop reference
-
-        bool status = false;
-        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XBIN");
-        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YBIN");
-/* 	psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.XBIN",PS_META_REPLACE,"",output->xBin); */
-/* 	psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.YBIN",PS_META_REPLACE,"",output->yBin); */
-        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XSIZE");
-        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YSIZE");
-/* 	psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.XSIZE",PS_META_REPLACE,"",numCols / output->xBin); */
-/* 	psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.YSIZE",PS_META_REPLACE,"",numRows / output->yBin); */
-        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XPARITY");
-        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YPARITY");
-        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.X0");
-        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.Y0");
-
-	
-    }
-
-    // XXX this is not a sufficient test
-    view->chip = 0;
-    view->cell = 0;
-    view->readout = -1;
-    pmHDU *phu = pmFPAviewThisPHU(view, skycell->fpa); ///< Skycell PHU
-    pmHDU *hdu = pmFPAviewThisHDU(view, skycell->fpa); ///< Skycell header
-
-    pmAstromWCS *WCS = pmAstromWCSfromHeader(hdu->header);
-
-    double cd1f = 1.0 * output->xBin;
-    double cd2f = 1.0 * output->yBin;
-    
-    WCS->crpix1 = WCS->crpix1 / cd1f;
-    WCS->crpix2 = WCS->crpix2 / cd2f;
-    
-    WCS->cdelt1 *= cd1f;
-    WCS->cdelt2 *= cd2f;
-
-    WCS->trans->x->coeff[1][0] *= cd1f;
-    WCS->trans->x->coeff[0][1] *= cd2f;
-    WCS->trans->y->coeff[1][0] *= cd1f;
-    WCS->trans->y->coeff[0][1] *= cd2f;
-    
-    
-    pmAstromWCStoHeader (hdu->header,WCS);
-
-    bool bilevelAstrometry = false;
-    if (phu) {
-        char *ctype = psMetadataLookupStr(NULL, phu->header, "CTYPE1");
-        if (ctype) {
-            bilevelAstrometry = !strcmp(&ctype[4], "-DIS");
-        }
-    }
-
-    // We read from the skycell into the output.  i.e., the output receives the desired astrometry.
-    pmChip *outputChip = pmFPAviewThisChip(view, output->fpa); ///< Chip in the output
-    if (bilevelAstrometry) {
-        if (!pmAstromReadBilevelMosaic(output->fpa, phu->header)) {
-            psError(psErrorCodeLast(), false, "Unable to read bilevel mosaic astrometry for skycell.");
-            psFree(view);
-            return false;
-        }
-        if (!pmAstromReadBilevelChip(outputChip, hdu->header)) {
-            psError(psErrorCodeLast(), false, "Unable to read bilevel chip astrometry for skycell.");
-            psFree(view);
-            return false;
-        }
-    } else {
-        // we use a default FPA pixel scale of 1.0
-      if (!pmAstromReadWCS(output->fpa, outputChip, hdu->header, 1.0)) {
-            psError(psErrorCodeLast(), false, "Unable to read WCS astrometry for skycell.");
-            psFree(view);
-            return false;
-        }
-    }
-
-    
-    view->chip = view->cell = view->readout = -1;
-    pmFPAAddSourceFromView(output->fpa, view, output->format);
-
-
-    psFree (view);
-    return true;
-}
Index: /branches/eam_branches/ipp-20130307/pswarp/src/pswarpDefineBackground.c
===================================================================
--- /branches/eam_branches/ipp-20130307/pswarp/src/pswarpDefineBackground.c	(revision 35373)
+++ /branches/eam_branches/ipp-20130307/pswarp/src/pswarpDefineBackground.c	(revision 35373)
@@ -0,0 +1,155 @@
+/** @file pswarpDefineBackground.c
+ * 
+ *  @brief generates the output background model
+ *  @ingroup pswarp
+ *
+ *  @author IfA
+ *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-05 20:44:04 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+# include "pswarp.h"
+
+bool pswarpDefineBackground (pmConfig *config) {
+
+    if (!psMetadataLookupBool(NULL,config->arguments,"BACKGROUND.MODEL")) return true;
+
+    // load the PSWARP recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    if (!recipe) {
+        psError(PSWARP_ERR_CONFIG, true, "Can't find PSWARP recipe!\n");
+        return false;
+    }
+
+    // select the input data sources
+    pmFPAfile *skycell = psMetadataLookupPtr (NULL, config->files, "PSWARP.SKYCELL");
+    if (!skycell) {
+        psError(PSWARP_ERR_CONFIG, false, "Can't find skycell data!\n");
+        return false;
+    }
+    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PSWARP.OUTPUT.BKGMODEL");
+    if (!output) {
+        psError(PSWARP_ERR_CONFIG, false, "Can't find output data!\n");
+        return false;
+    }
+    pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PSWARP.INPUT");
+    if (!input) {
+        psError(PSWARP_ERR_CONFIG, false, "Can't find input data!\n");
+        return false;
+    }
+    
+    // open the full skycell file; no need to defer different depths. only load the header data
+    pmFPAview *view = pmFPAviewAlloc (0);
+    pmFPAfileOpen (skycell, view, config);
+
+    // Read header and create target
+    {
+        if (!pmFPAReadHeaderSet(skycell->fpa, skycell->fits, config)) {
+            psError(psErrorCodeLast(), false, "Unable to read headers for skycell.");
+            psFree(view);
+            return false;
+        }
+        view->chip = 0;
+        view->cell = 0;
+        view->readout = 0;
+        pmCell *source = pmFPAfileThisCell(config->files, view, "PSWARP.SKYCELL"); ///< Source cell
+        pmHDU *hdu = pmHDUFromCell(source); ///< HDU for source
+        if (!hdu || !hdu->header) {
+            psError(PM_ERR_PROG, false, "Unable to find header for sky cell.");
+            psFree(view);
+            return false;
+        }
+        int numCols = psMetadataLookupS32(NULL, hdu->header, "NAXIS1"); ///< Number of columns
+        int numRows = psMetadataLookupS32(NULL, hdu->header, "NAXIS2"); ///< Number of rows
+        if ((numCols == 0) || (numRows == 0)) {
+            psError(PSWARP_ERR_DATA, false, "skycell has invalid dimensions %d x %d", numCols, numRows);
+            psFree(view);
+            return false;
+        }
+
+        pmCell *target = pmFPAviewThisCell(view, output->fpa); ///< Target cell
+        pmReadout *readout = pmReadoutAlloc(target); ///< Target readout
+        readout->image = psImageAlloc(numCols / output->xBin, numRows / output->yBin, PS_TYPE_F32);
+        psImageInit(readout->image, NAN);
+        psFree(readout);                // Drop reference
+
+        bool status = false;
+        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XBIN");
+        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YBIN");
+ 	// psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.XBIN",PS_META_REPLACE,"",output->xBin);
+ 	// psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.YBIN",PS_META_REPLACE,"",output->yBin);
+        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XSIZE");
+        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YSIZE");
+ 	// psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.XSIZE",PS_META_REPLACE,"",numCols / output->xBin); 
+ 	// psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.YSIZE",PS_META_REPLACE,"",numRows / output->yBin);
+        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XPARITY");
+        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YPARITY");
+        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.X0");
+        psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.Y0");
+    }
+
+    // XXX this is not a sufficient test
+    view->chip = 0;
+    view->cell = 0;
+    view->readout = -1;
+    pmHDU *phu = pmFPAviewThisPHU(view, skycell->fpa); ///< Skycell PHU
+    pmHDU *hdu = pmFPAviewThisHDU(view, skycell->fpa); ///< Skycell header
+
+    pmAstromWCS *WCS = pmAstromWCSfromHeader(hdu->header);
+
+    double cd1f = 1.0 * output->xBin;
+    double cd2f = 1.0 * output->yBin;
+    
+    WCS->crpix1 = WCS->crpix1 / cd1f;
+    WCS->crpix2 = WCS->crpix2 / cd2f;
+    
+    WCS->cdelt1 *= cd1f;
+    WCS->cdelt2 *= cd2f;
+
+    WCS->trans->x->coeff[1][0] *= cd1f;
+    WCS->trans->x->coeff[0][1] *= cd2f;
+    WCS->trans->y->coeff[1][0] *= cd1f;
+    WCS->trans->y->coeff[0][1] *= cd2f;
+    
+    
+    pmAstromWCStoHeader (hdu->header,WCS);
+
+    bool bilevelAstrometry = false;
+    if (phu) {
+        char *ctype = psMetadataLookupStr(NULL, phu->header, "CTYPE1");
+        if (ctype) {
+            bilevelAstrometry = !strcmp(&ctype[4], "-DIS");
+        }
+    }
+
+    // We read from the skycell into the output.  i.e., the output receives the desired astrometry.
+    pmChip *outputChip = pmFPAviewThisChip(view, output->fpa); ///< Chip in the output
+    if (bilevelAstrometry) {
+        if (!pmAstromReadBilevelMosaic(output->fpa, phu->header)) {
+            psError(psErrorCodeLast(), false, "Unable to read bilevel mosaic astrometry for skycell.");
+            psFree(view);
+            return false;
+        }
+        if (!pmAstromReadBilevelChip(outputChip, hdu->header)) {
+            psError(psErrorCodeLast(), false, "Unable to read bilevel chip astrometry for skycell.");
+            psFree(view);
+            return false;
+        }
+    } else {
+        // we use a default FPA pixel scale of 1.0
+      if (!pmAstromReadWCS(output->fpa, outputChip, hdu->header, 1.0)) {
+            psError(psErrorCodeLast(), false, "Unable to read WCS astrometry for skycell.");
+            psFree(view);
+            return false;
+        }
+    }
+
+    
+    view->chip = view->cell = view->readout = -1;
+    pmFPAAddSourceFromView(output->fpa, view, output->format);
+
+
+    psFree (view);
+    return true;
+}
Index: anches/eam_branches/ipp-20130307/pswarp/src/pswarpExit.c
===================================================================
--- /branches/eam_branches/ipp-20130307/pswarp/src/pswarpExit.c	(revision 35372)
+++ 	(revision )
@@ -1,77 +1,0 @@
-/** @file pswarpExit.c
- *
- *  @brief
- *
- *  @ingroup pswarp
- *
- *  @author IfA
- *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2009-02-05 20:44:04 $
- *  Copyright 2009 Institute for Astronomy, University of Hawaii
- */
-
-# include "pswarp.h"
-
-
-psExit pswarpExitCode(psExit exitValue)
-{
-    if (exitValue != PS_EXIT_SUCCESS) {
-        return exitValue;
-    }
-
-    // gcc -Wswitch complains here if err is declared as type psErrorCode
-    // the collection of ps*ErrorCode values are enums defined separately for 
-    // each module (psphot, pswarp, etc).  the lowest type, psErrorCode is only the base set and does
-    // not include the possible psphot values
-
-    // for now, to get around this, we just use an int for the switch
-
-    // psErrorCode errorCode = psErrorCodeLast(); // Error code
-    int errorCode = psErrorCodeLast(); // Error code
-
-    if (errorCode != PS_ERR_NONE) {
-        pmFPAfileFreeSetStrict(false);
-        psErrorStackPrint(stderr, "Unable to perform warp.");
-        switch (errorCode) {
-          case PSWARP_ERR_UNKNOWN:
-          case PS_ERR_UNKNOWN:
-            psLogMsg("pswarp", PS_LOG_WARN, "Unknown error code: %x", errorCode);
-            return PS_EXIT_UNKNOWN_ERROR;
-          case PS_ERR_IO:
-          case PS_ERR_DB_CLIENT:
-          case PS_ERR_DB_SERVER:
-          case PS_ERR_BAD_FITS:
-          case PS_ERR_OS_CALL_FAILED:
-          case PM_ERR_SYS:
-          case PSWARP_ERR_IO:
-            psLogMsg("pswarp", PS_LOG_WARN, "I/O error code: %x", errorCode);
-            return PS_EXIT_SYS_ERROR;
-          case PS_ERR_BAD_PARAMETER_VALUE:
-          case PS_ERR_BAD_PARAMETER_TYPE:
-          case PS_ERR_BAD_PARAMETER_NULL:
-          case PS_ERR_BAD_PARAMETER_SIZE:
-          case PSWARP_ERR_ARGUMENTS:
-          case PSWARP_ERR_CONFIG:
-            psLogMsg("pswarp", PS_LOG_WARN, "Configuration error code: %x", errorCode);
-            return PS_EXIT_CONFIG_ERROR;
-          case PSPHOT_ERR_PSF:
-          case PSWARP_ERR_DATA:
-          case PSWARP_ERR_NO_OVERLAP:
-            psLogMsg("pswarp", PS_LOG_WARN, "Data error code: %x", errorCode);
-            return PS_EXIT_DATA_ERROR;
-          case PS_ERR_UNEXPECTED_NULL:
-          case PS_ERR_PROGRAMMING:
-          case PSWARP_ERR_NOT_IMPLEMENTED:
-            psLogMsg("pswarp", PS_LOG_WARN, "Programming error code: %x", errorCode);
-            exitValue = PS_EXIT_PROG_ERROR;
-            break;
-          default:
-            // It's a programming error if we're not dealing with the error correctly
-            psLogMsg("pswarp", PS_LOG_WARN, "Unrecognised error code: %x", errorCode);
-            return PS_EXIT_PROG_ERROR;
-        }
-    }
-
-    return exitValue;
-}
-
Index: /branches/eam_branches/ipp-20130307/pswarp/src/pswarpExitCode.c
===================================================================
--- /branches/eam_branches/ipp-20130307/pswarp/src/pswarpExitCode.c	(revision 35373)
+++ /branches/eam_branches/ipp-20130307/pswarp/src/pswarpExitCode.c	(revision 35373)
@@ -0,0 +1,76 @@
+/** @file pswarpExit.c
+ *
+ *  @brief
+ *
+ *  @ingroup pswarp
+ *
+ *  @author IfA
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-05 20:44:04 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+# include "pswarp.h"
+
+psExit pswarpExitCode(psExit exitValue)
+{
+    if (exitValue != PS_EXIT_SUCCESS) {
+        return exitValue;
+    }
+
+    // gcc -Wswitch complains here if err is declared as type psErrorCode
+    // the collection of ps*ErrorCode values are enums defined separately for 
+    // each module (psphot, pswarp, etc).  the lowest type, psErrorCode is only the base set and does
+    // not include the possible psphot values
+
+    // for now, to get around this, we just use an int for the switch
+
+    // psErrorCode errorCode = psErrorCodeLast(); // Error code
+    int errorCode = psErrorCodeLast(); // Error code
+
+    if (errorCode != PS_ERR_NONE) {
+        pmFPAfileFreeSetStrict(false);
+        psErrorStackPrint(stderr, "Unable to perform warp.");
+        switch (errorCode) {
+          case PSWARP_ERR_UNKNOWN:
+          case PS_ERR_UNKNOWN:
+            psLogMsg("pswarp", PS_LOG_WARN, "Unknown error code: %x", errorCode);
+            return PS_EXIT_UNKNOWN_ERROR;
+          case PS_ERR_IO:
+          case PS_ERR_DB_CLIENT:
+          case PS_ERR_DB_SERVER:
+          case PS_ERR_BAD_FITS:
+          case PS_ERR_OS_CALL_FAILED:
+          case PM_ERR_SYS:
+          case PSWARP_ERR_IO:
+            psLogMsg("pswarp", PS_LOG_WARN, "I/O error code: %x", errorCode);
+            return PS_EXIT_SYS_ERROR;
+          case PS_ERR_BAD_PARAMETER_VALUE:
+          case PS_ERR_BAD_PARAMETER_TYPE:
+          case PS_ERR_BAD_PARAMETER_NULL:
+          case PS_ERR_BAD_PARAMETER_SIZE:
+          case PSWARP_ERR_ARGUMENTS:
+          case PSWARP_ERR_CONFIG:
+            psLogMsg("pswarp", PS_LOG_WARN, "Configuration error code: %x", errorCode);
+            return PS_EXIT_CONFIG_ERROR;
+          case PSPHOT_ERR_PSF:
+          case PSWARP_ERR_DATA:
+          case PSWARP_ERR_NO_OVERLAP:
+            psLogMsg("pswarp", PS_LOG_WARN, "Data error code: %x", errorCode);
+            return PS_EXIT_DATA_ERROR;
+          case PS_ERR_UNEXPECTED_NULL:
+          case PS_ERR_PROGRAMMING:
+          case PSWARP_ERR_NOT_IMPLEMENTED:
+            psLogMsg("pswarp", PS_LOG_WARN, "Programming error code: %x", errorCode);
+            exitValue = PS_EXIT_PROG_ERROR;
+            break;
+          default:
+            // It's a programming error if we're not dealing with the error correctly
+            psLogMsg("pswarp", PS_LOG_WARN, "Unrecognised error code: %x", errorCode);
+            return PS_EXIT_PROG_ERROR;
+        }
+    }
+
+    return exitValue;
+}
+
Index: /branches/eam_branches/ipp-20130307/pswarp/src/pswarpLoop.c
===================================================================
--- /branches/eam_branches/ipp-20130307/pswarp/src/pswarpLoop.c	(revision 35372)
+++ /branches/eam_branches/ipp-20130307/pswarp/src/pswarpLoop.c	(revision 35373)
@@ -1,6 +1,5 @@
 /** @file pswarpLoop.c
  *
- *  @brief
- *
+ *  @brief mail processing loop for pswarp
  *  @ingroup pswarp
  *
@@ -17,6 +16,4 @@
 #define WCS_NONLIN_TOL 0.001            // Non-linear tolerance for header WCS
 #define TESTING 0                       // Testing output?
-
-
 
 // Loop over the inputs, warp them to the output skycell and then write out the output.
@@ -155,5 +152,4 @@
             psError(psErrorCodeLast(), false, "Unable to read bilevel mosaic astrometry for input FPA.");
             psFree(view);
-            psFree(stats);
             goto DONE;
         }
@@ -185,5 +181,4 @@
                 psError(psErrorCodeLast(), false, "Unable to read bilevel chip astrometry for input FPA.");
                 psFree(view);
-                psFree(stats);
                 goto DONE;
             }
@@ -193,5 +188,4 @@
                 psError(psErrorCodeLast(), false, "Unable to read WCS astrometry for input FPA.");
                 psFree(view);
-                psFree(stats);
                 goto DONE;
             }
@@ -301,5 +295,4 @@
     if (!pmConceptsAverageCells(outCell, cells, NULL, NULL, false)) {
         psError(psErrorCodeLast(), false, "Unable to average cell concepts.");
-        psFree(stats);
         psFree(cells);
         psFree(view);
@@ -313,5 +306,4 @@
     if (!psMetadataCopy(outFPA->concepts, input->fpa->concepts)) {
         psError(psErrorCodeLast(), false, "Unable to copy FPA concepts from input to output.");
-        psFree(stats);
         psFree(view);
         goto DONE;
@@ -345,5 +337,4 @@
     if (!pmAstromWriteWCS(hdu->header, outFPA, outChip, WCS_NONLIN_TOL)) {
         psError(psErrorCodeLast(), false, "Unable to generate WCS header.");
-        psFree(stats);
         goto DONE;
     }
@@ -452,354 +443,2 @@
     return true;
 }
-
-// Loop over the inputs, warp them to the output skycell and then write out the output.
-bool pswarpLoopBackground(pmConfig *config, psMetadata *stats)
-{
-    bool status;
-    bool mdok;                          // Status of MD lookup
-    const char *skyCamera = psMetadataLookupStr(NULL, config->arguments,
-                                                "SKYCELL.CAMERA");  // Name of camera for skycell
-    pmConfigCamerasCull(config, skyCamera);
-    pmConfigRecipesCull(config, "PSWARP,PPSTATS,PSPHOT,PSASTRO,MASKS,JPEG");
-
-    // load the recipe
-    psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSWARP_RECIPE);
-    if (!recipe) {
-        psError(PSWARP_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
-        return false;
-    }
-
-    if (!pswarpSetMaskBits(config)) {
-        psError(psErrorCodeLast(), false, "failed to set mask bits");
-        return NULL;
-    }
-
-    // select the input data sources
-    pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PSWARP.BKGMODEL");
-    if (!input) {
-        psError(PSWARP_ERR_CONFIG, true, "Can't find input data!\n");
-        return false;
-    }
-
-    // use the external astrometry source if supplied
-    pmFPAfile *astrom = psMetadataLookupPtr(NULL, config->files, "PSWARP.ASTROM");
-    if (!astrom) {
-        astrom = input;
-    }
-
-    if (astrom->camera != input->camera) {
-        psError(PSWARP_ERR_DATA, true, "Input camera and astrometry camera do not match.");
-        return false;
-    }
-
-    // select the output readout
-    pmFPAview *view = pmFPAviewAlloc(0);
-    view->chip = 0;
-    view->cell = 0;
-    view->readout = 0;
-    pmReadout *output = pmFPAfileThisReadout(config->files, view, "PSWARP.OUTPUT.BKGMODEL");
-    if (!output) {
-        psError(PSWARP_ERR_CONFIG, true, "Can't find output background data!\n");
-        return false;
-    }
-    psFree (view);
-    // Turn all skycell files on to generate them, and then turn them off for the loop over the input images
-    // the input, which is in a different format.
-    {
-        pswarpFileActivation(config, detectorFiles, false);
-        pswarpFileActivation(config, photFiles, false);
-        pswarpFileActivation(config, independentFiles, false);
-        pswarpFileActivation(config, skycellFiles, true);
-        if (!pswarpIOChecksBefore(config)) {
-            psError(psErrorCodeLast(), false, "Unable to read files.");
-            goto DONE;
-        }
-        pswarpFileActivation(config, skycellFiles, false);
-    }
-    // Read the input astrometry
-    // XXX rather than use the activations here, this should just explicitly loop over the desired filerule
-    {
-
-      pmFPAfileActivate(config->files, true, "PSWARP.ASTROM");
-
-        pmChip *chip;
-        pmFPAview *view = pmFPAviewAlloc(0);
-        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
-            psError(psErrorCodeLast(), false, "Unable to read files.");
-            goto DONE;
-        }
-
-        while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
-#if 0
-	  // This needs to be removed because otherwise it throws an error of duplicate PSPHOT.DETECTIONS.
-            if (!chip->process || !chip->file_exists) { continue; }
-            if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
-                psError(psErrorCodeLast(), false, "Unable to read files.");
-                goto DONE;
-            }
-#endif
-            pmCell *cell;
-            while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
-	      psTrace ("pswarp", 4, "ACell %d: %x %x %d\n", view->cell, cell->file_exists, cell->process,psErrorCodeLast());
-                if (!cell->process || !cell->file_exists) { continue; }
-                if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE) ||
-                    !pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
-                    psError(psErrorCodeLast(), false, "Unable to read files.");
-                    goto DONE;
-                }
-            }
-            if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
-                psError(psErrorCodeLast(), false, "Unable to write files.");
-                goto DONE;
-            }
-        }
-        if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
-            psError(psErrorCodeLast(), false, "Unable to write files.");
-            goto DONE;
-        }
-        psFree(view);
-        pswarpFileActivation(config, detectorFiles, true);
-        pmFPAfileActivate(config->files, false, "PSWARP.ASTROM");
-    }
-
-    // Don't care about the skycell anymore --- we've read it, and that's all we need to do.
-    pmFPAfileActivate(config->files, false, "PSWARP.SKYCELL");
-    view = pmFPAviewAlloc(0);
-
-    // find the FPA phu
-    bool bilevelAstrometry = false;
-    pmHDU *phu = pmFPAviewThisPHU(view, astrom->fpa);
-
-    //    pmAstromWCS *WCSF = pmAstromWCSfromHeader(phu->header);
-    
-    if (phu) {
-        char *ctype = psMetadataLookupStr(NULL, phu->header, "CTYPE1");
-        if (ctype) {
-            bilevelAstrometry = !strcmp (&ctype[4], "-DIS");
-        }
-    }
-    if (bilevelAstrometry) {
-        if (!pmAstromReadBilevelMosaic(input->fpa, phu->header)) {
-            psError(psErrorCodeLast(), false, "Unable to read bilevel mosaic astrometry for input FPA.");
-            psFree(view);
-            psFree(stats);
-            goto DONE;
-        }
-    }
-
-    psList *cells = psListAlloc(NULL);  // List of cells, for concepts averaging
-
-    // files associated with the science image
-    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
-        psError(psErrorCodeLast(), false, "Unable to read files.");
-        goto DONE;
-    }
-    pmChip *chip;
-    while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
-        psTrace ("pswarp", 4, "DChip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
-        if (!chip->process || !chip->file_exists) { continue; }
-        if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
-            psError(psErrorCodeLast(), false, "Unable to read files.");
-            goto DONE;
-        }
-
-	// Pull information from the header of the background files so we can use it to set values.
-	pmHDU *hdu = pmFPAviewThisHDU(view,input->fpa);
-	psMetadata *header = hdu->header;
-	
-	int IMAXIS1 = psMetadataLookupS32(NULL,header,"IMNAXIS1");
-	int IMAXIS2 = psMetadataLookupS32(NULL,header,"IMNAXIS2");
-	int NAXIS1 = psMetadataLookupS32(NULL,header,"NAXIS1");
-	int NAXIS2 = psMetadataLookupS32(NULL,header,"NAXIS2");
-	char *CCDSUM = psMetadataLookupStr(NULL,header,"CCDSUM");
-	int CCDSUM1 = atoi(strtok(CCDSUM," "));
-	int CCDSUM2 = atoi(strtok(NULL," "));
-	
-	psMetadataAddF32(config->arguments,PS_LIST_TAIL,"BKG_WARP_XOFFSET", PS_META_REPLACE,
-			 "xoffset for background model data", (NAXIS1 * CCDSUM1 - IMAXIS1) / (2.0 * CCDSUM1));
-	psMetadataAddF32(config->arguments,PS_LIST_TAIL,"BKG_WARP_YOFFSET", PS_META_REPLACE,
-			 "yoffset for background model data", (NAXIS2 * CCDSUM2 - IMAXIS2) / (2.0 * CCDSUM2));
-	psTrace("pswarp",5,"%d %d %d %d %d %d %g %g %d %d",
-		psMetadataLookupS32(NULL,header,"IMNAXIS1"),
-		psMetadataLookupS32(NULL,header,"IMNAXIS2"),
-		psMetadataLookupS32(NULL,header,"NAXIS1"),
-		psMetadataLookupS32(NULL,header,"NAXIS2"),
-		CCDSUM1,CCDSUM2,
-		psMetadataLookupF32(NULL,config->arguments,"BKG_WARP_XOFFSET"),
-		psMetadataLookupF32(NULL,config->arguments,"BKG_WARP_YOFFSET"),
-		psMetadataLookupS32(NULL,config->arguments,"BKG.XGRID"),
-		psMetadataLookupS32(NULL,config->arguments,"BKG.YGRID"));
-	
-	
-        // read WCS data from the corresponding header
-        hdu = pmFPAviewThisHDU (view, astrom->fpa);
-
-	pmAstromWCS *WCS = pmAstromWCSfromHeader(hdu->header);
-
-	double cd1f = (1.0 * CCDSUM1);// * (1.0 * psMetadataLookupS32(NULL,config->arguments,"BKG.XGRID"));
-	double cd2f = (1.0 * CCDSUM2);// * (1.0 * psMetadataLookupS32(NULL,config->arguments,"BKG.YGRID"));
-
-	WCS->cdelt1 *= cd1f;
-	WCS->cdelt2 *= cd2f;
-	WCS->crpix1 = WCS->crpix1 / cd1f;
-	WCS->crpix2 = WCS->crpix2 / cd2f;
-
-	// WCS->trans->x->nX/nY
-	for (int q = 0; q <= WCS->trans->x->nX; q++) {
-	  for (int r = 0; r <= WCS->trans->x->nY; r++) {
-	    WCS->trans->x->coeff[q][r] *= pow(cd1f,q) * pow(cd2f,r);
-	  }
-	}
-	for (int q = 0; q <= WCS->trans->y->nX; q++) {
-	  for (int r = 0; r <= WCS->trans->y->nY; r++) {
-	    WCS->trans->y->coeff[q][r] *= pow(cd1f,q) * pow(cd2f,r);
-	  }
-	}
-	pmAstromWCStoHeader (hdu->header,WCS);
-	
-        if (bilevelAstrometry) {
-            if (!pmAstromReadBilevelChip (chip, hdu->header)) {
-                psError(psErrorCodeLast(), false, "Unable to read bilevel chip astrometry for input FPA.");
-                psFree(view);
-                psFree(stats);
-                goto DONE;
-            }
-        } else {
-            // we use a default FPA pixel scale of 1.0
-            if (!pmAstromReadWCS (astrom->fpa, chip, hdu->header, 1.0)) {
-                psError(psErrorCodeLast(), false, "Unable to read WCS astrometry for input FPA.");
-                psFree(view);
-                psFree(stats);
-                goto DONE;
-            }
-        }
-	// Modify structure here.
-
-	
-        pmCell *cell;
-        while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
-            psTrace ("pswarp", 4, "DCell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
-            if (!cell->process || !cell->file_exists) { continue; }
-            if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
-                psError(psErrorCodeLast(), false, "Unable to read files.");
-                goto DONE;
-            }
-
-            psListAdd(cells, PS_LIST_TAIL, cell);
-
-            // process each of the readouts
-            pmReadout *readout;
-            while ((readout = pmFPAviewNextReadout(view, input->fpa, 1)) != NULL) {
-                if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
-                    psError(psErrorCodeLast(), false, "Unable to read files.");
-                    goto DONE;
-                }
-                if (!readout->data_exists) {
-                    continue;
-                }
-
-		for (int x = 0; x < readout->image->numCols; x++) {
-		  for (int y = 0; y < readout->image->numRows; y++) {
-		    readout->image->data.F32[y][x] = readout->image->data.F32[y][x] * (cd1f * cd2f) /
-		      (psMetadataLookupS32(&mdok,config->arguments,"BKG.XGRID") *
-		       psMetadataLookupS32(&mdok,config->arguments,"BKG.YGRID"));
-		  }
-		}
-		
-		psMetadataAddS32(config->arguments,PS_LIST_TAIL, "INTERPOLATION.MODE", PS_META_REPLACE, "", 8);
-
-		psMetadataAddBool(config->arguments,PS_LIST_TAIL, "BACKGROUND_WARPING", PS_META_REPLACE, "", true);
-                pswarpTransformReadout(output, readout, config);
-		psMetadataAddBool(config->arguments,PS_LIST_TAIL, "BACKGROUND_WARPING", PS_META_REPLACE, "", false);
-
-                if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
-                    psError(psErrorCodeLast(), false, "Unable to write files.");
-                    goto DONE;
-                }
-            }
-            if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
-                psError(psErrorCodeLast(), false, "Unable to write files.");
-                goto DONE;
-            }
-        }
-        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
-            psError(psErrorCodeLast(), false, "Unable to write files.");
-            goto DONE;
-        }
-    }
-    if (!output->data_exists) {
-        psWarning("No overlap between input and skycell.");
-        psphotFilesActivate(config, false);
-        psFree(cells);
-        psFree(view);
-        goto DONE;
-    }
-    pmCell *outCell = output->parent;   ///< Output cell
-    pmChip *outChip = outCell->parent;  ///< Output chip
-    pmFPA *outFPA = outChip->parent;    ///< Output FP
-
-/*     if (!pswarpPixelsLit(output, stats, config)) { */
-/*         psError(psErrorCodeLast(), false, "Unable to calculate pixel regions."); */
-/*         psFree(cells); */
-/*         psFree(view); */
-/*         goto DONE; */
-/*     } */
-    psRegion *trimsec = psMetadataLookupPtr(NULL, outCell->concepts, "CELL.TRIMSEC"); ///< Trim section
-    trimsec->x0 = trimsec->x1 = trimsec->y0 = trimsec->y1 = 0; ///< All pixels
-
-    if (!psMetadataCopy(outFPA->concepts, input->fpa->concepts)) {
-        psError(psErrorCodeLast(), false, "Unable to copy FPA concepts from input to output.");
-        psFree(stats);
-        psFree(view);
-        goto DONE;
-    }
-
-    pmHDU *hdu = outFPA->hdu;           ///< HDU for the output warped image
-
-    // Copy header from target
-    {
-        pmFPAview *skyView = pmFPAviewAlloc(0); ///< View into skycell
-        skyView->chip = skyView->cell = 0;
-        pmCell *cell = pmFPAfileThisCell(config->files, skyView, "PSWARP.SKYCELL"); // Skycell cell
-        psFree(skyView);
-        pmHDU *skyHDU = pmHDUFromCell(cell); ///< HDU
-        if (!skyHDU) {
-            psError(PSWARP_ERR_DATA, false, "Unable to find skycell HDU.");
-            psFree(view);
-            goto DONE;
-        }
-        hdu->header = psMetadataCopy(hdu->header, skyHDU->header);
-    }
-    pswarpVersionHeader(hdu->header);
-    
-    if (!pmAstromWriteWCS(hdu->header, outFPA, outChip, WCS_NONLIN_TOL)) {
-        psError(psErrorCodeLast(), false, "Unable to generate WCS header.");
-        psFree(stats);
-        goto DONE;
-    }
-    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
-        psError(psErrorCodeLast(), false, "Unable to write files.");
-        goto DONE;
-    }
-    // Done with the detector side of things
-    pswarpFileActivation(config, detectorFiles, false);
-    pswarpFileActivation(config, independentFiles, false);
-
-
-    // Add MD5 information for readout
-    const char *chipName = psMetadataLookupStr(NULL, output->parent->parent->concepts, "CHIP.NAME");
-    const char *cellName = psMetadataLookupStr(NULL, output->parent->concepts, "CELL.NAME");
-    psString headerName = NULL; ///< Header name for MD5
-    psStringAppend(&headerName, "MD5_%s_%s_%d", chipName, cellName, view->readout);
-    psVector *md5 = psImageMD5(output->image); ///< md5 hash
-    psString md5string = psMD5toString(md5); ///< String
-    psFree(md5);
-    psMetadataAddStr(hdu->header, PS_LIST_TAIL, headerName, PS_META_REPLACE,
-                     "Image MD5", md5string);
-    psFree(md5string);
-    psFree(headerName);
-    psFree(view);
- DONE:
-
-    return true;
-}
Index: /branches/eam_branches/ipp-20130307/pswarp/src/pswarpLoopBackground.c
===================================================================
--- /branches/eam_branches/ipp-20130307/pswarp/src/pswarpLoopBackground.c	(revision 35373)
+++ /branches/eam_branches/ipp-20130307/pswarp/src/pswarpLoopBackground.c	(revision 35373)
@@ -0,0 +1,370 @@
+/** @file pswarpLoopBackground.c
+ *
+ *  @brief background model processing loop for pswarp
+ *  @ingroup pswarp
+ *
+ *  @author IfA
+ *  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-13 21:54:32 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+#include "pswarp.h"
+#include <ppStats.h>
+#include "pswarpFileNames.h"            // Lists of file rules used at different stages
+
+#define WCS_NONLIN_TOL 0.001            // Non-linear tolerance for header WCS
+#define TESTING 0                       // Testing output?
+
+// Loop over the inputs, warp them to the output skycell and then write out the output.
+bool pswarpLoopBackground(pmConfig *config, psMetadata *stats)
+{
+    bool status;
+    bool mdok;                          // Status of MD lookup
+    const char *skyCamera = psMetadataLookupStr(NULL, config->arguments,
+                                                "SKYCELL.CAMERA");  // Name of camera for skycell
+    if (!psMetadataLookupBool(NULL,config->arguments,"BACKGROUND.MODEL")) return true;
+
+    pmConfigCamerasCull(config, skyCamera);
+    pmConfigRecipesCull(config, "PSWARP,PPSTATS,PSPHOT,PSASTRO,MASKS,JPEG");
+
+    // load the recipe
+    psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSWARP_RECIPE);
+    if (!recipe) {
+        psError(PSWARP_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
+        return false;
+    }
+
+    if (!pswarpSetMaskBits(config)) {
+        psError(psErrorCodeLast(), false, "failed to set mask bits");
+        return NULL;
+    }
+
+    // select the input data sources
+    pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PSWARP.BKGMODEL");
+    if (!input) {
+        psError(PSWARP_ERR_CONFIG, true, "Can't find input data!\n");
+        return false;
+    }
+
+    // use the external astrometry source if supplied
+    pmFPAfile *astrom = psMetadataLookupPtr(NULL, config->files, "PSWARP.ASTROM");
+    if (!astrom) {
+        astrom = input;
+    }
+
+    if (astrom->camera != input->camera) {
+        psError(PSWARP_ERR_DATA, true, "Input camera and astrometry camera do not match.");
+        return false;
+    }
+
+    // select the output readout
+    pmFPAview *view = pmFPAviewAlloc(0);
+    view->chip = 0;
+    view->cell = 0;
+    view->readout = 0;
+    pmReadout *output = pmFPAfileThisReadout(config->files, view, "PSWARP.OUTPUT.BKGMODEL");
+    if (!output) {
+        psError(PSWARP_ERR_CONFIG, true, "Can't find output background data!\n");
+        return false;
+    }
+    psFree (view);
+    // Turn all skycell files on to generate them, and then turn them off for the loop over the input images
+    // the input, which is in a different format.
+    {
+        pswarpFileActivation(config, detectorFiles, false);
+        pswarpFileActivation(config, photFiles, false);
+        pswarpFileActivation(config, independentFiles, false);
+        pswarpFileActivation(config, skycellFiles, true);
+        if (!pswarpIOChecksBefore(config)) {
+            psError(psErrorCodeLast(), false, "Unable to read files.");
+            goto DONE;
+        }
+        pswarpFileActivation(config, skycellFiles, false);
+    }
+    // Read the input astrometry
+    // XXX rather than use the activations here, this should just explicitly loop over the desired filerule
+    {
+
+      pmFPAfileActivate(config->files, true, "PSWARP.ASTROM");
+
+        pmChip *chip;
+        pmFPAview *view = pmFPAviewAlloc(0);
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+            psError(psErrorCodeLast(), false, "Unable to read files.");
+            goto DONE;
+        }
+
+        while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
+#if 0
+	  // This needs to be removed because otherwise it throws an error of duplicate PSPHOT.DETECTIONS.
+            if (!chip->process || !chip->file_exists) { continue; }
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                psError(psErrorCodeLast(), false, "Unable to read files.");
+                goto DONE;
+            }
+#endif
+            pmCell *cell;
+            while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
+	      psTrace ("pswarp", 4, "ACell %d: %x %x %d\n", view->cell, cell->file_exists, cell->process,psErrorCodeLast());
+                if (!cell->process || !cell->file_exists) { continue; }
+                if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE) ||
+                    !pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
+                    psError(psErrorCodeLast(), false, "Unable to read files.");
+                    goto DONE;
+                }
+            }
+            if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
+                psError(psErrorCodeLast(), false, "Unable to write files.");
+                goto DONE;
+            }
+        }
+        if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
+            psError(psErrorCodeLast(), false, "Unable to write files.");
+            goto DONE;
+        }
+        psFree(view);
+        pswarpFileActivation(config, detectorFiles, true);
+        pmFPAfileActivate(config->files, false, "PSWARP.ASTROM");
+    }
+
+    // Don't care about the skycell anymore --- we've read it, and that's all we need to do.
+    pmFPAfileActivate(config->files, false, "PSWARP.SKYCELL");
+    view = pmFPAviewAlloc(0);
+
+    // find the FPA phu
+    bool bilevelAstrometry = false;
+    pmHDU *phu = pmFPAviewThisPHU(view, astrom->fpa);
+
+    //    pmAstromWCS *WCSF = pmAstromWCSfromHeader(phu->header);
+    
+    if (phu) {
+        char *ctype = psMetadataLookupStr(NULL, phu->header, "CTYPE1");
+        if (ctype) {
+            bilevelAstrometry = !strcmp (&ctype[4], "-DIS");
+        }
+    }
+    if (bilevelAstrometry) {
+        if (!pmAstromReadBilevelMosaic(input->fpa, phu->header)) {
+            psError(psErrorCodeLast(), false, "Unable to read bilevel mosaic astrometry for input FPA.");
+            psFree(view);
+            psFree(stats);
+            goto DONE;
+        }
+    }
+
+    psList *cells = psListAlloc(NULL);  // List of cells, for concepts averaging
+
+    // files associated with the science image
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
+        psError(psErrorCodeLast(), false, "Unable to read files.");
+        goto DONE;
+    }
+    pmChip *chip;
+    while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
+        psTrace ("pswarp", 4, "DChip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+        if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
+            psError(psErrorCodeLast(), false, "Unable to read files.");
+            goto DONE;
+        }
+
+	// Pull information from the header of the background files so we can use it to set values.
+	pmHDU *hdu = pmFPAviewThisHDU(view,input->fpa);
+	psMetadata *header = hdu->header;
+	
+	int IMAXIS1 = psMetadataLookupS32(NULL,header,"IMNAXIS1");
+	int IMAXIS2 = psMetadataLookupS32(NULL,header,"IMNAXIS2");
+	int NAXIS1 = psMetadataLookupS32(NULL,header,"NAXIS1");
+	int NAXIS2 = psMetadataLookupS32(NULL,header,"NAXIS2");
+	char *CCDSUM = psMetadataLookupStr(NULL,header,"CCDSUM");
+	int CCDSUM1 = atoi(strtok(CCDSUM," "));
+	int CCDSUM2 = atoi(strtok(NULL," "));
+	
+	psMetadataAddF32(config->arguments,PS_LIST_TAIL,"BKG_WARP_XOFFSET", PS_META_REPLACE,
+			 "xoffset for background model data", (NAXIS1 * CCDSUM1 - IMAXIS1) / (2.0 * CCDSUM1));
+	psMetadataAddF32(config->arguments,PS_LIST_TAIL,"BKG_WARP_YOFFSET", PS_META_REPLACE,
+			 "yoffset for background model data", (NAXIS2 * CCDSUM2 - IMAXIS2) / (2.0 * CCDSUM2));
+	psTrace("pswarp",5,"%d %d %d %d %d %d %g %g %d %d",
+		psMetadataLookupS32(NULL,header,"IMNAXIS1"),
+		psMetadataLookupS32(NULL,header,"IMNAXIS2"),
+		psMetadataLookupS32(NULL,header,"NAXIS1"),
+		psMetadataLookupS32(NULL,header,"NAXIS2"),
+		CCDSUM1,CCDSUM2,
+		psMetadataLookupF32(NULL,config->arguments,"BKG_WARP_XOFFSET"),
+		psMetadataLookupF32(NULL,config->arguments,"BKG_WARP_YOFFSET"),
+		psMetadataLookupS32(NULL,config->arguments,"BKG.XGRID"),
+		psMetadataLookupS32(NULL,config->arguments,"BKG.YGRID"));
+	
+	
+        // read WCS data from the corresponding header
+        hdu = pmFPAviewThisHDU (view, astrom->fpa);
+
+	pmAstromWCS *WCS = pmAstromWCSfromHeader(hdu->header);
+
+	double cd1f = (1.0 * CCDSUM1);// * (1.0 * psMetadataLookupS32(NULL,config->arguments,"BKG.XGRID"));
+	double cd2f = (1.0 * CCDSUM2);// * (1.0 * psMetadataLookupS32(NULL,config->arguments,"BKG.YGRID"));
+
+	WCS->cdelt1 *= cd1f;
+	WCS->cdelt2 *= cd2f;
+	WCS->crpix1 = WCS->crpix1 / cd1f;
+	WCS->crpix2 = WCS->crpix2 / cd2f;
+
+	// WCS->trans->x->nX/nY
+	for (int q = 0; q <= WCS->trans->x->nX; q++) {
+	  for (int r = 0; r <= WCS->trans->x->nY; r++) {
+	    WCS->trans->x->coeff[q][r] *= pow(cd1f,q) * pow(cd2f,r);
+	  }
+	}
+	for (int q = 0; q <= WCS->trans->y->nX; q++) {
+	  for (int r = 0; r <= WCS->trans->y->nY; r++) {
+	    WCS->trans->y->coeff[q][r] *= pow(cd1f,q) * pow(cd2f,r);
+	  }
+	}
+	pmAstromWCStoHeader (hdu->header,WCS);
+	
+        if (bilevelAstrometry) {
+            if (!pmAstromReadBilevelChip (chip, hdu->header)) {
+                psError(psErrorCodeLast(), false, "Unable to read bilevel chip astrometry for input FPA.");
+                psFree(view);
+                psFree(stats);
+                goto DONE;
+            }
+        } else {
+            // we use a default FPA pixel scale of 1.0
+            if (!pmAstromReadWCS (astrom->fpa, chip, hdu->header, 1.0)) {
+                psError(psErrorCodeLast(), false, "Unable to read WCS astrometry for input FPA.");
+                psFree(view);
+                psFree(stats);
+                goto DONE;
+            }
+        }
+	// Modify structure here.
+
+	
+        pmCell *cell;
+        while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
+            psTrace ("pswarp", 4, "DCell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+            if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
+                psError(psErrorCodeLast(), false, "Unable to read files.");
+                goto DONE;
+            }
+
+            psListAdd(cells, PS_LIST_TAIL, cell);
+
+            // process each of the readouts
+            pmReadout *readout;
+            while ((readout = pmFPAviewNextReadout(view, input->fpa, 1)) != NULL) {
+                if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                    psError(psErrorCodeLast(), false, "Unable to read files.");
+                    goto DONE;
+                }
+                if (!readout->data_exists) {
+                    continue;
+                }
+
+		for (int x = 0; x < readout->image->numCols; x++) {
+		  for (int y = 0; y < readout->image->numRows; y++) {
+		    readout->image->data.F32[y][x] = readout->image->data.F32[y][x] * (cd1f * cd2f) /
+		      (psMetadataLookupS32(&mdok,config->arguments,"BKG.XGRID") *
+		       psMetadataLookupS32(&mdok,config->arguments,"BKG.YGRID"));
+		  }
+		}
+		
+		psMetadataAddS32(config->arguments,PS_LIST_TAIL, "INTERPOLATION.MODE", PS_META_REPLACE, "", 8);
+
+		psMetadataAddBool(config->arguments,PS_LIST_TAIL, "BACKGROUND_WARPING", PS_META_REPLACE, "", true);
+                pswarpTransformReadout(output, readout, config);
+		psMetadataAddBool(config->arguments,PS_LIST_TAIL, "BACKGROUND_WARPING", PS_META_REPLACE, "", false);
+
+                if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+                    psError(psErrorCodeLast(), false, "Unable to write files.");
+                    goto DONE;
+                }
+            }
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+                psError(psErrorCodeLast(), false, "Unable to write files.");
+                goto DONE;
+            }
+        }
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+            psError(psErrorCodeLast(), false, "Unable to write files.");
+            goto DONE;
+        }
+    }
+    if (!output->data_exists) {
+        psWarning("No overlap between input and skycell.");
+        psphotFilesActivate(config, false);
+        psFree(cells);
+        psFree(view);
+        goto DONE;
+    }
+    pmCell *outCell = output->parent;   ///< Output cell
+    pmChip *outChip = outCell->parent;  ///< Output chip
+    pmFPA *outFPA = outChip->parent;    ///< Output FP
+
+/*     if (!pswarpPixelsLit(output, stats, config)) { */
+/*         psError(psErrorCodeLast(), false, "Unable to calculate pixel regions."); */
+/*         psFree(cells); */
+/*         psFree(view); */
+/*         goto DONE; */
+/*     } */
+    psRegion *trimsec = psMetadataLookupPtr(NULL, outCell->concepts, "CELL.TRIMSEC"); ///< Trim section
+    trimsec->x0 = trimsec->x1 = trimsec->y0 = trimsec->y1 = 0; ///< All pixels
+
+    if (!psMetadataCopy(outFPA->concepts, input->fpa->concepts)) {
+        psError(psErrorCodeLast(), false, "Unable to copy FPA concepts from input to output.");
+        psFree(stats);
+        psFree(view);
+        goto DONE;
+    }
+
+    pmHDU *hdu = outFPA->hdu;           ///< HDU for the output warped image
+
+    // Copy header from target
+    {
+        pmFPAview *skyView = pmFPAviewAlloc(0); ///< View into skycell
+        skyView->chip = skyView->cell = 0;
+        pmCell *cell = pmFPAfileThisCell(config->files, skyView, "PSWARP.SKYCELL"); // Skycell cell
+        psFree(skyView);
+        pmHDU *skyHDU = pmHDUFromCell(cell); ///< HDU
+        if (!skyHDU) {
+            psError(PSWARP_ERR_DATA, false, "Unable to find skycell HDU.");
+            psFree(view);
+            goto DONE;
+        }
+        hdu->header = psMetadataCopy(hdu->header, skyHDU->header);
+    }
+    pswarpVersionHeader(hdu->header);
+    
+    if (!pmAstromWriteWCS(hdu->header, outFPA, outChip, WCS_NONLIN_TOL)) {
+        psError(psErrorCodeLast(), false, "Unable to generate WCS header.");
+        psFree(stats);
+        goto DONE;
+    }
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+        psError(psErrorCodeLast(), false, "Unable to write files.");
+        goto DONE;
+    }
+    // Done with the detector side of things
+    pswarpFileActivation(config, detectorFiles, false);
+    pswarpFileActivation(config, independentFiles, false);
+
+    // Add MD5 information for readout
+    const char *chipName = psMetadataLookupStr(NULL, output->parent->parent->concepts, "CHIP.NAME");
+    const char *cellName = psMetadataLookupStr(NULL, output->parent->concepts, "CELL.NAME");
+    psString headerName = NULL; ///< Header name for MD5
+    psStringAppend(&headerName, "MD5_%s_%s_%d", chipName, cellName, view->readout);
+    psVector *md5 = psImageMD5(output->image); ///< md5 hash
+    psString md5string = psMD5toString(md5); ///< String
+    psFree(md5);
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, headerName, PS_META_REPLACE,
+                     "Image MD5", md5string);
+    psFree(md5string);
+    psFree(headerName);
+    psFree(view);
+ DONE:
+
+    return true;
+}
Index: /branches/eam_branches/ipp-20130307/pswarp/src/pswarpStatsFile.c
===================================================================
--- /branches/eam_branches/ipp-20130307/pswarp/src/pswarpStatsFile.c	(revision 35373)
+++ /branches/eam_branches/ipp-20130307/pswarp/src/pswarpStatsFile.c	(revision 35373)
@@ -0,0 +1,93 @@
+/** @file pswarpStatsFile.c
+ *
+ *  @brief functions for managing the stats file (or return NULL, or exit with an error)
+ *  @ingroup pswarp
+ *
+ *  @author IfA
+ *  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-13 21:54:32 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+#include "pswarp.h"
+
+static void pswarpStatsFileFree (pswarpStatsFile *statsFile) {
+    psFree (statsFile->name);
+    psFree (statsFile->md);
+}
+
+pswarpStatsFile *pswarpStatsFileAlloc () {
+
+    pswarpStatsFile *statsFile = psAlloc(sizeof(pswarpStatsFile));
+    psMemSetDeallocator(statsFile, (psFreeFunc)pswarpStatsFileFree);
+
+    statsFile->f = NULL;
+    statsFile->name = NULL;
+    statsFile->md = NULL;
+
+    return statsFile;
+}
+
+// Open the statistics file
+pswarpStatsFile *pswarpStatsFileOpen (pmConfig *config) {
+
+    bool mdok;
+
+    char *name = psMetadataLookupStr(&mdok, config->arguments, "STATS"); ///< Filename for statistics
+
+    if (!mdok) return NULL; // XXX this is probably a config error, but treat as ok for now
+    if (!name) return NULL;
+    if (strlen(name) == 0) return NULL;
+
+    pswarpStatsFile *statsFile = pswarpStatsFileAlloc ();
+    statsFile->name = name;
+
+    psString resolved = pmConfigConvertFilename(name, config, true, true);
+
+    statsFile->f = fopen(resolved, "w");
+    if (!statsFile->f) {
+	psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.\n", resolved);
+	psFree(resolved);
+        pswarpCleanup(config, statsFile);
+    }
+    psFree(resolved);
+
+    statsFile->md = psMetadataAlloc();
+    psMetadataAddS32(statsFile->md, PS_LIST_TAIL, "QUALITY", 0, "No problems", 0);
+
+    return statsFile;
+}
+
+bool pswarpStatsFileSave (pmConfig *config, pswarpStatsFile *statsFile) {
+
+    if (!statsFile) return true;
+
+    // Write out summary statistics
+    psMetadataAddF32(statsFile->md, PS_LIST_TAIL, "DT_WARP", 0, "Time for warp completion", psTimerMark("pswarp"));
+
+    // convert the psMetadata to a string block
+    const char *statsMDC = psMetadataConfigFormat(statsFile->md);
+    if (!statsMDC) {
+	psError(psErrorCodeLast(), false, "Unable to get statistics file.");
+	return false;
+    }
+
+    if (fprintf(statsFile->f, "%s", statsMDC) != strlen(statsMDC)) {
+	psError(PSWARP_ERR_IO, true, "Unable to write statistics file.");
+	return false;
+    }
+    psFree(statsMDC);
+
+    if (fclose(statsFile->f) == EOF) {
+	psError(PSWARP_ERR_IO, true, "Unable to close statistics file.");
+	statsFile->f = NULL;
+	return false;
+    }
+    statsFile->f = NULL;
+
+    pmConfigRunFilenameAddWrite(config, "STATS", statsFile->name);
+    psFree(statsFile);
+
+    return true;
+}
+
