Index: trunk/psModules/test/objects/Makefile.am
===================================================================
--- trunk/psModules/test/objects/Makefile.am	(revision 15715)
+++ trunk/psModules/test/objects/Makefile.am	(revision 15726)
@@ -11,5 +11,26 @@
 	$(PSMODULES_LIBS)
 
-TEST_PROGS =
+TEST_PROGS = \
+	tap_pmPeaks \
+	tap_pmGrowthCurve \
+	tap_pmGrowthCurve02 \
+	tap_pmMoments \
+	tap_pmSource \
+	tap_pmModel \
+	tap_pmModelUtils \
+	tap_pmModelClass \
+	tap_pmPSF \
+	tap_pmTrend2D \
+	tap_pmResiduals \
+	tap_pmSourceExtendedPars \
+	tap_pmSourceSky \
+	tap_pmSourceIO_PS1_DEV_0 \
+	tap_pmSourceIO_PS1_DEV_1 \
+	tap_pmSourceIO_SMPDATA \
+	tap_pmSourceContour \
+	tap_pmSourceUtils \
+	tap_pmSourceFitSet \
+	tap_pmPSF_IO \
+	tap_pmSourceIO_SMPDATA
 
 if BUILD_TESTS
Index: trunk/psModules/test/objects/tap_pmFringe.c
===================================================================
--- trunk/psModules/test/objects/tap_pmFringe.c	(revision 15715)
+++ trunk/psModules/test/objects/tap_pmFringe.c	(revision 15726)
@@ -129,3 +129,2 @@
     }
 }
-//HERE
Index: trunk/psModules/test/objects/tap_pmGrowthCurve.c
===================================================================
--- trunk/psModules/test/objects/tap_pmGrowthCurve.c	(revision 15715)
+++ trunk/psModules/test/objects/tap_pmGrowthCurve.c	(revision 15726)
@@ -3,18 +3,80 @@
 #include <pslib.h>
 #include <psmodules.h>
-
 #include "tap.h"
 #include "pstap.h"
 
-int main (void)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         10
+
+int main(int argc, char* argv[])
 {
-    pmModelGroupInit ();
-
-    plan_tests(57);
-
-    diag("pmGrowthCurve tests");
-
-    // test allocation
-    diag("offset of 0.0,0.0 wrt growth ref source");
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(15);
+
+    // ----------------------------------------------------------------------
+    // pmGrowthCurveAlloc() tests
+    // call pmGrowthCurveAlloc() with acceptable input parameters.
+    {
+        psMemId id = psMemGetId();
+        pmGrowthCurve *growthCurve = pmGrowthCurveAlloc(1.0, 2.0, 3.0);
+        ok(growthCurve && psMemCheckGrowthCurve(growthCurve), "pmGrowthCurveAlloc() allocated a pmGrowthCurve correctly");
+        ok(growthCurve->radius && psMemCheckVector(growthCurve->radius), "pmGrowthCurveAlloc() allocated the radius psVector correctly");
+        ok(growthCurve->apMag  && psMemCheckVector(growthCurve->apMag) &&
+           growthCurve->apMag->n == growthCurve->radius->n, "pmGrowthCurveAlloc() allocated the apMag psVector correctly");
+        ok(growthCurve->refRadius == 3.0, "pmGrowthCurveAlloc() set growthCurve->refRadius correctly");
+        ok(growthCurve->maxRadius == 2.0, "pmGrowthCurveAlloc() set growthCurve->maxRadius correctly");
+        ok(growthCurve->apLoss == 0.0, "pmGrowthCurveAlloc() set growthCurve->apLoss correctly");
+        ok(growthCurve->fitMag == 0.0, "pmGrowthCurveAlloc() set growthCurve->fitMag correctly");
+        psFree(growthCurve);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmGrowthCurveCorrect() tests
+    // Call pmGrowthCurveCorrect() with NULL input pmGrowthCurve
+    {
+        psMemId id = psMemGetId();
+        pmGrowthCurve *growthCurve = pmGrowthCurveAlloc(1.0, 2.0, 3.0);
+        ok(isnan(pmGrowthCurveCorrect(NULL, 0.0)), "pmGrowthCurveCorrect() returned NAN with NULL input pmGrowthCurve");
+        psFree(growthCurve);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call pmGrowthCurveCorrect() with bad type for input pmGrowthCurve arg
+    // XX: This is commented out for now because we are not asserting, inside
+    // pmGrowthCurveCorrect(), that input parameters are of the correct type.
+    if (0) {
+        psMemId id = psMemGetId();
+        pmGrowthCurve *growthCurve = pmGrowthCurveAlloc(1.0, 2.0, 3.0);
+        psVector *junkVec = psVectorAlloc(10, PS_TYPE_F32);
+        ok(isnan(pmGrowthCurveCorrect((pmGrowthCurve *) junkVec, 0.0)), "pmGrowthCurveCorrect() returned NAN with NULL input pmGrowthCurve");
+        psFree(growthCurve);
+        psFree(junkVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmGrowthCurveCorrect() with acceptable input parameters.
+    {
+        #define RADIUS 0.5
+        psMemId id = psMemGetId();
+        pmGrowthCurve *growthCurve = pmGrowthCurveAlloc(1.0, 2.0, 3.0);
+        float testCor = pmGrowthCurveCorrect(growthCurve, RADIUS);
+        float actRad = psVectorInterpolate (growthCurve->radius, growthCurve->apMag, RADIUS);
+        float actCor = growthCurve->apRef - actRad;
+
+        ok(!isnan(testCor), "pmGrowthCurveCorrect() call was successful");
+        ok(actCor == testCor, "pmGrowthCurveCorrect() calculated the correction correctly");
+
+        psFree(growthCurve);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // EM test 01: test allocation
+    // offset of 0.0,0.0 wrt growth ref source
     {
         psMemId id = psMemGetId();
@@ -43,8 +105,9 @@
 
         // generate a simple psf
-        pmPSF *psf = pmPSFBuildSimple ("PS_MODEL_GAUSS", 1.5, 1.5, 0.0);
+        pmModelClassInit();
+        pmPSF *psf = pmPSFBuildSimple("PS_MODEL_GAUSS", 1.5, 1.5, 0.0);
         psf->growth = growth;
 
-        pmGrowthCurveGenerate (readout, psf, false);
+        pmGrowthCurveGenerate(readout, psf, false, 0, 0);
 
         // check ap mags for a few radii set by hand
@@ -71,5 +134,5 @@
         source->type = PM_SOURCE_TYPE_STAR;
         source->pixels = psMemIncrRefCounter (readout->image);
-        source->mask = psMemIncrRefCounter (readout->mask);
+        source->maskObj = psMemIncrRefCounter (readout->mask);
 
         source->modelPSF->dparams->data.F32[PM_PAR_I0] = 1;
@@ -77,29 +140,30 @@
 
         source->modelPSF->radiusFit = 15.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         double refMag = source->apMag;
 
         source->modelPSF->radiusFit = 10.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 8.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 6.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0003, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 4.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0020, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 3.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, -0.0001, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 2.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, -0.0075, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
@@ -116,6 +180,7 @@
     }
 
-    // test allocation
-    diag("offset of 0.2,0.2 wrt growth ref source");
+
+    // EM test 02: test allocation
+    // offset of 0.2,0.2 wrt growth ref source
     {
         psMemId id = psMemGetId();
@@ -147,5 +212,5 @@
         psf->growth = growth;
 
-        pmGrowthCurveGenerate (readout, psf, false);
+        pmGrowthCurveGenerate (readout, psf, false, 0, 0);
 
         // check ap mags for a few radii set by hand
@@ -172,5 +237,5 @@
         source->type = PM_SOURCE_TYPE_STAR;
         source->pixels = psMemIncrRefCounter (readout->image);
-        source->mask = psMemIncrRefCounter (readout->mask);
+        source->maskObj = psMemIncrRefCounter (readout->mask);
 
         source->modelPSF->dparams->data.F32[PM_PAR_I0] = 1;
@@ -178,29 +243,29 @@
 
         source->modelPSF->radiusFit = 15.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         double refMag = source->apMag;
 
         source->modelPSF->radiusFit = 10.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 8.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 6.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0004, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 4.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0026, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 3.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, -0.0001, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 2.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, -0.0103, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
@@ -217,6 +282,7 @@
     }
 
-    // test allocation
-    diag("offset of 0.4,0.4 wrt growth ref source");
+
+    // EM test 03: test allocation
+    // offset of 0.4,0.4 wrt growth ref source
     {
         psMemId id = psMemGetId();
@@ -248,5 +314,5 @@
         psf->growth = growth;
 
-        pmGrowthCurveGenerate (readout, psf, false);
+        pmGrowthCurveGenerate(readout, psf, false, 0, 0);
 
         // check ap mags for a few radii set by hand
@@ -273,5 +339,5 @@
         source->type = PM_SOURCE_TYPE_STAR;
         source->pixels = psMemIncrRefCounter (readout->image);
-        source->mask = psMemIncrRefCounter (readout->mask);
+        source->maskObj = psMemIncrRefCounter (readout->mask);
 
         source->modelPSF->dparams->data.F32[PM_PAR_I0] = 1;
@@ -279,29 +345,29 @@
 
         source->modelPSF->radiusFit = 15.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         double refMag = source->apMag;
 
         source->modelPSF->radiusFit = 10.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 8.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 6.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0006, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 4.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0038, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 3.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
         source->modelPSF->radiusFit = 2.0;
-        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
         ok_float_tol(refMag - source->apMag, -0.0164, 0.0001, "growth offset is is %f", refMag - source->apMag);
 
@@ -317,5 +383,4 @@
         ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
     }
-
-    return exit_status();
 }
+
Index: trunk/psModules/test/objects/tap_pmModel.c
===================================================================
--- trunk/psModules/test/objects/tap_pmModel.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmModel.c	(revision 15726)
@@ -0,0 +1,265 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8+1)
+#define TEST_NUM_COLS           (8+1)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define NUM_ROWS		8
+#define NUM_COLS		16
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(1);
+
+    // ----------------------------------------------------------------------
+    // pmModelAlloc() tests
+    // call pmModelAlloc() with unallowable model class type
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(-1);
+        ok(model == NULL, "pmModelAlloc() returned a NULL with unallowable model class type");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelAlloc() with acceptable input params
+    {
+        #define TEST_MODEL_CLASS_TYPE 1
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        ok(model != NULL && psMemCheckModel(model), "pmModelAlloc() returned a non-NULL pmModel");
+        skip_start(!model, 1, "Skipping tests because pmModelAlloc() returned NULL");
+        ok(model->type == TEST_MODEL_CLASS_TYPE, "pmModelAlloc() set pmModel->type correctly");
+        ok(model->chisq == 0.0, "pmModelAlloc() set pmModel->chisq correctly");
+        ok(model->nDOF == 0, "pmModelAlloc() set pmModel->nDOF correctly");
+        ok(model->nIter == 0, "pmModelAlloc() set pmModel->nIter correctly");
+        ok(model->radiusFit == 0, "pmModelAlloc() set pmModel->radiusFit correctly");
+        ok(model->flags == PM_MODEL_STATUS_NONE, "pmModelAlloc() set pmModel->flags correctly");
+        ok(model->residuals == NULL, "pmModelAlloc() set pmModel->residuals correctly");
+        int nParams = pmModelClassParameterCount(TEST_MODEL_CLASS_TYPE);
+        ok(model->params != NULL && model->params->n == nParams, "pmModelAlloc() set the pmModel->params psVector correctly");
+        ok(model->dparams != NULL && model->dparams->n == nParams, "pmModelAlloc() set the pmModel->dparams psVector correctly");
+        bool errorFlag = false;
+        for (psS32 i = 0; i < nParams; i++) {
+            if (model->params->data.F32[i] != 0.0 || model->dparams->data.F32[i] != 0.0) {
+                if (VERBOSE) {
+                    diag("ERROR: params/dparams[%d] is (%.2f %.2f) should be (%.2f %.2f)\n", i, model->params->data.F32[i], model->dparams->data.F32[i], 0.0, 0.0);
+		}
+                errorFlag = true;
+	    }
+        }
+        ok(!errorFlag, "pmModelAlloc() set the members of the model->params and model->dparams psVectors correctly");
+        pmModelClass *class = pmModelClassSelect(TEST_MODEL_CLASS_TYPE);
+        ok(model->modelFunc == class->modelFunc, "pmModelAlloc() set pmModel->modelFunc correctly");
+        ok(model->modelFlux == class->modelFlux, "pmModelAlloc() set pmModel->modelFlux correctly");
+        ok(model->modelRadius == class->modelRadius, "pmModelAlloc() set pmModel->modelRadius correctly");
+        ok(model->modelLimits == class->modelLimits, "pmModelAlloc() set pmModel->modelLimits correctly");
+        ok(model->modelGuess == class->modelGuess, "pmModelAlloc() set pmModel->modelGuess correctly");
+        ok(model->modelFromPSF == class->modelFromPSF, "pmModelAlloc() set pmModel->modelFromPSF correctly");
+        ok(model->modelParamsFromPSF == class->modelParamsFromPSF, "pmModelAlloc() set pmModel->modelParamsFromPSF correctly");
+        ok(model->modelFitStatus == class->modelFitStatus, "pmModelAlloc() set pmModel->modelFitStatus correctly");
+
+        psFree(model);
+        skip_end();
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmModelCopy() tests
+    // call pmModelCopy() with NULL input pmModel parameter
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelCopy(NULL);
+        ok(model == NULL, "pmModelCopy() returned NULL with NULL input pmModel parameter");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // call pmModelCopy() with acceptable input params
+    {
+        #define TEST_MODEL_CLASS_TYPE 1
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *modelSrc = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        ok(modelSrc != NULL && psMemCheckModel(modelSrc), "pmModelAlloc() returned a non-NULL pmModel");
+        modelSrc->chisq = 1.0;
+        modelSrc->nDOF = 2;
+        modelSrc->nIter = 3;
+        modelSrc->flags = PM_MODEL_STATUS_NONE;
+        modelSrc->radiusFit = 4;
+        pmModel *modelDst = pmModelCopy(modelSrc);
+        ok(modelDst != NULL && psMemCheckModel(modelDst), "pmModelCopy() returned a non-NULL pmModel");
+        ok(modelDst->chisq == 1.0, "pmModelCopy() set the pmModel->chisq member correctly");
+        ok(modelDst->nDOF == 2, "pmModelCopy() set the pmModel->nDOF member correctly");
+        ok(modelDst->nIter == 3, "pmModelCopy() set the pmModel->nIter member correctly");
+        ok(modelDst->flags == PM_MODEL_STATUS_NONE, "pmModelCopy() set the pmModel->flags member correctly");
+        ok(modelDst->radiusFit == 4, "pmModelCopy() set the pmModel->radiusFit member correctly");
+
+        psFree(modelSrc);
+        psFree(modelDst);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmModelEval() tests
+    // psF32 pmModelEval(pmModel *model, psImage *image, psS32 col, psS32 row)
+    // call pmModelEval() with NULL input pmModel parameter
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psF32 tmpF;
+        tmpF = pmModelEval(NULL, img, 0, 0);
+        ok(isnan(tmpF), "pmModelEval() returned NAN with NULL input pmModel parameter");
+        psFree(model);
+        psFree(img);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psF32 pmModelEval(pmModel *model, psImage *image, psS32 col, psS32 row)
+    // call pmModelEval() with NULL input psImage parameter
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psF32 tmpF;
+        tmpF = pmModelEval(model, NULL, 0, 0);
+        ok(isnan(tmpF), "pmModelEval() returned NAN with NULL input psImage parameter");
+        psFree(model);
+        psFree(img);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psF32 pmModelEval(pmModel *model, psImage *image, psS32 col, psS32 row)
+    // call pmModelEval() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < NUM_ROWS ; i++) {
+            for (int j = 0 ; j < NUM_COLS ; j++) {
+                img->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+        x->data.F32[0] = (float) (NUM_COLS / 2);
+        x->data.F32[1] = (float) (NUM_ROWS / 2);
+        psF32 testF = model->modelFunc (NULL, model->params, x);
+        psF32 tmpF;
+        tmpF = pmModelEval(model, img, (int) x->data.F32[0], (int) x->data.F32[1]);
+        ok(!isnan(tmpF), "pmModelEval() returned successfully");
+        ok(testF == tmpF, "pmModelEval() evaluated the model correctly");
+        psFree(model);
+        psFree(img);
+        psFree(x);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmModelEvalWithOffset() tests
+    // psF32 pmModelEvalWithOffsetWithOffset(pmModel *model, psImage *image, 
+    //                             psS32 col, psS32 row, int dx, int dy)
+    // call pmModelEvalWithOffset() with NULL input pmModel parameter
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psF32 tmpF;
+        tmpF = pmModelEvalWithOffset(NULL, img, 0, 0, 0, 0);
+        ok(isnan(tmpF), "pmModelEvalWithOffset() returned NAN with NULL input pmModel parameter");
+        psFree(model);
+        psFree(img);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psF32 pmModelEvalWithOffsetWithOffset(pmModel *model, psImage *image, 
+    //                             psS32 col, psS32 row, int dx, int dy)
+    // call pmModelEvalWithOffset() with NULL input psImage parameter
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psF32 tmpF;
+        tmpF = pmModelEvalWithOffset(model, NULL, 0, 0, 0, 0);
+        ok(isnan(tmpF), "pmModelEvalWithOffset() returned NAN with NULL input psImage parameter");
+        psFree(model);
+        psFree(img);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psF32 pmModelEvalWithOffset(pmModel *model, psImage *image, psS32 col, psS32 row)
+    // call pmModelEvalWithOffset() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < NUM_ROWS ; i++) {
+            for (int j = 0 ; j < NUM_COLS ; j++) {
+                img->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+        x->data.F32[0] = (float) ((NUM_COLS / 2) + (NUM_COLS / 4));
+        x->data.F32[1] = (float) ((NUM_ROWS / 2) + (NUM_ROWS / 4));
+        psF32 testF = model->modelFunc (NULL, model->params, x);
+        psF32 tmpF;
+        tmpF = pmModelEvalWithOffset(model, img, (int) x->data.F32[0], (int) x->data.F32[1], NUM_COLS/4, NUM_ROWS/4);
+        ok(!isnan(tmpF), "pmModelEvalWithOffset() returned successfully");
+        ok(testF == tmpF, "pmModelEvalWithOffset() evaluated the model correctly");
+        psFree(model);
+        psFree(img);
+        psFree(x);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: trunk/psModules/test/objects/tap_pmModelClass.c
===================================================================
--- trunk/psModules/test/objects/tap_pmModelClass.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmModelClass.c	(revision 15726)
@@ -0,0 +1,173 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8+1)
+#define TEST_NUM_COLS           (8+1)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#include "models/pmModel_GAUSS.c"
+#include "models/pmModel_PGAUSS.c"
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(1);
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassAlloc()
+    // pmModelClass *pmModelClassAlloc (int nModels)
+    {
+        psMemId id = psMemGetId();
+        pmModelClass *modelClass = pmModelClassAlloc(4);
+        ok(modelClass != NULL && psMemCheckModelClass(modelClass), "pmModelClassAlloc() returned a non-NULL pmModelClass");
+        psFree(modelClass);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassCleanup()
+    // Basically, call pmModelClassInit(), then pmModelClassCleanup(), and ensure that
+    // various default models are not there.
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModelClassCleanup();
+        ok(NULL == pmModelClassSelect(0), "pmModelClassCleanup(): removed PS_MODEL_GAUSS");
+        ok(NULL == pmModelClassSelect(1), "pmModelClassCleanup(): removed PS_MODEL_PGAUSS");
+        ok(NULL == pmModelClassSelect(2), "pmModelClassCleanup(): removed PS_MODEL_QGAUSS");
+        ok(NULL == pmModelClassSelect(3), "pmModelClassCleanup(): removed PS_MODEL_RGAUSS");
+        ok(NULL == pmModelClassSelect(4), "pmModelClassCleanup(): removed PS_MODEL_SERSIC");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassInit(), pmModelClassGetName()
+    // Basically, call pmModelClassCleanup(), then pmModelClassInit() and ensure that
+    // various default models are there.
+    {
+        psMemId id = psMemGetId();
+
+        pmModelClassCleanup();
+        ok(pmModelClassInit(), "pmModelClassInit() returned TRUE");
+        ok(!strcmp(pmModelClassGetName(0), "PS_MODEL_GAUSS"), "pmModelClassInit() added pmModel PS_MODEL_GAUSS");
+        ok(!strcmp(pmModelClassGetName(1), "PS_MODEL_PGAUSS"), "pmModelClassInit() added pmModel PS_MODEL_PGAUSS");
+        ok(!strcmp(pmModelClassGetName(2), "PS_MODEL_QGAUSS"), "pmModelClassInit() added pmModel PS_MODEL_QGAUSS");
+        ok(!strcmp(pmModelClassGetName(3), "PS_MODEL_RGAUSS"), "pmModelClassInit() added pmModel PS_MODEL_RGAUSS");
+        ok(!strcmp(pmModelClassGetName(4), "PS_MODEL_SERSIC"), "pmModelClassInit() added pmModel PS_MODEL_SERSIC");
+        ok(!pmModelClassInit(), "pmModelClassInit() returned FALSE (2nd time)");
+        ok(NULL == pmModelClassGetName(-1), "pmModelClassGetName(-1) returned NULL");
+        ok(NULL == pmModelClassGetName(1000), "pmModelClassGetName(1000) returned NULL");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassGetType()
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        ok(-1 == pmModelClassGetType("BOGUS"), "pmModelClassGetType(BOGUS) returned -1");
+        ok(0 == pmModelClassGetType("PS_MODEL_GAUSS"), "pmModelClassGetType(PS_MODEL_GAUSS) successful");
+        ok(1 == pmModelClassGetType("PS_MODEL_PGAUSS"), "pmModelClassGetType(PS_MODEL_PGAUSS) successful");
+        ok(2 == pmModelClassGetType("PS_MODEL_QGAUSS"), "pmModelClassGetType(PS_MODEL_QGAUSS) successful");
+        ok(3 == pmModelClassGetType("PS_MODEL_RGAUSS"), "pmModelClassGetType(PS_MODEL_RGAUSS) successful");
+        ok(4 == pmModelClassGetType("PS_MODEL_SERSIC"), "pmModelClassGetType(PS_MODEL_SERSIC) successful");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassParameterCount()
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        ok(0 == pmModelClassParameterCount(-1), "pmModelClassParameterCount(-1) returned 0");
+        ok(0 == pmModelClassParameterCount(1000), "pmModelClassParameterCount(1000) returned 0");
+        ok(7 == pmModelClassParameterCount(0), "pmModelClassParameterCount(0) returned 7");
+        ok(7 == pmModelClassParameterCount(1), "pmModelClassParameterCount(1) returned 7");
+        ok(8 == pmModelClassParameterCount(2), "pmModelClassParameterCount(2) returned 8");
+        ok(8 == pmModelClassParameterCount(3), "pmModelClassParameterCount(3) returned 8");
+        ok(8 == pmModelClassParameterCount(4), "pmModelClassParameterCount(4) returned 8");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassSelect()
+    // pmModelClass *pmModelClassSelect (pmModelType type)
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModelClass *model = NULL;
+        model = pmModelClassSelect(-1);
+        ok(model == NULL, "pmModelClassSelect(-1) successful");
+        model = pmModelClassSelect(1000);
+        ok(model == NULL, "pmModelClassSelect(1000) successful");
+        model = pmModelClassSelect(0);
+        ok(model != NULL && !strcmp(model->name, "PS_MODEL_GAUSS"), "pmModelClassSelect(0) successful");
+        model = pmModelClassSelect(1);
+        ok(model != NULL && !strcmp(model->name, "PS_MODEL_PGAUSS"), "pmModelClassSelect(1) successful");
+        model = pmModelClassSelect(2);
+        ok(model != NULL && !strcmp(model->name, "PS_MODEL_QGAUSS"), "pmModelClassSelect(2) successful");
+        model = pmModelClassSelect(3);
+        ok(model != NULL && !strcmp(model->name, "PS_MODEL_RGAUSS"), "pmModelClassSelect(3) successful");
+        model = pmModelClassSelect(4);
+        ok(model != NULL && !strcmp(model->name, "PS_MODEL_SERSIC"), "pmModelClassSelect(4) successful");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassAdd()
+    // We create a new modelClass, then add it, then ensure that it exists.
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModelClass *newModel = pmModelClassAlloc(1);
+        newModel->name = psStringCopy("PS_MODEL_NEW00");
+        newModel->nParams = 22;
+        pmModelClassAdd(newModel);
+        int ID = pmModelClassGetType("PS_MODEL_NEW00");
+        ok(ID != -1 && !strcmp("PS_MODEL_NEW00", pmModelClassGetName(ID)), "pmModelClassAdd() added the new model successfully");
+        psFree(newModel->name);
+        psFree(newModel);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: trunk/psModules/test/objects/tap_pmModelUtils.c
===================================================================
--- trunk/psModules/test/objects/tap_pmModelUtils.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmModelUtils.c	(revision 15726)
@@ -0,0 +1,200 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define NUM_ROWS		8
+#define NUM_COLS		16
+#define TEST_MODEL_CLASS_TYPE 1
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(46);
+
+    // ----------------------------------------------------------------------
+    // pmModelFromPSF() tests
+    // pmModel *pmModelFromPSF (pmModel *modelEXT, pmPSF *psf)
+    // call pmModelFromPSF() with NULL pmModel input parameter
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+        pmModel *tmpModel = pmModelFromPSF(NULL, psf);
+        ok(tmpModel == NULL, "pmModelFromPSF() returned NULL with NULL pmModel input parameter");
+        psFree(model);
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelFromPSF() with NULL pmPSF input parameter
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+        pmModel *tmpModel = pmModelFromPSF(model, NULL);
+        ok(tmpModel == NULL, "pmModelFromPSF() returned NULL with NULL pmPSF input parameter");
+        psFree(model);
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelFromPSF() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+        pmModel *tmpModel = pmModelFromPSF(model, psf);
+        ok(tmpModel != NULL, "pmModelFromPSF() returned non-NULL with acceptable input parameters");
+
+        pmModel *testModelPSF = pmModelAlloc(psf->type);
+        model->modelFromPSF(testModelPSF, model, psf);
+        ok(tmpModel->type == testModelPSF->type, "pmModelFromPSF() set the model->type correctly");
+        ok(tmpModel->chisq == testModelPSF->chisq, "pmModelFromPSF() set the model->chisq correctly");
+        ok(tmpModel->chisqNorm == testModelPSF->chisqNorm, "pmModelFromPSF() set the model->chisqNorm correctly");
+        ok(tmpModel->nDOF == testModelPSF->nDOF, "pmModelFromPSF() set the model->nDOF correctly");
+        ok(tmpModel->nIter == testModelPSF->nIter, "pmModelFromPSF() set the model->nIter correctly");
+        ok(tmpModel->flags == testModelPSF->flags, "pmModelFromPSF() set the model->flags correctly");
+        ok(tmpModel->radiusFit == testModelPSF->radiusFit, "pmModelFromPSF() set the model->radiusFit correctly");
+        ok(tmpModel->modelFunc == testModelPSF->modelFunc, "pmModelFromPSF() set the model->modelFunc correctly");
+        ok(tmpModel->modelFlux == testModelPSF->modelFlux, "pmModelFromPSF() set the model->modelFlux correctly");
+        ok(tmpModel->modelRadius == testModelPSF->modelRadius, "pmModelFromPSF() set the model->modelRadius correctly");
+        ok(tmpModel->modelLimits == testModelPSF->modelLimits, "pmModelFromPSF() set the model->modelLimits correctly");
+        ok(tmpModel->modelGuess == testModelPSF->modelGuess, "pmModelFromPSF() set the model->modelGuess correctly");
+        ok(tmpModel->modelFromPSF == testModelPSF->modelFromPSF, "pmModelFromPSF() set the model->modelFromPSF correctly");
+        ok(tmpModel->modelParamsFromPSF == testModelPSF->modelParamsFromPSF, "pmModelFromPSF() set the model->modelParamsFromPSF correctly");
+        ok(tmpModel->modelFitStatus == testModelPSF->modelFitStatus, "pmModelFromPSF() set the model->modelFitStatus correctly");
+
+        psFree(testModelPSF);
+        psFree(tmpModel);
+        psFree(model);
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmModelFromPSFforXY() tests
+    // pmModel *pmModelFromPSFforXY (pmPSF *psf, float Xo, float Yo, float Io)
+    // call pmModelFromPSFforXY() with NULL pmPSF input parameter
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+        pmModel *tmpModel = pmModelFromPSFforXY(NULL, 1.0, 2.0, 3.0);
+        ok(tmpModel == NULL, "pmModelFromPSFforXY() returned NULL with NULL pmPSF input parameter");
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelFromPSFforXY() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+
+        pmModel *testModelPSF = pmModelAlloc (psf->type);
+        testModelPSF->modelParamsFromPSF(testModelPSF, psf, 1.0, 2.0, 3.0);
+
+        pmModel *tmpModel = pmModelFromPSFforXY(psf, 1.0, 2.0, 3.0);
+        ok(tmpModel != NULL, "pmModelFromPSFforXY() returned non-NULL with acceptable input parameters");
+
+        ok(tmpModel->type == testModelPSF->type, "pmModelFromPSF() set the model->type correctly");
+        ok(tmpModel->chisq == testModelPSF->chisq, "pmModelFromPSF() set the model->chisq correctly");
+        ok(TEST_FLOATS_EQUAL(tmpModel->chisqNorm, testModelPSF->chisqNorm), "pmModelFromPSF() set the model->chisqNorm correctly");
+        ok(tmpModel->nDOF == testModelPSF->nDOF, "pmModelFromPSF() set the model->nDOF correctly");
+        ok(tmpModel->nIter == testModelPSF->nIter, "pmModelFromPSF() set the model->nIter correctly");
+        ok(tmpModel->flags == testModelPSF->flags, "pmModelFromPSF() set the model->flags correctly");
+        ok(tmpModel->radiusFit == testModelPSF->radiusFit, "pmModelFromPSF() set the model->radiusFit correctly");
+        ok(tmpModel->modelFunc == testModelPSF->modelFunc, "pmModelFromPSF() set the model->modelFunc correctly");
+        ok(tmpModel->modelFlux == testModelPSF->modelFlux, "pmModelFromPSF() set the model->modelFlux correctly");
+        ok(tmpModel->modelRadius == testModelPSF->modelRadius, "pmModelFromPSF() set the model->modelRadius correctly");
+        ok(tmpModel->modelLimits == testModelPSF->modelLimits, "pmModelFromPSF() set the model->modelLimits correctly");
+        ok(tmpModel->modelGuess == testModelPSF->modelGuess, "pmModelFromPSF() set the model->modelGuess correctly");
+        ok(tmpModel->modelFromPSF == testModelPSF->modelFromPSF, "pmModelFromPSF() set the model->modelFromPSF correctly");
+        ok(tmpModel->modelParamsFromPSF == testModelPSF->modelParamsFromPSF, "pmModelFromPSF() set the model->modelParamsFromPSF correctly");
+        ok(tmpModel->modelFitStatus == testModelPSF->modelFitStatus, "pmModelFromPSF() set the model->modelFitStatus correctly");
+
+        psFree(tmpModel);
+        psFree(testModelPSF);
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmModelSetFlux() tests
+    // bool pmModelSetFlux(pmModel *model, float flux) {
+    // call pmModelSetFlux() with NULL pmPSF input parameter
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        bool rc = pmModelSetFlux(NULL, 1.0);
+        ok(!rc, "pmModelSetFlux(() returned FALSE with NULL pmModel input parameter");
+        psFree(model);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelSetFlux() with acceptable input parameters
+    // XXX: We should probably test with more input values
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        model->params->data.F32[PM_PAR_SXX] = 1.0;
+        model->params->data.F32[PM_PAR_SYY] = 1.0;
+        model->params->data.F32[PM_PAR_SXY] = 1.0;
+
+        // Compute the test flux value
+        float tmpF = model->params->data.F32[PM_PAR_I0];
+        model->params->data.F32[PM_PAR_I0] = 1.0;
+        float testFlux = model->modelFlux (model->params);
+        testFlux = 1.0 / testFlux;    
+        model->params->data.F32[PM_PAR_I0] = tmpF;
+
+        bool rc = pmModelSetFlux(model, 1.0);
+        ok(rc, "pmModelSetFlux(() returned TRUE with acceptable input parameters");
+        ok(TEST_FLOATS_EQUAL(testFlux, model->params->data.F32[PM_PAR_I0]), "pmModelSetFlux() set the flux correctly");
+        psFree(model);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: trunk/psModules/test/objects/tap_pmMoments.c
===================================================================
--- trunk/psModules/test/objects/tap_pmMoments.c	(revision 15715)
+++ trunk/psModules/test/objects/tap_pmMoments.c	(revision 15726)
@@ -32,3 +32,2 @@
     }
 }
-
Index: trunk/psModules/test/objects/tap_pmPSF.c
===================================================================
--- trunk/psModules/test/objects/tap_pmPSF.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmPSF.c	(revision 15726)
@@ -0,0 +1,189 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/*
+Tested:
+    pmPSFOptions *pmPSFOptionsAlloc()
+    pmPSF *pmPSFAlloc (pmPSFOptions *options)
+    bool psMemCheckPSF(psPtr ptr)
+Must test:
+    double pmPSF_SXYfromModel (psF32 *modelPar)
+    double pmPSF_SXYtoModel (psF32 *fittedPar)
+    bool pmGrowthCurveGenerate (pmReadout *readout, pmPSF *psf, bool ignore, psMas!
+    pmPSF *pmPSFBuildSimple (char *typeName, float sxx, float syy, float sxy, ...)
+    bool pmPSF_AxesToModel (psF32 *modelPar, psEllipseAxes axes)
+    bool pmPSF_FitToModel (psF32 *fittedPar, float minMinorAxis)
+    psEllipsePol pmPSF_ModelToFit (psF32 *modelPar)
+    psEllipseAxes pmPSF_ModelToAxes (psF32 *modelPar, double maxAR)
+*/
+
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         10
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(15);
+
+    // ----------------------------------------------------------------------
+    // pmPSFOptionsAlloc() tests
+    // pmPSFOptions *pmPSFOptionsAlloc()
+    {
+        psMemId id = psMemGetId();
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        ok(psfOptions != NULL && psMemCheckPSFOptions(psfOptions), "pmPSFOptionsAlloc() returned non-NULL");
+        ok(psfOptions->type == 0, "pmPSFOptionsAlloc set pmPSFOptions->type ");
+        ok(psfOptions->stats == NULL, "pmPSFOptionsAlloc set pmPSFOptions->stats ");
+        ok(psfOptions->psfTrendMode == PM_TREND_NONE, "pmPSFOptionsAlloc set pmPSFOptions->psfTrendMode ");
+        ok(psfOptions->psfTrendNx == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfTrendNx ");
+        ok(psfOptions->psfTrendNy == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfTrendNy ");
+        ok(psfOptions->psfFieldNx == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfFieldNx ");
+        ok(psfOptions->psfFieldNy == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfFieldNy ");
+        ok(psfOptions->psfFieldXo == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfFieldXo ");
+        ok(psfOptions->psfFieldYo == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfFieldYo ");
+        ok(psfOptions->poissonErrorsPhotLMM == true, "pmPSFOptionsAlloc set pmPSFOptions->poissonErrorsPhotLMM ");
+        ok(psfOptions->poissonErrorsPhotLin == false, "pmPSFOptionsAlloc set pmPSFOptions->poissonErrorsPhotLin ");
+        ok(psfOptions->poissonErrorsParams  == true, "pmPSFOptionsAlloc set pmPSFOptions->poissonErrorsParams ");
+        psFree(psfOptions);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSFAlloc() tests
+    // call pmPSFAlloc() with NULL input parameters
+    #define TEST_POISSON_ERRORS true
+    {
+        psMemId id = psMemGetId();
+        pmPSF *psf = pmPSFAlloc(NULL);
+        ok(psf == NULL, "pmPSFAlloc() returned NULL with NULL input parameters");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmPSFAlloc() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->psfTrendNx = 1;
+        psfOptions->psfTrendNy = 2;
+        psfOptions->psfFieldNx = 3;
+        psfOptions->psfFieldNy = 4;
+        psfOptions->psfFieldXo = 5;
+        psfOptions->psfFieldYo = 6;
+        pmModelClassInit();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+        ok(psf != NULL && psMemCheckPSF(psf), "pmPSFAlloc() returned non-NULL");
+        ok(psf->type == psfOptions->type, "pmPSFAlloc() set the pmPSF->type correctly");
+        ok(psf->chisq == 0.0, "pmPSFAlloc() set the pmPSF->chisq correctly");
+        ok(psf->ApResid == 0.0, "pmPSFAlloc() set the pmPSF->ApResid correctly");
+        ok(psf->dApResid == 0.0, "pmPSFAlloc() set the pmPSF->dApResid correctly");
+        ok(psf->skyBias == 0.0, "pmPSFAlloc() set the pmPSF->skyBias correctly");
+        ok(psf->skySat == 0.0, "pmPSFAlloc() set the pmPSF->skySat correctly");
+        ok(psf->nPSFstars == 0, "pmPSFAlloc() set the pmPSF->nPSFstars correctly");
+        ok(psf->nApResid == 0, "pmPSFAlloc() set the pmPSF->nApResid correctly");
+        int Nparams = pmModelClassParameterCount(psfOptions->type);
+        ok(psf->params != NULL &&
+           psMemCheckArray(psf->params) &&
+           psf->params->n == Nparams, "pmPSFAlloc() set the pmPSF->params correctly");
+        ok(psf->poissonErrorsPhotLMM == psfOptions->poissonErrorsPhotLMM, "pmPSFAlloc() set the pmPSF->poissonErrorsPhotLMM");
+        ok(psf->poissonErrorsPhotLin == psfOptions->poissonErrorsPhotLin, "pmPSFAlloc() set the pmPSF->poissonErrorsPhotLin");
+        ok(psf->poissonErrorsParams == psfOptions->poissonErrorsParams, "pmPSFAlloc() set the pmPSF->poissonErrorsParams");
+        ok(psf->ApTrend == NULL, "pmPSFAlloc() set the pmPSF->ApTrend");
+        ok(psf->FluxScale == NULL, "pmPSFAlloc() set the pmPSF->FluxScale");
+        ok(psf->growth == NULL, "pmPSFAlloc() set the pmPSF->growth");
+        ok(psf->residuals == NULL, "pmPSFAlloc() set the pmPSF->residuals");
+        ok(psf->psfTrendMode == psfOptions->psfTrendMode, "pmPSFAlloc() set the pmPSF->psfTrendMode");
+        ok(psf->trendNx == psfOptions->psfTrendNx, "pmPSFAlloc() set the pmPSF->trendNx (%d %d)", psf->trendNx, psfOptions->psfTrendNx);
+        ok(psf->trendNy == psfOptions->psfTrendNy, "pmPSFAlloc() set the pmPSF->trendNy (%d %d)", psf->trendNy, psfOptions->psfTrendNy);
+        ok(psf->fieldNx == psfOptions->psfFieldNx, "pmPSFAlloc() set the pmPSF->fieldNx");
+        ok(psf->fieldNy == psfOptions->psfFieldNy, "pmPSFAlloc() set the pmPSF->fieldNy");
+        ok(psf->fieldXo == psfOptions->psfFieldXo, "pmPSFAlloc() set the pmPSF->fieldXo");
+        ok(psf->fieldYo == psfOptions->psfFieldYo, "pmPSFAlloc() set the pmPSF->fieldYo");
+        ok(psf->ApTrend == NULL, "pmPSFAlloc() set the pmPSF->ApTrend correctly");
+        ok(psf->FluxScale == NULL, "pmPSFAlloc() set the pmPSF->FluxScale correctly");
+
+        if (psf->poissonErrorsPhotLMM) {
+            ok(psf->ChiTrend->nX == 1, "pmPSFAlloc() set the pmPSF->ChiTrend correctly");
+	} else {
+            ok(psf->ChiTrend->nX == 2, "pmPSFAlloc() set the pmPSF->ChiTrend correctly");
+	}
+        ok(psf->growth == NULL, "pmPSFAlloc() set the pmPSF->growth correctly");
+        ok(psf->residuals == NULL, "pmPSFAlloc() set the pmPSF->residuals correctly");
+        ok(psf->params != NULL && psMemCheckArray(psf->params) && psf->params->n == Nparams, 
+           "pmPSFAlloc() set the pmPSF->params psVector correctly");
+
+        pmModelClassCleanup();
+        psFree(psf);
+        psFree(psfOptions);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSF_SXYfromModel() tests
+    // double pmPSF_SXYfromModel (psF32 *modelPar)
+    // Call pmPSF_SXYfromModel() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        double tmpD = pmPSF_SXYfromModel(NULL);
+        ok(isnan(tmpD), "pmPSF_SXYfromModel() returned NULL with NULL input parameters");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSF_SXYfromModel() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        psF32 modelPar[20];
+        modelPar[PM_PAR_SXX] = 2.0;
+        modelPar[PM_PAR_SYY] = 3.0;
+        modelPar[PM_PAR_SXY] = 5.0;
+        double SXX = modelPar[PM_PAR_SXX];
+        double SYY = modelPar[PM_PAR_SYY];
+        double SXY = modelPar[PM_PAR_SXY];
+        psF32 verF = SXY / PS_SQR(1.0 / PS_SQR(SXX) + 1.0 / PS_SQR(SYY));
+        psF32 testF = pmPSF_SXYfromModel(modelPar);
+        ok(verF == testF, "pmPSF_SXYfromModel() calculated correctly");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSF_SXYtoModel() tests
+    // double pmPSF_SXYtoModel (psF32 *modelPar)
+    // Call pmPSF_SXYtoModel() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        double tmpD = pmPSF_SXYtoModel(NULL);
+        ok(isnan(tmpD), "pmPSF_SXYtoModel() returned NULL with NULL input parameters");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSF_SXYtoModel() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        psF32 fittedPar[20];
+        fittedPar[PM_PAR_SXX] = 2.0;
+        fittedPar[PM_PAR_SYY] = 3.0;
+        fittedPar[PM_PAR_SXY] = 5.0;
+        double SXX = fittedPar[PM_PAR_SXX];
+        double SYY = fittedPar[PM_PAR_SYY];
+        double fit = fittedPar[PM_PAR_SXY];
+        double verF = fit * PS_SQR(1.0 / PS_SQR(SXX) + 1.0 / PS_SQR(SYY));
+        psF32 testF = pmPSF_SXYtoModel(fittedPar);
+        ok(TEST_FLOATS_EQUAL(verF, testF), "pmPSF_SXYtoModel() calculated correctly (%f %f)", verF, testF);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+}
Index: trunk/psModules/test/objects/tap_pmPSF_IO.c
===================================================================
--- trunk/psModules/test/objects/tap_pmPSF_IO.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmPSF_IO.c	(revision 15726)
@@ -0,0 +1,477 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_MODELS		5
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = generateSimpleReadout(cell);
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+//    psRegion *region = psRegionAlloc(0.0, TEST_NUM_COLS-1, 0.0, TEST_NUM_ROWS-1);
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = generateSimpleCell(chip);
+    }
+
+    // XXX: Add code to initialize chip pmConcepts
+
+
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = generateSimpleChip(fpa);
+    }
+
+    // XXX: Eventually, when you finish the pmConcepts tests, add full concept
+    // reading code from wherever.
+    pmConceptsBlankFPA(fpa);
+//    bool mdok;
+//    psMetadata *fileData = psMetadataLookupMetadata(&mdok, fpa->hdu->format, "FILE");
+//    char *fpaNameHdr = psMetadataLookupStr(&mdok, fileData, "FPA.NAME");
+//    psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.NAME", PS_META_REPLACE, NULL, fpaNameHdr);
+
+    return(fpa);
+}
+
+// XXX: This should only be necessary until the psFree() functions for
+// FPA/chip/cell/readout correctly free all child chips/cells/readouts
+void myFreeCell(pmCell *cell)
+{
+    for (int k = 0 ; k < cell->readouts->n ; k++) {
+        psFree(cell->readouts->data[k]);
+    }
+    psFree(cell);
+}
+
+void myFreeChip(pmChip *chip) {
+    for (int j = 0 ; j < chip->cells->n ; j++) {
+        myFreeCell(chip->cells->data[j]);
+    }
+    psFree(chip);
+}
+
+void myFreeFPA(pmFPA *fpa)
+{
+    for (int i = 0 ; i < fpa->chips->n ; i++) {
+        myFreeChip(fpa->chips->data[i]);
+    }
+    psFree(fpa);
+}
+
+
+
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(22);
+
+
+    // ----------------------------------------------------------------------
+    // pmPSFmodelCheckDataStatusForView() tests
+    // bool pmPSFmodelCheckDataStatusForView (const pmFPAview *view, const pmFPAfile *file)
+    // Call pmPSFmodelCheckDataStatusForView() with NULL pmFPAview input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        bool rc = pmPSFmodelCheckDataStatusForView(NULL, file);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForView() returned FALSE with NULL pmFPAview input parameter");
+        psFree(view);
+        psFree(file);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelCheckDataStatusForView() with NULL pmFPAfile input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        bool rc = pmPSFmodelCheckDataStatusForView(view, NULL);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForView() returned FALSE with NULL pmFPAfile input parameter");
+        psFree(view);
+        psFree(file);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelCheckDataStatusForView() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+
+        pmFPAview *view = pmFPAviewAlloc(32);
+        view->chip = -1;
+        view->cell = -1;
+        pmFPAfile *file = pmFPAfileAlloc();
+        psMetadata *camera = psMetadataAlloc();
+        file->fpa = generateSimpleFPA(camera);
+        bool rc = pmPSFmodelCheckDataStatusForView(view, file);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForView() returned FALSE acceptable input parameters, but no PSPHOT.PSF");
+
+        // Add PSPHOT.PSF to chip->analysis and call pmPSFmodelCheckDataStatusForChip()
+        pmChip *chip = file->fpa->chips->data[0];
+        psVector *junk = psVectorAlloc(10, PS_TYPE_F32);
+        bool rc2 = psMetadataAddPtr(chip->analysis, PS_LIST_HEAD, "PSPHOT.PSF", PS_DATA_VECTOR, NULL, junk);
+        ok(rc2 == true, "added PSPHOT.PSF metadata to chip->analysis");
+        rc = pmPSFmodelCheckDataStatusForView(view, file);
+        ok(rc == true, "pmPSFmodelCheckDataStatusForView() returned TRUE acceptable input parameters");
+
+        psFree(view);
+        myFreeFPA(file->fpa);
+        file->fpa = NULL;
+        psFree(file);
+        psFree(camera);
+        psFree(junk);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSFmodelCheckDataStatusForFPA() tests
+    // bool pmPSFmodelCheckDataStatusForFPA (const pmFPA *fpa)
+    // Call pmPSFmodelCheckDataStatusForFPA() with NULL pmFPA input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        bool rc = pmPSFmodelCheckDataStatusForFPA(NULL);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForFPA() returned FALSE with NULL pmFPA input parameter");
+        myFreeFPA(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelCheckDataStatusForFPA() with NULL pmFPA->chips input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        for (int i = 0 ; i < fpa->chips->n ; i++) {
+            myFreeChip(fpa->chips->data[i]);
+	}
+        bool rc = pmPSFmodelCheckDataStatusForFPA(NULL);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForFPA() returned FALSE with NULL pmFPA->chips input parameter");
+        myFreeFPA(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelCheckDataStatusForFPA() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        bool rc = pmPSFmodelCheckDataStatusForFPA(fpa);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForFPA() returned FALSE with acceptable input parameters, but no PSPHOT.PSF");
+
+        // Add PSPHOT.PSF to chip->analysis and call pmPSFmodelCheckDataStatusForChip()
+        psVector *junk = psVectorAlloc(10, PS_TYPE_F32);
+        pmChip *chip = fpa->chips->data[0];
+        bool rc2 = psMetadataAddPtr(chip->analysis, PS_LIST_HEAD, "PSPHOT.PSF", PS_DATA_VECTOR, NULL, junk);
+        ok(rc2 == true, "added PSPHOT.PSF metadata to chip->analysis");
+        rc = pmPSFmodelCheckDataStatusForFPA(fpa);
+        ok(rc == true, "pmPSFmodelCheckDataStatusForFPA() returned TRUE with acceptable input parameters");
+
+        myFreeFPA(fpa);
+        psFree(camera);
+        psFree(junk);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSFmodelCheckDataStatusForChip() tests
+    // bool pmPSFmodelCheckDataStatusForChip (const pmChip *chip)
+    // Call pmPSFmodelCheckDataStatusForChip() with NULL pmChip input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        bool rc = pmPSFmodelCheckDataStatusForChip(NULL);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForChip() returned FALSE with NULL pmChip input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelCheckDataStatusForChip() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        bool rc = pmPSFmodelCheckDataStatusForChip(chip);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForChip() returned false with acceptable pmChip, but no PSPHOT.PSF");
+
+        // Add PSPHOT.PSF to chip->analysis and call pmPSFmodelCheckDataStatusForChip()
+        psVector *junk = psVectorAlloc(10, PS_TYPE_F32);
+        bool rc2 = psMetadataAddPtr(chip->analysis, PS_LIST_HEAD, "PSPHOT.PSF", PS_DATA_VECTOR, NULL, junk);
+        ok(rc2 == true, "added PSPHOT.PSF metadata to chip->analysis");
+        rc = pmPSFmodelCheckDataStatusForChip(chip);
+        ok(rc == true, "pmPSFmodelCheckDataStatusForChip() returned TRUE with acceptable input parameters");
+    
+        myFreeFPA(fpa);
+        psFree(camera);
+        psFree(junk);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSFmodelWrite() tests
+    // bool pmPSFmodelWrite (psMetadata *analysis, const pmFPAview *view,
+    //                       pmFPAfile *file, const pmConfig *config)
+    // Call pmPSFmodelWrite() with NULL pmFPAview input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        psMetadata *camera = psMetadataAlloc();
+        file->fpa = generateSimpleFPA(camera);
+        psMetadata *analysis = psMetadataAlloc();
+        pmConfig *config = pmConfigAlloc();
+
+        bool rc = pmPSFmodelWrite(analysis, NULL, file, config);
+        ok(rc == false, "pmPSFmodelWrite() returned FALSE with NULL pmFPAview input parameter");
+
+        psFree(view);
+        myFreeFPA(file->fpa);
+        file->fpa = NULL;
+        psFree(file);
+        psFree(camera);
+        psFree(analysis);
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelWrite() with NULL pmFPAfile input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        psMetadata *camera = psMetadataAlloc();
+        file->fpa = generateSimpleFPA(camera);
+        psMetadata *analysis = psMetadataAlloc();
+        pmConfig *config = pmConfigAlloc();
+
+        bool rc = pmPSFmodelWrite(analysis, view, NULL, config);
+        ok(rc == false, "pmPSFmodelWrite() returned FALSE with NULL pmFPAfile input parameter");
+
+        psFree(view);
+        myFreeFPA(file->fpa);
+        file->fpa = NULL;
+        psFree(file);
+        psFree(camera);
+        psFree(analysis);
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelWrite() with NULL pmFPAfile->file input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        psMetadata *analysis = psMetadataAlloc();
+        pmConfig *config = pmConfigAlloc();
+
+        bool rc = pmPSFmodelWrite(analysis, view, NULL, config);
+        ok(rc == false, "pmPSFmodelWrite() returned FALSE with NULL pmFPAfile->fpa input parameter");
+
+        psFree(view);
+        psFree(file);
+        psFree(analysis);
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelWrite() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        psMetadata *camera = psMetadataAlloc();
+        file->fpa = generateSimpleFPA(camera);
+        psMetadata *analysis = psMetadataAlloc();
+        pmConfig *config = pmConfigAlloc();
+
+        // XXX: I failed here and then moved on.
+        /*
+        The function reads the PSPHOT recipes and requires that it contains a
+	PSPHOT key in the metadata.  I'm not sure how to do that, but I could
+	have hacked around it.  Then, however, it required several keys in
+	that metadata like PSF.CLUMP.X, PSF.CLUMP.Y, PSF.CLUMP.DX,
+	PSF.CLUMP.DY.  I could also put them in there, but I just gave up.
+	What should I do here?  I could easily create a metadata file with all
+	those metadata keys, but I'd rather use an existing one.
+        */
+
+        if (0) {
+            psMetadata *junk = psMetadataAlloc();
+            bool rc0 = pmConfigFileRead(&junk, "../dataFiles/recipes/psphot.config", "SAVE.PSF");
+            if (!rc0) {
+                rc0 = pmConfigFileRead(&junk, "dataFiles/recipes/psphot.config", "SAVE.PSF");
+	    }
+            ok(rc0, "Successfully read the PSPHOT recipe file");
+//          psMetadata *recipe = psMetadataLookupPtr(&rc0, junk, "SAVE.OUTPUT");
+            bool rc2 = psMetadataLookupBool(&rc0, junk, "SAVE.OUTPUT");
+            printf("rc0 is %d\n", (int) rc0);
+            printf("rc2 is %d\n", (int) rc2);
+//          if (recipe == NULL) printf("ERROR: recipe is NULL\n");
+            psMetadataPrint(stdout, junk, 0);
+            psFree(junk);
+	}
+        bool rc0 = pmConfigFileRead(&config->recipes, "../dataFiles/recipes/psphot.config", "SAVE.PSF");
+        if (!rc0) {
+            rc0 = pmConfigFileRead(&config->recipes, "dataFiles/recipes/psphot.config", "SAVE.PSF");
+	}
+        ok(rc0, "Successfully read the PSPHOT recipe file");
+
+        bool rc = pmPSFmodelWrite(analysis, view, file, config);
+        ok(rc == true, "pmPSFmodelWrite() returned TRUE with acceptable input parameters");
+
+        psFree(view);
+        myFreeFPA(file->fpa);
+        file->fpa = NULL;
+        psFree(file);
+        psFree(camera);
+        psFree(analysis);
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: trunk/psModules/test/objects/tap_pmPeaks.c
===================================================================
--- trunk/psModules/test/objects/tap_pmPeaks.c	(revision 15715)
+++ trunk/psModules/test/objects/tap_pmPeaks.c	(revision 15726)
@@ -14,4 +14,11 @@
 Must test
     pmCullPeaks()
+	Doesn't exist
+    pmPeakTest()
+	Get rid of this
+    pmPeakSortBySN()
+	Easy
+    pmPeakSortByY()
+	Easy
 */
 
@@ -698,5 +705,4 @@
         ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
     }
-//HERE
 }
 
Index: trunk/psModules/test/objects/tap_pmResiduals.c
===================================================================
--- trunk/psModules/test/objects/tap_pmResiduals.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmResiduals.c	(revision 15726)
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(35);
+
+
+    // Test pmFringeRegionsAlloc()
+    // pmResiduals *pmResidualsAlloc (int xSize, int ySize, int xBin, int yBin);
+    {
+        psMemId id = psMemGetId();
+        int xSize = 1;
+        int ySize = 2;
+        int xBin = 3;
+        int yBin = 4;
+        pmResiduals *resid = pmResidualsAlloc(xSize, ySize, xBin, yBin);
+        ok(resid != NULL && psMemCheckResiduals(resid), "pmResidualsAlloc() allocated a pmResiduals struct correctly");
+        ok(resid->Ro && psMemCheckImage(resid->Ro), "pmResidualsAlloc() allocated the resid->Ro image");
+        ok(resid->Rx && psMemCheckImage(resid->Rx), "pmResidualsAlloc() allocated the resid->Rx image");
+        ok(resid->Ry && psMemCheckImage(resid->Ry), "pmResidualsAlloc() allocated the resid->Ry image");
+        ok(resid->weight && psMemCheckImage(resid->weight), "pmResidualsAlloc() allocated the resid->weight image");
+        ok(resid->mask && psMemCheckImage(resid->mask), "pmResidualsAlloc() allocated the resid->mask image");
+
+        int nX = xSize * xBin;
+        int nY = ySize * yBin;
+        nX = (nX % 2) ? nX : nX + 1;
+        nY = (nY % 2) ? nY : nY + 1;
+        ok(resid->xBin == xBin, "pmResidualsAlloc() set resid->xBin correctly");
+        ok(resid->yBin == yBin, "pmResidualsAlloc() set resid->yBin correctly");
+        ok(resid->xCenter == 0.5*(nX - 1), "pmResidualsAlloc() set resid->xCenter correctly");
+        ok(resid->yCenter == 0.5*(nY - 1), "pmResidualsAlloc() set resid->xCenter correctly");
+
+        psFree(resid);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: trunk/psModules/test/objects/tap_pmSource.c
===================================================================
--- trunk/psModules/test/objects/tap_pmSource.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmSource.c	(revision 15726)
@@ -0,0 +1,560 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/*
+Tested:
+    pmSourceAlloc()
+    psMemCheckSource()
+    pmSourceCopy()
+    pmSourceDefinePixels()
+    pmSourceRedefinePixels()
+    pmSourcePSFClump()
+    pmSourceGetModel()
+Must Test:
+    pmSourceFreePixels()
+    pmSourceTest()
+    pmSourceRoughClass()
+    pmSourceMoments()
+    pmSourceAdd()
+    pmSourceSub()
+    pmSourceAddWithOffset()
+    pmSourceSubWithOffset()
+    pmSourceOp()
+    pmSourceCacheModel()
+    pmSourceCachePSF()
+*/
+
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8+1)
+#define TEST_NUM_COLS           (8+1)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(1);
+
+    // ----------------------------------------------------------------------
+    // Test pmSourceAlloc()
+    // pmSource *pmSourceAlloc();
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        ok(src != NULL && psMemCheckSource(src), "pmSourceAlloc() returned a non-NULL pmSource");
+        skip_start(src == NULL, 24, "Skipping tests because pmSourceAlloc() returned NULL");
+        ok(src->peak == NULL, "pmSourceAlloc() pmSource->peak correctly");
+        ok(src->pixels == NULL, "pmSourceAlloc() pmSource->pixels correctly");
+        ok(src->weight == NULL, "pmSourceAlloc() pmSource->weight correctly");
+        ok(src->maskObj == NULL, "pmSourceAlloc() pmSource->maskObj correctly");
+        ok(src->maskView == NULL, "pmSourceAlloc() pmSource->maskView correctly");
+        ok(src->modelFlux == NULL, "pmSourceAlloc() pmSource->modelFlux correctly");
+        ok(src->psfFlux == NULL, "pmSourceAlloc() pmSource->psfFlux correctly");
+        ok(src->moments == NULL, "pmSourceAlloc() pmSource->moments correctly");
+        ok(src->blends == NULL, "pmSourceAlloc() pmSource->blends correctly");
+        ok(src->modelPSF == NULL, "pmSourceAlloc() pmSource->modelPSF correctly");
+        ok(src->modelEXT == NULL, "pmSourceAlloc() pmSource->modelEXT correctly");
+        ok(src->modelConv == NULL, "pmSourceAlloc() pmSource->modelConv correctly");
+        ok(src->type == PM_SOURCE_TYPE_UNKNOWN, "pmSourceAlloc() pmSource->type correctly");
+        ok(src->mode == PM_SOURCE_MODE_DEFAULT, "pmSourceAlloc() pmSource->mode correctly");
+
+        ok(isnan(src->psfMag), "pmSourceAlloc() pmSource->psfMag correctly");
+        ok(isnan(src->extMag), "pmSourceAlloc() pmSource->extMag correctly");
+        ok(isnan(src->errMag), "pmSourceAlloc() pmSource->errMag correctly");
+        ok(isnan(src->apMag), "pmSourceAlloc() pmSource->apMag correctly");
+        ok(isnan(src->sky), "pmSourceAlloc() pmSource->sky correctly");
+        ok(isnan(src->skyErr), "pmSourceAlloc() pmSource->skyErr correctly");
+        ok(isnan(src->pixWeight), "pmSourceAlloc() pmSource->pixWeight correctly");
+        int srcID = src->id;
+        psFree(src);
+
+        // Allocate another pmSource to ensure that pmSource->id is incremented
+        pmSource *src = pmSourceAlloc();
+        ok(src != NULL, "pmSourceAlloc() returned a non-NULL pmSource");
+        ok(src->id == srcID+1, "pmSourceAlloc() incremented the pmSource->id correctly");
+        psFree(src);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceCopy() tests
+    // Call pmSourceCopy() with NULL input
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceCopy(NULL);
+        ok(src == NULL, "pmSourceCopy(NULL) returned NULL");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceCopy() with non-NULL input, but NULL members
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        ok(src != NULL, "pmSourceAlloc() returned a non-NULL pmSource");
+        pmSource *dst = pmSourceCopy(src);
+        ok(dst != NULL, "pmSourceCopy() returned a non-NULL pmSource");
+        ok(dst != src, "pmSourceCopy() allocated a new pmSource");
+        ok(dst->type == src->type, "pmSourceCopy() set the pmSource->type");
+        ok(dst->mode == src->mode, "pmSourceCopy() set the pmSource->mode");
+        psFree(src);
+        psFree(dst);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceCopy() with non-NULL input, non-NULL members
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        ok(src != NULL, "pmSourceAlloc() returned a non-NULL pmSource");
+        // Set pmPeak values
+        src->peak = pmPeakAlloc (1, 2, 3.0, PM_PEAK_LONE);
+        src->peak->xf = 4.0;
+        src->peak->yf = 5.0;
+        src->peak->flux = 6.0;
+        src->peak->SN = 10.0;
+        src->moments = pmMomentsAlloc();
+        src->moments->x = 11.0;
+        src->moments->y = 12.0;
+        src->moments->Sx = 15.0;
+        src->moments->Sy = 16.0;
+        src->moments->Sxy = 19.0;
+
+        src->pixels = psImageAlloc(2, 4, PS_TYPE_F32);
+        src->weight = psImageAlloc(6, 8, PS_TYPE_F32);
+        src->maskView  = psImageAlloc(10, 12, PS_TYPE_U8);
+        pmSource *dst = pmSourceCopy(src);
+        ok(dst != NULL, "pmSourceCopy() returned a non-NULL pmSource");
+        ok(dst != src, "pmSourceCopy() allocated a new pmSource");
+        ok(dst->type == src->type, "pmSourceCopy() set the pmSource->type");
+        ok(dst->mode == src->mode, "pmSourceCopy() set the pmSource->mode");
+        ok(dst->peak != NULL, "pmSourceCopy() allocated a new pmSource->peak");
+        ok(dst->peak->xf == src->peak->xf, "pmSourceCopy() pmSource->peak->xf");
+        ok(dst->peak->yf == src->peak->yf, "pmSourceCopy() pmSource->peak->yf");
+        ok(dst->peak->flux == src->peak->flux, "pmSourceCopy() pmSource->peak->flux");
+        ok(dst->peak->SN == src->peak->SN, "pmSourceCopy() pmSource->peak->SN");
+        ok(dst->moments != NULL, "pmSourceCopy() allocated a new pmSource->moments");
+        ok(dst->moments->x == src->moments->x, "pmSourceCopy() pmSource->moments->x");
+        ok(dst->moments->y == src->moments->y, "pmSourceCopy() pmSource->moments->y");
+        ok(dst->moments->Sx == src->moments->Sx, "pmSourceCopy() pmSource->moments->Sx");
+        ok(dst->moments->Sy == src->moments->Sy, "pmSourceCopy() pmSource->moments->Sy");
+        ok(dst->moments->Sxy == src->moments->Sxy, "pmSourceCopy() pmSource->moments->Sxy");
+
+        // XXX: We should possibly do a better job testing that these images are copied correctly.
+        ok(dst->pixels != NULL, "pmSourceCopy() allocated a new pmSource->pixels");
+        ok(dst->pixels->numCols == src->pixels->numCols && dst->pixels->numRows == src->pixels->numRows, 
+           "pmSourceCopy() generated correct size pmSource->pixels");
+        ok(dst->weight != NULL, "pmSourceCopy() allocated a new pmSource->weight");
+        ok(dst->weight->numCols == src->weight->numCols && dst->weight->numRows == src->weight->numRows, 
+           "pmSourceCopy() generated correct size pmSource->weight");
+        ok(dst->maskView != NULL, "pmSourceCopy() allocated a new pmSource->maskView");
+        ok(dst->maskView->numCols == src->maskView->numCols && dst->maskView->numRows == src->maskView->numRows, 
+           "pmSourceCopy() generated correct size pmSource->maskView");
+
+        psFree(src);
+        psFree(dst);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceDefinePixels() tests
+    // Call pmSourceDefinePixels() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceDefinePixels(NULL, readout, 1.0, 2.0, 3.0),
+           "pmSourceDefinePixels() returned false with NULL pmSource input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceDefinePixels() with NULL pmReadout input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceDefinePixels(src, NULL, 1.0, 2.0, 3.0),
+           "pmSourceDefinePixels() returned false with NULL pmReadout input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceDefinePixels() with NULL pmReadout->image input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        psFree(readout->image);
+        readout->image = NULL;
+        ok(!pmSourceDefinePixels(src, NULL, 1.0, 2.0, 3.0),
+           "pmSourceDefinePixels() returned false with NULL pmReadout input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceDefinePixels() with negative radius input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceDefinePixels(src, readout, 1.0, 2.0, -3.0),
+           "pmSourceDefinePixels() returned false with negative radius input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceDefinePixels() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        for (int i = 0 ; i < readout->image->numRows ; i++) {
+            for (int j = 0 ; j < readout->image->numCols ; j++) {
+                readout->image->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        bool rc = pmSourceDefinePixels(src, readout, (float) TEST_NUM_COLS/2, (float) TEST_NUM_ROWS/2, 2.0);
+        ok(rc, "pmSourceDefinePixels() returned TRUE with acceptable input parameters");
+        int expectedNumCols = 1 + (TEST_NUM_COLS/2);
+        int expectedNumRows = 1 + (TEST_NUM_COLS/2);
+        // XX: We only verify the size of the pixels, weight, maskView, and maskObj
+        // images.  A better test would verify that the actual data is set correctly.
+        // We don't do that here since it basically duplicated psLib function tests.
+        ok(src->pixels->numCols == expectedNumCols && src->pixels->numRows == expectedNumRows, 
+               "pmSourceDefinePixels() set the size of pmSource->pixels correctly");
+        ok(src->weight->numCols == expectedNumCols && src->weight->numRows == expectedNumRows, 
+               "pmSourceDefinePixels() set the size of pmSource->weight correctly");
+        ok(src->maskView->numCols == expectedNumCols && src->maskView->numRows == expectedNumRows, 
+               "pmSourceDefinePixels() set the size of pmSource->maskView correctly");
+        ok(src->maskObj->numCols == expectedNumCols && src->maskObj->numRows == expectedNumRows, 
+               "pmSourceDefinePixels() set the size of pmSource->maskObj correctly");
+
+        psRegion region = psRegionForSquare((float) TEST_NUM_COLS/2, (float) TEST_NUM_ROWS/2, 2.0);
+        region = psRegionForImage(readout->image, region);
+        ok(src->region.x0 == region.x0 && src->region.x1 == region.x1 &&
+           src->region.y0 == region.y0 && src->region.y1 == region.y1,
+          "pmSourceDefinePixels() set pmSource->region correctly");
+
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceRedefinePixels() tests
+    // Call pmSourceRedefinePixels() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceRedefinePixels(NULL, readout, 1.0, 2.0, 3.0),
+           "pmSourceRedefinePixels() returned false with NULL pmSource input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceRedefinePixels() with NULL pmReadout input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceRedefinePixels(src, NULL, 1.0, 2.0, 3.0),
+           "pmSourceRedefinePixels() returned false with NULL pmReadout input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceRedefinePixels() with NULL pmReadout->image input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        psFree(readout->image);
+        readout->image = NULL;
+        ok(!pmSourceRedefinePixels(src, NULL, 1.0, 2.0, 3.0),
+           "pmSourceRedefinePixels() returned false with NULL pmReadout input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceRedefinePixels() with negative radius input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceRedefinePixels(src, readout, 1.0, 2.0, -3.0),
+           "pmSourceRedefinePixels() returned false with negative radius input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceRedefinePixels() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        for (int i = 0 ; i < readout->image->numRows ; i++) {
+            for (int j = 0 ; j < readout->image->numCols ; j++) {
+                readout->image->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        // First set the pixels region to a square of radius 1.
+        bool rc = pmSourceDefinePixels(src, readout, (float) TEST_NUM_COLS/2, (float) TEST_NUM_ROWS/2, 1.0);
+        ok(rc, "pmSourceDefinePixels() returned TRUE with radius 1");
+
+        // Set these flux images so we can verify they are later psFree'ed and set to NULL
+        src->modelFlux = psImageAlloc(2, 2, PS_TYPE_F32);
+        src->psfFlux = psImageAlloc(2, 2, PS_TYPE_F32);
+
+        // Now set the radius to 2, and call pmSourceRedefinePixels()
+        rc = pmSourceRedefinePixels(src, readout, (float) TEST_NUM_COLS/2, (float) TEST_NUM_ROWS/2, 2.0);
+        ok(rc, "pmSourceRedefinePixels() returned TRUE with acceptable input parameters");
+        int expectedNumCols = 1 + (TEST_NUM_COLS/2);
+        int expectedNumRows = 1 + (TEST_NUM_COLS/2);
+        // XX: We only verify the size of the pixels, weight, maskView, and maskObj
+        // images.  A better test would verify that the actual data is set correctly.
+        // We don't do that here since it basically duplicated psLib function tests.
+        ok(src->pixels->numCols == expectedNumCols && src->pixels->numRows == expectedNumRows, 
+               "pmSourceRedefinePixels() set the size of pmSource->pixels correctly");
+        ok(src->weight->numCols == expectedNumCols && src->weight->numRows == expectedNumRows, 
+               "pmSourceRedefinePixels() set the size of pmSource->weight correctly");
+        ok(src->maskView->numCols == expectedNumCols && src->maskView->numRows == expectedNumRows, 
+               "pmSourceRedefinePixels() set the size of pmSource->maskView correctly");
+        ok(src->maskObj->numCols == expectedNumCols && src->maskObj->numRows == expectedNumRows, 
+               "pmSourceRedefinePixels() set the size of pmSource->maskObj correctly");
+
+        psRegion region = psRegionForSquare((float) TEST_NUM_COLS/2, (float) TEST_NUM_ROWS/2, 2.0);
+        region = psRegionForImage(readout->image, region);
+        ok(src->region.x0 == region.x0 && src->region.x1 == region.x1 &&
+           src->region.y0 == region.y0 && src->region.y1 == region.y1,
+          "pmSourceRedefinePixels() set pmSource->region correctly");
+
+        ok(src->modelFlux == NULL, "pmSourceRedefinePixels() set the pmSource->modelFlux to NULL");
+        ok(src->psfFlux == NULL, "pmSourceRedefinePixels() set the pmSource->psfFlux to NULL");
+
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcePSFClump() tests
+    // pmPSFClump pmSourcePSFClump(psArray *sources, psMetadata *recipe)
+    // Call pmSourcePSFClump() with NULL pmSource input parameter
+    #define NUM_SOURCES 10
+    {
+        psMemId id = psMemGetId();
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        psMetadata *recipe = psMetadataAlloc();
+        bool rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "PSF_CLUMP_SN_LIM", 0, NULL, 0.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SX_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SY_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_AR_MAX", 0, NULL, 3.0);
+
+        pmPSFClump clump = pmSourcePSFClump(NULL, recipe);
+        ok(clump.X == -1.0 && clump.dX == -1.0 && 
+           clump.Y == 0.0 && clump.dY == 0.0, "pmSourcePSFClump(NULL, recipe) returned the error clump");
+
+        psFree(sources);
+        psFree(recipe);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcePSFClump() with NULL recipe input parameter
+    {
+        psMemId id = psMemGetId();
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        psMetadata *recipe = psMetadataAlloc();
+        bool rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "PSF_CLUMP_SN_LIM", 0, NULL, 0.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SX_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SY_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_AR_MAX", 0, NULL, 3.0);
+
+        pmPSFClump clump = pmSourcePSFClump(sources, NULL);
+        ok(clump.X == -1.0 && clump.dX == -1.0 && 
+           clump.Y == 0.0 && clump.dY == 0.0, "pmSourcePSFClump(sources, NULL) returned the error clump");
+
+        psFree(sources);
+        psFree(recipe);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcePSFClump() with acceptable input parameters
+    // XX: This is a fairly simplistic test.  We set the moments of all test pmSources
+    // to (5.0, 5.0), so the clump should be fairly easy to detect.  For further testing
+    // add:
+    //	  Add outliers to the Sx and Sy data, make sure they aren't used in the calculation
+    //    Force it to get the various metadata from the recipes arg.
+    //    Add a few non pmSource types to the sources input pmArray
+    //    Add a few NULL pmSources, or NULL pmSource->moments to the sources input pmArray
+    //    Ensure the data is saved with the KEEP_PSF_CLUMP metadata item
+    //    Add cases where you fail to find a peak.
+    //    Modify data so that the inputs have different moments
+    //
+    {
+        psMemId id = psMemGetId();
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->moments = pmMomentsAlloc();
+            src->moments->Sx = 5.0;
+            src->moments->Sy = 5.0;
+            sources->data[i] = src;
+	}
+        psMetadata *recipe = psMetadataAlloc();
+        bool rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "PSF_CLUMP_SN_LIM", 0, NULL, 0.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SX_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SY_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_AR_MAX", 0, NULL, 3.0);
+
+        pmPSFClump clump = pmSourcePSFClump(sources, recipe);
+        ok(clump.X == 5.0 && clump.dX == 0.0 && 
+           clump.Y == 5.0 && clump.dY == 0.0, "pmSourcePSFClump(sources, NULL) returned the correct clump");
+
+        if (VERBOSE) {
+            printf("clump: (%.2f %.2f %.2f %.2f)\n", clump.X, clump.dX, clump.Y, clump.dY);
+	}
+        psFree(sources);
+        psFree(recipe);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceGetModel() tests
+    // pmModel *pmSourceGetModel (bool *isPSF, const pmSource *source)
+    // Call pmSourceGetModel() with NULL pmSource input parameter
+    #define NUM_SOURCES 10
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        bool isPDF;
+        pmModel *model = pmSourceGetModel(&isPDF, NULL);
+        ok(model == NULL, "pmSourceGetModel() returned NULL with NULL pmSource input parameter");
+
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceGetModel() with acceptable input parameters
+    #define NUM_SOURCES 10
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        // For testing only:
+        src->modelPSF = (pmModel *) 1;
+        src->modelConv = (pmModel *) 2;
+        src->modelEXT = (pmModel *) 3;
+        bool isPDF;
+
+        src->modelConv = (pmModel *) 0;
+        src->type = PM_SOURCE_TYPE_UNKNOWN;
+        pmModel *model = pmSourceGetModel(&isPDF, src);
+        ok(model == NULL, "pmSourceGetModel() returned a NULL pmModel with acceptable input parameters and src->type = PM_SOURCE_TYPE_UNKNOWN");
+        ok(false == isPDF, "pmSourceGetModel() set isPDF to FALSE");
+
+        src->type = PM_SOURCE_TYPE_STAR;
+        model = pmSourceGetModel(&isPDF, src);
+        ok(model != NULL, "pmSourceGetModel() returned a non-NULL pmModel with acceptable input parameters");
+        ok(1 == (int) model, "pmSourceGetModel() returned the correct model with pmSource->type == PM_SOURCE_TYPE_STAR");
+        ok(true == isPDF, "pmSourceGetModel() set isPDF to TRUE");
+
+        src->type = PM_SOURCE_TYPE_EXTENDED;
+        src->modelConv = (pmModel *) 2;
+        model = pmSourceGetModel(&isPDF, src);
+        ok(model != NULL, "pmSourceGetModel() returned a non-NULL pmModel with acceptable input parameters");
+        ok(2 == (int) model, "pmSourceGetModel() returned the correct model with pmSource->type == PM_SOURCE_TYPE_EXTENDED (%d)", (int) model);
+        ok(false == isPDF, "pmSourceGetModel() set isPDF to FALSE");
+
+        src->modelConv = (pmModel *) 0;
+        src->type = PM_SOURCE_TYPE_EXTENDED;
+        model = pmSourceGetModel(&isPDF, src);
+        ok(model != NULL, "pmSourceGetModel() returned a non-NULL pmModel with acceptable input parameters");
+        ok(3 == (int) model, "pmSourceGetModel() returned the correct model with pmSource->type == PM_SOURCE_TYPE_EXTENDED");
+        ok(false == isPDF, "pmSourceGetModel() set isPDF to FALSE");
+
+
+        src->modelPSF = NULL;
+        src->modelConv = NULL;
+        src->modelEXT = NULL;
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceOp() tests
+    // bool pmSourceOp (pmSource *source, pmModelOpMode mode, bool add,
+    //                  psMaskType maskVal, int dx, int dy)
+    // Call pmSourceOp() with NULL pmSource input parameter
+    #define NUM_SOURCES 10
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        bool rc = pmSourceOp(NULL, PM_MODEL_OP_NONE, true, 1, 0, 0);
+        ok(!rc, "pmSourceOpl() returned FALSE with NULL pmSource input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
Index: trunk/psModules/test/objects/tap_pmSourceContour.c
===================================================================
--- trunk/psModules/test/objects/tap_pmSourceContour.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmSourceContour.c	(revision 15726)
@@ -0,0 +1,181 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+// XXX: We only test with unallowable input parameters.
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (16)
+#define TEST_NUM_COLS           (30)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_SOURCES		100
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(14);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceContour() tests
+    // psArray *pmSourceContour (psImage *image, int xc, int yc, float threshold)
+    // Call pmSourceContour() with NULL psImage input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psArray *array = pmSourceContour(NULL, 1, 2, 3.0);
+        ok(array == NULL, "pmSourceContour() returned NULL with NULL psImage input parameter");
+        psFree(img);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceContour() with unallowed row/column numbers
+    if (1) {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psArray *array = pmSourceContour(img, -1, 2, 3.0);
+        ok(array == NULL, "pmSourceContour() returned NULL with column = -1");
+        array = pmSourceContour(img, TEST_NUM_COLS, 2, 3.0);
+        ok(array == NULL, "pmSourceContour() returned NULL with column >= numCols");
+        array = pmSourceContour(img, 1, -1, 3.0);
+        ok(array == NULL, "pmSourceContour() returned NULL with row = -1");
+        array = pmSourceContour(img, 1, TEST_NUM_ROWS, 3.0);
+        ok(array == NULL, "pmSourceContour() returned NULL with row >= numRows");
+
+        psFree(img);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceContour() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < img->numRows ; i++) {
+            for (int j = 0 ; j < img->numCols ; j++) {
+                if ((i >= TEST_NUM_ROWS/4) && (i < 3*TEST_NUM_ROWS/4) &&
+                    (j >= TEST_NUM_COLS/4) && (j < 3*TEST_NUM_COLS/4)) {
+                    img->data.F32[i][j] = 5.0;
+		} else {
+                    img->data.F32[i][j] = 0.0;
+		}
+	    }
+	}
+        if (0) {
+            for (int i = 0 ; i < img->numRows ; i++) {
+                for (int j = 0 ; j < img->numCols ; j++) {
+                    printf("(%.0f)", img->data.F32[i][j]);
+    	    }
+                printf("\n");
+	    }
+	}
+
+        img->data.F32[TEST_NUM_ROWS/2][TEST_NUM_COLS/2] = 5.0;
+
+        psArray *array = pmSourceContour(img, TEST_NUM_COLS/2, TEST_NUM_ROWS/2, 3.0);
+        ok(array != NULL, "pmSourceContour() returned non-NULL with acceptable input parameters");
+
+        psFree(array);
+        psFree(img);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceContour_Crude() tests
+    // psArray *pmSourceContour_Crude_Crude(pmSource *source, psImage *image, psF32 level)
+    // Call pmSourceContour_Crude() with NULL psSource input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->moments = pmMomentsAlloc();
+        src->modelEXT = pmModelAlloc(1);
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < img->numRows ; i++) {
+            for (int j = 0 ; j < img->numCols ; j++) {
+                if ((i >= TEST_NUM_ROWS/4) && (i < 3*TEST_NUM_ROWS/4) &&
+                    (j >= TEST_NUM_COLS/4) && (j < 3*TEST_NUM_COLS/4)) {
+                    img->data.F32[i][j] = 5.0;
+		} else {
+                    img->data.F32[i][j] = 0.0;
+		}
+	    }
+	}
+        psArray *array = pmSourceContour_Crude(NULL, img, 3.0);
+        ok(array == NULL, "pmSourceContour_Crude() returned NULL with NULL pmSource input parameter");
+        psFree(img);
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceContour_Crude() with NULL psImage input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->moments = pmMomentsAlloc();
+        src->modelEXT = pmModelAlloc(1);
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < img->numRows ; i++) {
+            for (int j = 0 ; j < img->numCols ; j++) {
+                if ((i >= TEST_NUM_ROWS/4) && (i < 3*TEST_NUM_ROWS/4) &&
+                    (j >= TEST_NUM_COLS/4) && (j < 3*TEST_NUM_COLS/4)) {
+                    img->data.F32[i][j] = 5.0;
+		} else {
+                    img->data.F32[i][j] = 0.0;
+		}
+	    }
+	}
+        psArray *array = pmSourceContour_Crude(src, NULL, 3.0);
+        ok(array == NULL, "pmSourceContour_Crude() returned NULL with NULL pmImage input parameter");
+        psFree(img);
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceContour_Crude() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->moments = pmMomentsAlloc();
+        src->modelEXT = pmModelAlloc(1);
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+
+if (0)        for (int i = 0 ; i < img->numRows ; i++) {
+            for (int j = 0 ; j < img->numCols ; j++) {
+                if ((i >= TEST_NUM_ROWS/4) && (i < 3*TEST_NUM_ROWS/4) &&
+                    (j >= TEST_NUM_COLS/4) && (j < 3*TEST_NUM_COLS/4)) {
+                    img->data.F32[i][j] = 5.0;
+		} else {
+                    img->data.F32[i][j] = 0.0;
+		}
+	    }
+	}
+//        psArray *array = pmSourceContour_Crude(src, img, 3.0);
+//        ok(array != NULL, "pmSourceContour_Crude() returned non-NULL with NULL pmImage input parameter");
+        psFree(img);
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+}
Index: trunk/psModules/test/objects/tap_pmSourceExtendedPars.c
===================================================================
--- trunk/psModules/test/objects/tap_pmSourceExtendedPars.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmSourceExtendedPars.c	(revision 15726)
@@ -0,0 +1,118 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         10
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(36);
+
+    // ----------------------------------------------------------------------
+    // pmSourceExtendedParsAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourceExtendedPars *tmp = pmSourceExtendedParsAlloc();
+        ok(tmp && psMemCheckSourceExtendedPars(tmp), "pmSourceExtendedParsAlloc() allocated a pmSourceExtendedPars struct");
+
+        ok(tmp->profile == NULL, "pmSourceExtendedParsAlloc() set the ->profile member to NULL");
+        ok(tmp->annuli == NULL, "pmSourceExtendedParsAlloc() set the ->annuli member to NULL");
+        ok(tmp->isophot == NULL, "pmSourceExtendedParsAlloc() set the ->isophot member to NULL");
+        ok(tmp->petrosian == NULL, "pmSourceExtendedParsAlloc() set the ->petrosian member to NULL");
+        ok(tmp->kron == NULL, "pmSourceExtendedParsAlloc() set the ->kron member to NULL");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceRadialProfileAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourceRadialProfile *tmp = pmSourceRadialProfileAlloc();
+        ok(tmp && psMemCheckSourceRadialProfile(tmp), "pmSourceRadialProfile() allocated a pmSourceRadialProfilestruct");
+
+        ok(tmp->radius == NULL, "pmSourceRadialProfileAlloc() set the ->radius member to NULL");
+        ok(tmp->flux == NULL, "pmSourceRadialProfileAlloc() set the ->flux member to NULL");
+        ok(tmp->weight == NULL, "pmSourceRadialProfileAlloc() set the ->weight member to NULL");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceIsophotalValuesAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourceIsophotalValues *tmp = pmSourceIsophotalValuesAlloc();
+        ok(tmp && psMemCheckSourceIsophotalValues(tmp), "pmSourceIsophotalValues() allocated a pmSourceIsophotalValuesstruct");
+
+        ok(tmp->mag == 0.0, "pmSourceIsophotalValuesAlloc() set the ->mag member to 0.0");
+        ok(tmp->magErr == 0.0, "pmSourceIsophotalValuesAlloc() set the ->magErr member to 0.0");
+        ok(tmp->rad == 0.0, "pmSourceIsophotalValuesAlloc() set the ->rad member to 0.0");
+        ok(tmp->radErr == 0.0, "pmSourceIsophotalValuesAlloc() set the ->radErr member to 0.0");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcePetrosianValuesAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourcePetrosianValues *tmp = pmSourcePetrosianValuesAlloc();
+        ok(tmp && psMemCheckSourcePetrosianValues(tmp), "pmSourcePetrosianValues() allocated a pmSourcePetrosianValuesstruct");
+
+        ok(tmp->mag == 0.0, "pmSourcePetrosianValuesAlloc() set the ->mag member to 0.0");
+        ok(tmp->magErr == 0.0, "pmSourcePetrosianValuesAlloc() set the ->magErr member to 0.0");
+        ok(tmp->rad == 0.0, "pmSourcePetrosianValuesAlloc() set the ->rad member to 0.0");
+        ok(tmp->radErr == 0.0, "pmSourcePetrosianValuesAlloc() set the ->radErr member to 0.0");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceKronValuesAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourceKronValues *tmp = pmSourceKronValuesAlloc();
+        ok(tmp && psMemCheckSourceKronValues(tmp), "pmSourceKronValues() allocated a pmSourceKronValuesstruct");
+
+        ok(tmp->mag == 0.0, "pmSourceKronValuesAlloc() set the ->mag member to 0.0");
+        ok(tmp->magErr == 0.0, "pmSourceKronValuesAlloc() set the ->magErr member to 0.0");
+        ok(tmp->rad == 0.0, "pmSourceKronValuesAlloc() set the ->rad member to 0.0");
+        ok(tmp->radErr == 0.0, "pmSourceKronValuesAlloc() set the ->radErr member to 0.0");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceAnnuliAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourceAnnuli *tmp = pmSourceAnnuliAlloc();
+        ok(tmp && psMemCheckSourceAnnuli(tmp), "pmSourceAnnuli() allocated a pmSourceAnnulistruct");
+
+        ok(tmp->flux == NULL, "pmSourceAnnuliAlloc() set the ->flux member to NULL");
+        ok(tmp->fluxErr == NULL, "pmSourceAnnuliAlloc() set the ->fluxErr member to NULL");
+        ok(tmp->fluxVar == NULL, "pmSourceAnnuliAlloc() set the ->fluxVar member to NULL");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
Index: trunk/psModules/test/objects/tap_pmSourceFitSet.c
===================================================================
--- trunk/psModules/test/objects/tap_pmSourceFitSet.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmSourceFitSet.c	(revision 15726)
@@ -0,0 +1,142 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+// XXX: This source code file is very lighted test so far.
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (16)
+#define TEST_NUM_COLS           (30)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_MODELS		5
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(14);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceFitSetDataAlloc() tests
+    // Call pmSourceFitSetDataAlloc() with NULL psArray input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(1);
+	}
+        pmSourceFitSetData *fitSetData = pmSourceFitSetDataAlloc(NULL);
+        ok(fitSetData == NULL, "pmSourceFitSetDataAlloc() returned NULL with NULL psArray input parameter");
+        psFree(fitSetData);
+        pmModelClassCleanup();
+        psFree(modelSet); 
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSetDataAlloc() with acceptable input parameters
+    // STATUS: fully tested
+    if (1) {
+        psMemId id = psMemGetId();
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        ok(set != NULL && psMemCheckSourceFitSetData(set),
+          "pmSourceFitSetDataAlloc() returned non-NULL with acceptable input parameters");
+        ok(set->paramSet != NULL && set->paramSet->n == modelSet->n, 
+          "pmSourceFitSetDataAlloc() set the set->paramSet psArray correctly");
+        ok(set->derivSet != NULL && set->derivSet->n == modelSet->n, 
+          "pmSourceFitSetDataAlloc() set the set->derivSet psArray correctly");
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            int nParams = pmModelClassParameterCount(i);
+            psVector *tmpV = (psVector *) (set->paramSet->data[i]);
+            ok(tmpV != NULL && psMemCheckVector(tmpV) && tmpV->n == nParams,
+               "pmSourceFitSetDataAlloc() set the set->paramSet->data psVector correctly");
+
+            tmpV = (psVector *) (set->derivSet->data[i]);
+            ok(tmpV != NULL && psMemCheckVector(tmpV) && tmpV->n == nParams,
+               "pmSourceFitSetDataAlloc() set the set->derivSet->data psVector correctly");
+
+            bool errorFlag = false;
+            for (int i = 0 ; i < tmpV->n ; i++) {
+                if (tmpV->data.F32[i] != 0.0) {
+                    errorFlag = true;
+		}
+	    }
+            ok(!errorFlag, "pmSourceFitSetDataAlloc() set the set->derivSet->data correctly");
+	}
+        
+        psFree(set);
+        pmModelClassCleanup();
+        psFree(modelSet); 
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceFitSetCheckLimits() tests
+    // bool pmSourceFitSetCheckLimits (psMinConstraintMode mode, int nParam, 
+    //                                 float *params, float *betas)
+    // Call pmSourceFitSetCheckLimits() with thisSet == NULL
+    if (1) {
+        psMemId id = psMemGetId();
+        #define NUM_PARAMS 10
+        psF32 *params = (psF32 *) psAlloc(NUM_PARAMS * sizeof(psF32));
+        psF32 *betas = (psF32 *) psAlloc(NUM_PARAMS * sizeof(psF32));
+        bool rc = pmSourceFitSetCheckLimits(PS_MINIMIZE_PARAM_MIN, 10, params, betas);
+        ok(rc == false, "pmSourceFitSetCheckLimits() returned NULL with thisSet == FALSE");
+        psFree(params);
+        psFree(betas);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSetCheckLimits() with acceptable data
+    // XXX: Must finish this.  Use pmSourceFitSet() to set thisSet
+    if (0) {
+        psMemId id = psMemGetId();
+        #define NUM_PARAMS 10
+        psF32 *params = (psF32 *) psAlloc(NUM_PARAMS * sizeof(psF32));
+        psF32 *betas = (psF32 *) psAlloc(NUM_PARAMS * sizeof(psF32));
+        bool rc = pmSourceFitSetCheckLimits(PS_MINIMIZE_PARAM_MIN, 10, params, betas);
+        ok(rc == false, "pmSourceFitSetCheckLimits() returned NULL with thisSet == FALSE");
+        psFree(params);
+        psFree(betas);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceFitSet() tests
+    // bool pmSourceFitSet (pmSource *source, psArray *modelSet,
+    //                 pmSourceFitMode mode, psMaskType maskVal)
+    // Call pmSourceFitSet() with thisSet == NULL
+    if (1) {
+        psMemId id = psMemGetId();
+        #define NUM_PARAMS 10
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+        psArray *set = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < set->n ; i++) {
+            set->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        bool rc = pmSourceFitSet(src, set, PM_SOURCE_FIT_PSF, 1);
+        ok(rc == false, "pmSourceFitSet() returned NULL with thisSet == FALSE");
+        psFree(src);
+        psFree(set);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
Index: trunk/psModules/test/objects/tap_pmSourceIO_PS1_DEV_0.c
===================================================================
--- trunk/psModules/test/objects/tap_pmSourceIO_PS1_DEV_0.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmSourceIO_PS1_DEV_0.c	(revision 15726)
@@ -0,0 +1,242 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_SOURCES		5
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(79);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesWrite_PS1_DEV_0() tests
+    // bool pmSourcesWrite_PS1_DEV_0 (psFits *fits, psArray *sources, 
+    //      psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
+    // Call pmSourcesWrite_PS1_DEV_0() with NULL psFits input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            src->type = PM_SOURCE_TYPE_STAR;
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_0(NULL, sources, imageHeader, tableHeader, extname);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_0() returned FALSE with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_PS1_DEV_0() with NULL pmSource input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_0(fitsFile, NULL, imageHeader, tableHeader, extname);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_0() returned FALSE with NULL pmSource input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_PS1_DEV_0() with NULL extname input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_0(fitsFile, sources, imageHeader, tableHeader, NULL);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_0() returned FALSE with NULL extname input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesRead_PS1_DEV_0() tests
+    // psArray *pmSourcesRead_PS1_DEV_0 (psFits *fits, psMetadata *header)
+    // 
+    // Call pmSourcesRead_PS1_DEV_0() with NULL psFits input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_0(NULL, header);
+        ok(array == NULL, "pmSourcesRead_PS1_DEV_0() returned NULL with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesRead_PS1_DEV_0() with NULL header input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_0(fitsFile, NULL);
+        ok(array == NULL, "pmSourcesRead_PS1_DEV_0() returned NULL with NULL header input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Call pmSourcesWrite_PS1_DEV_0() with acceptable input parameters
+    #define TEST_BASE_X_POS		10.0
+    #define TEST_BASE_Y_POS		20.0
+    #define TEST_BASE_X_ERR		30.0
+    #define TEST_BASE_Y_ERR		40.0
+    #define TEST_BASE_PSF_MAG	50.0
+    #define TEST_BASE_ERR_MAG	60.0
+    #define TEST_BASE_SKY		70.0
+    #define TEST_BASE_SKY_ERR	80.0
+    #define TEST_BASE_PIX_WEIGHT	90.0
+    #define TEST_BASE_PEAK_FLUX	120.0
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            // Set even numbered sources to PM_SOURCE_TYPE_STAR
+            pmModel *model = NULL;
+            if (i%2) {
+                src->type = PM_SOURCE_TYPE_STAR;
+                src->modelPSF = pmModelAlloc(1);
+                model = src->modelPSF;
+	    } else {
+                src->type = PM_SOURCE_TYPE_EXTENDED;
+                src->modelConv = pmModelAlloc(1);
+                model = src->modelConv;
+ 	    }
+            for (int p = 0 ; p < model->params->n ; p++) {
+                model->params->data.F32[p] = (float) (i + p);
+                model->dparams->data.F32[p] = (float) (i + p);
+	    }
+            model->params->data.F32[PM_PAR_XPOS] = TEST_BASE_X_POS + (float) i;
+            model->params->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_POS + (float) i;
+            model->dparams->data.F32[PM_PAR_XPOS] = TEST_BASE_X_ERR + (float) i;
+            model->dparams->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_ERR + (float) i;
+            src->psfMag = TEST_BASE_PSF_MAG + (float) i;
+            src->errMag = TEST_BASE_ERR_MAG + (float) i;
+            src->peak->flux = TEST_BASE_PEAK_FLUX + (float) i;
+            src->sky = TEST_BASE_SKY + (float) i;
+            src->skyErr = TEST_BASE_SKY_ERR + (float) i;
+            src->pixWeight = TEST_BASE_PIX_WEIGHT + (float) i;
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_0(fitsFile, sources, imageHeader, tableHeader, extname);
+        ok(rc == true, "pmSourcesWrite_PS1_DEV_0() returned TRUE with acceptable input parameters");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesRead_PS1_DEV_0() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_0(fitsFile, header);
+        ok(array != NULL, "pmSourcesRead_PS1_DEV_0() returned non-NULL with acceptable input parameters");
+        skip_start(array == NULL, 1, "Skipping tests because pmSourcesRead_PS1_DEV_0() returned NULL");
+        for (int i = 0 ; i < array->n ; i++) {
+             pmSource *src = (pmSource *) array->data[i];
+             ok(src != NULL && psMemCheckSource(src), "pmSourcesRead_PS1_DEV_0() read source %d correctly", i);
+
+             // XXX: Source code always sets the type to PM_SOURCE_TYPE_STAR.  Is that right?
+             ok(src->type == PM_SOURCE_TYPE_STAR, "pmSourcesRead_PS1_DEV_0() set the source type correctly (is %d, should be %d)",
+                src->type, PM_SOURCE_TYPE_STAR);
+
+             ok(src->sky == (TEST_BASE_SKY + (float) i), "pmSourcesRead_PS1_DEV_0() set src->sky correctly (is %.2f, should be %.2f)",
+                src->sky, (TEST_BASE_SKY + (float) i));
+             ok(src->skyErr == (TEST_BASE_SKY_ERR + (float) i), "pmSourcesRead_PS1_DEV_0() set src->skyErr correctly (is %.2f, should be %.2f)",
+                src->skyErr, (TEST_BASE_SKY_ERR + (float) i));
+             ok(src->pixWeight == (TEST_BASE_PIX_WEIGHT + (float) i), "pmSourcesRead_PS1_DEV_0() set src->pixWeight correctly (is %.2f, should be %.2f)",
+                src->pixWeight, (TEST_BASE_PIX_WEIGHT + (float) i));
+             ok(TEST_FLOATS_EQUAL(src->peak->flux, (TEST_BASE_PEAK_FLUX + (float) i)), "pmSourcesRead_PS1_DEV_0() set src->peak->flux correctly (is %.2f, should be %.2f)",
+                src->peak->flux, (TEST_BASE_PEAK_FLUX + (float) i));
+             ok(src->psfMag == (TEST_BASE_PSF_MAG + (float) i), "pmSourcesRead_PS1_DEV_0() set src->psfMag correctly (is %.2f, should be %.2f)",
+                src->psfMag, (TEST_BASE_PSF_MAG + (float) i));
+             ok(src->errMag == (TEST_BASE_ERR_MAG + (float) i), "pmSourcesRead_PS1_DEV_0() set src->errMag correctly (is %.2f, should be %.2f)",
+                src->errMag, (TEST_BASE_ERR_MAG + (float) i));
+
+             // XXX: Source code always sets src->modelPSF.  Is that right?
+             pmModel *model = src->modelPSF;
+             ok(model != NULL  && psMemCheckModel(model), "pmSourcesRead_PS1_DEV_0() set src->modelPSF correctly");
+             skip_start(model == NULL, 2, "Skipping tests because pmSourcesRead_PS1_DEV_0() did not set src->modelPSF");
+             ok(model->params->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_POS + (float) i),
+               "pmSourcesRead_PS1_DEV_0() set src->model->params->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                model->params->data.F32[PM_PAR_XPOS], (TEST_BASE_X_POS + (float) i));
+             ok(model->params->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_POS + (float) i),
+               "pmSourcesRead_PS1_DEV_0() set src->model->params->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                model->params->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_POS + (float) i));
+             ok(model->dparams->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_ERR + (float) i),
+               "pmSourcesRead_PS1_DEV_0() set src->model->dparams->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                model->dparams->data.F32[PM_PAR_XPOS], (TEST_BASE_X_ERR + (float) i));
+             ok(model->dparams->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_ERR + (float) i),
+               "pmSourcesRead_PS1_DEV_0() set src->model->dparams->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                model->dparams->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_ERR + (float) i));
+             skip_end();
+	}
+        skip_end();
+        psFree(fitsFile);
+        psFree(header);
+        psFree(array);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: trunk/psModules/test/objects/tap_pmSourceIO_PS1_DEV_1.c
===================================================================
--- trunk/psModules/test/objects/tap_pmSourceIO_PS1_DEV_1.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmSourceIO_PS1_DEV_1.c	(revision 15726)
@@ -0,0 +1,308 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8)
+#define TEST_NUM_COLS           (16)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         10
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_SOURCES		5
+#define TABLE_FILENAME	"table.fits"
+const char* tableFilename = "table.fits";
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(80);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesWrite_PS1_DEV_1() tests
+    // bool pmSourcesWrite_PS1_DEV_1 (psFits *fits, psArray *sources, 
+    //      psMetadata *imageHeader, psMetadata *tableHeader, char *extname char *xsrcname)
+    // Call pmSourcesWrite_PS1_DEV_1() with NULL psFits input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            src->type = PM_SOURCE_TYPE_STAR;
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_1(NULL, sources, imageHeader, tableHeader, extname, NULL);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_1() returned FALSE with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_PS1_DEV_1() with NULL pmSource input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_1(fitsFile, NULL, imageHeader, tableHeader, extname, NULL);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_1() returned FALSE with NULL pmSource input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_PS1_DEV_1() with NULL extname input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_1(fitsFile, sources, imageHeader, tableHeader, NULL, NULL);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_1() returned FALSE with NULL extname input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesRead_PS1_DEV_1() tests
+    // psArray *pmSourcesRead_PS1_DEV_1 (psFits *fits, psMetadata *header)
+    // 
+    // Call pmSourcesRead_PS1_DEV_1() with NULL psFits input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_1(NULL, header);
+        ok(array == NULL, "pmSourcesRead_PS1_DEV_1() returned NULL with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesRead_PS1_DEV_1() with NULL header input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_1(fitsFile, NULL);
+        ok(array == NULL, "pmSourcesRead_PS1_DEV_1() returned NULL with NULL header input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Call pmSourcesWrite_PS1_DEV_1() with acceptable input parameters
+    #define TEST_BASE_X_POS             10.0
+    #define TEST_BASE_Y_POS             20.0
+    #define TEST_BASE_X_ERR             30.0
+    #define TEST_BASE_Y_ERR             40.0
+    #define TEST_BASE_PSF_MAG		50.0
+    #define TEST_BASE_ERR_MAG		60.0
+    #define TEST_BASE_SKY               500.0
+    #define TEST_BASE_SKY_ERR		80.0
+    #define TEST_BASE_PIX_WEIGHT        90.0
+    #define TEST_BASE_PEAK_FLUX		120.0
+    #define TEST_BASE_PSF_PROB		150.0
+    #define TEST_BASE_CR_N_SIGMA	160.0
+    #define TEST_BASE_EXT_N_SIGMA       170.0   
+    #define TEST_BASE_MODE		1
+
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "w");
+        if (fitsFile == NULL) {
+            diag("ERROR: Could not create 'table' FITS file");
+            return false;
+        }
+
+        if (1) {
+            // make the PHU an image (per FITS standard, it must be)
+            psImage* image = psImageAlloc(16, 16, PS_TYPE_F32);
+            if (!psFitsWriteImage(fitsFile, NULL, image, 1, NULL)) {
+                diag("ERROR: Could not write PHU image");
+                return false;
+            }
+            psFree(image);
+        }
+
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            // Set even numbered sources to PM_SOURCE_TYPE_STAR
+            pmModel *model = NULL;
+            if (i%2) {
+                src->type = PM_SOURCE_TYPE_STAR;
+                src->modelPSF = pmModelAlloc(1);
+                model = src->modelPSF;
+	    } else {
+                src->type = PM_SOURCE_TYPE_EXTENDED;
+                src->modelConv = pmModelAlloc(1);
+                model = src->modelConv;
+	    }
+            for (int p = 0 ; p < model->params->n ; p++) {
+                model->params->data.F32[p] = (float) (i + p);
+                model->dparams->data.F32[p] = (float) (i + p);
+	    }
+
+            model->params->data.F32[PM_PAR_XPOS] = TEST_BASE_X_POS + (float) i;
+            model->params->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_POS + (float) i;
+            model->dparams->data.F32[PM_PAR_XPOS] = TEST_BASE_X_ERR + (float) i;
+            model->dparams->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_ERR + (float) i;
+            src->psfMag = TEST_BASE_PSF_MAG + (float) i;
+            src->errMag = TEST_BASE_ERR_MAG + (float) i;
+            src->peak->flux = TEST_BASE_PEAK_FLUX + (float) i;
+            src->sky = TEST_BASE_SKY + (float) i;
+            src->skyErr = TEST_BASE_SKY_ERR + (float) i;
+            src->pixWeight = TEST_BASE_PIX_WEIGHT + (float) i;
+            sources->data[i] = (psPtr *) src;
+            src->psfMag = TEST_BASE_PSF_MAG + (float) i;
+            src->errMag = TEST_BASE_ERR_MAG + (float) i;
+            src->sky = TEST_BASE_SKY + (float) i;
+            src->skyErr = TEST_BASE_SKY_ERR + (float) i;
+            src->psfProb = TEST_BASE_PSF_PROB + (float) i;
+            src->crNsigma = TEST_BASE_CR_N_SIGMA + (float) i;
+            src->extNsigma = TEST_BASE_EXT_N_SIGMA + (float) i;
+            src->mode = TEST_BASE_MODE + i;
+            src->peak->SN = (float) (10 - i);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_1(fitsFile, sources, imageHeader, tableHeader, extname, NULL);
+        ok(rc == true, "pmSourcesWrite_PS1_DEV_1() returned TRUE with acceptable input parameters");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesRead_PS1_DEV_1() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(tableFilename, "rw");
+        if (fitsFile == NULL) {
+            diag("ERROR: Could not create 'table' FITS file");
+            return false;
+        }
+
+        // XXX: I'm not exactly sure why, but without this, the psFitsReadTableSize() call
+        // in pmSourcesRead_PS1_DEV_1() fails.  However, Robert also did this in psFits.
+        if (1) {
+            psFitsMoveExtNum(fitsFile, 1, false);
+	}
+
+        // XX: Debugging purposes only.  Trying to duplicate the call to
+        // psFitsTableRead() from DEV_0
+        if (0) {
+            psArray *table = psFitsReadTable(fitsFile);
+            if (table == NULL) {
+                printf("ERROR: table is NULL\n");
+                exit(0);
+	    }
+            for (int i = 0; i < table->n; i++) {
+                psMetadata *row = table->data[i];
+                float sky = psMetadataLookupF32(NULL, row, "SKY");
+                printf("For row %d, the psFitsReadTable() produces a sky of %.2f\n", i, sky);
+	    }
+	}
+
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_1(fitsFile, header);
+        ok(array != NULL, "pmSourcesRead_PS1_DEV_1() returned non-NULL with acceptable input parameters");
+        skip_start(array == NULL, 1, "Skipping tests because pmSourcesRead_PS1_DEV_1() returned NULL");
+        for (int i = 0 ; i < array->n ; i++) {
+             pmSource *src = (pmSource *) array->data[i];
+             ok(src != NULL && psMemCheckSource(src), "pmSourcesRead_PS1_DEV_1() read source %d correctly", i);
+
+             // XXX: Source code always sets the type to PM_SOURCE_TYPE_STAR.  Is that right?
+             ok(src->type == PM_SOURCE_TYPE_STAR, "pmSourcesRead_PS1_DEV_1() set the source type correctly (is %d, should be %d)",
+                src->type, PM_SOURCE_TYPE_STAR);
+
+             ok(src->sky == (TEST_BASE_SKY + (float) i), "pmSourcesRead_PS1_DEV_1() set src->sky correctly (is %.2f, should be %.2f)",
+                src->sky, (TEST_BASE_SKY + (float) i));
+             ok(src->skyErr == (TEST_BASE_SKY_ERR + (float) i), "pmSourcesRead_PS1_DEV_1() set src->skyErr correctly (is %.2f, should be %.2f)",
+                src->skyErr, (TEST_BASE_SKY_ERR + (float) i));
+             ok(src->pixWeight == (TEST_BASE_PIX_WEIGHT + (float) i), "pmSourcesRead_PS1_DEV_1() set src->pixWeight correctly (is %.2f, should be %.2f)",
+                src->pixWeight, (TEST_BASE_PIX_WEIGHT + (float) i));
+             ok(TEST_FLOATS_EQUAL(src->peak->flux, (TEST_BASE_PEAK_FLUX + (float) i)), "pmSourcesRead_PS1_DEV_1() set src->peak->flux correctly (is %.2f, should be %.2f)",
+                src->peak->flux, (TEST_BASE_PEAK_FLUX + (float) i));
+             ok(src->psfMag == (TEST_BASE_PSF_MAG + (float) i), "pmSourcesRead_PS1_DEV_1() set src->psfMag correctly (is %.2f, should be %.2f)",
+                src->psfMag, (TEST_BASE_PSF_MAG + (float) i));
+             ok(src->errMag == (TEST_BASE_ERR_MAG + (float) i), "pmSourcesRead_PS1_DEV_1() set src->errMag correctly (is %.2f, should be %.2f)",
+                src->errMag, (TEST_BASE_ERR_MAG + (float) i));
+
+             // XXX: Source code always sets src->modelPSF.  Is that right?
+             pmModel *model = src->modelPSF;
+             ok(model != NULL  && psMemCheckModel(model), "pmSourcesRead_PS1_DEV_1() set src->modelPSF correctly");
+             skip_start(model == NULL, 2, "Skipping tests because pmSourcesRead_PS1_DEV_1() did not set src->modelPSF");
+             ok(model->params->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_POS + (float) i),
+               "pmSourcesRead_PS1_DEV_1() set src->model->params->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                model->params->data.F32[PM_PAR_XPOS], (TEST_BASE_X_POS + (float) i));
+             ok(model->params->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_POS + (float) i),
+               "pmSourcesRead_PS1_DEV_1() set src->model->params->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                model->params->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_POS + (float) i));
+             ok(model->dparams->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_ERR + (float) i),
+               "pmSourcesRead_PS1_DEV_1() set src->model->dparams->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                model->dparams->data.F32[PM_PAR_XPOS], (TEST_BASE_X_ERR + (float) i));
+             ok(model->dparams->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_ERR + (float) i),
+               "pmSourcesRead_PS1_DEV_1() set src->model->dparams->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                model->dparams->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_ERR + (float) i));
+             skip_end();
+	}
+        skip_end();
+        psFree(fitsFile);
+        psFree(header);
+        psFree(array);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: trunk/psModules/test/objects/tap_pmSourceIO_SMPDATA.c
===================================================================
--- trunk/psModules/test/objects/tap_pmSourceIO_SMPDATA.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmSourceIO_SMPDATA.c	(revision 15726)
@@ -0,0 +1,276 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_SOURCES		5
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(69);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesWrite_SMPDATA() tests
+    // bool pmSourcesWrite_SMPDATA (psFits *fits, psArray *sources, 
+    //      psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
+    // Call pmSourcesWrite_SMPDATA() with NULL psFits input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            src->type = PM_SOURCE_TYPE_STAR;
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_SMPDATA(NULL, sources, imageHeader, tableHeader, extname);
+        ok(rc == false, "pmSourcesWrite_SMPDATA() returned FALSE with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_SMPDATA() with NULL pmSource input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_SMPDATA(fitsFile, NULL, imageHeader, tableHeader, extname);
+        ok(rc == false, "pmSourcesWrite_SMPDATA() returned FALSE with NULL pmSource input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_SMPDATA() with NULL extname input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_SMPDATA(fitsFile, sources, imageHeader, tableHeader, NULL);
+        ok(rc == false, "pmSourcesWrite_SMPDATA() returned FALSE with NULL extname input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesRead_SMPDATA() tests
+    // psArray *pmSourcesRead_SMPDATA (psFits *fits, psMetadata *header)
+    // 
+    // Call pmSourcesRead_SMPDATA() with NULL psFits input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_SMPDATA(NULL, header);
+        ok(array == NULL, "pmSourcesRead_SMPDATA() returned NULL with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesRead_SMPDATA() with NULL header input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_SMPDATA(fitsFile, NULL);
+        ok(array == NULL, "pmSourcesRead_SMPDATA() returned NULL with NULL header input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Call pmSourcesWrite_SMPDATA() with acceptable input parameters
+    #define TEST_BASE_X_POS		10.0
+    #define TEST_BASE_Y_POS		20.0
+    #define TEST_BASE_X_ERR		30.0
+    #define TEST_BASE_Y_ERR		40.0
+    #define TEST_BASE_PSF_MAG		50.0
+    #define TEST_BASE_ERR_MAG		60.0
+    #define TEST_BASE_SKY		70.0
+    #define TEST_BASE_SKY_ERR		80.0
+    #define TEST_BASE_PIX_WEIGHT	90.0
+    #define TEST_BASE_PEAK_FLUX		120.0
+    #define TEST_BASE_EXT_MAG		150.0
+    #define TEST_BASE_AP_MAG		160.0
+    // XXX: The following metadata items are not tested: FWHM_X, FWHM_Y, THETA
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            // Set even numbered sources to PM_SOURCE_TYPE_STAR
+            pmModel *model = NULL;
+            if (i%2) {
+                src->type = PM_SOURCE_TYPE_STAR;
+                src->modelPSF = pmModelAlloc(1);
+                model = src->modelPSF;
+	    } else {
+                src->type = PM_SOURCE_TYPE_EXTENDED;
+                src->modelConv = pmModelAlloc(1);
+                model = src->modelConv;
+ 	    }
+            for (int p = 0 ; p < model->params->n ; p++) {
+                model->params->data.F32[p] = (float) (i + p);
+                model->dparams->data.F32[p] = (float) (i + p);
+	    }
+            model->params->data.F32[PM_PAR_XPOS] = TEST_BASE_X_POS + (float) i;
+            model->params->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_POS + (float) i;
+            model->dparams->data.F32[PM_PAR_XPOS] = TEST_BASE_X_ERR + (float) i;
+            model->dparams->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_ERR + (float) i;
+            src->psfMag = TEST_BASE_PSF_MAG + (float) i;
+            src->errMag = TEST_BASE_ERR_MAG + (float) i;
+            src->peak->flux = TEST_BASE_PEAK_FLUX + (float) i;
+            src->sky = TEST_BASE_SKY + (float) i;
+            src->skyErr = TEST_BASE_SKY_ERR + (float) i;
+            src->pixWeight = TEST_BASE_PIX_WEIGHT + (float) i;
+            src->extMag = TEST_BASE_EXT_MAG + (float) i;
+            src->apMag = TEST_BASE_AP_MAG + (float) i;
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_SMPDATA(fitsFile, sources, imageHeader, tableHeader, extname);
+        ok(rc == true, "pmSourcesWrite_SMPDATA() returned TRUE with acceptable input parameters");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call pmSourcesRead_SMPDATA() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "r");
+        float ZERO_POINT = 25.0;
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_SMPDATA(fitsFile, header);
+        ok(array != NULL, "pmSourcesRead_SMPDATA() returned non-NULL with acceptable input parameters");
+        skip_start(array == NULL, 1, "Skipping tests because pmSourcesRead_SMPDATA() returned NULL");
+        for (int i = 0 ; i < array->n ; i++) {
+             pmSource *src = (pmSource *) array->data[i];
+             ok(src != NULL && psMemCheckSource(src), "pmSourcesRead_SMPDATA() read source %d correctly", i);
+
+             // src->model data
+             pmModel *model = src->modelPSF;
+             ok(model != NULL  && psMemCheckModel(model), "pmSourcesRead_SMPDATA() set src->modelPSF correctly");
+             skip_start(model == NULL, 2, "Skipping tests because pmSourcesRead_SMPDATA() did not set src->modelPSF");
+             {
+                 ok(model->params->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_POS + (float) i),
+                   "pmSourcesRead_SMPDATA() set src->model->params->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                    model->params->data.F32[PM_PAR_XPOS], (TEST_BASE_X_POS + (float) i));
+
+                 ok(model->params->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_POS + (float) i),
+                   "pmSourcesRead_SMPDATA() set src->model->params->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                    model->params->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_POS + (float) i));
+
+                 float tmpSrcSky = TEST_BASE_SKY + (float) i;
+                 float lsky = (tmpSrcSky < 1.0) ? 0.0 : log10(tmpSrcSky);
+                 float tmpF = pow(10.0, lsky);
+                 ok(model->params->data.F32[PM_PAR_SKY] == tmpF,
+                   "pmSourcesRead_SMPDATA() set src->model->params->data.F32[PM_PAR_SKY] correctly (is %.2f, should be %.2f)",
+                    model->params->data.F32[PM_PAR_SKY], tmpF);
+	     }
+             ok(src->psfMag == (TEST_BASE_PSF_MAG + (float) i), "pmSourcesRead_SMPDATA() set src->psfMag correctly (is %.2f, should be %.2f)",
+                src->psfMag, (TEST_BASE_PSF_MAG + (float) i));
+             float tmpF =  0.001 * PS_MIN(999, (1000 * (TEST_BASE_ERR_MAG + (float) i)));
+             ok(src->errMag == tmpF, "pmSourcesRead_SMPDATA() set src->errMag correctly (is %.2f, should be %.2f)",
+                src->errMag, tmpF);
+             tmpF = PS_MIN(99.0, (TEST_BASE_EXT_MAG + ZERO_POINT)) - ZERO_POINT;
+             ok(src->extMag == tmpF, "pmSourcesRead_SMPDATA() set src->extMag correctly (is %.2f, should be %.2f)",
+                src->extMag, tmpF);
+             tmpF = PS_MIN(99.0, (TEST_BASE_AP_MAG + ZERO_POINT)) - ZERO_POINT;
+             ok(src->apMag == tmpF, "pmSourcesRead_SMPDATA() set src->apMag correctly (is %.2f, should be %.2f)",
+                src->apMag, tmpF);
+             if (i%2) {
+                 ok(src->type == PM_SOURCE_TYPE_STAR, "pmSourcesRead_SMPDATA() set the source type correctly (is %d, should be %d)",
+                    src->type, PM_SOURCE_TYPE_STAR);
+	     } else {
+                 ok(src->type == PM_SOURCE_TYPE_EXTENDED, "pmSourcesRead_SMPDATA() set the source type correctly (is %d, should be %d)",
+                    src->type, PM_SOURCE_TYPE_EXTENDED);
+	     }
+             tmpF = PS_MIN(255, PS_MAX(0, (255*(TEST_BASE_PIX_WEIGHT + (float) i)))) / 255.0;
+             ok(src->pixWeight == tmpF, "pmSourcesRead_SMPDATA() set src->pixWeight correctly (is %.2f, should be %.2f)",
+                src->pixWeight, tmpF);
+
+             skip_end();
+
+             if (0) { // OLD
+                 // XXX: Source code always sets the type to PM_SOURCE_TYPE_STAR.  Is that right?
+                 ok(src->sky == (TEST_BASE_SKY + (float) i), "pmSourcesRead_SMPDATA() set src->sky correctly (is %.2f, should be %.2f)",
+                    src->sky, (TEST_BASE_SKY + (float) i));
+                 if (0) {
+                     ok(src->pixWeight == (TEST_BASE_PIX_WEIGHT + (float) i), "pmSourcesRead_SMPDATA() set src->pixWeight correctly (is %.2f, should be %.2f)",
+                        src->pixWeight, (TEST_BASE_PIX_WEIGHT + (float) i));
+		 }
+                 ok(TEST_FLOATS_EQUAL(src->peak->flux, 0.0), "pmSourcesRead_SMPDATA() set src->peak->flux correctly (is %.2f, should be %.2f)",
+                    src->peak->flux, 0.0);
+                 // XXX: Source code always sets src->modelPSF.  Is that right?
+                 ok(model->dparams->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_ERR + (float) i),
+                   "pmSourcesRead_SMPDATA() set src->model->dparams->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                    model->dparams->data.F32[PM_PAR_XPOS], (TEST_BASE_X_ERR + (float) i));
+                 ok(model->dparams->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_ERR + (float) i),
+                   "pmSourcesRead_SMPDATA() set src->model->dparams->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                    model->dparams->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_ERR + (float) i));
+	     }
+	}
+        skip_end();
+        psFree(fitsFile);
+        psFree(header);
+        psFree(array);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: trunk/psModules/test/objects/tap_pmSourceSky.c
===================================================================
--- trunk/psModules/test/objects/tap_pmSourceSky.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmSourceSky.c	(revision 15726)
@@ -0,0 +1,262 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8)
+#define TEST_NUM_COLS           (16)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(26);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceLocalSky() tests
+    // Call pmSourceLocalSky() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->pixels->numRows ; i++) {
+            for (int j = 0 ; j < src->pixels->numCols ; j++) {
+                src->pixels->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSky(NULL, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSky() returned FALSE with NULL pmSource input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSky() with NULL pmSource->pixels input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSky(src, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSky() returned FALSE with NULL pmSource->pixels input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSky() with NULL pmSource->peak input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->pixels->numRows ; i++) {
+            for (int j = 0 ; j < src->pixels->numCols ; j++) {
+                src->pixels->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        bool rc = pmSourceLocalSky(src, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSky() returned FALSE with NULL pmSource->peak input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSky() with NULL pmSource->maskObj input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->pixels->numRows ; i++) {
+            for (int j = 0 ; j < src->pixels->numCols ; j++) {
+                src->pixels->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSky(src, PS_STAT_SAMPLE_MEAN, -10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSky() returned FALSE with NULL pmSource->maskObj input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSky() with negative input radius
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->pixels->numRows ; i++) {
+            for (int j = 0 ; j < src->pixels->numCols ; j++) {
+                src->pixels->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSky(src, PS_STAT_SAMPLE_MEAN, -10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSky() returned FALSE with negative input radius");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    
+    // Call pmSourceLocalSky() with acceptable input parameters
+    // XX: Future Improvements:
+    //     Test more PS_STATS types
+    //     Test more psRegion values (region bigger than image, 0 region, etc.)
+    //     Test mask values
+    //
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        psF32 mean = 0.0;
+        for (int i = 0 ; i < src->pixels->numRows ; i++) {
+            for (int j = 0 ; j < src->pixels->numCols ; j++) {
+                src->pixels->data.F32[i][j] = (float) (i + j);
+                mean+= (float) (i + j);
+                src->maskObj->data.U8[i][j] = 0;
+	    }
+	}
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSky(src, PS_STAT_SAMPLE_MEAN, 10.0, 0, 0);
+        ok(rc == true, "pmSourceLocalSky() returned TRUE with acceptable input parameters");
+        psF32 actualMean =  mean / (int) (TEST_NUM_ROWS * TEST_NUM_COLS);
+        psF32 testMean = src->moments->Sky;
+        ok(TEST_FLOATS_EQUAL(actualMean, testMean), "pmSourceLocalSky() calculated the mean correctly");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceLocalSkyVariance() tests
+    // Call pmSourceLocalSkyVariance() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->weight->numRows ; i++) {
+            for (int j = 0 ; j < src->weight->numCols ; j++) {
+                src->weight->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSkyVariance(NULL, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSkyVariance() returned FALSE with NULL pmSource input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSkyVariance() with NULL pmSource->weight input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSkyVariance(src, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSkyVariance() returned FALSE with NULL pmSource->weight input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSkyVariance() with NULL pmSource->maskObj input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->weight->numRows ; i++) {
+            for (int j = 0 ; j < src->weight->numCols ; j++) {
+                src->weight->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSkyVariance(src, PS_STAT_SAMPLE_MEAN, -10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSkyVariance() returned FALSE with NULL pmSource->maskObj input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSkyVariance() with NULL pmSource->peak input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->weight->numRows ; i++) {
+            for (int j = 0 ; j < src->weight->numCols ; j++) {
+                src->weight->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        bool rc = pmSourceLocalSkyVariance(src, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSkyVariance() returned FALSE with NULL pmSource->peak input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSkyVariance() with negative input radius
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->weight->numRows ; i++) {
+            for (int j = 0 ; j < src->weight->numCols ; j++) {
+                src->weight->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSkyVariance(src, PS_STAT_SAMPLE_MEAN, -10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSkyVariance() returned FALSE with negative input radius");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSkyVariance() with acceptable input parameters
+    // XX: Future Improvements:
+    //     Test more PS_STATS types
+    //     Test more psRegion values (region bigger than image, 0 region, etc.)
+    //     Test mask values
+    //
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        psF32 mean = 0.0;
+        for (int i = 0 ; i < src->weight->numRows ; i++) {
+            for (int j = 0 ; j < src->weight->numCols ; j++) {
+                src->weight->data.F32[i][j] = (float) (i + j);
+                mean+= (float) (i + j);
+                src->maskObj->data.U8[i][j] = 0;
+	    }
+	}
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSkyVariance(src, PS_STAT_SAMPLE_MEAN, 10.0, 0, 0);
+        ok(rc == true, "pmSourceLocalSkyVariance() returned TRUE with acceptable input parameters");
+        psF32 actualMean =  mean / (int) (TEST_NUM_ROWS * TEST_NUM_COLS);
+        psF32 testMean = src->moments->dSky;
+        ok(TEST_FLOATS_EQUAL(actualMean, testMean), "pmSourceLocalSky() calculated the mean correctly");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: trunk/psModules/test/objects/tap_pmSourceUtils.c
===================================================================
--- trunk/psModules/test/objects/tap_pmSourceUtils.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmSourceUtils.c	(revision 15726)
@@ -0,0 +1,252 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+// XXX: We only test with unallowable input parameters so far.
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8)
+#define TEST_NUM_COLS           (16)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_SOURCES		100
+
+#define CELL_ALLOC_NAME        "CellName"
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = generateSimpleReadout(cell);
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+//    psRegion *region = psRegionAlloc(0.0, TEST_NUM_COLS-1, 0.0, TEST_NUM_ROWS-1);
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+void myFreeCell(pmCell *cell)
+{
+    for (int k = 0 ; k < cell->readouts->n ; k++) {
+        psFree(cell->readouts->data[k]);
+    }
+    psFree(cell);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    psTraceSetLevel("psModules.objects", 0);
+    plan_tests(14);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceModelGuess() tests
+    // pmModel *pmSourceModelGuess(pmSource *source, pmModelType modelType)
+    // Call pmSourceModelGuess() with NULL pmSource input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        src->moments = pmMomentsAlloc();
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *model = pmSourceModelGuess(NULL, type);
+        ok(model == NULL, "pmSourceModelGuess() returned NULL with NULL pmSource input parameter");
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceModelGuess() with NULL pmSource->peak input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->moments = pmMomentsAlloc();
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *model = pmSourceModelGuess(NULL, type);
+        ok(model == NULL, "pmSourceModelGuess() returned NULL with NULL pmSource->peak input parameter");
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceModelGuess() with NULL pmSource->moments input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *model = pmSourceModelGuess(NULL, type);
+        ok(model == NULL, "pmSourceModelGuess() returned NULL with NULL pmSource->moments input parameter");
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmModel *pmSourceModelGuess(pmSource *source, pmModelType modelType)
+    // Call pmSourceModelGuess() with acceptable input parameters
+    // XXX: Must verify that the values of the new pmModel are set correctly.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        src->moments = pmMomentsAlloc();
+
+        src->moments->Sx = 1.0;
+        src->moments->y = 2.0;
+        src->moments->Sxy = 3.0;
+        src->moments->Sky = 4.0;
+        src->moments->Peak = 5.0;
+        src->moments->x = 6.0;
+        src->moments->y = 7.0;
+
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *testModel = pmModelAlloc(type);
+        testModel->modelGuess(testModel, src);
+        pmModel *model = pmSourceModelGuess(src, type);
+        ok(model != NULL, "pmSourceModelGuess() returned non-NULL with acceptable input parameters");
+
+        psFree(src);
+        psFree(testModel);
+        psFree(model);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceModelGuess() tests
+    // pmSource *pmSourceFromModel (pmModel *model, pmReadout *readout, 
+    //                              float radius, pmSourceType type)
+    // Call pmSourceFromModel() with NULL pmModel input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *model = pmModelAlloc(type);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *readout = cell->readouts->data[0];
+        pmSource *src = pmSourceFromModel(NULL, readout, 10.0, PM_SOURCE_TYPE_STAR);
+        ok(src == NULL, "pmSourceFromModel() returned NULL with NULL pmModel input parameter");
+        psFree(model);
+        psFree(src);
+        myFreeCell(cell);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFromModel() with NULL pmReadout input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *model = pmModelAlloc(type);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmSource *src = pmSourceFromModel(model, NULL, 10.0, PM_SOURCE_TYPE_STAR);
+        ok(src == NULL, "pmSourceFromModel() returned NULL with NULL pmReadout input parameter");
+        psFree(model);
+        psFree(src);
+        myFreeCell(cell);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFromModel() with acceptable input parameters
+    // XXX: Must verify that the values of the new pmSource are set correctly.
+    if (1) {
+        psMemId id = psMemGetId();
+
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *model = pmModelAlloc(type);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *readout = cell->readouts->data[0];
+        pmSource *src = pmSourceFromModel(model, readout, 10.0, PM_SOURCE_TYPE_STAR);
+        ok(src != NULL, "pmSourceFromModel() returned non-NULL with acceptable input parameters");
+        psFree(model);
+        // XXX: We get psMemory aborts if the following is not done.
+        // There is probably an issue with psMemIncrRefCounter() in pmSourceUtils.c
+        src->modelPSF = NULL;
+        src->modelEXT = NULL;
+        psFree(src);
+        myFreeCell(cell);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+}
+
Index: trunk/psModules/test/objects/tap_pmTrend2D.c
===================================================================
--- trunk/psModules/test/objects/tap_pmTrend2D.c	(revision 15726)
+++ trunk/psModules/test/objects/tap_pmTrend2D.c	(revision 15726)
@@ -0,0 +1,333 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_ROWS 8
+#define NUM_COLS 16
+#define ERR_TRACE_LEVEL 0
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(35);
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DAlloc()
+    // pmTrend2D *pmTrend2DAlloc(pmTrend2DMode mode, psImage *image,
+    //                           int nXtrend, int nYtrend, psStats *stats)
+    // Call pmTrend2DAlloc() with NULL psImage input parameter (PM_TREND_MAP)
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DAlloc(PM_TREND_MAP, NULL, 2, 2, stats);
+        ok(trend == NULL, "pmTrend2DAlloc() returned NULL with NULL psImage input parameter");
+        psFree(img);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DAlloc() with NULL psImage input parameter (PM_TREND_POLY_ORD)
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DAlloc(PM_TREND_POLY_ORD, NULL, 2, 2, stats);
+        ok(trend != NULL, "pmTrend2DAlloc() returned NULL with NULL psImage input parameter");
+        psFree(img);
+        psFree(stats);
+        psFree(trend);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DAlloc() with NULL psStats input parameter
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DAlloc(PM_TREND_POLY_ORD, img, 2, 2, NULL);
+        ok(trend == NULL, "pmTrend2DAlloc() returned NULL with NULL psStats input parameter");
+        psFree(img);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DAlloc() with unallowed pmTrend2DMode
+    // XXX: We skip this test because pmTrend2DAlloc() aborts.
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DAlloc(999, img, 2, 2, stats);
+        ok(trend == NULL, "pmTrend2DAlloc() returned NULL with unallowed pmTrend2DMode");
+        psFree(img);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DAlloc() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+
+        // Call pmTrend2DAlloc() with PM_TREND_POLY_ORD
+        pmTrend2D *trend = pmTrend2DAlloc(PM_TREND_POLY_ORD, img, 2, 4, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), 
+          "pmTrend2DAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->map == NULL, "pmTrend2DAlloc() set trend->map to NULL");
+        ok(trend->mode == PM_TREND_POLY_ORD, "pmTrend2DAlloc() set trend->mode correctly");
+        ok(trend->stats == stats, "pmTrend2DAlloc() set trend->stats correctly");
+        ok(trend->poly != NULL && trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->nX == 2, "pmTrend2DAlloc() set trend->poly->nX correctly");
+        ok(trend->poly->nY == 4, "pmTrend2DAlloc() set trend->poly->nY correctly");
+        psFree(trend);
+
+        // Call pmTrend2DAlloc() with PM_TREND_POLY_CHEB
+        trend = pmTrend2DAlloc(PM_TREND_POLY_CHEB, img, 2, 4, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), 
+          "pmTrend2DAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->map == NULL, "pmTrend2DAlloc() set trend->map to NULL");
+        ok(trend->mode == PM_TREND_POLY_CHEB, "pmTrend2DAlloc() set trend->mode correctly");
+        ok(trend->stats == stats, "pmTrend2DAlloc() set trend->stats correctly");
+        ok(trend->poly != NULL && trend->poly->type == PS_POLYNOMIAL_CHEB, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->type == PS_POLYNOMIAL_CHEB, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->nX == 2, "pmTrend2DAlloc() set trend->poly->nX correctly");
+        ok(trend->poly->nY == 4, "pmTrend2DAlloc() set trend->poly->nY correctly");
+        psFree(trend);
+
+        // Create a new pmTrend with PM_TREND_MAP
+        trend = pmTrend2DAlloc(PM_TREND_MAP, img, 2, 4, stats);
+        ok(trend->map != NULL && psMemCheckImageMap(trend->map), 
+           "pmTrend2DAlloc() set trend->map correctly");
+        psFree(trend);
+
+        psFree(img);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DNoImageAlloc()
+    // pmTrend2D *pmTrend2DNoImageAlloc (pmTrend2DMode mode,
+    //          psImageBinning *binning, psStats *stats)
+    // Call pmTrend2DNoImageAlloc() with NULL psImageBinning input parameter
+    {
+        psMemId id = psMemGetId();
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psImageBinning *binning = psImageBinningAlloc();
+        pmTrend2D *trend = pmTrend2DNoImageAlloc(PM_TREND_MAP, NULL, stats);
+        ok(trend == NULL, "pmTrend2DNoImageAlloc() returned NULL with NULL psImageBinning input parameter");
+        psFree(stats);
+        psFree(binning);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DNoImageAlloc() with NULL psStats input parameter
+    {
+        psMemId id = psMemGetId();
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psImageBinning *binning = psImageBinningAlloc();
+        pmTrend2D *trend = pmTrend2DNoImageAlloc(PM_TREND_MAP, binning, NULL);
+        ok(trend == NULL, "pmTrend2DNoImageAlloc() returned NULL with NULL psStats input parameter");
+        psFree(stats);
+        psFree(binning);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DNoImageAlloc() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psImageBinning *binning = psImageBinningAlloc();
+        binning->nXruff = 2;
+        binning->nYruff = 4;
+
+        // Call pmTrend2DNoImageAlloc() with PM_TREND_POLY_ORD
+        pmTrend2D *trend = pmTrend2DNoImageAlloc(PM_TREND_POLY_ORD, binning, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), "pmTrend2DNoImageAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->map == NULL, "pmTrend2DAlloc() set trend->map to NULL");
+        ok(trend->mode == PM_TREND_POLY_ORD, "pmTrend2DAlloc() set trend->mode correctly");
+        ok(trend->stats == stats, "pmTrend2DAlloc() set trend->stats correctly");
+        ok(trend->poly != NULL && trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->nX == 2, "pmTrend2DAlloc() set trend->poly->nX correctly");
+        ok(trend->poly->nY == 4, "pmTrend2DAlloc() set trend->poly->nY correctly");
+        psFree(trend);
+
+        // Call pmTrend2DNoImageAlloc() with PM_TREND_POLY_CHEB
+        trend = pmTrend2DNoImageAlloc(PM_TREND_POLY_CHEB, binning, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), "pmTrend2DNoImageAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->map == NULL, "pmTrend2DAlloc() set trend->map to NULL");
+        ok(trend->mode == PM_TREND_POLY_CHEB, "pmTrend2DAlloc() set trend->mode correctly");
+        ok(trend->stats == stats, "pmTrend2DAlloc() set trend->stats correctly");
+        ok(trend->poly != NULL && trend->poly->type == PS_POLYNOMIAL_CHEB, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->type == PS_POLYNOMIAL_CHEB, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->nX == 2, "pmTrend2DAlloc() set trend->poly->nX correctly");
+        ok(trend->poly->nY == 4, "pmTrend2DAlloc() set trend->poly->nY correctly");
+        psFree(trend);
+
+        // Call pmTrend2DNoImageAlloc() with PM_TREND_MAP
+        trend = pmTrend2DNoImageAlloc(PM_TREND_MAP, binning, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), "pmTrend2DNoImageAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->map && psMemCheckImageMap(trend->map), "pmTrend2DNoImageAlloc() set the trend->map correctly");
+        psFree(trend);
+
+        psFree(stats);
+        psFree(binning);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DFieldAlloc()
+    // pmTrend2D *pmTrend2DFieldAlloc (pmTrend2DMode mode, int nXfield,
+    //           int nYfield, int nXtrend, int nYtrend, psStats *stats)
+    // 
+    // Call pmTrend2DFieldAlloc() with NULL psStats input parameter
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DFieldAlloc(PM_TREND_MAP, 1, 2, 3, 4, NULL);
+        ok(trend == NULL, "pmTrend2DFieldAlloc() returned NULL with NULL psStats input parameter");
+        psFree(img);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DFieldAlloc() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DFieldAlloc(PM_TREND_POLY_ORD, 1, 2, 3, 4, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), "pmTrend2DFieldAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->poly != NULL && trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DFieldAlloc() set trend->poly->type correctly");
+        ok(trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DFieldAlloc() set trend->poly->type correctly");
+        ok(trend->poly->nX == 3, "pmTrend2DFieldAlloc() set trend->poly->nX correctly");
+        ok(trend->poly->nY == 4, "pmTrend2DFieldAlloc() set trend->poly->nY correctly");
+        psFree(trend);
+
+        // Create a new pmTrend with PM_TREND_MAP
+        // XXX: This currently fails due to a big in pmTrend2DFieldAlloc():
+        // psImageMapAlloc() is called with a NULL field input parameter.
+        {
+            trend = pmTrend2DFieldAlloc(PM_TREND_MAP, 1, 2, 3, 4, stats);
+            ok(trend->map != NULL && psMemCheckImageMap(trend->map), 
+               "pmTrend2DAlloc() set trend->map correctly");
+	}
+
+        psFree(stats);
+        psFree(trend);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DModeToString()
+    // psString pmTrend2DModeToString (pmTrend2DMode mode)
+    // Call pmTrend2DModeToString() with unallowed pmTrend2DMode.
+    // XXX: We comment this out because pmTrend2DModeToString() aborts.
+    if (0) {
+        psMemId id = psMemGetId();
+        psString str = pmTrend2DModeToString(99);
+        ok(str == NULL, "pmTrend2DModeToString() returned NULL with unallowed pmTrend2DMode");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeToString() with unallowed pmTrend2DMode.
+    // XXX: We comment this out because pmTrend2DModeToString() aborts.
+    {
+        psMemId id = psMemGetId();
+        psString str = pmTrend2DModeToString(PM_TREND_NONE);
+        ok(!strcmp(str, "NONE"), "pmTrend2DModeToString(PM_TREND_NONE)");
+        psFree(str);
+
+        str = pmTrend2DModeToString(PM_TREND_POLY_ORD);
+        ok(!strcmp(str, "POLY_ORD"), "pmTrend2DModeToString(PM_TREND_POLY_ORD)");
+        psFree(str);
+
+        str = pmTrend2DModeToString(PM_TREND_POLY_CHEB);
+        ok(!strcmp(str, "POLY_CHEB"), "pmTrend2DModeToString(PM_TREND_POLY_CHEB)");
+        psFree(str);
+
+        str = pmTrend2DModeToString(PM_TREND_MAP);
+        ok(!strcmp(str, "MAP"), "pmTrend2DModeToString(PM_TREND_MAP)");
+        psFree(str);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DModeFromString()
+    // pmTrend2DMode pmTrend2DModeFromString (psString name) {
+    // Call pmTrend2DModeFromString() with NULL input parameter
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString(NULL);
+        ok(PM_TREND_NONE == mode, "pmTrend2DModeFromString(NULL) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeFromString() with unallowed input string
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString("BOGUS");
+        ok(PM_TREND_NONE == mode, "pmTrend2DModeFromString(BOGUS) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeFromString() with unallowed input string
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString("NONE");
+        ok(PM_TREND_NONE == mode, "pmTrend2DModeFromString(NONE) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeFromString() with unallowed input string
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString("POLY_ORD");
+        ok(PM_TREND_POLY_ORD == mode, "pmTrend2DModeFromString(POLY_ORD) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeFromString() with unallowed input string
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString("POLY_CHEB");
+        ok(PM_TREND_POLY_CHEB == mode, "pmTrend2DModeFromString(POLY_CHEB) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeFromString() with unallowed input string
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString("MAP");
+        ok(PM_TREND_MAP == mode, "pmTrend2DModeFromString(MAP) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+}
