Index: /branches/eam_branches/ipp-20130419/pswarp/src/Makefile.am
===================================================================
--- /branches/eam_branches/ipp-20130419/pswarp/src/Makefile.am	(revision 35520)
+++ /branches/eam_branches/ipp-20130419/pswarp/src/Makefile.am	(revision 35521)
@@ -39,4 +39,5 @@
 	pswarpErrorCodes.c		\
 	pswarpLoadAstrometry.c          \
+	pswarpMakePSF.c			\
 	pswarpMapGrid.c			\
 	pswarpMaskStats.c               \
Index: /branches/eam_branches/ipp-20130419/pswarp/src/pswarp.h
===================================================================
--- /branches/eam_branches/ipp-20130419/pswarp/src/pswarp.h	(revision 35520)
+++ /branches/eam_branches/ipp-20130419/pswarp/src/pswarp.h	(revision 35521)
@@ -22,4 +22,5 @@
 #include <psmodules.h>
 #include <psphot.h>
+#include <ppStats.h>
 
 #define THREADED 1
@@ -198,4 +199,4 @@
 
 bool pswarpTransformToTarget (pmFPA *output, pmReadout *input, pmConfig *config);
-bool pswarpMakePSF (pmFPA *output);
+bool pswarpMakePSF (pmConfig *config, pmFPAfile *output, psMetadata *stats);
 bool pswarpUpdateStatistics (pmFPA *output, psMetadata *stats, pmFPA *input, pmFPA *astrom, pmConfig *config);
Index: /branches/eam_branches/ipp-20130419/pswarp/src/pswarpCleanup.c
===================================================================
--- /branches/eam_branches/ipp-20130419/pswarp/src/pswarpCleanup.c	(revision 35520)
+++ /branches/eam_branches/ipp-20130419/pswarp/src/pswarpCleanup.c	(revision 35521)
@@ -19,7 +19,7 @@
     // Ensure everything is written out, at every level
     pswarpFileActivation(config, detectorFiles, false);
-    pswarpFileActivation(config, photFiles, false);
     pswarpFileActivation(config, independentFiles, false);
 
+    pswarpFileActivation(config, photFiles, true);
     pswarpFileActivation(config, skycellFiles, true);
     pmFPAfileActivate(config->files, true, "PSWARP.OUTPUT.SOURCES");
Index: /branches/eam_branches/ipp-20130419/pswarp/src/pswarpLoop.c
===================================================================
--- /branches/eam_branches/ipp-20130419/pswarp/src/pswarpLoop.c	(revision 35520)
+++ /branches/eam_branches/ipp-20130419/pswarp/src/pswarpLoop.c	(revision 35521)
@@ -11,9 +11,5 @@
 
 #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.
@@ -33,5 +29,5 @@
     }
 
-    // XXX this should probably happen elsewhere (logically it belongs to file I/O, right?)
+    // XXX move this to pswarpParseCamera?  has to come after input mask header is read
     if (!pswarpSetMaskBits(config)) {
         psError(psErrorCodeLast(), false, "failed to set mask bits");
@@ -70,6 +66,4 @@
         return false;
     }
-
-    // XXX NOTE : 'output' was a readout, now we need to loop over all output targets
 
     // ensure everyone is off except what we need below
@@ -79,8 +73,4 @@
     pswarpFileActivation(config, skycellFiles, false);
     
-    // Turn on the source output --- we need to get rid of these so that we can measure the PSF
-    // XXX NOTE : do not tackle source issues yet...
-    // XXX pmFPAfileActivate(config->files, true, "PSWARP.OUTPUT.SOURCES");
-
     // the loops below load the input data
     pswarpFileActivation(config, detectorFiles, true);
@@ -90,5 +80,4 @@
 
     // pswarpFileActivation(config, independentFiles, true);
-
 
     pmFPAview *view = pmFPAviewAlloc(0);
@@ -171,6 +160,9 @@
     }
 
-    // XXXX turn these on later .. pswarpMakePSF (output);
-    // XXX have not yet written the output to disk
+    if (!pswarpMakePSF (config, output, stats)) {
+      psError(psErrorCodeLast(), false, "problem generating PSF.");
+      goto FAIL;
+    }
+
     psFree(view);
     return true;
Index: /branches/eam_branches/ipp-20130419/pswarp/src/pswarpMakePSF.c
===================================================================
--- /branches/eam_branches/ipp-20130419/pswarp/src/pswarpMakePSF.c	(revision 35520)
+++ /branches/eam_branches/ipp-20130419/pswarp/src/pswarpMakePSF.c	(revision 35521)
@@ -11,6 +11,4 @@
 
 #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
@@ -19,5 +17,8 @@
 // We need a new PSF model for the warped frame.  It would be good to generate this analytically, but
 // that's going to be tricky.  We have a list of sources, so we use those to redetermine the PSF model.
-bool pswarpMakePSF (pmConfig *config) {
+
+bool pswarpMakePSF (pmConfig *config, pmFPAfile *output, psMetadata *stats) {
+
+    bool status = false;
 
     // load the recipe
@@ -28,69 +29,96 @@
     }
 
-    if (psMetadataLookupBool(&mdok, recipe, "PSF")) {
-        pswarpFileActivation(config, photFiles, true);
-        if (!pswarpIOChecksBefore(config)) {
-            psError(psErrorCodeLast(), false, "Unable to read files.");
-            goto DONE;
-        }
+    if (!psMetadataLookupBool(&status, recipe, "PSF")) {
+	psLogMsg("pswarp", PS_LOG_INFO, "Skipping PSF measurement");
+	return true;
+    }
 
-        // supply the readout and fpa of interest to psphot
-        pmFPAfile *photFile = psMetadataLookupPtr(NULL, config->files, "PSPHOT.INPUT");
-        pmFPACopy(photFile->fpa, outFPA);
+    // XXX What was being read here??  skip this for now
+    if (false && !pswarpIOChecksBefore(config)) {
+	psError(psErrorCodeLast(), false, "Unable to read files.");
+	return false;
+    }
 
-        pmFPAview *view = pmFPAviewAlloc(0); ///< View into skycell
-        view->chip = view->cell = view->readout = 0;
+    // supply the readout and fpa of interest to psphot
+    pmFPAfile *photFile = psMetadataLookupPtr(&status, config->files, "PSPHOT.INPUT");
+    pmFPACopy(photFile->fpa, output->fpa);
 
-        // grab the sources of interest from the storage location (pmFPAfile PSPHOT.INPUT.CMF)
-        psArray *sources = psphotLoadPSFSources (config, view);
-        if (!sources) {
-            psError(psErrorCodeLast(), false, "No sources supplied to measure PSF");
-            goto DONE;
-        }
+    pmFPAview *view = pmFPAviewAlloc(0); ///< View into skycell
 
-        pmModelClassSetLimits(PM_MODEL_LIMITS_STRICT);
+    pmChip *chip;
+    while ((chip = pmFPAviewNextChip (view, photFile->fpa, 1)) != NULL) {
+        psTrace ("pswarpMakePSF", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
 
-        // measure the PSF using these sources
-        if (!psphotReadoutFindPSF(config, view, "PSPHOT.INPUT", sources)) {
-            // This is likely a data quality issue
-            // XXX Split into multiple cases using error codes?
-            psErrorStackPrint(stderr, "Unable to determine PSF");
-            psWarning("Unable to determine PSF --- suspect bad data quality.");
-            if (stats && psMetadataLookupS32(NULL, stats, "QUALITY") == 0) {
-                psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", PS_META_REPLACE,
-                                 "Unable to determine PSF", psErrorCodeLast());
-            }
-            psErrorClear();
-            psphotFilesActivate(config, false);
-        }
+        pmCell *cell;
+        while ((cell = pmFPAviewNextCell (view, photFile->fpa, 1)) != NULL) {
+            psTrace ("pswarpMakePSF", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
 
-        // Ensure seeing is carried over
-        pmChip *photChip = pmFPAviewThisChip(view, photFile->fpa);                 // Chip with seeing
-        psMetadataItem *item = psMetadataLookup(outChip->concepts, "CHIP.SEEING"); // Concept with seeing
-        item->data.F32 = psMetadataLookupF32(NULL, photChip->concepts, "CHIP.SEEING");
+            // process each of the readouts
+            pmReadout *readout;
+            while ((readout = pmFPAviewNextReadout(view, photFile->fpa, 1)) != NULL) {
+                if (!readout->data_exists) {
+                    continue;
+                }
 
-// XXX EAM : put this in a visualization function
-#if (TESTING)
-        {
-            #define PSF_SIZE 20         ///< Half-size of PSF
-            #define PSF_FLUX 10000      ///< Central flux for PSF
-            pmChip *photChip = pmFPAviewThisChip(view, photFile->fpa);
-            pmPSF *psf = psMetadataLookupPtr(NULL, photChip->analysis, "PSPHOT.PSF");
-            psImage *image = psImageAlloc(2 * PSF_SIZE + 1, 2 * PSF_SIZE + 1, PS_TYPE_F32);
-            psImageInit(image, 0);
-            pmModel *model = pmModelFromPSFforXY(psf, PSF_SIZE, PSF_SIZE, PSF_FLUX);
-            pmModelAdd(image, NULL, model, PM_MODEL_OP_FULL, 0);
-            psFree(model);
-            psFits *fits = psFitsOpen("psf.fits", "w");
-            psFitsWriteImage(fits, NULL, image, 0, NULL);
-            psFitsClose(fits);
-            psFree(image);
-        }
-#endif
+		// grab the sources of interest from the storage location (pmFPAfile PSPHOT.INPUT.CMF)
+		psArray *sources = psphotLoadPSFSources (config, view);
+		if (!sources) {
+		    // psError(psErrorCodeLast(), false, "No sources supplied to measure PSF");
+		    psLogMsg ("psphot", 3, "no psf sources for this readout (%d %d %d)", view->chip, view->cell, view->readout);
+		    continue;
+		}
 
-        psFree(view);
+		// XXX move above the loop
+		pmModelClassSetLimits(PM_MODEL_LIMITS_STRICT);
+		
+		// measure the PSF using these sources
+		if (!psphotReadoutFindPSF(config, view, "PSPHOT.INPUT", sources)) {
+		    // A failure is likely a data quality issue.  raise a quality flag, but do not skip other readouts
+		    // XXX Split into multiple cases using error codes?
+		    psErrorStackPrint(stderr, "Unable to determine PSF for readout (%d %d %d)", view->chip, view->cell, view->readout);
+		    psWarning("Unable to determine PSF --- suspect bad data quality : readout (%d %d %d)", view->chip, view->cell, view->readout);
+		    if (stats) {
+			int currentQuality = psMetadataLookupS32(&status, stats, "QUALITY");
+			if (currentQuality == 0) {
+			    psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", PS_META_REPLACE, "Unable to determine PSF", psErrorCodeLast());
+			}
+		    }
+		    psErrorClear();
+		}
+	    }
+	}
+
+	// Ensure seeing is carried over from the PSPHOT.INPUT chip to the output chip
+	pmChip *outChip = pmFPAviewThisChip(view, output->fpa); // Chip with seeing
+	psMetadataItem *item = psMetadataLookup(outChip->concepts, "CHIP.SEEING"); // Concept with seeing
+	item->data.F32 = psMetadataLookupF32(&status, chip->concepts, "CHIP.SEEING");
     }
+
+    // XXX test function found below
+    // pswarpMakePSF_test ();
+
+    psFree(view);
+    return true;
+}
+
+# if (0)
+bool pswarpMakePSF_test () {
+
+#define PSF_SIZE 20         ///< Half-size of PSF
+#define PSF_FLUX 10000      ///< Central flux for PSF
+    pmChip *photChip = pmFPAviewThisChip(view, photFile->fpa);
+    pmPSF *psf = psMetadataLookupPtr(NULL, photChip->analysis, "PSPHOT.PSF");
+    psImage *image = psImageAlloc(2 * PSF_SIZE + 1, 2 * PSF_SIZE + 1, PS_TYPE_F32);
+    psImageInit(image, 0);
+    pmModel *model = pmModelFromPSFforXY(psf, PSF_SIZE, PSF_SIZE, PSF_FLUX);
+    pmModelAdd(image, NULL, model, PM_MODEL_OP_FULL, 0);
+    psFree(model);
+    psFits *fits = psFitsOpen("psf.fits", "w");
+    psFitsWriteImage(fits, NULL, image, 0, NULL);
+    psFitsClose(fits);
+    psFree(image);
     return true;
 }
 # endif
-
Index: /branches/eam_branches/ipp-20130419/pswarp/src/pswarpMaskStats.c
===================================================================
--- /branches/eam_branches/ipp-20130419/pswarp/src/pswarpMaskStats.c	(revision 35520)
+++ /branches/eam_branches/ipp-20130419/pswarp/src/pswarpMaskStats.c	(revision 35521)
@@ -1,4 +1,3 @@
 #include "pswarp.h"
-#include <ppStats.h>
 
 bool pswarpMaskStats(const pmReadout *readout, psMetadata *stats, const pmConfig *config)
Index: /branches/eam_branches/ipp-20130419/pswarp/src/pswarpParseCamera.c
===================================================================
--- /branches/eam_branches/ipp-20130419/pswarp/src/pswarpParseCamera.c	(revision 35520)
+++ /branches/eam_branches/ipp-20130419/pswarp/src/pswarpParseCamera.c	(revision 35521)
@@ -179,9 +179,9 @@
     }
     
-    /// XXX re-enable after sources work
-    if (false && psMetadataLookupBool(&mdok, recipe, "PSF")) {
+    if (psMetadataLookupBool(&mdok, recipe, "PSF")) {
         // This file, PSPHOT.INPUT, is just used as a carrier; output files (eg, PSPHOT.RESID) are defined by
         // psphotDefineFiles
-        pmFPAfile *psphotInput = pmFPAfileDefineSkycell(config, NULL, "PSPHOT.INPUT");
+	// XXX old : pmFPAfile *psphotInput = pmFPAfileDefineSkycell(config, NULL, "PSPHOT.INPUT");
+	pmFPAfile *psphotInput = pmFPAfileDefineOutputForFormat(config, NULL, "PSPHOT.INPUT", skycell->cameraName, skycell->formatName);
         if (!psphotInput) {
             psError(psErrorCodeLast(), false, _("Unable to generate output file from PSPHOT.INPUT"));
@@ -189,8 +189,15 @@
         }
         psphotInput->src = psMemIncrRefCounter(output->fpa);
-        // specify the number of psphot input images
+
+        // specify the number of psphot input images (psphotReadout loops over all input images)
         psMetadataAddS32 (config->arguments, PS_LIST_TAIL, "PSPHOT.INPUT.NUM", PS_META_REPLACE, "number of inputs", 1);
 
-        pmFPAfile *psphotInSources = pmFPAfileDefineSkycell(config, output->fpa, "PSPHOT.INPUT.CMF");
+	// the input sources (read from the input astrometry file) are transformed (in pswarpLoop) to the readout->analysis
+	// entries of the output file PSWARP.OUTPUT.SOURCES, associated with the main output pmFPAfile PSWARP.OUTPUT
+
+	// the PSPHOT.INPUT.CMF is used to supply those sources to psphot (specifically psphotLoadPSFSources).  
+
+        // pmFPAfile *psphotInSources = pmFPAfileDefineSkycell(config, output->fpa, "PSPHOT.INPUT.CMF");
+	pmFPAfile *psphotInSources = pmFPAfileDefineOutputForFormat(config, output->fpa, "PSPHOT.INPUT.CMF", skycell->cameraName, skycell->formatName);
         if (!psphotInSources) {
             psError(psErrorCodeLast(), false, _("Unable to generate output file from PSPHOT.INPUT.CMF"));
Index: /branches/eam_branches/ipp-20130419/pswarp/src/pswarpUpdateStatistics.c
===================================================================
--- /branches/eam_branches/ipp-20130419/pswarp/src/pswarpUpdateStatistics.c	(revision 35520)
+++ /branches/eam_branches/ipp-20130419/pswarp/src/pswarpUpdateStatistics.c	(revision 35521)
@@ -11,5 +11,4 @@
 
 #include "pswarp.h"
-#include <ppStats.h>
 
 // once the output fpa elements have been built, loop over the fpa and generate stats
Index: /branches/eam_branches/ipp-20130419/pswarp/src/pswarpVersion.c
===================================================================
--- /branches/eam_branches/ipp-20130419/pswarp/src/pswarpVersion.c	(revision 35520)
+++ /branches/eam_branches/ipp-20130419/pswarp/src/pswarpVersion.c	(revision 35521)
@@ -13,10 +13,4 @@
 #include <config.h>
 #endif
-
-#include <stdio.h>
-#include <pslib.h>
-#include <psmodules.h>
-#include <psphot.h>
-#include <ppStats.h>
 
 #include "pswarp.h"
