Index: branches/czw_branch/20101203/psModules/src/camera/pmFPAFlags.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/camera/pmFPAFlags.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/camera/pmFPAFlags.c	(revision 30118)
@@ -49,4 +49,54 @@
 }
 
+bool pmReadoutSetFileStatus(pmReadout *readout, bool status)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+
+    readout->file_exists = status;
+    return true;
+}
+
+bool pmFPAviewSetFileStatus (pmFPA *fpa, const pmFPAview *view, bool status) {
+
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    if (view->chip == -1) {
+	bool set = pmFPASetFileStatus (fpa, status);
+        return set;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %ld", view->chip, fpa->chips->n);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        bool set = pmChipSetFileStatus (chip, status);
+        return set;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %ld", view->cell, chip->cells->n);
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        bool set = pmCellSetFileStatus (cell, status);
+        return set;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouds->n == %ld", view->readout, cell->readouts->n);
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    bool set = pmReadoutSetFileStatus (readout, status);
+    return set;
+}
+
 bool pmFPACheckFileStatus(const pmFPA *fpa)
 {
@@ -125,7 +175,57 @@
     for (int i = 0; i < cell->readouts->n; i++) {
         pmReadout *readout = cell->readouts->data[i];
-        readout->data_exists = status;
-    }
-    return true;
+        pmReadoutSetDataStatus(readout, status);
+    }
+    return true;
+}
+
+bool pmReadoutSetDataStatus (pmReadout *readout, bool status)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+
+    readout->data_exists = status;
+    return true;
+}
+
+bool pmFPAviewSetDataStatus (pmFPA *fpa, const pmFPAview *view, bool status) {
+
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    if (view->chip == -1) {
+	bool set = pmFPASetDataStatus (fpa, status);
+        return set;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %ld", view->chip, fpa->chips->n);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        bool set = pmChipSetDataStatus (chip, status);
+        return set;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %ld", view->cell, chip->cells->n);
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        bool set = pmCellSetDataStatus (cell, status);
+        return set;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouds->n == %ld", view->readout, cell->readouts->n);
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    bool set = pmReadoutSetDataStatus (readout, status);
+    return set;
 }
 
Index: branches/czw_branch/20101203/psModules/src/camera/pmFPAFlags.h
===================================================================
--- branches/czw_branch/20101203/psModules/src/camera/pmFPAFlags.h	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/camera/pmFPAFlags.h	(revision 30118)
@@ -34,4 +34,8 @@
                         );
 
+bool pmReadoutSetFileStatus(pmReadout *readout, bool status);
+
+bool pmFPAviewSetFileStatus (pmFPA *fpa, const pmFPAview *view, bool status);
+
 // Functions to check the file_exists flags
 
@@ -65,4 +69,7 @@
                         );
 
+bool pmReadoutSetDataStatus (pmReadout *readout, bool status);
+
+bool pmFPAviewSetDataStatus (pmFPA *fpa, const pmFPAview *view, bool status);
 
 // Functions the check the data_exists flags
Index: branches/czw_branch/20101203/psModules/src/camera/pmFPAfile.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/camera/pmFPAfile.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/camera/pmFPAfile.c	(revision 30118)
@@ -36,5 +36,5 @@
         return;
     }
-    psTrace ("pmFPAfileFree", 5, "freeing %s %ld\n", file->name,(psU64) file->fits);
+    psTrace ("pmFPAfileFree", 5, "freeing %s %p\n", file->name, file->fits);
     psAssert(!fpaFileFreeStrict || file->fits == NULL, "File %s wasn't closed.", file->name);
 
Index: branches/czw_branch/20101203/psModules/src/camera/pmFPAfileIO.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/camera/pmFPAfileIO.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/camera/pmFPAfileIO.c	(revision 30118)
@@ -135,7 +135,4 @@
     PS_ASSERT_PTR_NON_NULL(view, false);
 
-    // an internal file should not be sent here (should not be left on config->files)
-    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
-
     // skip the following states
     if (file->state & PM_FPA_STATE_INACTIVE) {
@@ -143,4 +140,8 @@
         return true;
     }
+
+    // an active internal file should not be sent here (should not be left on config->files)
+    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
+
     if (file->mode != PM_FPA_MODE_READ) {
         psTrace("psModules.camera", 6, "skip read for %s, mode is not READ", file->name);
@@ -258,11 +259,12 @@
         return true;
     }
+
+    // an active internal file should not be returned to here
+    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
+
     if (file->mode != PM_FPA_MODE_WRITE) {
         psTrace("psModules.camera", 6, "skip create for non-write file %s", file->name);
         return true;
     }
-
-    // an internal file should not be returned to here
-    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
 
     // get the current level
@@ -335,13 +337,10 @@
     }
 
+    // an ACTIVE internal file should not be sent here
+    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
+
     if (file->mode != PM_FPA_MODE_WRITE) {
         psTrace("psModules.camera", 6, "skip write for %s, mode is not WRITE", file->name);
         return true;
-    }
-
-    // an internal file should not be returned to here
-    if (file->mode == PM_FPA_MODE_INTERNAL) {
-        psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_INTERNAL");
-        return false;
     }
 
@@ -523,7 +522,4 @@
     PS_ASSERT_PTR_NON_NULL(view, false);
 
-    // an internal file should not be sent here (should not be left on config->files)
-    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
-
     // skip the following states
     if (file->state & PM_FPA_STATE_INACTIVE) {
@@ -531,8 +527,12 @@
         return true;
     }
+
     if (file->state == PM_FPA_STATE_CLOSED) {
         psTrace("psModules.camera", 6, "skip close for %s, files is closed", file->name);
         return true;
     }
+
+    // an active internal file should not be sent here (should not be left on config->files)
+    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
 
     // is current level == open level?
@@ -596,11 +596,11 @@
     PS_ASSERT_PTR_NON_NULL(view, false);
 
-    // an internal file should not be sent here (should not be left on config->files)
-    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
-
     if (file->state & PM_FPA_STATE_INACTIVE) {
         psTrace("psModules.camera", 6, "skip free for %s, files is inactive", file->name);
         return true;
     }
+
+    // an active internal file should not be sent here (should not be left on config->files)
+    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
 
     // get the current level
@@ -746,5 +746,5 @@
     }
 
-    // these are programming errors
+    // an ACTIVE internal file should not be sent here
     PS_ASSERT(file->mode != PM_FPA_MODE_NONE, false);
     PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
Index: branches/czw_branch/20101203/psModules/src/concepts/pmConceptsAverage.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/concepts/pmConceptsAverage.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/concepts/pmConceptsAverage.c	(revision 30118)
@@ -136,4 +136,51 @@
     return average;
 }
+float medianWithDropouts (psList *sources, char *name) {
+
+    bool status;
+
+    psListIterator *sourcesIter = psListIteratorAlloc(sources, PS_LIST_HEAD, false); // Iterator for sources
+    pmCell *cell = NULL;                // Source cell from iteration
+
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN);
+    psVector *values = psVectorAlloc(sources->n, PS_TYPE_F32);
+    int nvalues = 0;
+    while ((cell = psListGetAndIncrement(sourcesIter))) {
+        if (!cell) {
+            continue;
+        }
+
+        float value = psMetadataLookupF32(&status, cell->concepts, name);
+        if (!status) continue;
+        if (!isfinite(value)) continue;
+
+        values->data.F32[nvalues++] = value;
+    }
+    psFree (sourcesIter);
+    if (!nvalues) {
+        psWarning("no valid values found for %s\n", name);
+        psFree(values);
+        psFree(stats);
+        return INFINITY;
+    }
+    if (!(values = psVectorRealloc(values, nvalues))) {
+        psWarning("failed to reallocate values vector for %s\n", name);
+        psFree(stats);
+        return INFINITY;
+    }
+    if (!psVectorStats(stats, values, NULL, NULL, 0)) {
+        psWarning("psVectorStats failed for %s\n", name);
+        psFree(values);
+        psFree(stats);
+        return INFINITY;
+    }
+
+    psF32 median = psStatsGetValue(stats, PS_STAT_SAMPLE_MEDIAN);
+
+    psFree(values);
+    psFree(stats);
+
+    return median;
+}
 
 // Set a variety of concepts in a cell by averaging over several
@@ -145,5 +192,4 @@
     PS_ASSERT_INT_POSITIVE(sources->n, false);
 
-    float saturation = INFINITY;        // Saturation level
     float bad        = -INFINITY;       // Bad level
     double time      = 0.0;             // Time of observation
@@ -158,4 +204,5 @@
     float exposure  = averageWithDropouts (sources, "CELL.EXPOSURE");
     float darktime  = averageWithDropouts (sources, "CELL.DARKTIME");
+    float saturation = medianWithDropouts(sources, "CELL.SATURATION");
 
     // other concepts are a bit more "special"
@@ -221,13 +268,4 @@
         }
 
-        float cellSaturation = psMetadataLookupF32(NULL, cell->concepts, "CELL.SATURATION");
-	if (cellSaturation > 10000) {
-	    // do not allow invalid values to polute this calculation
-	    // XXX really need to do this on the basis of the fraction of the cell that contributes..
-	    // if a cell is completely masked, it should not be included.
-	    if (cellSaturation < saturation) {
-		saturation = cellSaturation;
-	    }
-	}
         float cellBad = psMetadataLookupF32(NULL, cell->concepts, "CELL.BAD");
         if (cellBad > bad) {
Index: branches/czw_branch/20101203/psModules/src/config/pmConfigDump.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/config/pmConfigDump.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/config/pmConfigDump.c	(revision 30118)
@@ -150,5 +150,12 @@
     }
 
-    if (!psMetadataConfigWrite(config->user, resolved)) {
+    // check for Metadata compression options:
+    char *compressMode = NULL;
+    bool status = false;
+    if (config->camera) {
+	compressMode = psMetadataLookupStr(&status, config->camera, "METADATA.COMPRESSION");
+    }
+
+    if (!psMetadataConfigWrite(config->user, resolved, compressMode)) {
         psError(psErrorCodeLast(), false, "Unable to dump configuration to %s", filename);
         psFree(resolved);
Index: branches/czw_branch/20101203/psModules/src/detrend/pmNonLinear.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/detrend/pmNonLinear.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/detrend/pmNonLinear.c	(revision 30118)
@@ -332,7 +332,4 @@
 	return(0.0);
     }
-/*     if (flux > correction_fluxes->data.F32[bin]) { */
-/* 	return(0.0); */
-/*     } */
   
     for (int i = 0; i < correction_fluxes->n - 1; i++) {
@@ -347,16 +344,7 @@
     }
 
-/*   PS_BIN_FOR_VALUE(bin,correction_fluxes,flux); */
-/*   if ((bin < 0)||(bin > correction_fluxes->n)) { */
-/*     return(1.0); */
-/*   } */
-  
-/*   PS_BIN_INTERPOLATE(result,correction_fluxes,correction_factors,bin,flux); */
     if (!isfinite(result)) {
 	result = 0.0;
     }
-/*     if (result <= 0) { */
-/* 	result = 1.0; */
-/*     } */
     return(result);
 }
@@ -372,7 +360,4 @@
 	return(0.0);
     }
-/*     if (flux > correction_fluxes->data.F32[bin]) { */
-/* 	return(0.0); */
-/*     } */
 
     for (int i = 0; i < correction_fluxes->n - 1; i++) {
@@ -389,19 +374,7 @@
     }
 
-/*   PS_BIN_FOR_VALUE(bin,correction_fluxes,flux); */
-/*   if ((bin < 0)||(bin > correction_fluxes->n)) { */
-/*     return(1.0); */
-/*   } */
-  
-/*   PS_BIN_INTERPOLATE(result,correction_fluxes,correction_factors,bin,flux); */
     if (!isfinite(result)) {
 	result = 0.0;
     }
-/*     if (result <= 0) { */
-/* 	result = 1.0; */
-/*     } */
     return(result);
 }
-
-  
-  
Index: branches/czw_branch/20101203/psModules/src/objects/pmPSF_IO.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/objects/pmPSF_IO.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/objects/pmPSF_IO.c	(revision 30118)
@@ -62,4 +62,6 @@
 #include "pmSourceIO.h"
 
+bool pmPSFmodelReadPSFClump (psMetadata *analysis, psMetadata *header);
+
 bool pmPSFmodelCheckDataStatusForView (const pmFPAview *view, const pmFPAfile *file)
 {
@@ -851,65 +853,13 @@
 
     // read the psf clump data for each region
+    status = false;
     if (roAnalysis) {
-        int nRegions = psMetadataLookupS32 (&status, header, "PSF_CLN");
-        if (!status) {
-            // read old-style psf clump data
-
-            char regionName[64];
-            snprintf (regionName, 64, "PSF.CLUMP.REGION.000");
-            psMetadataAddS32 (roAnalysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", 1);
-
-            psMetadata *regionMD = psMetadataLookupPtr (&status, roAnalysis, regionName);
-            if (!regionMD) {
-                regionMD = psMetadataAlloc();
-                psMetadataAddMetadata (roAnalysis, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD);
-                psFree (regionMD);
-            }
-
-            // psf clump data
-            pmPSFClump psfClump;
-
-            psfClump.X  = psMetadataLookupF32 (&status, header, "PSF_CLX" );  assert(status);
-            psfClump.Y  = psMetadataLookupF32 (&status, header, "PSF_CLY" );  assert(status);
-            psfClump.dX = psMetadataLookupF32 (&status, header, "PSF_CLDX");  assert(status);
-            psfClump.dY = psMetadataLookupF32 (&status, header, "PSF_CLDY");  assert(status);
-
-            psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
-            psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y",  PS_META_REPLACE, "psf clump center", psfClump.Y);
-            psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
-            psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
-        } else {
-            psMetadataAddS32 (roAnalysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", nRegions);
-
-            for (int i = 0; i < nRegions; i++) {
-                char key[10];
-                char regionName[64];
-                snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", i);
-
-                psMetadata *regionMD = psMetadataLookupPtr (&status, roAnalysis, regionName);
-                if (!regionMD) {
-                    regionMD = psMetadataAlloc();
-                    psMetadataAddMetadata (roAnalysis, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD);
-                    psFree (regionMD);
-                }
-
-                // psf clump data
-                pmPSFClump psfClump;
-
-                snprintf (key, 9, "CLX_%03d", i);
-                psfClump.X  = psMetadataLookupF32 (&status, header, key);  assert(status);
-                snprintf (key, 9, "CLY_%03d", i);
-                psfClump.Y  = psMetadataLookupF32 (&status, header, key);  assert(status);
-                snprintf (key, 9, "CLDX_%03d", i);
-                psfClump.dX = psMetadataLookupF32 (&status, header, key);  assert(status);
-                snprintf (key, 9, "CLDY_%03d", i);
-                psfClump.dY = psMetadataLookupF32 (&status, header, key);  assert(status);
-
-                psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
-                psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y",  PS_META_REPLACE, "psf clump center", psfClump.Y);
-                psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
-                psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
-            }
-        }
+	status = pmPSFmodelReadPSFClump (roAnalysis, header);
+	if (!status) {
+	    psMetadataAddS32 (roAnalysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", 0);
+	}
+    } 
+    if (!roAnalysis || !status) {
+	psWarning ("no PSF.CLUMP data available for PSF model");
     }
 
@@ -1123,3 +1073,66 @@
 }
 
-// XXX pmPSF to/from Metadata functions were defined for 1.22 and earlier, but were dropped
+bool pmPSFmodelReadPSFClump (psMetadata *analysis, psMetadata *header) {
+
+    bool status = false;;
+
+    int nRegions = psMetadataLookupS32 (&status, header, "PSF_CLN");
+    if (!status) {
+	// read old-style psf clump data
+
+	char regionName[64];
+	snprintf (regionName, 64, "PSF.CLUMP.REGION.000");
+	psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
+
+	if (!regionMD) {
+	    regionMD = psMetadataAlloc();
+	    psMetadataAddMetadata (analysis, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD);
+	    psFree (regionMD);
+	}
+
+	// psf clump data
+	pmPSFClump psfClump;
+	psfClump.X  = psMetadataLookupF32 (&status, header, "PSF_CLX" );  if (!status) return false;
+	psfClump.Y  = psMetadataLookupF32 (&status, header, "PSF_CLY" );  if (!status) return false;
+	psfClump.dX = psMetadataLookupF32 (&status, header, "PSF_CLDX");  if (!status) return false;
+	psfClump.dY = psMetadataLookupF32 (&status, header, "PSF_CLDY");  if (!status) return false;
+
+	psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
+	psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y",  PS_META_REPLACE, "psf clump center", psfClump.Y);
+	psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
+	psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
+	psMetadataAddS32 (analysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", 1);
+    } else {
+	for (int i = 0; i < nRegions; i++) {
+	    char key[10];
+	    char regionName[64];
+	    snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", i);
+
+	    psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
+	    if (!regionMD) {
+		regionMD = psMetadataAlloc();
+		psMetadataAddMetadata (analysis, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD);
+		psFree (regionMD);
+	    }
+
+	    // psf clump data
+	    pmPSFClump psfClump;
+
+	    snprintf (key, 9, "CLX_%03d", i);
+	    psfClump.X  = psMetadataLookupF32 (&status, header, key);  if (!status) return false;
+	    snprintf (key, 9, "CLY_%03d", i);
+	    psfClump.Y  = psMetadataLookupF32 (&status, header, key);  if (!status) return false;
+	    snprintf (key, 9, "CLDX_%03d", i);
+	    psfClump.dX = psMetadataLookupF32 (&status, header, key);  if (!status) return false;
+	    snprintf (key, 9, "CLDY_%03d", i);
+	    psfClump.dY = psMetadataLookupF32 (&status, header, key);  if (!status) return false;
+
+	    psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
+	    psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y",  PS_META_REPLACE, "psf clump center", psfClump.Y);
+	    psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
+	    psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
+	}
+	psMetadataAddS32 (analysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", nRegions);
+    }
+    return true;
+}
Index: branches/czw_branch/20101203/psModules/src/objects/pmPSFtry.h
===================================================================
--- branches/czw_branch/20101203/psModules/src/objects/pmPSFtry.h	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/objects/pmPSFtry.h	(revision 30118)
@@ -100,5 +100,5 @@
 bool pmPSFtryFitEXT (pmPSFtry *psfTry, pmPSFOptions *options, psImageMaskType maskVal, psImageMaskType markVal);
 
-bool pmPSFtryMakePSF (pmPSFtry *psfTry);
+bool pmPSFtryMakePSF (bool *pGoodFit, pmPSFtry *psfTry);
 
 bool pmPSFtryFitPSF (pmPSFtry *psfTry, pmPSFOptions *options, psImageMaskType maskVal, psImageMaskType markVal);
@@ -123,5 +123,5 @@
 );
 
-bool pmPSFFitShapeParams (pmPSF *psf, psArray *sources, psVector *x, psVector *y, psVector *srcMask);
+bool pmPSFFitShapeParams (bool *pGoodFit, pmPSF *psf, psArray *sources, psVector *x, psVector *y, psVector *srcMask);
 
 float psVectorSystematicError (psVector *residuals, psVector *errors, float clipFraction);
Index: branches/czw_branch/20101203/psModules/src/objects/pmPSFtryMakePSF.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/objects/pmPSFtryMakePSF.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/objects/pmPSFtryMakePSF.c	(revision 30118)
@@ -50,5 +50,5 @@
 Note: some of the array entries may be NULL (failed fits); ignore them.
  *****************************************************************************/
-bool pmPSFtryMakePSF (pmPSFtry *psfTry)
+bool pmPSFtryMakePSF (bool *pGoodFit, pmPSFtry *psfTry)
 {
     PS_ASSERT_PTR_NON_NULL(psfTry, false);
@@ -74,8 +74,14 @@
 
     // fit the shape parameters (SXX, SYY, SXY) as a function of position
-    if (!pmPSFFitShapeParams (psf, psfTry->sources, x, y, srcMask)) {
+    if (!pmPSFFitShapeParams (pGoodFit, psf, psfTry->sources, x, y, srcMask)) {
         psFree(x);
         psFree(y);
         return false;
+    }
+    if (!*pGoodFit) {
+	psWarning ("poor fit to PSF shape parameters for trend order %d, %d, skipping\n", psf->trendNx, psf->trendNy);
+	psFree(x);
+	psFree(y);
+	return true;
     }
 
@@ -115,5 +121,5 @@
         // the mask is carried from previous steps and updated with this operation
         // the weight is either the flux error or NULL, depending on 'psf->poissonErrorParams'
-        if (!pmTrend2DFit (trend, srcMask, 0xff, x, y, z, NULL)) {
+        if (!pmTrend2DFit (pGoodFit, trend, srcMask, 0xff, x, y, z, NULL)) {
             psError(PS_ERR_UNKNOWN, false, "failed to build psf model for parameter %d", i);
             psFree(x);
@@ -122,4 +128,13 @@
             return false;
         }
+	if (!*pGoodFit) {
+	    // if we do not get a good fit (but do not actually hit an error), 
+	    // tell the calling program to try something else
+	    psWarning ("poor fit to PSF parameter %d for trend order %d, %d, skipping\n", i, psf->trendNx, psf->trendNy);
+            psFree(x);
+            psFree(y);
+            psFree(z);
+            return true;
+	}
 	if (trend->mode == PM_TREND_MAP) {
 	    // p_psImagePrint (2, trend->map->map, "param N Before"); // XXX TEST:
@@ -139,4 +154,12 @@
 
             pmModel *modelPSF = pmModelFromPSF (source->modelEXT, psf);
+            if (!modelPSF) {
+                fprintf(f, "modelPSF is NULL\n");
+                break;
+            }
+            if (!source->modelEXT) {
+                fprintf(f, "source->modelEXT is NULL\n");
+                break;
+            }
 
             fprintf (f, "%f %f : ", source->modelEXT->params->data.F32[PM_PAR_XPOS], source->modelEXT->params->data.F32[PM_PAR_YPOS]);
@@ -163,5 +186,5 @@
 
 // fit the shape parameters using the supplied order (pmPSF->trendNx,trendNy)
-bool pmPSFFitShapeParams (pmPSF *psf, psArray *sources, psVector *x, psVector *y, psVector *srcMask) {
+bool pmPSFFitShapeParams (bool *pGoodFit, pmPSF *psf, psArray *sources, psVector *x, psVector *y, psVector *srcMask) {
 
     // we are doing a robust fit.  after each pass, we drop points which are more deviant than
@@ -219,5 +242,11 @@
 	trend = psf->params->data[PM_PAR_E0];
 	trend->stats->clipIter = 1; // in allocation, this value is set to the value of nIter, but we should use 1 here
-	status &= pmTrend2DFit (trend, srcMask, 0xff, x, y, e0, NULL);
+	status &= pmTrend2DFit (pGoodFit, trend, srcMask, 0xff, x, y, e0, NULL);
+	if (!*pGoodFit) {
+	    psFree (e0);
+	    psFree (e1);
+	    psFree (e2);
+	    return true;
+	}
 	mean = psStatsGetValue (trend->stats, meanOption);
 	stdev = psStatsGetValue (trend->stats, stdevOption);
@@ -228,5 +257,11 @@
 	trend = psf->params->data[PM_PAR_E1];
 	trend->stats->clipIter = 1; // in allocation, this value is set to the value of nIter, but we should use 1 here
-	status &= pmTrend2DFit (trend, srcMask, 0xff, x, y, e1, NULL);
+	status &= pmTrend2DFit (pGoodFit, trend, srcMask, 0xff, x, y, e1, NULL);
+	if (!*pGoodFit) {
+	    psFree (e0);
+	    psFree (e1);
+	    psFree (e2);
+	    return true;
+	}
 	mean = psStatsGetValue (trend->stats, meanOption);
 	stdev = psStatsGetValue (trend->stats, stdevOption);
@@ -237,5 +272,11 @@
 	trend = psf->params->data[PM_PAR_E2];
 	trend->stats->clipIter = 1; // in allocation, this value is set to the value of nIter, but we should use 1 here
-	status &= pmTrend2DFit (trend, srcMask, 0xff, x, y, e2, NULL);
+	status &= pmTrend2DFit (pGoodFit, trend, srcMask, 0xff, x, y, e2, NULL);
+	if (!*pGoodFit) {
+	    psFree (e0);
+	    psFree (e1);
+	    psFree (e2);
+	    return true;
+	}
 	mean = psStatsGetValue (trend->stats, meanOption);
 	stdev = psStatsGetValue (trend->stats, stdevOption);
@@ -246,4 +287,7 @@
 	if (!status) {
 	    psError (PS_ERR_UNKNOWN, true, "failed to fit PSF shape params");
+	    psFree (e0);
+	    psFree (e1);
+	    psFree (e2);
 	    return false;
 	}
Index: branches/czw_branch/20101203/psModules/src/objects/pmPSFtryModel.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/objects/pmPSFtryModel.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/objects/pmPSFtryModel.c	(revision 30118)
@@ -136,9 +136,14 @@
 
         // stage 2: construct a psf (pmPSF) from this collection of model fits, including the 2D variation
-        if (!pmPSFtryMakePSF (psfTry)) {
+	bool goodFit = false;
+        if (!pmPSFtryMakePSF (&goodFit, psfTry)) {
             psError(PS_ERR_UNKNOWN, false, "failed to construct a psf model from collection of sources");
             psFree(psfTry);
             return NULL;
         }
+	if (!goodFit) {
+	    psWarning ("poor psf fit for order %d, skipping\n", i);
+	    continue;
+	}
 
         // stage 3: refit with fixed shape parameters, measure pmPSFtry->metric
@@ -169,4 +174,10 @@
     }
     psFree (srcMask);
+
+    if (!minPSF) {
+	psError(PS_ERR_UNKNOWN, false, "failed to construct a valid psf model from the sources");
+	psFree(psfTry);
+	return NULL;
+    }
 
     // keep the ones matching the min systematic error:
Index: branches/czw_branch/20101203/psModules/src/objects/pmSource.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/objects/pmSource.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/objects/pmSource.c	(revision 30118)
@@ -189,6 +189,6 @@
     // pixels.  Modifying these pixels (ie, subtracting the model) will affect the pixels seen
     // by all copies.
-    source->pixels   = psImageCopyView(NULL, in->pixels);
-    source->variance   = psImageCopyView(NULL, in->variance);
+    source->pixels   = in->pixels   ? psImageCopyView(NULL, in->pixels)   : NULL;
+    source->variance = in->variance ? psImageCopyView(NULL, in->variance) : NULL;
     source->maskView = in->maskView ? psImageCopyView(NULL, in->maskView) : NULL;
 
Index: branches/czw_branch/20101203/psModules/src/objects/pmSourcePhotometry.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/objects/pmSourcePhotometry.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/objects/pmSourcePhotometry.c	(revision 30118)
@@ -107,5 +107,5 @@
     // XXX handle negative flux, low-significance
     if (model->dparams->data.F32[PM_PAR_I0] > 0) {
-        SN = model->params->data.F32[PM_PAR_I0] / model->dparams->data.F32[PM_PAR_I0];
+        SN = fabs(model->params->data.F32[PM_PAR_I0] / model->dparams->data.F32[PM_PAR_I0]);
         source->errMag = 1.0 / SN;
     } else {
@@ -331,5 +331,5 @@
     }
     if (apFluxOut) *apFluxOut = apFlux;
-    if (apFluxErr) *apFluxErr = sqrt(apFluxVar);
+    if (apFluxErr) *apFluxErr = sqrt(fabs(apFluxVar));
 
     if (apFlux <= 0) {
Index: branches/czw_branch/20101203/psModules/src/objects/pmTrend2D.c
===================================================================
--- branches/czw_branch/20101203/psModules/src/objects/pmTrend2D.c	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/objects/pmTrend2D.c	(revision 30118)
@@ -179,5 +179,5 @@
 }
 
-bool pmTrend2DFit(pmTrend2D *trend, psVector *mask, psVectorMaskType maskVal, const psVector *x,
+bool pmTrend2DFit(bool *pGoodFit, pmTrend2D *trend, psVector *mask, psVectorMaskType maskVal, const psVector *x,
                   const psVector *y, const psVector *f, const psVector *df)
 {
@@ -188,5 +188,13 @@
     PS_ASSERT_VECTOR_NON_NULL(f, false);
 
-    bool status;
+    bool status = false;
+    *pGoodFit = false;
+    // for the psImageMap fit, it is possible to have valid data but no valid solution for
+    // example, an isolated cell may not be reached from other cells, making the solution
+    // degenerate.  psImageMapFit should probably handle this case, but until it does, we allow
+    // it to fail on the result, but not yield an error (pGoodFit = false).
+    // psVectorClipFitPolynomial2D can not fail in this way (really?), so pGoodFit is always
+    // true
+
     switch (trend->mode) {
       case PM_TREND_POLY_ORD:
@@ -196,4 +204,5 @@
         // of points in the image, and potentially based on the fractional range of the
         // data?
+	*pGoodFit = true;
         break;
 
@@ -201,5 +210,5 @@
         // XXX supply fraction from trend elements
         // XXX need to add the API which adjusts the scale
-        status = psImageMapClipFit(trend->map, trend->stats, mask, maskVal, x, y, f, df);
+        status = psImageMapClipFit(pGoodFit, trend->map, trend->stats, mask, maskVal, x, y, f, df);
         break;
 
Index: branches/czw_branch/20101203/psModules/src/objects/pmTrend2D.h
===================================================================
--- branches/czw_branch/20101203/psModules/src/objects/pmTrend2D.h	(revision 29965)
+++ branches/czw_branch/20101203/psModules/src/objects/pmTrend2D.h	(revision 30118)
@@ -76,5 +76,6 @@
     );
 
-bool pmTrend2DFit(pmTrend2D *trend,
+bool pmTrend2DFit(bool *goodFit,
+		  pmTrend2D *trend,
                   psVector *mask,       // Warning: mask is modified!
                   psVectorMaskType maskVal,
