Index: trunk/psModules/src/objects/pmSourceFitModel.c
===================================================================
--- trunk/psModules/src/objects/pmSourceFitModel.c	(revision 26070)
+++ trunk/psModules/src/objects/pmSourceFitModel.c	(revision 29004)
@@ -23,37 +23,47 @@
 #include "pmHDU.h"
 #include "pmFPA.h"
+
+#include "pmTrend2D.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
 #include "pmSpan.h"
+#include "pmFootprintSpans.h"
 #include "pmFootprint.h"
 #include "pmPeaks.h"
 #include "pmMoments.h"
-#include "pmGrowthCurve.h"
-#include "pmResiduals.h"
-#include "pmTrend2D.h"
-#include "pmPSF.h"
+#include "pmModelFuncs.h"
 #include "pmModel.h"
+#include "pmModelUtils.h"
+#include "pmModelClass.h"
+#include "pmSourceMasks.h"
+#include "pmSourceExtendedPars.h"
+#include "pmSourceDiffStats.h"
 #include "pmSource.h"
-#include "pmModelClass.h"
 #include "pmSourceFitModel.h"
 
-// save as static values so they may be set externally
-static psF32 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = 15;
-static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1;
-static psF32 PM_SOURCE_FIT_MODEL_WEIGHT = 1.0;
-static bool  PM_SOURCE_FIT_MODEL_PIX_WEIGHTS = true;
-
-bool pmSourceFitModelInit (float nIter, float tol, float weight, bool poissonErrors)
+void pmSourceFitOptionsFree(pmSourceFitOptions *opt)
 {
-
-    PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = nIter;
-    PM_SOURCE_FIT_MODEL_TOLERANCE = tol;
-    PM_SOURCE_FIT_MODEL_WEIGHT = weight;
-    PM_SOURCE_FIT_MODEL_PIX_WEIGHTS = poissonErrors;
-
-    return true;
+    return;
+}
+
+pmSourceFitOptions *pmSourceFitOptionsAlloc(void) {
+
+    pmSourceFitOptions *opt = (pmSourceFitOptions *) psAlloc(sizeof(pmSourceFitOptions));
+    psMemSetDeallocator(opt, (psFreeFunc) pmSourceFitOptionsFree);
+
+    opt->mode = PM_SOURCE_FIT_PSF;
+    opt->nIter  = 15;
+    opt->minTol = 0.01;
+    opt->maxTol = 1.00;
+    opt->weight = 1.00;
+    opt->maxChisqDOF = NAN;
+    opt->poissonErrors = true;
+
+    return opt;
 }
 
 bool pmSourceFitModel (pmSource *source,
                        pmModel *model,
-                       pmSourceFitMode mode,
+                       pmSourceFitOptions *options,
                        psImageMaskType maskVal)
 {
@@ -76,4 +86,9 @@
     psVector *yErr = psVectorAllocEmpty(nPix, PS_TYPE_F32);
 
+    // XXX for a test, skip the central pixel in the sersic fit
+    bool skipCenter = false && (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
+    float Xo = model->params->data.F32[PM_PAR_XPOS];
+    float Yo = model->params->data.F32[PM_PAR_YPOS];
+
     // fill in the coordinate and value entries
     nPix = 0;
@@ -95,14 +110,24 @@
             // skip nan values in image
             if (!isfinite(source->variance->data.F32[i][j])) {
-	      fprintf (stderr, "impossible! %x vs %x\n", source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[i][j], maskVal);
-	      continue;
-            }
-
-            psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
+		fprintf (stderr, "impossible! %x vs %x\n", source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[i][j], maskVal);
+		continue;
+            }
 
             // Convert i/j to image space:
 	    // 0.5 PIX: the coordinate values must be in pixel coords, not index	    
-            coord->data.F32[0] = (psF32) (j + 0.5 + source->pixels->col0);
-            coord->data.F32[1] = (psF32) (i + 0.5 + source->pixels->row0);
+            float Xv = (psF32) (j + 0.5 + source->pixels->col0);
+            float Yv = (psF32) (i + 0.5 + source->pixels->row0);
+
+	    // XXX possible skip of center pixel:
+	    if (skipCenter) {
+		float r = hypot(Xv - Xo, Yv - Yo);
+		if (r < 0.75) {
+		    continue;
+		}
+	    }
+
+            psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
+            coord->data.F32[0] = Xv;
+            coord->data.F32[1] = Yv;
             x->data[nPix] = (psPtr *) coord;
             y->data.F32[nPix] = source->pixels->data.F32[i][j];
@@ -111,8 +136,8 @@
             // as variance to avoid the bias from systematic errors here we would just use the
             // source sky variance
-            if (PM_SOURCE_FIT_MODEL_PIX_WEIGHTS) {
+            if (options->poissonErrors) {
                 yErr->data.F32[nPix] = 1.0 / source->variance->data.F32[i][j];
             } else {
-                yErr->data.F32[nPix] = 1.0 / PM_SOURCE_FIT_MODEL_WEIGHT;
+                yErr->data.F32[nPix] = 1.0 / options->weight;
             }
             nPix++;
@@ -133,6 +158,6 @@
     // set parameter mask based on fitting mode
     int nParams = 0;
-    switch (mode) {
-    case PM_SOURCE_FIT_NORM:
+    switch (options->mode) {
+      case PM_SOURCE_FIT_NORM:
         // NORM-only model fits only source normalization (Io)
         nParams = 1;
@@ -140,5 +165,5 @@
         constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
         break;
-    case PM_SOURCE_FIT_PSF:
+      case PM_SOURCE_FIT_PSF:
         // PSF model only fits x,y,Io
         nParams = 3;
@@ -148,5 +173,5 @@
         constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_YPOS] = 0;
         break;
-    case PM_SOURCE_FIT_EXT:
+      case PM_SOURCE_FIT_EXT:
         // EXT model fits all params (except sky)
         nParams = params->n - 1;
@@ -154,11 +179,33 @@
         constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
         break;
-    default:
-        psAbort("invalid fitting mode");
+      case PM_SOURCE_FIT_INDEX:
+        // PSF model only fits Io, index (PAR7) -- only Io for models with < 8 params
+	psVectorInit (constraint->paramMask, 1);
+	constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
+        if (params->n == 7) {
+	    nParams = 1;
+	} else {
+	    nParams = 2;
+	    constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_7] = 0;
+	}
+	break;
+      case PM_SOURCE_FIT_NO_INDEX:
+        // PSF model only fits Io, index (PAR7) -- only Io for models with < 8 params
+	psVectorInit (constraint->paramMask, 0);
+	constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
+        if (params->n == 7) {
+	    nParams = params->n - 1;
+	} else {
+	    nParams = params->n - 2;
+	    constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_7] = 1;
+	}
+	break;
+      default:
+	psAbort("invalid fitting mode");
     }
     // force the floating parameters to fall within the contraint ranges
     for (int i = 0; i < params->n; i++) {
-        model->modelLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL);
-        model->modelLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL);
+	model->modelLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL);
+	model->modelLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL);
     }
 
@@ -173,5 +220,5 @@
     }
 
-    psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_TOLERANCE);
+    psMinimization *myMin = psMinimizationAlloc (options->nIter, options->minTol, options->maxTol);
 
     psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
@@ -194,4 +241,5 @@
     model->flags |= PM_MODEL_STATUS_FITTED;
     if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE;
+    if (myMin->lastDelta > myMin->minTol) model->flags |= PM_MODEL_STATUS_WEAK_FIT;
 
     // get the Gauss-Newton distance for fixed model parameters
