Index: /branches/eam_branches/psphot.20100506/src/psphotCleanup.c
===================================================================
--- /branches/eam_branches/psphot.20100506/src/psphotCleanup.c	(revision 27887)
+++ /branches/eam_branches/psphot.20100506/src/psphotCleanup.c	(revision 27888)
@@ -19,4 +19,5 @@
     pmConceptsDone ();
     pmConfigDone ();
+    psLibFinalize();
     // fprintf (stderr, "found %d leaks at %s\n", psMemCheckLeaks (0, NULL, NULL, false), "psphot");
     fprintf (stderr, "found %d leaks at %s\n", psMemCheckLeaks (0, NULL, stdout, false), "psphot");
Index: /branches/eam_branches/psphot.20100506/src/psphotStackImageLoop.c
===================================================================
--- /branches/eam_branches/psphot.20100506/src/psphotStackImageLoop.c	(revision 27887)
+++ /branches/eam_branches/psphot.20100506/src/psphotStackImageLoop.c	(revision 27888)
@@ -53,5 +53,5 @@
 
 		// XXX for now, we assume there is only a single chip in the PHU:
-		if (!psphotStackReadout (config, view)) {
+		if (0 && !psphotStackReadout (config, view)) {
                     psError(psErrorCodeLast(), false, "failure in psphotStackReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
                     psFree (view);
Index: /branches/eam_branches/psphot.20100506/src/psphotStackMatchPSFs.c
===================================================================
--- /branches/eam_branches/psphot.20100506/src/psphotStackMatchPSFs.c	(revision 27887)
+++ /branches/eam_branches/psphot.20100506/src/psphotStackMatchPSFs.c	(revision 27888)
@@ -58,4 +58,6 @@
 	}
     }
+
+    psFree (options);
     return true;
 }
@@ -78,5 +80,5 @@
     pmReadout *readoutOut = pmFPAviewThisReadout(view, fileOut->fpa);
     if (readoutOut == NULL) {
-	readoutOut = pmFPAGenerateReadout(config, view, "PSPHOT.STACK.OUTPUT.IMAGE", fileSrc->fpa, NULL, 0);
+	readoutOut = pmFPAGenerateReadout(config, view, "PSPHOT.STACK.OUTPUT.IMAGE", fileSrc->fpa, NULL, index);
 	psAssert (readoutOut, "missing readout?");
     }
Index: /branches/eam_branches/psphot.20100506/src/psphotStackMatchPSFsPrepare.c
===================================================================
--- /branches/eam_branches/psphot.20100506/src/psphotStackMatchPSFsPrepare.c	(revision 27887)
+++ /branches/eam_branches/psphot.20100506/src/psphotStackMatchPSFsPrepare.c	(revision 27888)
@@ -83,5 +83,5 @@
 }
 
-    // determine the input seeing
+// determine the input seeing
 bool determineSeeing (pmPSF *psf, psphotStackOptions *options, int index) {
 
Index: /branches/eam_branches/psphot.20100506/src/psphotStackMatchPSFsUtils.c
===================================================================
--- /branches/eam_branches/psphot.20100506/src/psphotStackMatchPSFsUtils.c	(revision 27887)
+++ /branches/eam_branches/psphot.20100506/src/psphotStackMatchPSFsUtils.c	(revision 27888)
@@ -45,4 +45,5 @@
 }
 
+# define SN_MIN 50.0
 psArray *stackSourcesFilter(psArray *sources, // Source list to filter
 			    int exclusion // Exclusion zone, pixels
@@ -62,4 +63,6 @@
             continue;
         }
+	if (!source->peak) continue;
+	if (source->peak->SN < SN_MIN) continue;
         coordsFromSource(&x->data.F32[numGood], &y->data.F32[numGood], source);
         numGood++;
@@ -77,4 +80,6 @@
             continue;
         }
+	if (!source->peak) continue;
+	if (source->peak->SN < SN_MIN) continue;
         float xSource, ySource;         // Coordinates of source
         coordsFromSource(&xSource, &ySource, source);
@@ -325,5 +330,5 @@
 
     // These values are specified specifically for stacking
-    const char *stampsName = psMetadataLookupStr(NULL, config->arguments, "STAMPS");// Stamps filename
+    const char *stampsName = psMetadataLookupStr(&mdok, config->arguments, "STAMPS");// Stamps filename
 
     psVector *widthsCopy = NULL;
Index: /branches/eam_branches/psphot.20100506/src/psphotStackOptions.c
===================================================================
--- /branches/eam_branches/psphot.20100506/src/psphotStackOptions.c	(revision 27887)
+++ /branches/eam_branches/psphot.20100506/src/psphotStackOptions.c	(revision 27888)
@@ -5,10 +5,17 @@
     if (options == NULL) return;
 
+    // free the psf
     psFree (options->psf);
-    psFree (options->inputSeeing);
+
+    // free the array elements
+    psFree (options->psfs);
     psFree (options->sourceLists);
-    psFree (options->norm);
     psFree (options->kernels);
     psFree (options->regions);
+
+    // free the vector elements
+    psFree (options->inputMask);
+    psFree (options->inputSeeing);
+    psFree (options->norm);
     psFree (options->matchChi2);
     psFree (options->weightings);
Index: /branches/eam_branches/psphot.20100506/src/psphotStackPSF.c
===================================================================
--- /branches/eam_branches/psphot.20100506/src/psphotStackPSF.c	(revision 27887)
+++ /branches/eam_branches/psphot.20100506/src/psphotStackPSF.c	(revision 27888)
@@ -4,43 +4,60 @@
 {
     bool mdok = false;
+    pmPSF *psf = NULL;
 
-#ifndef TESTING
     // Get the recipe values
-    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "PPSTACK"); // ppStack recipe
-    psAssert(recipe, "We've thrown an error on this before.");
+    psMetadata *psphotRecipe = psMetadataLookupMetadata(NULL, config->recipes, "PSPHOT"); // psphot recipe
+    psAssert(psphotRecipe, "We've thrown an error on this before.");
 
-    int psfInstances = psMetadataLookupS32(NULL, recipe, "PSF.INSTANCES"); // Number of instances for PSF
-    float psfRadius = psMetadataLookupF32(NULL, recipe, "PSF.RADIUS"); // Radius for PSF
-    const char *psfModel = psMetadataLookupStr(NULL, recipe, "PSF.MODEL"); // Model for PSF
-    int psfOrder = psMetadataLookupS32(NULL, recipe, "PSF.ORDER"); // Spatial order for PSF
+    bool autoPSF = psMetadataLookupBool (&mdok, psphotRecipe, "PSPHOT.STACK.TARGET.PSF.AUTO");
 
-    psString maskValStr = psMetadataLookupStr(&mdok, recipe, "MASK.VAL"); // Name of bits to mask going in
-    if (!mdok || !maskValStr) {
-        psError(PSPHOT_ERR_CONFIG, false, "Unable to find MASK.VAL in recipe");
-        return false;
+    if (autoPSF) {
+	// Get the recipe values
+	psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "PPSTACK"); // ppStack recipe
+	psAssert(recipe, "We've thrown an error on this before.");
+
+	int psfInstances = psMetadataLookupS32(NULL, recipe, "PSF.INSTANCES"); // Number of instances for PSF
+	float psfRadius = psMetadataLookupF32(NULL, recipe, "PSF.RADIUS"); // Radius for PSF
+	const char *psfModel = psMetadataLookupStr(NULL, recipe, "PSF.MODEL"); // Model for PSF
+	int psfOrder = psMetadataLookupS32(NULL, recipe, "PSF.ORDER"); // Spatial order for PSF
+
+	psString maskValStr = psMetadataLookupStr(&mdok, recipe, "MASK.VAL"); // Name of bits to mask going in
+	if (!mdok || !maskValStr) {
+	    psError(PSPHOT_ERR_CONFIG, false, "Unable to find MASK.VAL in recipe");
+	    return false;
+	}
+	psImageMaskType maskVal = pmConfigMaskGet(maskValStr, config); // Bits to mask
+
+	for (int i = 0; i < psfs->n; i++) {
+	    if (inputMask->data.U8[i]) {
+		psFree(psfs->data[i]);
+		psfs->data[i] = NULL;
+	    }
+	}
+
+	// Solve for the target PSF
+	psf = pmPSFEnvelope(numCols, numRows, psfs, psfInstances, psfRadius, psfModel, psfOrder, psfOrder, maskVal);
+	if (!psf) {
+	    psError(PSPHOT_ERR_PSF, false, "Unable to determine output PSF.");
+	    return NULL;
+	}
+
+    } else {
+
+	// externally-defined PSF
+	// XXX need to test for compatibility of target with inputs
+
+	float targetFWHM = psMetadataLookupF32 (&mdok, psphotRecipe, "PSPHOT.STACK.TARGET.PSF.FWHM");
+	psAssert (isfinite(targetFWHM), "missing psphot recipe value PSPHOT.STACK.TARGET.PSF.FWHM");
+
+	float Sxx = sqrt(2.0)*targetFWHM / 2.35;
+
+	// XXX probably should make the model type (and par 7) optional from recipe
+	psf = pmPSFBuildSimple("PS_MODEL_PS1_V1", Sxx, Sxx, 0.0, 1.0);
+	if (!psf) {
+	    psError(PSPHOT_ERR_PSF, false, "Unable to build dummy PSF.");
+	    return NULL;
+	}
     }
-    psImageMaskType maskVal = pmConfigMaskGet(maskValStr, config); // Bits to mask
-
-    for (int i = 0; i < psfs->n; i++) {
-        if (inputMask->data.U8[i]) {
-            psFree(psfs->data[i]);
-            psfs->data[i] = NULL;
-        }
-    }
-
-    // Solve for the target PSF
-    pmPSF *psf = pmPSFEnvelope(numCols, numRows, psfs, psfInstances, psfRadius, psfModel, psfOrder, psfOrder, maskVal);
-    if (!psf) {
-        psError(PSPHOT_ERR_PSF, false, "Unable to determine output PSF.");
-        return NULL;
-    }
-#else
-    // Dummy PSF
-    pmPSF *psf = pmPSFBuildSimple("PS_MODEL_PS1_V1", 4.0, 4.0, 0.0, 1.0);
-    if (!psf) {
-        psError(PSPHOT_ERR_PSF, false, "Unable to build dummy PSF.");
-        return NULL;
-    }
-#endif
 
     return psf;
Index: /branches/eam_branches/psphot.20100506/src/psphotStackParseCamera.c
===================================================================
--- /branches/eam_branches/psphot.20100506/src/psphotStackParseCamera.c	(revision 27887)
+++ /branches/eam_branches/psphot.20100506/src/psphotStackParseCamera.c	(revision 27888)
@@ -125,4 +125,5 @@
 	    }
 	    outputMask->save = true;
+	    outputMask->fileID = i;		// this is used to generate output names
 
 	    pmFPAfile *outputVariance = pmFPAfileDefineOutput(config, outputImage->fpa, "PSPHOT.STACK.OUTPUT.VARIANCE");
@@ -136,4 +137,5 @@
 	    }
 	    outputVariance->save = true;
+	    outputVariance->fileID = i;		// this is used to generate output names
 
 	    // the output sources are carried on the outputImage->fpa structures
