Index: /trunk/psphot/src/Makefile.am
===================================================================
--- /trunk/psphot/src/Makefile.am	(revision 6378)
+++ /trunk/psphot/src/Makefile.am	(revision 6379)
@@ -31,4 +31,5 @@
 	psphotModelGroupInit.c	\
 	psphotGrowthCurve.c	\
+	psphotCleanup.c	        \
 	psphotEvalPSF.c		\
 	psphotEvalFLT.c		\
Index: /trunk/psphot/src/pmCellSetMask.c
===================================================================
--- /trunk/psphot/src/pmCellSetMask.c	(revision 6378)
+++ /trunk/psphot/src/pmCellSetMask.c	(revision 6379)
@@ -1,4 +1,5 @@
 # include "psphot.h"
 
+// 2006.02.04 : no leaks
 bool pmCellSetMask (pmCell *cell, psMetadata *recipe) {
     
Index: /trunk/psphot/src/pmModelFitSet.c
===================================================================
--- /trunk/psphot/src/pmModelFitSet.c	(revision 6378)
+++ /trunk/psphot/src/pmModelFitSet.c	(revision 6379)
@@ -18,4 +18,11 @@
 
     return true;
+}
+
+void pmModelFitSetClear (void) {
+
+    psFree (onePar);
+    psFree (oneDeriv);
+    return;
 }
 
Index: /trunk/psphot/src/pmSourceFitSet.c
===================================================================
--- /trunk/psphot/src/pmSourceFitSet.c	(revision 6378)
+++ /trunk/psphot/src/pmSourceFitSet.c	(revision 6379)
@@ -105,7 +105,12 @@
     for (psS32 i = 0; i < source->pixels->numRows; i++) {
         for (psS32 j = 0; j < source->pixels->numCols; j++) {
+	    // skip masked points
             if (source->mask->data.U8[i][j]) {
 		continue;
 	    }
+	    // skip zero-weight points
+	    if (source->weight->data.F32[i][j] == 0) {
+		continue;
+	    } 
 	    psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
 
@@ -115,9 +120,5 @@
 	    x->data[nPix] = (psPtr *) coord;
 	    y->data.F32[nPix] = source->pixels->data.F32[i][j];
-
 	    // psMinimizeLMChi2 takes wt = 1/dY^2
-	    if (source->weight->data.F32[i][j] == 0) {
-		continue;
-	    } 
 	    yErr->data.F32[nPix] = 1.0 / source->weight->data.F32[i][j];
 	    nPix++;
@@ -131,4 +132,7 @@
 	psFree (y);
 	psFree (yErr);
+	psFree (params);
+	psFree (dparams);
+	psFree (paramMask);
         return(false);
     }
@@ -180,4 +184,5 @@
             dparams->data.F32[i] = delta->data.F64[i];
         }
+	psFree (delta);
     }
 
@@ -217,4 +222,12 @@
     psFree(covar);
     psFree(paramMask);
+    psFree(params);
+    psFree(dparams);
+    psFree(params_min);
+    psFree(params_max);
+    psFree(beta_lim);
+
+    // free static memory used by pmModelFitSet
+    pmModelFitSetClear ();
 
     rc = (onPic && fitStatus);
Index: /trunk/psphot/src/psModulesUtils.c
===================================================================
--- /trunk/psphot/src/psModulesUtils.c	(revision 6378)
+++ /trunk/psphot/src/psModulesUtils.c	(revision 6379)
@@ -180,4 +180,10 @@
 
   if (config == NULL) return;
+  psFree (config->site);
+  psFree (config->camera);
+  psFree (config->recipe);
+  psFree (config->arguments);
+  psFree (config->options);
+  psFree (config->database);
   return;
 }
@@ -202,4 +208,8 @@
 
   if (file == NULL) return;
+  psFree (file->phu);
+  psFree (file->filename);
+  psFree (file->fpa);
+  psFitsClose (file->fits);
   return;
 }
Index: /trunk/psphot/src/psSparse.c
===================================================================
--- /trunk/psphot/src/psSparse.c	(revision 6378)
+++ /trunk/psphot/src/psSparse.c	(revision 6379)
@@ -70,4 +70,5 @@
 	tSj->data.S32[i]  = Sj->data.S32[j];
     }
+    psFree (index);
     psFree (Aij);
     psFree (Si);
Index: /trunk/psphot/src/psphot.c
===================================================================
--- /trunk/psphot/src/psphot.c	(revision 6378)
+++ /trunk/psphot/src/psphot.c	(revision 6379)
@@ -22,4 +22,9 @@
 
     psLogMsg ("psphot", 3, "complete psphot run: %f sec\n", psTimerMark ("complete"));
+
+    psFree (input);
+    psFree (config);
+    psphotCleanup ();
+
     exit (0);
 }
Index: /trunk/psphot/src/psphot.h
===================================================================
--- /trunk/psphot/src/psphot.h	(revision 6378)
+++ /trunk/psphot/src/psphot.h	(revision 6379)
@@ -13,5 +13,6 @@
 # include "psModulesUtils.h"
 # include "psSparse.h"
-#include "pmFPAConstruct.h"
+# include "pmFPAConstruct.h"
+# include "pmConcepts.h"
 
 # define PSPHOT_RECIPE "PSPHOT"
@@ -27,4 +28,5 @@
 bool            psphotReadout (pmReadout *readout, psMetadata *config);
 bool            ppImageLoadPixels (ppFile *input, psDB *db, int chipNum, int cellNum);
+void            psphotCleanup (void);
 
 // psphotReadout functions
@@ -89,4 +91,5 @@
 char           *psphotSplitName (psMetadata *header);
 void            psphotOutputPrep (ppFile *file, ppConfig *config);
+void            psphotOutputCleanup (void);
 char           *psphotNameSubstitute (char *input, char *replace, char *key);
 
@@ -103,4 +106,5 @@
 psF32           pmModelFitSet (psVector *deriv, const psVector *params, const psVector *x);
 bool            pmModelFitSetInit (pmModelType type);
+void            pmModelFitSetClear (void);
 
 //  functions to support the source fitting process
Index: /trunk/psphot/src/psphotApResid.c
===================================================================
--- /trunk/psphot/src/psphotApResid.c	(revision 6378)
+++ /trunk/psphot/src/psphotApResid.c	(revision 6379)
@@ -1,3 +1,4 @@
 # include "psphot.h"
+static char DEFAULT_OPTION[] = "SKYBIAS";
 
 // measure the aperture residual statistics
@@ -69,5 +70,5 @@
     // APTREND options : NONE SKYBIAS XY_LIN XY_QUAD SKY_XY_LIN FULL 
     char *ApTrendOption = psMetadataLookupPtr (&status, config, "APTREND");
-    if (!status) ApTrendOption = psStringCopy ("SKYBIAS");
+    if (!status) ApTrendOption = DEFAULT_OPTION;
 
     // 3hi/1lo sigma clipping on the rflux vs metric fit
@@ -190,18 +191,4 @@
 	psf->ApTrend  = psVectorChiClipFitPolynomial4D (psf->ApTrend, stats, mask, PSFTRY_MASK_ALL, apResid, dMag, xPos, yPos, r2rflux, flux);
     }
-
-# if (1)
-    psPolynomial4D *poly = psf->ApTrend;
-    for (int nt = 0; nt <= poly->nT; nt++) {
-	for (int nz = 0; nz <= poly->nZ; nz++) {
-	    for (int ny = 0; ny <= poly->nY; ny++) {
-		for (int nx = 0; nx <= poly->nX; nx++) {
-		    if (poly->mask[nx][ny][nz][nt]) continue;
-		    fprintf (stderr, "%d %d %d %d : %22.15g\n", nx, ny, nz, nt, poly->coeff[nx][ny][nz][nt]);
-		}
-	    }
-	}
-    }
-# endif
 
     // construct the fitted values and the residuals
@@ -256,9 +243,16 @@
 	      1e6*psf->ApTrend->coeff[0][2][0][0]);
 
-    // psFree (stats);
-    // psFree (mask);
-    // psFree (rflux);
-    // psFree (apResid);
-
+    psFree (mask);
+    psFree (xPos);
+    psFree (yPos);
+    psFree (flux);
+    psFree (r2rflux);
+    psFree (apResid);
+    psFree (dMag);
+
+    psFree (fit);
+    psFree (resid);
+    psFree (stats);
+    psFree (residStats);
     return true;
 }
Index: /trunk/psphot/src/psphotArguments.c
===================================================================
--- /trunk/psphot/src/psphotArguments.c	(revision 6378)
+++ /trunk/psphot/src/psphotArguments.c	(revision 6379)
@@ -27,5 +27,5 @@
     if ((N = psArgumentGet (*argc, argv, "-mask"))) {
 	psArgumentRemove (N, argc, argv);
-	psMetadataAddStr (config->arguments, PS_LIST_TAIL, "MASK_IMAGE", PS_META_REPLACE, "", psStringCopy(argv[N]));
+	psMetadataAddStr (config->arguments, PS_LIST_TAIL, "MASK_IMAGE", PS_META_REPLACE, "", argv[N]);
 	psArgumentRemove (N, argc, argv);
     }
@@ -34,5 +34,5 @@
     if ((N = psArgumentGet (*argc, argv, "-weight"))) {
 	psArgumentRemove (N, argc, argv);
-	psMetadataAddStr (config->arguments, PS_LIST_TAIL, "WEIGHT_IMAGE", PS_META_REPLACE, "", psStringCopy(argv[N]));
+	psMetadataAddStr (config->arguments, PS_LIST_TAIL, "WEIGHT_IMAGE", PS_META_REPLACE, "", argv[N]);
 	psArgumentRemove (N, argc, argv);
     }
@@ -41,5 +41,5 @@
     if ((N = psArgumentGet (*argc, argv, "-resid"))) {
 	psArgumentRemove (N, argc, argv);
-	psMetadataAddStr (config->arguments, PS_LIST_TAIL, "RESID_IMAGE", PS_META_REPLACE, "", psStringCopy(argv[N]));
+	psMetadataAddStr (config->arguments, PS_LIST_TAIL, "RESID_IMAGE", PS_META_REPLACE, "", argv[N]);
 	psArgumentRemove (N, argc, argv);
     }
@@ -48,5 +48,5 @@
     if ((N = psArgumentGet (*argc, argv, "-chip"))) {
 	psArgumentRemove (N, argc, argv);
-	psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CHIP_SELECTION", PS_META_REPLACE, "", psStringCopy(argv[N]));
+	psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CHIP_SELECTION", PS_META_REPLACE, "", argv[N]);
 	psArgumentRemove (N, argc, argv);
     }
@@ -65,5 +65,5 @@
 	if ((N = psArgumentGet (*argc, argv, "-model"))) {
 	    psArgumentRemove (N, argc, argv);
-	    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "TEST_FIT_MODEL", 0, "", psStringCopy (argv[N]));
+	    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "TEST_FIT_MODEL", 0, "", argv[N]);
 	    psArgumentRemove (N, argc, argv);
 	}
@@ -72,10 +72,10 @@
 	if ((N = psArgumentGet (*argc, argv, "-fitmode"))) {
 	    psArgumentRemove (N, argc, argv);
-	    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "TEST_FIT_MODE", 0, "", psStringCopy (argv[N]));
+	    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "TEST_FIT_MODE", 0, "", argv[N]);
 	    psArgumentRemove (N, argc, argv);
 	}
 	if ((N = psArgumentGet (*argc, argv, "-fitset"))) {
 	    psArgumentRemove (N, argc, argv);
-	    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "TEST_FIT_SET", 0, "", psStringCopy (argv[N]));
+	    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "TEST_FIT_SET", 0, "", argv[N]);
 	    psArgumentRemove (N, argc, argv);
 	}
@@ -88,5 +88,5 @@
     if ((N = psArgumentGet (*argc, argv, "-psf"))) {
 	psArgumentRemove (N, argc, argv);
-	psMetadataAddStr (config->options, PS_LIST_TAIL, "PSF_INPUT_FILE", PS_META_REPLACE, "", psStringCopy(argv[N]));
+	psMetadataAddStr (config->options, PS_LIST_TAIL, "PSF_INPUT_FILE", PS_META_REPLACE, "", argv[N]);
 	psArgumentRemove (N, argc, argv);
     }
@@ -95,5 +95,5 @@
     if ((N = psArgumentGet (*argc, argv, "-photcode"))) {
 	psArgumentRemove (N, argc, argv);
-	psMetadataAddStr (config->options, PS_LIST_TAIL, "PHOTCODE", PS_META_REPLACE, "", psStringCopy(argv[N]));
+	psMetadataAddStr (config->options, PS_LIST_TAIL, "PHOTCODE", PS_META_REPLACE, "", argv[N]);
 	psArgumentRemove (N, argc, argv);
     }
@@ -102,5 +102,5 @@
     if ((N = psArgumentGet (*argc, argv, "-break"))) {
 	psArgumentRemove (N, argc, argv);
-	psMetadataAddStr (config->options, PS_LIST_TAIL, "BREAK_POINT", PS_META_REPLACE, "", psStringCopy(argv[N]));
+	psMetadataAddStr (config->options, PS_LIST_TAIL, "BREAK_POINT", PS_META_REPLACE, "", argv[N]);
 	psArgumentRemove (N, argc, argv);
     }
@@ -109,5 +109,5 @@
     if ((N = psArgumentGet (*argc, argv, "-fitmode"))) {
 	psArgumentRemove (N, argc, argv);
-	psMetadataAddStr (config->options, PS_LIST_TAIL, "FITMODE", PS_META_REPLACE, "", psStringCopy(argv[N]));
+	psMetadataAddStr (config->options, PS_LIST_TAIL, "FITMODE", PS_META_REPLACE, "", argv[N]);
 	psArgumentRemove (N, argc, argv);
     }
@@ -116,5 +116,5 @@
     if ((N = psArgumentGet (*argc, argv, "-region"))) {
 	psArgumentRemove (N, argc, argv);
-	psMetadataAddStr (config->options, PS_LIST_TAIL, "ANALYSIS_REGION", 0, "", psStringCopy(argv[N]));
+	psMetadataAddStr (config->options, PS_LIST_TAIL, "ANALYSIS_REGION", 0, "", argv[N]);
 	psArgumentRemove (N, argc, argv);
     }
Index: /trunk/psphot/src/psphotBasicDeblend.c
===================================================================
--- /trunk/psphot/src/psphotBasicDeblend.c	(revision 6378)
+++ /trunk/psphot/src/psphotBasicDeblend.c	(revision 6379)
@@ -1,6 +1,5 @@
 # include "psphot.h"
 
-// 2006.02.02 : no leaks? (creates source->blend entries)
-// XXX if I free sources, I still have 54 leaks?
+// 2006.02.07 : no leaks
 bool psphotBasicDeblend (psArray *sources, psMetadata *config, psStats *sky) { 
 
@@ -35,7 +34,4 @@
     // this results in an index of increasing SN
 
-    // temporary array for overlapping objects we find
-    psArray *overlap = psArrayAlloc (100);
-
     // examine sources in decreasing SN order
     for (int i = sources->n - 1; i >= 0; i--) {
@@ -45,4 +41,10 @@
 	if (source->mode & PM_SOURCE_BLEND) continue;
 
+	// temporary array for overlapping objects we find
+	// XXX psArrayAlloc should set ->n to 0 *and* all objects to NULL
+	// XXX I need a psArrayEmpty function to free the elements without the array
+	// XXX then, I could allocate 'overlap' once outside the loop and only
+	// XXX clear at the end of each loop
+	psArray *overlap = psArrayAlloc (100);
 	overlap->n = 0;
 
@@ -73,54 +75,61 @@
 	}
 
+	if (overlap->n == 0) {
+	    psFree (overlap);
+	    continue;
+	}
+
+	// this source has overlapping neighbors, check for actual blends
 	// generate source contour (1/4 peak counts)
-	if (overlap->n > 0) {
-	    // set the threshold based on user inputs
-	    threshold = FRACTION * (source->peak->counts - source->moments->Sky) + source->moments->Sky; 
-	    threshold = PS_MAX (threshold, minThreshold);
+	// set the threshold based on user inputs
+	threshold = FRACTION * (source->peak->counts - source->moments->Sky) + source->moments->Sky; 
+	threshold = PS_MAX (threshold, minThreshold);
 
-	    // generate a basic contour (set of x,y coordinates at-or-below flux level)
-	    psArray *contour = pmSourceContour_EAM (source->pixels, source->peak->x, source->peak->y, threshold);
-	    if (contour == NULL) continue;
+	// generate a basic contour (set of x,y coordinates at-or-below flux level)
+	psArray *contour = pmSourceContour_EAM (source->pixels, source->peak->x, source->peak->y, threshold);
+	if (contour == NULL) {
+	    psFree (overlap);
+	    continue;
+	}
 
-	    // the source contour consists of two vectors, xv and yv.  the contour is 
-	    // a series of coordinate pairs, (xv[i],yv[i]) & (xv[i+1],yv[i+1]).  both
-	    // coordinate pairs have the same yv[] value, with xv[i] corresponding to
-	    // the left boundary and xv[i+1] corresponding to the right boundary
+	// the source contour consists of two vectors, xv and yv.  the contour is 
+	// a series of coordinate pairs, (xv[i],yv[i]) & (xv[i+1],yv[i+1]).  both
+	// coordinate pairs have the same yv[] value, with xv[i] corresponding to
+	// the left boundary and xv[i+1] corresponding to the right boundary
 
-	    psVector *xv = contour->data[0];
-	    psVector *yv = contour->data[1];
-	    for (int k = 0; k < overlap->n; k++) {
-		testSource = overlap->data[k];
-		if (testSource->peak->counts > source->peak->counts) continue;
-		for (int j = 0; j < xv->n; j+=2) {
-		    if (fabs(yv->data.F32[j] - testSource->peak->y) > 0.5) continue;
-		    if (xv->data.F32[j+0] > testSource->peak->x) break;
-		    if (xv->data.F32[j+1] < testSource->peak->x) break;
+	psVector *xv = contour->data[0];
+	psVector *yv = contour->data[1];
+	for (int k = 0; k < overlap->n; k++) {
+	    testSource = overlap->data[k];
+	    if (testSource->peak->counts > source->peak->counts) continue;
+	    for (int j = 0; j < xv->n; j+=2) {
+		if (fabs(yv->data.F32[j] - testSource->peak->y) > 0.5) continue;
+		if (xv->data.F32[j+0] > testSource->peak->x) break;
+		if (xv->data.F32[j+1] < testSource->peak->x) break;
 
-		    testSource->mode |= PM_SOURCE_BLEND;
+		testSource->mode |= PM_SOURCE_BLEND;
 
-		    // add this to the list of source->blends
-		    if (source->blends == NULL) {
-			source->blends = psArrayAlloc (16);
-			source->blends->n = 0;
-		    }
-		    psArrayAdd (source->blends, 16, testSource);
+		// add this to the list of source->blends
+		if (source->blends == NULL) {
+		    source->blends = psArrayAlloc (16);
+		    source->blends->n = 0;
+		}
 
-		    Nblend ++;
-		    j = xv->n;
-		}
-	    }  
-	    psFree (contour);
-	}
+		psArrayAdd (source->blends, 16, testSource);
+
+		Nblend ++;
+		j = xv->n;
+	    }
+	}  
+	psFree (overlap);
+	psFree (contour);
     }
     psLogMsg ("psphot.deblend", 3, "identified %d blended objects (%f sec)\n", Nblend, psTimerMark ("psphot"));
 
-    char *breakPt = psMetadataLookupPtr (&status, config, "BREAK_POINT");
+    char *breakPt = psMetadataLookupStr (&status, config, "BREAK_POINT");
     if (!strcasecmp (breakPt, "DEBLEND")) exit (0);
 
     psFree (SN);
     psFree (index);
-    psFree (overlap);
-    
     return true;
 }
Index: /trunk/psphot/src/psphotBlendFit.c
===================================================================
--- /trunk/psphot/src/psphotBlendFit.c	(revision 6378)
+++ /trunk/psphot/src/psphotBlendFit.c	(revision 6379)
@@ -30,4 +30,5 @@
 	psTrace ("psphot.blend", 5, "trying source at %f, %f\n", source->moments->x, source->moments->y);
 
+	// try fitting PSFs, then try extended sources
 	if (psphotFitBlend (readout, source)) continue;
 	if (psphotFitBlob (readout, source, sources)) continue;
Index: /trunk/psphot/src/psphotChoosePSF.c
===================================================================
--- /trunk/psphot/src/psphotChoosePSF.c	(revision 6378)
+++ /trunk/psphot/src/psphotChoosePSF.c	(revision 6379)
@@ -1,4 +1,5 @@
 # include "psphot.h"
 
+// 2006.02.07 : no leaks!
 // try PSF models and select best option
 pmPSF *psphotChoosePSF (psMetadata *config, psArray *sources, psStats *skystats) { 
@@ -8,5 +9,4 @@
     pmPSFtry 	   *try   = NULL;
     psArray    	   *stars = NULL;
-    psMetadataItem *item  = NULL;
 
     psTimerStart ("psphot");
@@ -37,4 +37,5 @@
     psMetadataItem *mdi = psMetadataLookup (config, "PSF_MODEL");
     if (mdi == NULL) psAbort ("psphotChoosePSF", "missing PSF_MODEL selection");
+
     if (mdi->type == PS_DATA_STRING) {
 	list = psListAlloc(NULL);
@@ -51,11 +52,10 @@
     psListIterator *iter = psListIteratorAlloc (list, PS_LIST_HEAD, FALSE); 
     for (int i = 0; i < models->n; i++) { 
-
-	item = psListGetAndIncrement (iter);
+	// XXX psListGetAndIncrement does not increment ref counter!?
+	// XXX if it did, i should free 'item' below
+	psMetadataItem *item = psListGetAndIncrement (iter);
 	modelName = item->data.V;
-
 	models->data[i] = pmPSFtryModel (stars, modelName, RADIUS);
-	psFree (modelName);
-	psFree (item);
+	// psFree (item);
     }
     psFree (iter);
@@ -98,5 +98,5 @@
     psLogMsg ("psphot.pspsf", 3, "selected psf model %s, ApResid: %f +/- %f\n", modelName, psf->ApResid, psf->dApResid);
 
-    char *breakPt = psMetadataLookupPtr (&status, config, "BREAK_POINT");
+    char *breakPt = psMetadataLookupStr (&status, config, "BREAK_POINT");
     if (!strcasecmp (breakPt, "PSFFIT")) exit (0);
 
Index: /trunk/psphot/src/psphotEnsemblePSF.c
===================================================================
--- /trunk/psphot/src/psphotEnsemblePSF.c	(revision 6378)
+++ /trunk/psphot/src/psphotEnsemblePSF.c	(revision 6379)
@@ -1,4 +1,6 @@
 # include "psphot.h"
 
+// 2006.02.07 : no leaks!
+// fit all reasonable sources with the linear PSF model
 bool psphotEnsemblePSF (pmReadout *readout, psMetadata *config, psArray *sources, pmPSF *psf, psStats *sky) { 
 
@@ -6,4 +8,5 @@
     float x;
     float y;
+    float f;
 
     psTimerStart ("psphot");
@@ -28,5 +31,5 @@
     bool UseAnalysisRegion = false;
     psRegion AnalysisRegion = {0, 0, 0, 0};
-    char *region = psMetadataLookupPtr (&status, config, "ANALYSIS_REGION");
+    char *region = psMetadataLookupStr (&status, config, "ANALYSIS_REGION");
     if (status) {
 	UseAnalysisRegion = true;
@@ -126,9 +129,8 @@
 	index->data.U32[models->n] = i;
 	psArrayAdd (models, 100, otSource);
+	psFree (otSource);
     }
     psLogMsg ("psphot.emsemble", 4, "built models: %f (%d objects)\n", psTimerMark ("psphot"), sources->n);
     
-    float f;
-
     // fill out the sparse matrix
     psSparse *sparse = psSparseAlloc (models->n, 100);
@@ -173,5 +175,6 @@
 	pmSource *Mi = models->data[i];
 
-	Fi->modelPSF = Mi->modelPSF;
+	// need to increment counter so we can free models here and sources above
+	Fi->modelPSF = psMemCopy (Mi->modelPSF);
 
 	// assign linearly-fitted normalization
@@ -183,6 +186,8 @@
 	Fi->mode |= PM_SOURCE_TEMPSUB;
     }
-
-    // XXX EAM : need to free up many things here
+    psFree (index);
+    psFree (sparse);
+    psFree (models);
+    psFree (norm);
 
     psLogMsg ("psphot.emsemble", 3, "measure ensemble of PSFs: %f sec\n", psTimerMark ("psphot"));
Index: /trunk/psphot/src/psphotFindPeaks.c
===================================================================
--- /trunk/psphot/src/psphotFindPeaks.c	(revision 6378)
+++ /trunk/psphot/src/psphotFindPeaks.c	(revision 6379)
@@ -39,13 +39,11 @@
 
     // optional dump of all peak data
-    char *output = psMetadataLookupPtr (&status, config, "PEAKS_OUTPUT_FILE");
+    char *output = psMetadataLookupStr (&status, config, "PEAKS_OUTPUT_FILE");
     if (status && (output != NULL) && (output[0])) {
 	pmPeaksWriteText (peaks, output);
-	psFree (output);
     }
-     
     psLogMsg ("psphot", 3, "%d peaks: %f sec\n", peaks->n, psTimerMark ("psphot"));
 
-    char *breakPt = psMetadataLookupPtr (&status, config, "BREAK_POINT");
+    char *breakPt = psMetadataLookupStr (&status, config, "BREAK_POINT");
     if (!strcasecmp (breakPt, "PEAKS")) exit (0);
 
Index: /trunk/psphot/src/psphotFitGalaxies.c
===================================================================
--- /trunk/psphot/src/psphotFitGalaxies.c	(revision 6378)
+++ /trunk/psphot/src/psphotFitGalaxies.c	(revision 6379)
@@ -14,5 +14,5 @@
     float EXT_MIN_SN  	   = psMetadataLookupF32 (&status, config, "EXT_MIN_SN");
     float EXT_MOMENTS_RAD  = psMetadataLookupF32 (&status, config, "EXT_MOMENTS_RADIUS");
-    char       *modelName  = psMetadataLookupPtr (&status, config, "EXT_MODEL");
+    char       *modelName  = psMetadataLookupStr (&status, config, "EXT_MODEL");
     pmModelType modelType  = pmModelSetType (modelName);
 
Index: /trunk/psphot/src/psphotFullFit.c
===================================================================
--- /trunk/psphot/src/psphotFullFit.c	(revision 6378)
+++ /trunk/psphot/src/psphotFullFit.c	(revision 6379)
@@ -19,5 +19,5 @@
 
     // extended source model descriptions
-    char         *modelNameEXT = psMetadataLookupPtr (&status, config, "EXT_MODEL");
+    char         *modelNameEXT = psMetadataLookupStr (&status, config, "EXT_MODEL");
     pmModelType   modelTypeEXT = pmModelSetType (modelNameEXT);
 
Index: /trunk/psphot/src/psphotGrowthCurve.c
===================================================================
--- /trunk/psphot/src/psphotGrowthCurve.c	(revision 6378)
+++ /trunk/psphot/src/psphotGrowthCurve.c	(revision 6379)
@@ -62,4 +62,10 @@
     psLogMsg ("psphot.growth", 4, "GrowthCurve : apLoss : %f\n", psf->growth->apLoss);
     
+    psFree (view);
+    psFree (image);
+    psFree (mask);
+    psFree (model);
+    psFree (modelRef);
+
     return true;
 }
Index: /trunk/psphot/src/psphotImageLoop.c
===================================================================
--- /trunk/psphot/src/psphotImageLoop.c	(revision 6378)
+++ /trunk/psphot/src/psphotImageLoop.c	(revision 6379)
@@ -32,5 +32,5 @@
         if (! chip->process) { continue; }
 
-        if (imageLoadDepth == PP_LOAD_CHIP) {
+	if (imageLoadDepth == PP_LOAD_CHIP) {
             psTrace(__func__, 1, "Loading pixels for chip %d...\n", i);
             ppImageLoadPixels(file, config->database, i, -1);
@@ -47,5 +47,5 @@
                 ppImageLoadPixels(file, config->database, i, j);
             }
-
+	    
 	    // XXX optional mask and weight input image should be loaded here?
 	    // this sets the weight map and basic mask applying CELL.BAD and CELL.SATURATION
@@ -61,5 +61,4 @@
 		// run a single-model test if desired
 		psphotModelTest (readout, config->arguments, config->recipe);
-
 		psphotReadout (readout, config->recipe);
 		psphotOutput (readout, config->arguments);
Index: /trunk/psphot/src/psphotLoadPixels.c
===================================================================
--- /trunk/psphot/src/psphotLoadPixels.c	(revision 6378)
+++ /trunk/psphot/src/psphotLoadPixels.c	(revision 6379)
@@ -24,5 +24,5 @@
         }
     }
-
+    
     // Read in the input pixels
     if (! pmFPARead(input->fpa, input->fits, input->phu, db)) {
@@ -30,4 +30,5 @@
         exit(EXIT_FAILURE);
     }
+
     return true;
 }
Index: /trunk/psphot/src/psphotModelTest.c
===================================================================
--- /trunk/psphot/src/psphotModelTest.c	(revision 6378)
+++ /trunk/psphot/src/psphotModelTest.c	(revision 6379)
@@ -1,4 +1,5 @@
 # include "psphot.h"
 # include "psEllipse.h"
+static char DEFAULT_MODE[] = "EXT";
 
 bool psphotModelTest (pmReadout *readout, psMetadata *arguments, psMetadata *recipe) {
@@ -17,7 +18,7 @@
 
     // what fitting mode to use?
-    char *psfModeWord = psMetadataLookupPtr (&status, arguments, "TEST_FIT_MODE");
+    char *psfModeWord = psMetadataLookupStr (&status, arguments, "TEST_FIT_MODE");
     if (!status) {
-	psfModeWord = psStringCopy ("EXT");
+	psfModeWord = DEFAULT_MODE;
     }
     bool psfMode = !strcasecmp (psfModeWord, "PSF");
@@ -25,5 +26,5 @@
     // in psfMode, psf sets the model type
     if (psfMode) {
-	char *psfFile = psMetadataLookupPtr (&status, arguments, "PSF_INPUT_FILE");
+	char *psfFile = psMetadataLookupStr (&status, arguments, "PSF_INPUT_FILE");
 	if (!status) psAbort ("psphotModelTest", "PSF_INPUT_FILE not supplied");
 	psMetadata *psfData = psMetadataConfigParse (NULL, &Nfail, psfFile, FALSE);
@@ -32,5 +33,5 @@
     } else {
 	// find the model: supplied by user or first in the PSF_MODEL list
-	char *modelName  = psMetadataLookupPtr (&status, arguments, "TEST_FIT_MODEL");
+	char *modelName  = psMetadataLookupStr (&status, arguments, "TEST_FIT_MODEL");
 	if (modelName == NULL) {
 	    // get the list pointers for the PSF_MODEL entries
@@ -153,5 +154,5 @@
     psImageKeepCircle (source->mask, xObj, yObj, RADIUS, "OR", PSPHOT_MASK_MARKED);
 
-    char *fitset = psMetadataLookupPtr (&status, arguments, "TEST_FIT_SET");
+    char *fitset = psMetadataLookupStr (&status, arguments, "TEST_FIT_SET");
     if (status) {
 	status = psphotFitSet (source, model, fitset, psfMode);
Index: /trunk/psphot/src/psphotOutput.c
===================================================================
--- /trunk/psphot/src/psphotOutput.c	(revision 6378)
+++ /trunk/psphot/src/psphotOutput.c	(revision 6379)
@@ -12,19 +12,31 @@
 static char *extRoot    = NULL;
 
+void psphotOutputCleanup () {
+
+    psFree (outputRoot);
+    psFree (outputName);
+    psFree (outputMode);
+    psFree (outputFormat);
+    psFree (extNumberFormat);
+    psFree (extNameKey);
+    psFree (extRoot);
+    return;
+}
+
 void psphotOutputPrep (ppFile *file, ppConfig *config) {
 
     bool status;
 
-    outputRoot   = psMetadataLookupPtr (&status, config->arguments, "OUTPUT_ROOT");
+    outputRoot      = psMetadataLookupStr (&status, config->arguments, "OUTPUT_ROOT");
     if (!status) psAbort ("psphot", "output file not specified");
 
-    outputName   = psMetadataLookupPtr (&status, config->recipe, "OUTPUT_NAME");
-    outputMode   = psMetadataLookupPtr (&status, config->recipe, "OUTPUT_MODE");
-    outputFormat = psMetadataLookupPtr (&status, config->recipe, "OUTPUT_FORMAT");
+    outputName      = psMetadataLookupStr (&status, config->recipe, "OUTPUT_NAME");
+    outputMode      = psMetadataLookupStr (&status, config->recipe, "OUTPUT_MODE");
+    outputFormat    = psMetadataLookupStr (&status, config->recipe, "OUTPUT_FORMAT");
 
     // rules to construct output names
-    extNumberFormat = psMetadataLookupPtr (&status, config->recipe, "EXTNUMBER_FORMAT");
-    extNameKey      = psMetadataLookupPtr (&status, config->recipe, "EXTNAME");
-    extRoot         = psMetadataLookupPtr (&status, config->recipe, "EXTROOT");
+    extNumberFormat = psMetadataLookupStr (&status, config->recipe, "EXTNUMBER_FORMAT");
+    extNameKey      = psMetadataLookupStr (&status, config->recipe, "EXTNAME");
+    extRoot         = psMetadataLookupStr (&status, config->recipe, "EXTROOT");
 
     if (extNumberFormat == NULL) {
@@ -63,4 +75,13 @@
     }
 
+    // save so freeing config will not drop these references
+    psMemCopy (outputRoot);
+    psMemCopy (outputName);
+    psMemCopy (outputMode);
+    psMemCopy (outputFormat);
+    psMemCopy (extNumberFormat);
+    psMemCopy (extNameKey);
+    psMemCopy (extRoot);
+
     return;
 }
@@ -79,5 +100,5 @@
 
     // find the extname:
-    char *extNameVal = psMetadataLookupPtr (&status, header, extNameKey);
+    char *extNameVal = psMetadataLookupStr (&status, header, extNameKey);
 	    
     extNameWord = extNameVal;
@@ -157,15 +178,9 @@
     if (!strcasecmp (outputMode, "SPLIT")) {
 	outputFile = psphotSplitName (header);
-    } else {
-	// construct appropriate extname
-	psAbort ("psphotOutput", "programming error");
-    }
-    
-    fprintf (stderr, "output file: %s\n", outputFile);
-    return;
-
-    char *psfFile    = psMetadataLookupPtr (&status, arguments, "PSF_OUTPUT_FILE");
-    char *psfSample  = psMetadataLookupPtr (&status, arguments, "PSF_SAMPLE_FILE");
-    char *residImage = psMetadataLookupPtr (&status, arguments, "RESID_IMAGE");
+    } 
+
+    char *psfFile    = psMetadataLookupStr (&status, arguments, "PSF_OUTPUT_FILE");
+    char *psfSample  = psMetadataLookupStr (&status, arguments, "PSF_SAMPLE_FILE");
+    char *residImage = psMetadataLookupStr (&status, arguments, "RESID_IMAGE");
 
     if (psfSample != NULL) psphotSamplePSFs (psf, readout->image, psfSample);
@@ -183,24 +198,30 @@
     if (outputFormat == NULL) {
 	psLogMsg ("output", 3, "no data output format selected");
+	psFree (outputFile);
 	return;
     }
     if (!strcasecmp (outputFormat, "SX")) {
 	pmSourcesWriteSX (sources, outputFile);
+	psFree (outputFile);
 	return;
     }
     if (!strcasecmp (outputFormat, "OBJ")) {
 	pmSourcesWriteOBJ (sources, outputFile);
+	psFree (outputFile);
 	return;
     }
     if (!strcasecmp (outputFormat, "CMP")) {
 	pmSourcesWriteCMP (sources, outputFile, header);
+	psFree (outputFile);
 	return;
     }
     if (!strcasecmp (outputFormat, "CMF")) {
 	pmSourcesWriteCMF (sources, outputFile, header);
+	psFree (outputFile);
 	return;
     }
     if (!strcasecmp (outputFormat, "TEXT")) {
 	pmSourcesWriteText (sources, outputFile);
+	psFree (outputFile);
 	return;
     }
@@ -610,4 +631,5 @@
     }
     fclose (f);
+    psFree (empty);
     return true;
 }
@@ -746,5 +768,5 @@
 
     // optional dump of all rough source data
-    char *output = psMetadataLookupPtr (&status, config, "MOMENTS_OUTPUT_FILE");
+    char *output = psMetadataLookupStr (&status, config, "MOMENTS_OUTPUT_FILE");
     if (!status) return false;
     if (output == NULL) return false;
@@ -752,5 +774,4 @@
 
     pmMomentsWriteText (sources, output);
-    psFree (output);
     return true;
 }
Index: /trunk/psphot/src/psphotParseCamera.c
===================================================================
--- /trunk/psphot/src/psphotParseCamera.c	(revision 6378)
+++ /trunk/psphot/src/psphotParseCamera.c	(revision 6379)
@@ -6,11 +6,13 @@
       if (ITEM == NULL) { \
 	psMetadataAdd##TYPE (CONFIG, PS_LIST_TAIL, NAME, 0, COMMENT, VALUE); \
-      } else { psFree (ITEM); } }
+      } }
 
+// 2006.02.07 : no leaks!
 ppFile *psphotParseCamera (ppConfig *config) {
 
     ppFile *input = ppFileAlloc ();
 
-    input->filename = psMemIncrRefCounter(psMetadataLookupStr(NULL, config->arguments, "INPUT_FILE"));
+    input->filename = psMetadataLookupStr(NULL, config->arguments, "INPUT_FILE");
+    psMemCopy (input->filename); // keep for external use
 
     // Open the input image
@@ -53,5 +55,4 @@
     while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
 	psMetadataAddItem (config->recipe, item, PS_LIST_TAIL, PS_META_REPLACE);
-	psFree (item);
     }
     psFree (iter);
Index: /trunk/psphot/src/psphotReadout.c
===================================================================
--- /trunk/psphot/src/psphotReadout.c	(revision 6378)
+++ /trunk/psphot/src/psphotReadout.c	(revision 6379)
@@ -1,11 +1,5 @@
 # include "psphot.h"
 
-# define MEM_0 psMemId ID = psMemGetId ();
-# define MEM_1(A) \
-    psTimerStop ();\
-    if (A != NULL) { psFree (A); } \
-    fprintf (stderr, "found %d leaks\n", psMemCheckLeaks (ID, NULL, NULL, false));\
-    exit (1);
-
+// XXX 2006.02.07 : no leaks!
 bool psphotReadout (pmReadout *readout, psMetadata *config) {
 
@@ -41,7 +35,5 @@
 
     // use bright stellar objects to measure PSF
-    MEM_0;
     psf = psphotChoosePSF (config, sources, sky);
-    MEM_1(psf);
 
     // XXX change FITMODE to a string
@@ -80,4 +72,12 @@
     status = psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSPHOT.SKY.MEAN",  PS_DATA_F32,     "psphot sky mean", sky->sampleMean);
     status = psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSPHOT.SKY.SIGMA", PS_DATA_F32,     "psphot sky stdev", sky->sampleStdev);
+
+    // free up the local copies of the data
+    psFree (psf);
+    psFree (sky);
+    psFree (model);
+    psFree (peaks);
+    psFree (sources);
+
     return true;
 }
Index: /trunk/psphot/src/psphotRoughClass.c
===================================================================
--- /trunk/psphot/src/psphotRoughClass.c	(revision 6378)
+++ /trunk/psphot/src/psphotRoughClass.c	(revision 6379)
@@ -15,5 +15,5 @@
     psphotDumpMoments (config, sources);
 
-    char *breakPt = psMetadataLookupPtr (&status, config, "BREAK_POINT");
+    char *breakPt = psMetadataLookupStr (&status, config, "BREAK_POINT");
     if (!strcasecmp (breakPt, "CLASS")) exit (0);
 
Index: /trunk/psphot/src/psphotSourceFits.c
===================================================================
--- /trunk/psphot/src/psphotSourceFits.c	(revision 6378)
+++ /trunk/psphot/src/psphotSourceFits.c	(revision 6379)
@@ -54,5 +54,5 @@
 
     // extended source model descriptions
-    char *modelNameEXT = psMetadataLookupPtr (&status, config, "EXT_MODEL");
+    char *modelNameEXT = psMetadataLookupStr (&status, config, "EXT_MODEL");
     modelTypeEXT = pmModelSetType (modelNameEXT);
     psphotInitRadiusEXT (config, sky, modelTypeEXT);
@@ -77,4 +77,5 @@
     psTrace ("psphot.blend", 5, "trying blob...\n");
 
+    // this temporary source is used as a place-holder by the psphotEval functions below
     pmSource *tmpSrc = pmSourceAlloc ();
 
@@ -89,4 +90,6 @@
     chiDBL = ONE->chisq / ONE->nDOF;
 
+    psFree (tmpSrc); // XXX should I keep / save the flags set in the eval functions?
+
     if (okEXT && okDBL) {
 	psTrace ("psphot.blend", 5, "blob chisq: %f vs %f\n", chiEXT, chiDBL);
@@ -98,8 +101,13 @@
     if (okEXT && !okDBL) goto keepEXT;
     if (!okEXT && okDBL) goto keepDBL;
+
+    // both models failed; reject them both
+    psFree (EXT);
+    psFree (DBL);
     return false;
 
 keepEXT:
     // sub EXT
+    psFree (DBL);
     pmSourceSubModel (source->pixels, source->mask, EXT, false, false);
     psTrace ("psphot.blend", 5, "blob as EXT: %f %f\n", EXT->params->data.F32[2], EXT->params->data.F32[3]);
@@ -113,4 +121,5 @@
 keepDBL:
     // sub DLB
+    psFree (EXT);
     pmSourceSubModel (source->pixels, source->mask, (pmModel *) DBL->data[0], false, false);
     pmSourceSubModel (source->pixels, source->mask, (pmModel *) DBL->data[1], false, false);
@@ -120,8 +129,4 @@
     source->mode |=  PM_SOURCE_SUBTRACTED;
     source->mode &= ~PM_SOURCE_TEMPSUB;
-
-    // save new model
-    // tmpSrc->modelPSF = (pmModel *) modelSet->data[1];
-    // psArrayAdd (sources, 100, tmpSrc);
 
     return true;
@@ -205,5 +210,4 @@
 	return status;
     }
-
     psTrace ("psphot.blend", 5, "trying blend...\n");
 
@@ -225,4 +229,8 @@
     psArrayAdd (sourceSet, 16, source);
 
+    // counter to track the blend elements used in the fit
+    psVector *index  = psVectorAlloc (source->blends->n + 1, PS_TYPE_S32);
+    index->data.S32[0] = -1; // first element corresponds to the primary source
+
     for (int i = 0; i < source->blends->n; i++) {
 	pmSource *blend = source->blends->data[i];
@@ -237,7 +245,7 @@
 	pmModel *model = blend->modelPSF;
 
-	for (psS32 i = 0; i < model->params->n; i++) {
-	    model->params->data.F32[i] = PSF->params->data.F32[i];
-	    model->dparams->data.F32[i] = PSF->dparams->data.F32[i];
+	for (int j = 0; j < model->params->n; j++) {
+	    model->params->data.F32[j] = PSF->params->data.F32[j];
+	    model->dparams->data.F32[j] = PSF->dparams->data.F32[j];
 	}
 
@@ -247,4 +255,5 @@
 
 	// add this blend to the list
+	index->data.S32[modelSet->n] = i;
 	psArrayAdd (modelSet, 16, model);
 	psArrayAdd (sourceSet, 16, blend);
@@ -261,7 +270,10 @@
 	pmModel *model = modelSet->data[i];
 
+	// if we skip this one, free the corresponding blend entry model
 	if (!psphotEvalPSF (src, model)) {
-	    psFree (model);
-	    src->modelPSF = NULL;
+	    int n = index->data.S32[i];
+	    pmSource *blend = source->blends->data[n];
+	    psFree (blend->modelPSF);
+	    blend->modelPSF = NULL;
 	    continue;
 	}
@@ -272,4 +284,7 @@
 	src->mode &= ~PM_SOURCE_TEMPSUB;
     }
+    psFree (index);
+    psFree (modelSet);
+    psFree (sourceSet);
 
     // evaluate the primary object
@@ -281,4 +296,5 @@
     psTrace ("psphot.blend", 5, "fitted primary as PSF\n");
     pmSourceSubModel (source->pixels, source->mask, PSF, false, false);
+    psFree (source->modelPSF);
     source->modelPSF = PSF;
     source->mode |=  PM_SOURCE_SUBTRACTED;
Index: /trunk/psphot/src/psphotSourceStats.c
===================================================================
--- /trunk/psphot/src/psphotSourceStats.c	(revision 6378)
+++ /trunk/psphot/src/psphotSourceStats.c	(revision 6379)
@@ -63,5 +63,5 @@
     psLogMsg ("psphot", 3, "%d moments: %f sec\n", sources->n, psTimerMark ("psphot"));
 
-    char *breakPt = psMetadataLookupPtr (&status, config, "BREAK_POINT");
+    char *breakPt = psMetadataLookupStr (&status, config, "BREAK_POINT");
     if (!strcasecmp (breakPt, "STATS")) exit (0);
 
