Index: /trunk/psModules/src/astrom/pmAstrometry.c
===================================================================
--- /trunk/psModules/src/astrom/pmAstrometry.c	(revision 5586)
+++ /trunk/psModules/src/astrom/pmAstrometry.c	(revision 5587)
@@ -8,9 +8,40 @@
 *  @author GLG, MHPCC
 *
-*  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-11-19 01:11:03 $
+*  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-11-23 23:54:30 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 /******************************************************************************/
@@ -22,22 +53,4 @@
 #include "psDB.h"
 #include "pmAstrometry.h"
-
-void PS_PRINT_POLY2D(psPolynomial2D *poly)
-{
-    for (psS32 x = 0 ; x < poly->nX+1 ; x++) {
-        for (psS32 y = 0 ; y < poly->nY+1 ; y++) {
-            printf("    (%.2f x^%d y^%d)\n", poly->coeff[x][y], x, y);
-        }
-    }
-}
-
-void PS_PRINT_PLANE_TRANSFORM(psPlaneTransform *pt)
-{
-    printf("---------------------- Plane Transform ----------------------\n");
-    printf("x:\n");
-    PS_PRINT_POLY2D(pt->x);
-    printf("y:\n");
-    PS_PRINT_POLY2D(pt->y);
-}
 
 /*****************************************************************************
@@ -70,4 +83,18 @@
         psFree(readout->mask);
         psFree(readout->weight);
+        //
+        // XXX: Not sure if this is the right way to do things.  Currently the psListAdd()
+        // increase the memory reference counter to the list data.  So, we
+        // iterate through the list, and decrement the reference counters.
+        //
+        if (1) {
+            if ((readout->bias != NULL) && (readout->bias->head != NULL)) {
+                psListElem *tmpElem = (psListElem *) readout->bias->head;
+                while (NULL != tmpElem) {
+                    psMemDecrRefCounter((psImage *) tmpElem->data);
+                    tmpElem = tmpElem->next;
+                }
+            }
+        }
         psFree(readout->bias);
         psFree(readout->analysis);
@@ -84,5 +111,4 @@
         psFree(cell->toSky);
         psFree(cell->concepts);
-        psFree(cell->camera);
         psFree(cell->analysis);
         //
@@ -195,5 +221,4 @@
     }
     tmpCell->camera = cameradata;
-    psMemIncrRefCounter((psMetadata *) cameradata);
     tmpCell->analysis = NULL;
     tmpCell->readouts = psArrayAlloc(0);
@@ -247,5 +272,4 @@
     tmpFPA->analysis = NULL;
     tmpFPA->camera = camera;
-    psMemIncrRefCounter((psPtr) camera);
     tmpFPA->chips = psArrayAlloc(0);
     tmpFPA->private = NULL;
@@ -338,8 +362,16 @@
 
     // Convert to those chip coordinates.
-    pmCoordFPAToChip(&chipCoord, fpaCoord, tmpChip);
+    psPlane *rc = pmCoordFPAToChip(&chipCoord, fpaCoord, tmpChip);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine Chip coords.\n");
+        return(NULL);
+    }
 
     // Determine which cell contains those chip coordinates.
     outCell = pmCellInChip(&chipCoord, tmpChip);
+    if (outCell == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the cell.\n");
+        return(NULL);
+    }
 
     return (outCell);
@@ -379,5 +411,5 @@
     }
 
-    // XXX: Print warning here?
+    psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the chip.\n");
     return (NULL);
 }
@@ -414,10 +446,12 @@
             chipToCell = p_psPlaneTransformLinearInvert(tmpCell->toChip);
         } else {
-            // XXX: Generate warning message.
-            // XXX: Can we use the following function to derive a transform?
-            // chipToCell = psPlaneTransformInvert(NULL, tmpCell->toChip, NULL, -1);
-        }
-
-        PS_ASSERT_PTR_NON_NULL(chipToCell, NULL);
+            psLogMsg(__func__, PS_LOG_WARN, "WARNING: non-linear cell->chip transforms are not yet implemented.\n");
+            //chipToCell = psPlaneTransformInvert(NULL, tmpCell->toChip, NULL, -1);
+            chipToCell = NULL;
+        }
+        if (chipToCell == NULL) {
+            psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not invert the Cell->toChip transform.\n");
+            return(NULL);
+        }
         psArray* readouts = tmpCell->readouts;
 
@@ -442,7 +476,56 @@
     }
 
+    psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the cell.\n");
     return (NULL);
 }
 
+
+psPlane* pmCoordCellToFPA(
+    psPlane* fpaCoord,
+    const psPlane* cellCoord,
+    const pmCell* cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cellCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+
+    psPlane *rc = psPlaneTransformApply(fpaCoord, cell->toFPA, cellCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform cell coords to FPA coords.\n");
+    }
+    return(rc);
+}
+
+
+psPlane* pmCoordChipToFPA(
+    psPlane* outCoord,
+    const psPlane* inCoord,
+    const pmChip* chip)
+{
+    PS_ASSERT_PTR_NON_NULL(inCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(chip, NULL);
+
+    psPlane *rc = psPlaneTransformApply(outCoord, chip->toFPA, inCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform chip coords to FPA coords.\n");
+    }
+    return(rc);
+}
+
+
+psPlane* pmCoordFPAToChip(
+    psPlane* chipCoord,
+    const psPlane* fpaCoord,
+    const pmChip* chip)
+{
+    PS_ASSERT_PTR_NON_NULL(fpaCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(chip, NULL);
+    PS_ASSERT_PTR_NON_NULL(chip->fromFPA, NULL);
+
+    psPlane *rc = psPlaneTransformApply(chipCoord, chip->fromFPA, fpaCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform FPA coords to Chip coords.\n");
+    }
+    return(rc);
+}
 
 psPlane* pmCoordCellToChip(
@@ -454,19 +537,47 @@
     PS_ASSERT_PTR_NON_NULL(cell, NULL);
 
-    return (psPlaneTransformApply(outCoord, cell->toChip, inCoord));
-}
-
-
-psPlane* pmCoordChipToFPA(
-    psPlane* outCoord,
-    const psPlane* inCoord,
-    const pmChip* chip)
-{
-    PS_ASSERT_PTR_NON_NULL(inCoord, NULL);
-    PS_ASSERT_PTR_NON_NULL(chip, NULL);
-
-    return (psPlaneTransformApply(outCoord, chip->toFPA, inCoord));
-}
-
+    psPlane *rc = psPlaneTransformApply(outCoord, cell->toChip, inCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform Cell coords to Chip coords.\n");
+    }
+    return(rc);
+}
+
+psPlane* pmCoordChipToCell(
+    psPlane* cellCoord,
+    const psPlane* chipCoord,
+    const pmCell* cell)
+{
+    PS_ASSERT_PTR_NON_NULL(chipCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->parent, NULL);
+
+    pmCell *tmpCell = pmCellInChip(chipCoord, cell->parent);
+    if (tmpCell == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the proper cell.\n");
+        return(NULL);
+    }
+
+    psPlaneTransform *tmpChipToCell = NULL;
+    PS_ASSERT_PTR_NON_NULL(tmpCell->toChip, NULL);
+    if (true ==  p_psIsProjectionLinear(tmpCell->toChip)) {
+        tmpChipToCell = p_psPlaneTransformLinearInvert(tmpCell->toChip);
+    } else {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: non-linear cell->chip transforms are not yet implemented.\n");
+        // XXX: tmpChipToCell = psPlaneTransformInvert(NULL, tmpCell->toChip, NULL, -1);
+        tmpChipToCell = NULL;
+    }
+    if (tmpChipToCell == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not invert the Cell->toChip transform.\n");
+        return(NULL);
+    }
+
+    psPlane *rc = psPlaneTransformApply(cellCoord, tmpChipToCell, chipCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform Chip coords to Cell coords.\n");
+    }
+    psFree(tmpChipToCell);
+    return(rc);
+}
 
 psPlane* pmCoordFPAToTP(
@@ -480,5 +591,52 @@
     PS_ASSERT_PTR_NON_NULL(fpa, NULL);
 
-    return(psPlaneDistortApply(outCoord, fpa->toTangentPlane, inCoord, color, magnitude));
+    psPlane *rc = psPlaneDistortApply(outCoord, fpa->toTangentPlane, inCoord, color, magnitude);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform FPA coords to tangent plane coords.\n");
+    }
+    return(rc);
+}
+
+psPlane* pmCoordTPToFPA(
+    psPlane* fpaCoord,
+    const psPlane* tpCoord,
+    double color,
+    double magnitude,
+    const pmFPA* fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(tpCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa->fromTangentPlane, NULL);
+
+    psPlane *rc = psPlaneDistortApply(fpaCoord, fpa->fromTangentPlane, tpCoord, color, magnitude);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform tangent plane coords to FPA coords.\n");
+    }
+    return(rc);
+}
+
+
+/*****************************************************************************
+XXXDeproject(outSphere, coord, projection): This private routine is a wrapper
+for p_psDeproject().  The reason: p_psDeproject() and p_psProject() combined
+do not seem to produce the original coordinates when they even though they
+should.  XXXDeproject() simply negates the ->r and ->d members of the output
+psSphere if the input ->y is larger than 0.0.  I don't know why it works.
+ 
+I'm guessing the p_psProject() and p_psDeproject() functions have bugs.
+ *****************************************************************************/
+psSphere* XXXDeproject(
+    psSphere *outSphere,
+    const psPlane* coord,
+    const psProjection* projection)
+{
+    psSphere *rc = p_psDeproject(outSphere, coord, projection);
+
+    if (coord->y >= 0.0) {
+        rc->d = -rc->d;
+        rc->r = -rc->r;
+    }
+
+    return(rc);
 }
 
@@ -496,5 +654,9 @@
     PS_ASSERT_PTR_NON_NULL(projection, NULL);
 
-    return(p_psDeproject(outSphere, tpCoord, projection));
+    psSphere *rc = XXXDeproject(outSphere, tpCoord, projection);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform tangent plane coords to sky coords.\n");
+    }
+    return(rc);
 }
 /*****************************************************************************
@@ -511,17 +673,9 @@
     PS_ASSERT_PTR_NON_NULL(projection, NULL);
 
-    return(p_psProject(tpCoord, in, projection));
-}
-
-
-psPlane* pmCoordCellToFPA(
-    psPlane* fpaCoord,
-    const psPlane* cellCoord,
-    const pmCell* cell)
-{
-    PS_ASSERT_PTR_NON_NULL(cellCoord, NULL);
-    PS_ASSERT_PTR_NON_NULL(cell, NULL);
-
-    return (psPlaneTransformApply(fpaCoord, cell->toFPA, cellCoord));
+    psPlane *rc = p_psProject(tpCoord, in, projection);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform sky to tangent plane coords.\n");
+    }
+    return(rc);
 }
 
@@ -545,16 +699,78 @@
     psPlane fpaCoord;
     psPlane tpCoord;
+    psPlane *rc;
     pmFPA* parFPA = (cell->parent)->parent;
 
     // Convert the input cell coordinates to FPA coordinates.
-    psPlaneTransformApply(&fpaCoord, cell->toFPA, cellCoord);
+    rc = psPlaneTransformApply(&fpaCoord, cell->toFPA, cellCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could transform cell coords to FPA coords.\n");
+        return(NULL);
+    }
 
     // Convert the FPA coordinates to tangent plane Coordinates.
-    psPlaneDistortApply(&tpCoord, parFPA->toTangentPlane, &fpaCoord, color, magnitude);
+    rc = psPlaneDistortApply(&tpCoord, parFPA->toTangentPlane, &fpaCoord, color, magnitude);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could transform FPA coords to tangent plane coords.\n");
+        return(NULL);
+    }
 
     // Convert the tangent plane Coordinates to sky coordinates.
-    return(pmCoordTPToSky(NULL, &tpCoord, parFPA->projection));
-}
-
+    psSphere *rc2 = pmCoordTPToSky(skyCoord, &tpCoord, parFPA->projection);
+    if (rc2 == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform cell coords to sky coords.\n");
+    }
+
+    return(rc2);
+}
+
+psPlane* pmCoordSkyToCell(
+    psPlane* cellCoord,
+    const psSphere* skyCoord,
+    float color,
+    float magnitude,
+    const pmCell* cell)
+{
+    PS_ASSERT_PTR_NON_NULL(skyCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->parent, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->parent->parent, NULL);
+    pmChip *parChip = cell->parent;
+    pmFPA *parFPA = parChip->parent;
+    psPlane tpCoord;
+    psPlane fpaCoord;
+    psPlane chipCoord;
+    psPlane *rc;
+
+    // Convert the skyCoords to tangent plane coords.
+    rc = pmCoordSkyToTP(&tpCoord, skyCoord, parFPA->projection);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine tangent plane coords.\n");
+        return(NULL);
+    }
+
+    // Convert the tangent plane coords to FPA coords.
+    rc = pmCoordTPToFPA(&fpaCoord, &tpCoord, color, magnitude, parFPA);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine FPA coords.\n");
+        return(NULL);
+    }
+
+    // Convert the FPA coords to chip coords.
+    rc = pmCoordFPAToChip(&chipCoord, &fpaCoord, parChip);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine chip coords.\n");
+        return(NULL);
+    }
+
+    // Convert the chip coords to cell coords.
+    rc = pmCoordChipToCell(cellCoord, &chipCoord, cell);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine cell coords.\n");
+        return(NULL);
+    }
+
+    return (cellCoord);
+}
 
 // XXX: This has not been tested.
@@ -569,5 +785,11 @@
     PS_ASSERT_PTR_NON_NULL(cell->toSky, NULL);
     psPlane outPlane;
-    psPlaneTransformApply(&outPlane, cell->toSky, cellCoord);
+    psPlane *rc;
+    rc = psPlaneTransformApply(&outPlane, cell->toSky, cellCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could transform cell coords to sky coords.\n");
+        return(NULL);
+    }
+
     psSphere *out = outSphere;
     if (out == NULL) {
@@ -577,5 +799,5 @@
     out->d = outPlane.x;
 
-    return(NULL);
+    return(out);
 }
 
@@ -599,86 +821,8 @@
     skyPlane.x = skyCoord->d;
 
-    return(psPlaneTransformApply(cellCoord, cell->toSky, &skyPlane));
-}
-
-
-psPlane* pmCoordTPToFPA(
-    psPlane* fpaCoord,
-    const psPlane* tpCoord,
-    double color,
-    double magnitude,
-    const pmFPA* fpa)
-{
-    PS_ASSERT_PTR_NON_NULL(tpCoord, NULL);
-    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
-    PS_ASSERT_PTR_NON_NULL(fpa->fromTangentPlane, NULL);
-
-    return (psPlaneDistortApply(fpaCoord, fpa->fromTangentPlane, tpCoord, color, magnitude));
-}
-
-
-psPlane* pmCoordFPAToChip(
-    psPlane* chipCoord,
-    const psPlane* fpaCoord,
-    const pmChip* chip)
-{
-    PS_ASSERT_PTR_NON_NULL(fpaCoord, NULL);
-    PS_ASSERT_PTR_NON_NULL(chip, NULL);
-    PS_ASSERT_PTR_NON_NULL(chip->fromFPA, NULL);
-
-    chipCoord = psPlaneTransformApply(chipCoord, chip->fromFPA, fpaCoord);
-    return(chipCoord);
-}
-
-psPlane* pmCoordChipToCell(
-    psPlane* cellCoord,
-    const psPlane* chipCoord,
-    const pmCell* cell)
-{
-    PS_ASSERT_PTR_NON_NULL(chipCoord, NULL);
-    PS_ASSERT_PTR_NON_NULL(cell, NULL);
-    PS_ASSERT_PTR_NON_NULL(cell->parent, NULL);
-
-    pmCell *tmpCell = pmCellInChip(chipCoord, cell->parent);
-    PS_ASSERT_PTR_NON_NULL(tmpCell->toChip, NULL);
-    psPlaneTransform *tmpChipToCell = p_psPlaneTransformLinearInvert(tmpCell->toChip);
-    PS_ASSERT_PTR_NON_NULL(tmpChipToCell, NULL);
-    cellCoord = psPlaneTransformApply(cellCoord, tmpChipToCell, chipCoord);
-    psFree(tmpChipToCell);
+    psPlane *rc = psPlaneTransformApply(cellCoord, cell->toSky, &skyPlane);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform sky to cell coords.\n");
+    }
     return(cellCoord);
 }
-
-
-psPlane* pmCoordSkyToCell(
-    psPlane* cellCoord,
-    const psSphere* skyCoord,
-    float color,
-    float magnitude,
-    const pmCell* cell)
-{
-    PS_ASSERT_PTR_NON_NULL(skyCoord, NULL);
-    PS_ASSERT_PTR_NON_NULL(cell, NULL);
-    PS_ASSERT_PTR_NON_NULL(cell->parent, NULL);
-    PS_ASSERT_PTR_NON_NULL(cell->parent->parent, NULL);
-    pmChip *parChip = cell->parent;
-    pmFPA *parFPA = parChip->parent;
-
-    // Convert the skyCoords to tangent plane coords.
-    psPlane *tpCoord = pmCoordSkyToTP(NULL, skyCoord, parFPA->projection);
-
-    // Convert the tangent plane coords to FPA coords.
-    psPlane *fpaCoord = pmCoordTPToFPA(NULL, tpCoord, color, magnitude, parFPA);
-
-    // Convert the FPA coords to chip coords.
-    psPlane *chipCoord = pmCoordFPAToChip(NULL, fpaCoord, parChip);
-
-    // Convert the chip coords to cell coords.
-    cellCoord = pmCoordChipToCell(cellCoord, chipCoord, cell);
-
-    psFree(tpCoord);
-    psFree(fpaCoord);
-    psFree(chipCoord);
-
-    return (cellCoord);
-}
-
Index: /trunk/psModules/src/imsubtract/pmSubtractBias.h
===================================================================
--- /trunk/psModules/src/imsubtract/pmSubtractBias.h	(revision 5586)
+++ /trunk/psModules/src/imsubtract/pmSubtractBias.h	(revision 5587)
@@ -6,6 +6,6 @@
  *  @author GLG, MHPCC
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-11-15 20:09:03 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-11-23 23:54:30 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -48,7 +48,4 @@
     const pmReadout *dark               ///< A possibly NULL bias pmReadout which is to be subtracted
 );
-// OLD: remove this
-//    const psList *overscans,      ///< A psList of overscan images
-//    pmOverscanAxis overScanAxis,  ///< Defines how overscans are applied
 
 /******************************************************************************
Index: /trunk/psModules/test/astrom/tst_pmAstrometry.c
===================================================================
--- /trunk/psModules/test/astrom/tst_pmAstrometry.c	(revision 5586)
+++ /trunk/psModules/test/astrom/tst_pmAstrometry.c	(revision 5587)
@@ -1,15 +1,13 @@
 /** @file  tst_pmAstrometry.c
  *
- *  @brief Contains the tests: pmAstrometry.[ch].  Only the pmxxxAlloc()
+ *  @brief Contains the tests: pmAstrometry.[ch].  The pmxxxAlloc()
  *  and psFree() functionality are used here.
  *
- *  @author George Gusciora, MHPCC
+ *  @author GLG, MHPCC
  *
- * XXX: Significant work needed: must test the variout coordinate transformation function.
+ *  XXX: Untested: pmFPACheckParents()
  *
- *
- *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-11-18 19:43:14 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-11-23 23:54:30 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -38,4 +36,116 @@
 #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 32
+#define TEST_NUM_COLS 32
+
+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);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmFPA *generateSimpleFPA()
+{
+    psBool rc;
+    pmFPA* fpa = pmFPAAlloc(psMetadataAlloc());
+
+    if (fpa == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc() returned a NULL.");
+        return(NULL);
+    }
+
+    //
+    // Test and create camera metadata.
+    //
+    if (fpa->camera == NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: fpa->camera is NULL.");
+        psFree(fpa);
+        return(NULL);
+    } else {
+        rc = psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+        if (rc == false) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not add metadata to fpa->camera.");
+            psFree(fpa);
+            return(NULL);
+        }
+        psS32 tmpS32 = psMetadataLookupS32(&rc, fpa->camera, MISC_NAME);
+        if ((rc == false) || (tmpS32 != MISC_NUM)) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not read metadata from fpa->camera.");
+            psFree(fpa);
+            return(NULL);
+        }
+    }
+
+    //
+    // Create various transforms and projections.
+    //
+    fpa->fromTangentPlane = PS_CREATE_4D_IDENTITY_PLANE_DISTORT();
+    fpa->toTangentPlane = PS_CREATE_4D_IDENTITY_PLANE_DISTORT();
+    fpa->projection = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+
+    //
+    // Ensure fpa concepts metadata was allocated properly.
+    //
+    if (fpa->concepts == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc did not set fpa->concepts.");
+        psFree(fpa);
+        return(NULL);
+    } else {
+        rc = psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+        if (rc == false) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not add data to fpa->concepts.");
+            psFree(fpa);
+            return(NULL);
+        }
+        psS32 tmpS32 = psMetadataLookupS32(&rc, fpa->concepts, MISC_NAME);
+        if ((rc == false) || (tmpS32 != MISC_NUM)) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not read metadata from fpa->concepts.");
+            psFree(fpa);
+            return(NULL);
+        }
+    }
+
+    //
+    // Create ->analysis metadata.
+    //
+    fpa->analysis = psMetadataAlloc();
+    rc = psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    //
+    // We test the fpa->chips array later.
+    //
+
+    //
+    // How to test the p_pmHDU *private member?
+    //
+
+    //
+    // Create ->phu metadata.
+    //
+    fpa->phu = psMetadataAlloc();
+    rc = psMetadataAddS32(fpa->phu, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    return(fpa);
+}
+
 
 psS32 main(psS32 argc, char* argv[])
@@ -47,12 +157,17 @@
 }
 
+/******************************************************************************
+testFPAAlloc()
+    1: We ensure that pmFPAAlloc() properly allocates a pmFPA struct.
+    2: We populate the members with real data to ensure they are being
+       free'ed correctly.
+ *****************************************************************************/
 static psS32 testFPAAlloc(void)
 {
-    // XXX: Do something more with these arguments.
-    const psMetadata *camera = psMetadataAlloc();
+    psMetadata *camera = psMetadataAlloc();
     pmFPA* fpa = pmFPAAlloc(camera);
 
     if (fpa == NULL) {
-        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc returned a NULL.");
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc() returned a NULL.");
         return 1;
     }
@@ -96,20 +211,59 @@
         return 9;
     }
-
-    psFree(fpa);
-    psFree(camera);
-
-    return 0;
+    psFree(fpa);
+
+    //
+    // Populate the pmFPA struct with real data to ensure they were
+    // psFree()'ed correctly.
+    //
+    fpa = generateSimpleFPA();
+    if (fpa == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: generateSimpleFPA() returned NULL.");
+        return(15);
+    }
+    psFree(fpa);
+
+    return(0);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    psBool rc;
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    if (chip == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmChipAlloc returned a NULL.");
+        return(NULL);
+    }
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    //
+    // We already ensured that chip->concepts was working properly.
+    //
+
+    //
+    // Create ->analysis metadata.
+    //
+    chip->analysis = psMetadataAlloc();
+    rc = psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    //
+    // We test the chip->cells array later.
+    //
+
+    //
+    // How to test the p_pmHDU *private member?
+    //
+
+    return(chip);
 }
 
 static psS32 testChipAlloc(void)
 {
-    const psMetadata *camera = psMetadataAlloc();
-    pmFPA* fpa = pmFPAAlloc(camera);
-    if (fpa == NULL) {
-        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc returned a NULL.");
-        return 1;
-    }
-
+    pmFPA* fpa = generateSimpleFPA();
     pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
     if (chip == NULL) {
@@ -174,28 +328,81 @@
         return 25;
     }
-
-    psFree(fpa);
-    //    psFree(chip);
-    psFree(camera);
-
-    return 0;
+    psFree(fpa);
+
+    //
+    // Populate the pmChip struct with real data to ensure they were
+    // psFree()'ed correctly.
+    //
+    fpa = generateSimpleFPA();
+    chip = generateSimpleChip(fpa);
+    psFree(fpa);
+
+    return(0);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmFPA *fpa, pmChip *chip)
+{
+    psBool rc;
+    pmCell *cell = pmCellAlloc(chip, (psMetadata *) fpa->camera, CELL_ALLOC_NAME);
+    if (cell == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmCellAlloc returned a NULL.");
+        return(NULL);
+    }
+    cell->toChip = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    cell->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    cell->toSky = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    //
+    // We already ensured that cell->concepts was working properly.
+    //
+
+    //
+    // Test camera metadata.
+    //
+    if (cell->camera == NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->camera is NULL.");
+        psFree(fpa);
+        return(NULL);
+    } else {
+        rc = psMetadataAddS32((psMetadata *) cell->camera, PS_LIST_HEAD, MISC_NAME2, 0, NULL, MISC_NUM);
+        if (rc == false) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not add metadata to cell->camera.");
+            psFree(fpa);
+            return(NULL);
+        }
+        psS32 tmpS32 = psMetadataLookupS32(&rc, cell->camera, MISC_NAME2);
+        if ((rc == false) || (tmpS32 != MISC_NUM)) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not read metadata from cell->camera.");
+            psFree(fpa);
+            return(NULL);
+        }
+    }
+
+    //
+    // Create ->analysis metadata.
+    //
+    cell->analysis = psMetadataAlloc();
+    rc = psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    //
+    // We test the cell->readouts array later.
+    //
+
+    //
+    // How to test the p_pmHDU *private member?
+    //
+
+    return(cell);
 }
 
 static psS32 testCellAlloc(void)
 {
-    const psMetadata *camera = psMetadataAlloc();
-    pmFPA* fpa = pmFPAAlloc(camera);
-    if (fpa == NULL) {
-        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc returned a NULL.n");
-        return 1;
-    }
-
+    pmFPA* fpa = generateSimpleFPA();
     pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
-    if (chip == NULL) {
-        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmChipAlloc returned a NULL.n");
-        return 2;
-    }
-
-    pmCell *cell = pmCellAlloc(chip, (psMetadata *) camera, CELL_ALLOC_NAME);
+    pmCell *cell = pmCellAlloc(chip, (psMetadata *) fpa->camera, CELL_ALLOC_NAME);
     if (cell == NULL) {
         psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmCellAlloc returned a NULL.n");
@@ -240,5 +447,5 @@
     }
 
-    if (cell->camera != camera) {
+    if (cell->camera != fpa->camera) {
         psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->camera set improperly.\n");
         return 20;
@@ -269,35 +476,72 @@
         return 27;
     }
-
-    psFree(fpa);
-    //    psFree(chip);
-    //    psFree(cell);
-    psFree(camera);
-
-    return 0;
-}
+    psFree(fpa);
+
+    //
+    // Populate the pmCell struct with real data to ensure they were
+    // psFree()'ed correctly.
+    //
+    fpa = generateSimpleFPA();
+    chip = generateSimpleChip(fpa);
+    cell = generateSimpleCell(fpa, chip);
+    psFree(fpa);
+
+    return(0);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmFPA *fpa, pmChip *chip, pmCell *cell)
+{
+    psBool rc;
+    pmReadout *readout = pmReadoutAlloc(cell);
+    if (readout == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmReadoutAlloc returned a NULL.");
+        return(NULL);
+    }
+    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);
+
+    //
+    // Create a psList of bias data.
+    //
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        if (readout->bias == NULL) {
+            readout->bias = psListAlloc(tmpImage);
+        } else {
+            psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        }
+    }
+
+    //
+    // Test readout->analysis metadata.
+    //
+    if (readout->analysis == NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: readout->analysis is NULL.");
+        psFree(fpa);
+        return(NULL);
+    } else {
+        rc = psMetadataAddS32((psMetadata *) readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+        if (rc == false) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not add metadata to readout->analysis.");
+            psFree(fpa);
+            return(NULL);
+        }
+    }
+
+    return(readout);
+}
+
 
 static psS32 testReadoutAlloc(void)
 {
-    const psMetadata *camera = psMetadataAlloc();
-    pmFPA* fpa = pmFPAAlloc(camera);
-
-    if (fpa == NULL) {
-        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc returned a NULL.\n");
-        return 1;
-    }
-
-    pmChip *chip = pmChipAlloc(fpa, "ChipName");
-    if (chip == NULL) {
-        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmChipAlloc returned a NULL.\n");
-        return 2;
-    }
-
-    pmCell *cell = pmCellAlloc(chip, (psMetadata *) camera, "CellName");
-    if (cell == NULL) {
-        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmCellAlloc returned a NULL.\n");
-        return 3;
-    }
-
+    pmFPA* fpa = generateSimpleFPA();
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    pmCell *cell = pmCellAlloc(chip, (psMetadata *) fpa->camera, CELL_ALLOC_NAME);
     pmReadout *readout = pmReadoutAlloc(cell);
     if (readout == NULL) {
@@ -355,11 +599,16 @@
         return 20;
     }
-
-    psFree(fpa);
-    //    psFree(chip);
-    //    psFree(cell);
-    //    psFree(readout);
-    psFree(camera);
-
-    return 0;
-}
+    psFree(fpa);
+
+    //
+    // Populate the pmReadout struct with real data to ensure they were
+    // psFree()'ed correctly.
+    //
+    fpa = generateSimpleFPA();
+    chip = generateSimpleChip(fpa);
+    cell = generateSimpleCell(fpa, chip);
+    readout = generateSimpleReadout(fpa, chip, cell);
+    psFree(fpa);
+
+    return(0);
+}
Index: /trunk/psModules/test/imsubtract/tst_pmSubtractBias.c
===================================================================
--- /trunk/psModules/test/imsubtract/tst_pmSubtractBias.c	(revision 5586)
+++ /trunk/psModules/test/imsubtract/tst_pmSubtractBias.c	(revision 5587)
@@ -25,6 +25,6 @@
  *  XXX: Memory leaks are not being detected.
  *
- *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-11-19 00:55:18 $
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-11-23 23:54:30 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -52,4 +52,6 @@
                           };
 
+psS32 currentId = 0;
+psS32 memLeaks = 0;             // XXX: remove
 
 int main(int argc, char* argv[])
@@ -67,4 +69,10 @@
     psTraceSetLevel("psSpline1DEval", 0);
     psTraceSetLevel("psSpline1DEvalVector", 0);
+
+    psS32 currentId = psMemGetId(); // XXX: remove
+    psS32 memLeaks = 0;             // XXX: remove
+    if (0) {
+        PRINT_MEMLEAKS(0);
+    }
 
     return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
@@ -661,43 +669,37 @@
     }
     oAverage/= (psF32) numOverscans;
-
-
-    if (fit == PM_FIT_NONE) {
-        myReadout = pmSubtractBias(myReadout, NULL, PM_FIT_NONE, overscanaxis,
-                                   stat, nBin, NULL, NULL);
-    } else if (fit == PM_FIT_POLYNOMIAL) {
-        myReadout = pmSubtractBias(myReadout, myPoly, PM_FIT_POLYNOMIAL, overscanaxis,
-                                   stat, nBin, NULL, NULL);
-    } else if (fit == PM_FIT_SPLINE) {
-        //        mySpline = psSpline1DAlloc();
-        myReadout = pmSubtractBias(myReadout, mySpline, PM_FIT_SPLINE, overscanaxis,
-                                   stat, nBin, NULL, NULL);
-    }
-
-    for (i=0;i<imageNumRows;i++) {
-        for (j=0;j<imageNumCols;j++) {
-            expect = ((float) (i + j)) - oAverage;
-            actual = myReadout->image->data.F32[i][j];
-            if (FLT_EPSILON < fabs(expect - actual)) {
-                printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
-                testStatus = 1;
-            } else {
-                //printf("COOL: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+    if (0) {
+        if (fit == PM_FIT_NONE) {
+            myReadout = pmSubtractBias(myReadout, NULL, PM_FIT_NONE, overscanaxis,
+                                       stat, nBin, NULL, NULL);
+        } else if (fit == PM_FIT_POLYNOMIAL) {
+            myReadout = pmSubtractBias(myReadout, myPoly, PM_FIT_POLYNOMIAL, overscanaxis,
+                                       stat, nBin, NULL, NULL);
+        } else if (fit == PM_FIT_SPLINE) {
+            //        mySpline = psSpline1DAlloc();
+            myReadout = pmSubtractBias(myReadout, mySpline, PM_FIT_SPLINE, overscanaxis,
+                                       stat, nBin, NULL, NULL);
+        }
+        if (myReadout == NULL ) {
+            printf("TEST ERROR: pmSubtractBias() returned NULL.\n");
+            testStatus = 1;
+        } else {
+            for (i=0;i<imageNumRows;i++) {
+                for (j=0;j<imageNumCols;j++) {
+                    expect = ((float) (i + j)) - oAverage;
+                    actual = myReadout->image->data.F32[i][j];
+                    if (FLT_EPSILON < fabs(expect - actual)) {
+                        printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                        testStatus = 1;
+                    } else {
+                        //printf("GOOD: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                    }
+                }
             }
         }
     }
-    // XXX: Figure out memory deallocation
+
+    // HEY
     psFree(fpa);
-    //    psFree(chip);
-    //    psFree(cell);
-    /*
-        psListElem *tmpElem = (psListElem *) myReadout->bias->head;
-        while (NULL != tmpElem) {
-            psFree((psImage *) tmpElem->data);
-            tmpElem = tmpElem->next;
-        }
-        psFree(myReadout);
-    */
-    psFree(camera);
     psFree(stat);
     psFree(myPoly);
@@ -1126,4 +1128,2 @@
 }
 
-
-// This code will
