Index: /trunk/psModules/test/objects/.cvsignore
===================================================================
--- /trunk/psModules/test/objects/.cvsignore	(revision 10193)
+++ /trunk/psModules/test/objects/.cvsignore	(revision 10194)
@@ -4,3 +4,6 @@
 Makefile.in
 temp
-tap_*
+tap_pmGrowthCurve
+tap_pmSourceFitModel
+tap_pmSourceFitModel_Delta
+tap_pmSourcePhotometry
Index: /trunk/psModules/test/objects/Makefile.am
===================================================================
--- /trunk/psModules/test/objects/Makefile.am	(revision 10193)
+++ /trunk/psModules/test/objects/Makefile.am	(revision 10194)
@@ -18,5 +18,6 @@
 	tap_pmSourcePhotometry \
 	tap_pmGrowthCurve \
-	tap_pmSourceFitModel
+	tap_pmSourceFitModel \
+	tap_pmSourceFitModel_Delta
 
 test: check
Index: /trunk/psModules/test/objects/tap_pmSourceFitModel.c
===================================================================
--- /trunk/psModules/test/objects/tap_pmSourceFitModel.c	(revision 10193)
+++ /trunk/psModules/test/objects/tap_pmSourceFitModel.c	(revision 10194)
@@ -8,8 +8,12 @@
 
 bool fitModels (psRandom *seed, float flux, float radius, float sigma);
-
-// create a single source (sigma =
 bool fitModelFlux (psRandom *seed, float flux, float radius, float sigma);
 
+// tests to check accuracy of fitted models for a range of fit radii, sigma, and flux.
+// we generate a fake source, then fit the model to it.  the difference or fractional
+// difference between the true and fitted parameters is saved.
+// we run these tests 200 times each an examine the resulting distribution of deviations.
+// the tests fail if the stdevs are more than 2x the expected stdev based on poisson noise
+// ** is 2x too generous?
 int main (void)
 {
@@ -68,22 +72,13 @@
     psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
     psVectorStats (stats, par1, NULL, NULL, 0);
-    // fprintf (stderr, "Io: %f +/- %f : %f sig\n", stats->sampleMean, stats->sampleStdev, stats->sampleStdev/dMag);
     ok ((stats->sampleStdev/dMag < 2.0), "Io ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dMag);
     psVectorStats (stats, par2, NULL, NULL, 0);
-    // fprintf (stderr, "Xo: %f +/- %f : %f sig\n", stats->sampleMean, stats->sampleStdev, stats->sampleStdev/dPos);
     ok ((stats->sampleStdev/dPos < 2.0), "Xo ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dPos);
-    // ok_float_tol (stats->sampleStdev, 0.0, 0.0, "Xo ref-fit stdev: %f", stats->sampleStdev);
     psVectorStats (stats, par3, NULL, NULL, 0);
-    // fprintf (stderr, "Yo: %f +/- %f : %f sig\n", stats->sampleMean, stats->sampleStdev, stats->sampleStdev/dPos);
     ok ((stats->sampleStdev/dPos < 2.0), "Yo ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dPos);
-    // ok_float_tol (stats->sampleStdev, 0.0, 0.0, "Yo ref-fit stdev: %f", stats->sampleStdev);
     psVectorStats (stats, par4, NULL, NULL, 0);
-    // fprintf (stderr, "Sx: %f +/- %f : %f sig\n", stats->sampleMean, stats->sampleStdev, stats->sampleStdev/dMag);
     ok ((stats->sampleStdev/dMag < 2.0), "Sx ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dMag);
-    // ok_float_tol (stats->sampleStdev, 0.0, 0.0, "Sx ref/fit stdev: %f", stats->sampleStdev);
     psVectorStats (stats, par5, NULL, NULL, 0);
-    // fprintf (stderr, "Sy: %f +/- %f : %f sig\n", stats->sampleMean, stats->sampleStdev, stats->sampleStdev/dMag);
     ok ((stats->sampleStdev/dMag < 2.0), "Sy ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dMag);
-    // ok_float_tol (stats->sampleStdev, 0.0, 0.0, "Sy ref/fit stdev: %f", stats->sampleStdev);
 
     psFree (par1);
Index: /trunk/psModules/test/objects/tap_pmSourceFitModel_Delta.c
===================================================================
--- /trunk/psModules/test/objects/tap_pmSourceFitModel_Delta.c	(revision 10194)
+++ /trunk/psModules/test/objects/tap_pmSourceFitModel_Delta.c	(revision 10194)
@@ -0,0 +1,238 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+bool fitModels (psRandom *seed, float flux, float radius, float sigma);
+bool fitModelFlux (psRandom *seed, float flux, float radius, float sigma);
+bool printDev (float *src, float *par, int Npar, bool absolute);
+
+int main (void)
+{
+    pmModelGroupInit ();
+    pmSourceFitModelInit (15, 0.01, 1.0, true);
+
+    float flux = 10000;
+    float sigma = 2.0;
+    float radius = 10.0;
+
+    plan_tests(240);
+
+    // build a gauss-deviate vector (mean = 0.0, sigma = 1.0)
+    psRandom *seed = psRandomAlloc (PS_RANDOM_TAUS, 0);
+
+    // noise vector to noise up the image
+    psVector *rnd = psVectorAlloc (1000, PS_TYPE_F32);
+    for (int i = 0; i < rnd->n; i++) {
+        rnd->data.F32[i] = psRandomGaussian (seed);
+    }
+
+    // construct a GAUSS model
+    pmSource *source = pmSourceAlloc ();
+    source->moments = pmMomentsAlloc ();
+
+    pmModelType type = pmModelSetType ("PS_MODEL_GAUSS");
+    source->modelEXT = pmModelAlloc (type);
+
+    source->modelEXT->params->data.F32[0] = 0;
+    source->modelEXT->params->data.F32[1] = flux;
+    source->modelEXT->params->data.F32[2] = 50;
+    source->modelEXT->params->data.F32[3] = 50;
+    source->modelEXT->params->data.F32[4] = 2.0*sqrt(sigma);
+    source->modelEXT->params->data.F32[5] = 2.0*sqrt(sigma);
+    source->modelEXT->params->data.F32[6] = 0;
+
+    source->pixels = psImageAlloc (100, 100, PS_TYPE_F32);
+    source->weight = psImageAlloc (100, 100, PS_TYPE_F32);
+    source->mask   = psImageAlloc (100, 100, PS_TYPE_U8);
+    psImageInit (source->pixels, 0.0);
+    psImageInit (source->weight, 0.0);
+    psImageInit (source->mask, 0);
+
+    // create an image with the model, and add noise: gain is 1, subtracted sky is 100, readnoise is 5
+    pmModelAdd (source->pixels, source->mask, source->modelEXT, false, false);
+    int npix = 0;
+    for (int j = 0; j < source->pixels->numRows; j++) {
+        for (int i = 0; i < source->pixels->numCols; i++) {
+            float flux = source->pixels->data.F32[j][i];
+            float var = flux + 100 + PS_SQR(5);
+            source->pixels->data.F32[j][i] += rnd->data.F32[npix]*sqrt(var);
+            source->weight->data.F32[j][i] = var;
+            npix ++;
+            if (npix == rnd->n)
+                npix = 0;
+        }
+    }
+
+    // fit with a PGAUSS model
+    pmModel *guess;
+
+    type = pmModelSetType ("PS_MODEL_PGAUSS");
+    guess = pmModelAlloc (type);
+
+    guess->params->data.F32[0] = 0;
+    guess->params->data.F32[1] = flux;
+    guess->params->data.F32[2] = 50;
+    guess->params->data.F32[3] = 50;
+    guess->params->data.F32[4] = 2.0*sqrt(sigma);
+    guess->params->data.F32[5] = 2.0*sqrt(sigma);
+    guess->params->data.F32[6] = 0;
+    // modify guess
+    guess->params->data.F32[1] *= 0.9;
+    guess->params->data.F32[2] += 1.0;
+    guess->params->data.F32[3] -= 1.0;
+    guess->params->data.F32[4] *= 0.9;
+    guess->params->data.F32[5] *= 0.9;
+
+    psImageKeepCircle (source->mask, 50, 50, radius, "OR", PM_MASK_MARK);
+    pmSourceFitModel (source, guess, PM_SOURCE_FIT_EXT);
+    psImageKeepCircle (source->mask, 50, 50, radius, "AND", PS_NOT_U8(PM_MASK_MARK));
+
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 1, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 2, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 3, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 4, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 5, false);
+
+    psImageKeepCircle (source->mask, 50, 50, radius, "OR", PM_MASK_MARK);
+    pmSourceFitModel (source, guess, PM_SOURCE_FIT_PSF);
+    psImageKeepCircle (source->mask, 50, 50, radius, "AND", PS_NOT_U8(PM_MASK_MARK));
+
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 1, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 2, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 3, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 4, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 5, false);
+
+    // muck up the Sx, Sy terms a little : how does this affect the dparams?
+    float Sx = guess->params->data.F32[4];
+    float Sy = guess->params->data.F32[5];
+    guess->params->data.F32[4] = 0.95*Sx;
+    guess->params->data.F32[5] = 0.95*Sy;
+
+    psImageKeepCircle (source->mask, 50, 50, radius, "OR", PM_MASK_MARK);
+    pmSourceFitModel (source, guess, PM_SOURCE_FIT_PSF);
+    psImageKeepCircle (source->mask, 50, 50, radius, "AND", PS_NOT_U8(PM_MASK_MARK));
+
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 1, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 2, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 3, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 4, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 5, false);
+
+    // muck up the Sx, Sy terms a little : how does this affect the dparams?
+    guess->params->data.F32[4] = 0.99*Sx;
+    guess->params->data.F32[5] = 0.99*Sy;
+
+    psImageKeepCircle (source->mask, 50, 50, radius, "OR", PM_MASK_MARK);
+    pmSourceFitModel (source, guess, PM_SOURCE_FIT_PSF);
+    psImageKeepCircle (source->mask, 50, 50, radius, "AND", PS_NOT_U8(PM_MASK_MARK));
+
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 1, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 2, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 3, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 4, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 5, false);
+
+    psFree (rnd);
+    psFree (source);
+    psFree (guess);
+
+    return true;
+}
+
+bool printDev (float *src, float *fit, int Npar, bool absolute)
+{
+    float dev;
+    if (absolute) {
+        dev = (src[Npar]-fit[Npar]);
+        fprintf (stderr, "par %d : %f vs %f : abso dev %f\n", Npar, src[Npar], fit[Npar], dev);
+    } else {
+        dev = (src[Npar]/fit[Npar]);
+        fprintf (stderr, "par %d : %f vs %f : frac dev %f\n", Npar, src[Npar], fit[Npar], dev);
+    }
+    return true;
+}
+
+# if (0)
+    int main (void)
+{
+    pmModelGroupInit ();
+    pmSourceFitModelInit (15, 0.01, 1.0, true);
+
+    plan_tests(240);
+
+    // build a gauss-deviate vector (mean = 0.0, sigma = 1.0)
+    psRandom *seed = psRandomAlloc (PS_RANDOM_TAUS, 0);
+
+    static float radius[] = {3.0, 5.0, 7.0, 10.0, 15.0, 25.0};
+    static float sigma[] = {1.0, 1.5, 2.0};
+    static float flux[] = {10000.0, 3000.0, 1000.0, 300.0, 100.0, 30.0, 10.0};
+
+    for (int i = 0; i < sizeof(sigma)/sizeof(float); i++) {
+        for (int j = 0; j < sizeof(radius)/sizeof(float); j++) {
+            for (int k = 0; k < sizeof(flux)/sizeof(float); k++) {
+                fitModels (seed, flux[k], radius[j], sigma[i]);
+            }
+        }
+    }
+
+    return exit_status();
+}
+
+static psVector *par1 = NULL;
+static psVector *par2 = NULL;
+static psVector *par3 = NULL;
+static psVector *par4 = NULL;
+static psVector *par5 = NULL;
+
+bool fitModels (psRandom *seed, float flux, float radius, float sigma)
+{
+
+    psMemId id = psMemGetId();
+
+    diag("test model fit - flux: %f, radius: %f, sigma: %f", flux, radius, sigma);
+
+    par1 = psVectorAllocEmpty (200, PS_TYPE_F32);
+    par2 = psVectorAllocEmpty (200, PS_TYPE_F32);
+    par3 = psVectorAllocEmpty (200, PS_TYPE_F32);
+    par4 = psVectorAllocEmpty (200, PS_TYPE_F32);
+    par5 = psVectorAllocEmpty (200, PS_TYPE_F32);
+
+    for (int i = 0; i < 200; i++) {
+        fitModelFlux (seed, flux, radius, sigma);
+    }
+
+    float signal = 2*M_PI*sigma*sigma*flux;
+    float noise = sqrt(signal + 4*M_PI*sigma*sigma*(100 + PS_SQR(5)));
+    float dMag = noise / signal;
+    float dPos = sigma * dMag;
+    diag ("signal: %f, noise: %f, dMag: %f, dPos: %f", signal, noise, dMag, dPos);
+
+    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+    psVectorStats (stats, par1, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dMag < 2.0), "Io ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dMag);
+    psVectorStats (stats, par2, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dPos < 2.0), "Xo ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dPos);
+    psVectorStats (stats, par3, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dPos < 2.0), "Yo ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dPos);
+    psVectorStats (stats, par4, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dMag < 2.0), "Sx ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dMag);
+    psVectorStats (stats, par5, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dMag < 2.0), "Sy ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dMag);
+
+    psFree (par1);
+    psFree (par2);
+    psFree (par3);
+    psFree (par4);
+    psFree (par5);
+    psFree (stats);
+
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    return true;
+}
+
+# endif
