Index: /tags/ipp-20101206/psLib/src/imageops/psImageMapFit.c
===================================================================
--- /tags/ipp-20101206/psLib/src/imageops/psImageMapFit.c	(revision 30032)
+++ /tags/ipp-20101206/psLib/src/imageops/psImageMapFit.c	(revision 30033)
@@ -48,8 +48,10 @@
 
 // map defines the output image dimensions and scaling.
-bool psImageMapFit(psImageMap *map, const psVector *mask, psVectorMaskType maskValue,
+bool psImageMapFit(bool *goodFit, psImageMap *map, const psVector *mask, psVectorMaskType maskValue,
                    const psVector *x, const psVector *y, const psVector *f, const psVector *df)
 {
     // XXX Add Asserts
+
+    *goodFit = false;
 
     // dimensions of the output map image
@@ -81,4 +83,5 @@
         map->map->data.F32[0][0]   = psStatsGetValue(map->stats, mean);
         map->error->data.F32[0][0] = psStatsGetValue(map->stats, stdev);
+	*goodFit = true;
         return true;
     }
@@ -86,10 +89,10 @@
     if (Nx == 1) {
         bool status;
-        status = psImageMapFit1DinY (map, mask, maskValue, x, y, f, df);
+        status = psImageMapFit1DinY (goodFit, map, mask, maskValue, x, y, f, df);
         return status;
     }
     if (Ny == 1) {
         bool status;
-        status = psImageMapFit1DinX (map, mask, maskValue, x, y, f, df);
+        status = psImageMapFit1DinX (goodFit, map, mask, maskValue, x, y, f, df);
         return status;
     }
@@ -310,8 +313,7 @@
 
     if (!psMatrixGJSolve(A, B)) {
-        psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.  Returning NULL.\n");
         psFree (A);
         psFree (B);
-        return false;
+        return true;
     }
 
@@ -337,9 +339,10 @@
     psFree (Empty);
 
+    *goodFit = true;
     return true;
 }
 
 // measure residuals on each pass and clip outliers based on stats
-bool psImageMapClipFit(psImageMap *map, psStats *stats, psVector *inMask, psVectorMaskType maskValue,
+bool psImageMapClipFit(bool *goodFit, psImageMap *map, psStats *stats, psVector *inMask, psVectorMaskType maskValue,
                        const psVector *x, const psVector *y, const psVector *f, const psVector *df)
 {
@@ -351,4 +354,6 @@
     psAssert(f, "impossible");
 
+    *goodFit = false;
+
     // the user supplies one of various stats option pairs,
     // determine the desired mean and stdev STATS options:
@@ -393,5 +398,5 @@
         psTrace("psLib.imageops", 6, "Loop iteration %d.  Calling psImageMapFit()\n", N);
         psS32 Nkeep = 0;
-        if (!psImageMapFit(map, mask, maskValue, x, y, f, df)) {
+        if (!psImageMapFit(goodFit, map, mask, maskValue, x, y, f, df)) {
             psError(PS_ERR_UNKNOWN, false, "Could not fit image map.\n");
             psFree(resid);
@@ -399,4 +404,8 @@
             return false;
         }
+	if (!goodFit) {
+	    psWarning ("bad fit to image map, try something else");
+	    return true;
+	}
 
         psVector *fit = psImageMapEvalVector(map, mask, maskValue, x, y);
@@ -454,13 +463,16 @@
     psFree(resid);
     if (!inMask) psFree (mask);
+    *goodFit = true; // XXX probably don't need to set this (set by psImageMapFit)
     return true;
 }
 
 // map defines the output image dimensions and scaling.
-bool psImageMapFit1DinY(psImageMap *map, const psVector *mask, psVectorMaskType maskValue,
+bool psImageMapFit1DinY(bool *goodFit, psImageMap *map, const psVector *mask, psVectorMaskType maskValue,
                         const psVector *x, const psVector *y, const psVector *f, const psVector *df)
 {
     // XXX Add Asserts
     assert (map->binning->nXruff == 1);
+
+    *goodFit = false;
 
     // dimensions of the output map image
@@ -578,9 +590,8 @@
 
     if (!psMatrixGJSolve(A, B)) {
-        psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.\n");
         psFree (A);
         psFree (B);
 	psFree (Empty);
-        return false;
+        return true;
     }
 
@@ -602,13 +613,16 @@
     psFree (Empty);
 
+    *goodFit = true;
     return true;
 }
 
 // map defines the output image dimensions and scaling.
-bool psImageMapFit1DinX(psImageMap *map, const psVector *mask, psVectorMaskType maskValue,
+bool psImageMapFit1DinX(bool *goodFit, psImageMap *map, const psVector *mask, psVectorMaskType maskValue,
                         const psVector *x, const psVector *y, const psVector *f, const psVector *df)
 {
     // XXX Add Asserts
     assert (map->binning->nYruff == 1);
+
+    *goodFit = false;
 
     // dimensions of the output map image
@@ -726,9 +740,8 @@
 
     if (!psMatrixGJSolve(A, B)) {
-        psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations..\n");
         psFree (A);
         psFree (B);
 	psFree (Empty);
-        return false;
+        return true;
     }
 
@@ -750,4 +763,5 @@
     psFree (Empty);
 
+    *goodFit = true;
     return true;
 }
Index: /tags/ipp-20101206/psLib/src/imageops/psImageMapFit.h
===================================================================
--- /tags/ipp-20101206/psLib/src/imageops/psImageMapFit.h	(revision 30032)
+++ /tags/ipp-20101206/psLib/src/imageops/psImageMapFit.h	(revision 30033)
@@ -8,5 +8,6 @@
 
 // fit the image map to a set of points
-bool psImageMapFit(psImageMap *map,
+bool psImageMapFit(bool *goodFit, 
+		   psImageMap *map,
                    const psVector *mask,
                    psVectorMaskType maskValue, // 
@@ -18,5 +19,6 @@
 
 // fit the image map to a set of points
-bool psImageMapClipFit(psImageMap *map,
+bool psImageMapClipFit(bool *goodFit, 
+		       psImageMap *map,
                        psStats *stats,
                        psVector *mask,  // WARNING: Mask is modified!
@@ -28,5 +30,6 @@
     );
 
-bool psImageMapFit1DinY(psImageMap *map,
+bool psImageMapFit1DinY(bool *goodFit, 
+			psImageMap *map,
                         const psVector *mask,
                         psVectorMaskType maskValue,
@@ -37,5 +40,6 @@
     );
 
-bool psImageMapFit1DinX(psImageMap *map,
+bool psImageMapFit1DinX(bool *goodFit, 
+			psImageMap *map,
                         const psVector *mask,
                         psVectorMaskType maskValue,
Index: /tags/ipp-20101206/psModules/src/objects/pmPSFtry.h
===================================================================
--- /tags/ipp-20101206/psModules/src/objects/pmPSFtry.h	(revision 30032)
+++ /tags/ipp-20101206/psModules/src/objects/pmPSFtry.h	(revision 30033)
@@ -100,5 +100,5 @@
 bool pmPSFtryFitEXT (pmPSFtry *psfTry, pmPSFOptions *options, psImageMaskType maskVal, psImageMaskType markVal);
 
-bool pmPSFtryMakePSF (pmPSFtry *psfTry);
+bool pmPSFtryMakePSF (bool *goodFit, 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 *goodFit, pmPSF *psf, psArray *sources, psVector *x, psVector *y, psVector *srcMask);
 
 float psVectorSystematicError (psVector *residuals, psVector *errors, float clipFraction);
Index: /tags/ipp-20101206/psModules/src/objects/pmPSFtryMakePSF.c
===================================================================
--- /tags/ipp-20101206/psModules/src/objects/pmPSFtryMakePSF.c	(revision 30032)
+++ /tags/ipp-20101206/psModules/src/objects/pmPSFtryMakePSF.c	(revision 30033)
@@ -50,5 +50,5 @@
 Note: some of the array entries may be NULL (failed fits); ignore them.
  *****************************************************************************/
-bool pmPSFtryMakePSF (pmPSFtry *psfTry)
+bool pmPSFtryMakePSF (bool *goodFit, 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 (goodFit, psf, psfTry->sources, x, y, srcMask)) {
         psFree(x);
         psFree(y);
         return false;
+    }
+    if (!goodFit) {
+	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 (goodFit, 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 (!goodFit) {
+	    // 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:
@@ -163,5 +178,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 *goodFit, 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 +234,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 (goodFit, trend, srcMask, 0xff, x, y, e0, NULL);
+	if (!goodFit) {
+	    psFree (e0);
+	    psFree (e1);
+	    psFree (e2);
+	    return true;
+	}
 	mean = psStatsGetValue (trend->stats, meanOption);
 	stdev = psStatsGetValue (trend->stats, stdevOption);
@@ -228,5 +249,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 (goodFit, trend, srcMask, 0xff, x, y, e1, NULL);
+	if (!goodFit) {
+	    psFree (e0);
+	    psFree (e1);
+	    psFree (e2);
+	    return true;
+	}
 	mean = psStatsGetValue (trend->stats, meanOption);
 	stdev = psStatsGetValue (trend->stats, stdevOption);
@@ -237,5 +264,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 (goodFit, trend, srcMask, 0xff, x, y, e2, NULL);
+	if (!goodFit) {
+	    psFree (e0);
+	    psFree (e1);
+	    psFree (e2);
+	    return true;
+	}
 	mean = psStatsGetValue (trend->stats, meanOption);
 	stdev = psStatsGetValue (trend->stats, stdevOption);
@@ -246,4 +279,7 @@
 	if (!status) {
 	    psError (PS_ERR_UNKNOWN, true, "failed to fit PSF shape params");
+	    psFree (e0);
+	    psFree (e1);
+	    psFree (e2);
 	    return false;
 	}
Index: /tags/ipp-20101206/psModules/src/objects/pmPSFtryModel.c
===================================================================
--- /tags/ipp-20101206/psModules/src/objects/pmPSFtryModel.c	(revision 30032)
+++ /tags/ipp-20101206/psModules/src/objects/pmPSFtryModel.c	(revision 30033)
@@ -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: /tags/ipp-20101206/psModules/src/objects/pmTrend2D.c
===================================================================
--- /tags/ipp-20101206/psModules/src/objects/pmTrend2D.c	(revision 30032)
+++ /tags/ipp-20101206/psModules/src/objects/pmTrend2D.c	(revision 30033)
@@ -179,5 +179,5 @@
 }
 
-bool pmTrend2DFit(pmTrend2D *trend, psVector *mask, psVectorMaskType maskVal, const psVector *x,
+bool pmTrend2DFit(bool *goodFit, 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;
+    *goodFit = 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 (goodFit = false).
+    // psVectorClipFitPolynomial2D can not fail in this way (really?), so goodFit 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?
+	*goodFit = 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(goodFit, trend->map, trend->stats, mask, maskVal, x, y, f, df);
         break;
 
Index: /tags/ipp-20101206/psModules/src/objects/pmTrend2D.h
===================================================================
--- /tags/ipp-20101206/psModules/src/objects/pmTrend2D.h	(revision 30032)
+++ /tags/ipp-20101206/psModules/src/objects/pmTrend2D.h	(revision 30033)
@@ -76,5 +76,6 @@
     );
 
-bool pmTrend2DFit(pmTrend2D *trend,
+bool pmTrend2DFit(bool *goodFit,
+		  pmTrend2D *trend,
                   psVector *mask,       // Warning: mask is modified!
                   psVectorMaskType maskVal,
Index: /tags/ipp-20101206/psphot/src/psphotApResid.c
===================================================================
--- /tags/ipp-20101206/psphot/src/psphotApResid.c	(revision 30032)
+++ /tags/ipp-20101206/psphot/src/psphotApResid.c	(revision 30033)
@@ -378,5 +378,12 @@
 
     // XXX test for errors here
-    if (!pmTrend2DFit (apTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft)) {
+    bool goodFit = false;
+    if (!pmTrend2DFit (&goodFit, apTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft)) {
+	// XXX this is probably a real error, and I should exit
+        psWarning("Failed to fit trend for %d x %d map", Nx, Ny);
+        psFree (apTrend);
+        return NULL;
+    }
+    if (!goodFit) {
         psWarning("Failed to fit trend for %d x %d map", Nx, Ny);
         psFree (apTrend);
Index: /tags/ipp-20101206/psphot/src/psphotMakeFluxScale.c
===================================================================
--- /tags/ipp-20101206/psphot/src/psphotMakeFluxScale.c	(revision 30032)
+++ /tags/ipp-20101206/psphot/src/psphotMakeFluxScale.c	(revision 30033)
@@ -55,6 +55,13 @@
     fPts->n = Npts;
 
-    if (!pmTrend2DFit (trend, NULL, 0xff, xPts, yPts, fPts, NULL)) {
+    // XXX we should allow the spatial sampling to decrease if the fit fails
+    bool goodFit = false;
+    if (!pmTrend2DFit (&goodFit, trend, NULL, 0xff, xPts, yPts, fPts, NULL)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to fit trend");
+        success = false;
+        goto DONE;
+    }
+    if (!goodFit) {
+        psError(PS_ERR_UNKNOWN, false, "poor fit to flux-scale trend");
         success = false;
         goto DONE;
