Index: /trunk/psModules/src/astrom/Makefile.am
===================================================================
--- /trunk/psModules/src/astrom/Makefile.am	(revision 15561)
+++ /trunk/psModules/src/astrom/Makefile.am	(revision 15562)
@@ -8,4 +8,5 @@
 	pmAstrometryDistortion.c \
 	pmAstrometryUtils.c \
+	pmAstrometryTable.c \
 	pmAstrometryWCS.c
 
@@ -15,4 +16,5 @@
 	pmAstrometryDistortion.h \
 	pmAstrometryUtils.h \
+	pmAstrometryTable.h \
 	pmAstrometryWCS.h
 
Index: /trunk/psModules/src/astrom/pmAstrometryTable.c
===================================================================
--- /trunk/psModules/src/astrom/pmAstrometryTable.c	(revision 15561)
+++ /trunk/psModules/src/astrom/pmAstrometryTable.c	(revision 15562)
@@ -1,16 +1,16 @@
 /** @file  pmAstrometryObjects.c
-*
-*  @brief This file defines the basic types for matching objects
-*  based on their astrometry.
-*
-*  @ingroup AstroImage
-*
-*  @author EAM, IfA
-*
-*  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2007-10-23 20:52:42 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*/
+ *
+ *  @brief This file defines the basic types for matching objects
+ *  based on their astrometry.
+ *
+ *  @ingroup AstroImage
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
 
 #ifdef HAVE_CONFIG_H
@@ -29,7 +29,13 @@
 #include <pslib.h>
 
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
 #include "pmHDU.h"
 #include "pmFPA.h"
-#include "pmAstrometryObjects.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmAstrometryTable.h"
+
 
 /********************* CheckDataStatus functions *****************************/
@@ -179,24 +185,28 @@
 bool pmAstromWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
-    // define the EXTNAME values used for the table data, and residual image segments
-    {
-        // lookup the EXTNAME values used for table data and image header segments
-        char *rule = NULL;
-
-        // Menu of EXTNAME rules
-        psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
-        if (!menu) {
-            psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
-            return false;
-        }
-
-        // EXTNAME for image header
-        rule = psMetadataLookupStr(&status, menu, "ASTROMETRY");
-        if (!rule) {
-            psError(PS_ERR_UNKNOWN, false, "missing entry for ASTROMETRY in EXTNAME.RULES in camera.config");
-            return false;
-        }
-        extname = pmFPAfileNameFromRule (rule, file, view);
-    }
+    bool status;
+    // *** define the EXTNAME values used for the table data, and residual image segments ***
+
+    // lookup the EXTNAME values used for table data and image header segments
+    char *rule = NULL;
+
+    // Menu of EXTNAME rules
+    psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
+    if (!menu) {
+	psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
+	return false;
+    }
+
+    // EXTNAME for image header
+    rule = psMetadataLookupStr(&status, menu, "ASTROMETRY");
+    if (!rule) {
+	psError(PS_ERR_UNKNOWN, false, "missing entry for ASTROMETRY in EXTNAME.RULES in camera.config");
+	return false;
+    }
+
+    // XXX need to finish this: uncomment when used
+    # if (0)
+    char *extname = pmFPAfileNameFromRule (rule, file, view);
+    # endif
 
     // write the chip elements in the following form:
@@ -244,24 +254,27 @@
 bool pmAstromReadChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
-    // define the EXTNAME values used for the table data, and residual image segments
-    {
-        // lookup the EXTNAME values used for table data and image header segments
-        char *rule = NULL;
-
-        // Menu of EXTNAME rules
-        psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
-        if (!menu) {
-            psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
-            return false;
-        }
-
-        // EXTNAME for image header
-        rule = psMetadataLookupStr(&status, menu, "ASTROMETRY");
-        if (!rule) {
-            psError(PS_ERR_UNKNOWN, false, "missing entry for ASTROMETRY in EXTNAME.RULES in camera.config");
-            return false;
-        }
-        extname = pmFPAfileNameFromRule (rule, file, view);
-    }
+    bool status;
+
+    // lookup the EXTNAME values used for table data and image header segments
+    char *rule = NULL;
+
+    // Menu of EXTNAME rules
+    psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
+    if (!menu) {
+	psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
+	return false;
+    }
+
+    // EXTNAME for image header
+    rule = psMetadataLookupStr(&status, menu, "ASTROMETRY");
+    if (!rule) {
+	psError(PS_ERR_UNKNOWN, false, "missing entry for ASTROMETRY in EXTNAME.RULES in camera.config");
+	return false;
+    }
+
+    // XXX finish this: uncomment when used
+    # if (0)
+    char *extname = pmFPAfileNameFromRule (rule, file, view);
+    # endif
 
     // read the chip elements in the following form:
Index: /trunk/psModules/src/astrom/pmAstrometryTable.h
===================================================================
--- /trunk/psModules/src/astrom/pmAstrometryTable.h	(revision 15562)
+++ /trunk/psModules/src/astrom/pmAstrometryTable.h	(revision 15562)
@@ -0,0 +1,31 @@
+/* @file  pmAstrometryTable.h
+ * @brief Astrometry table I/O functions
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_ASTROMETRY_TABLE_H
+#define PM_ASTROMETRY_TABLE_H
+
+/// @addtogroup Astrometry
+/// @{
+
+bool pmAstromCheckDataStatusForView (const pmFPAview *view, pmFPAfile *file);
+bool pmAstromCheckDataStatusForFPA (const pmFPA *fpa);
+bool pmAstromCheckDataStatusForChip (const pmChip *chip);
+
+bool pmAstromWritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromWriteForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromWriteFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+
+bool pmAstromReadForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromReadFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromReadChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+
+/// @}
+#endif
Index: /trunk/psModules/src/camera/pmFPAfile.h
===================================================================
--- /trunk/psModules/src/camera/pmFPAfile.h	(revision 15561)
+++ /trunk/psModules/src/camera/pmFPAfile.h	(revision 15562)
@@ -4,6 +4,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-10-03 21:32:43 $
+ * @version $Revision: 1.23 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
  */
@@ -35,4 +35,5 @@
     PM_FPA_FILE_FRINGE,
     PM_FPA_FILE_HEADER,
+    PM_FPA_FILE_ASTROM,
 } pmFPAfileType;
 
Index: /trunk/psModules/src/camera/pmFPAfileDefine.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 15561)
+++ /trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 15562)
@@ -438,4 +438,5 @@
                 return NULL;
             }
+	    // EXTWORD (fits->extword) is not relevant to the PHU
             fits = psFitsOpen (realName, "r");
             if (!fits) {
@@ -556,4 +557,5 @@
             return NULL;
         }
+	// EXTWORD (fits->extword) is not relevant to the PHU
         fits = psFitsOpen (realName, "r");
         if (!fits) {
@@ -665,4 +667,5 @@
     // associated each filename with an element of the FPA
     // save the association on file->names
+    // EXTWORD (fits->extword) is not relevant to the PHU
     fits = psFitsOpen (infiles->data[entry], "r");
     phu = psFitsReadHeader (NULL, fits);
Index: /trunk/psModules/src/camera/pmFPAfileIO.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfileIO.c	(revision 15561)
+++ /trunk/psModules/src/camera/pmFPAfileIO.c	(revision 15562)
@@ -34,4 +34,5 @@
 #include "pmResiduals.h"
 #include "pmPSF_IO.h"
+#include "pmAstrometryTable.h"
 #include "pmFPA_JPEG.h"
 #include "pmSourcePlots.h"
@@ -192,4 +193,7 @@
         status = pmPSFmodelReadForView (view, file, config);
         break;
+      case PM_FPA_FILE_ASTROM:
+        status = pmAstromReadForView (view, file, config);
+        break;
       case PM_FPA_FILE_JPEG:
       case PM_FPA_FILE_KAPA:
@@ -273,4 +277,5 @@
     case PM_FPA_FILE_CMF:
     case PM_FPA_FILE_PSF:
+    case PM_FPA_FILE_ASTROM:
     case PM_FPA_FILE_JPEG:
     case PM_FPA_FILE_KAPA:
@@ -336,4 +341,10 @@
     // have their data stored on the readout->analysis metadata structure of another
     // (existing) fpa
+    if (file->type == PM_FPA_FILE_CMF) {
+      if (!pmFPAviewCheckDataStatusForSources (view, file)) {
+        psTrace("psModules.camera", 6, "skip write for %s, no data for this entry", file->name);
+        return true;
+      }
+    }
     if (file->type == PM_FPA_FILE_PSF) {
       if (!pmPSFmodelCheckDataStatusForView (view, file)) {
@@ -342,6 +353,6 @@
       }
     }
-    if (file->type == PM_FPA_FILE_CMF) {
-      if (!pmFPAviewCheckDataStatusForSources (view, file)) {
+    if (file->type == PM_FPA_FILE_ASTROM) {
+      if (!pmAstromCheckDataStatusForView (view, file)) {
         psTrace("psModules.camera", 6, "skip write for %s, no data for this entry", file->name);
         return true;
@@ -449,4 +460,8 @@
       case PM_FPA_FILE_PSF:
         status = pmPSFmodelWriteForView (view, file, config);
+        break;
+
+      case PM_FPA_FILE_ASTROM:
+        status = pmAstromWriteForView (view, file, config);
         break;
 
@@ -508,4 +523,5 @@
       case PM_FPA_FILE_CMF:
       case PM_FPA_FILE_PSF:
+      case PM_FPA_FILE_ASTROM:
         psTrace ("psModules.camera", 5, "closing %s (%s) (%d:%d:%d)\n", file->filename, file->name, view->chip, view->cell, view->readout);
         status = psFitsClose (file->fits);
@@ -574,4 +590,5 @@
       case PM_FPA_FILE_CMF:
       case PM_FPA_FILE_PSF:
+      case PM_FPA_FILE_ASTROM:
         psTrace ("psModules.camera", 5, "NOT freeing %s (%s) : save for further analysis\n", file->filename, file->name);
         return true;
@@ -712,4 +729,5 @@
       case PM_FPA_FILE_CMF:
       case PM_FPA_FILE_PSF:
+      case PM_FPA_FILE_ASTROM:
         psTrace ("psModules.camera", 5, "opening %s (%s) (%d:%d:%d)\n",
                  file->filename, file->name, view->chip, view->cell, view->readout);
@@ -861,4 +879,7 @@
         status = pmPSFmodelWritePHU (view, file, config);
         break;
+      case PM_FPA_FILE_ASTROM:
+        status = pmAstromWritePHU (view, file, config);
+        break;
       case PM_FPA_FILE_SX:
       case PM_FPA_FILE_RAW:
Index: /trunk/psModules/src/detrend/pmDetrendDB.c
===================================================================
--- /trunk/psModules/src/detrend/pmDetrendDB.c	(revision 15561)
+++ /trunk/psModules/src/detrend/pmDetrendDB.c	(revision 15562)
@@ -101,4 +101,5 @@
         DETREND_STRING_CASE (SHUTTER);
         DETREND_STRING_CASE (FRINGE);
+        DETREND_STRING_CASE (ASTROM);
     default:
         return NULL;
Index: /trunk/psModules/src/detrend/pmDetrendDB.h
===================================================================
--- /trunk/psModules/src/detrend/pmDetrendDB.h	(revision 15561)
+++ /trunk/psModules/src/detrend/pmDetrendDB.h	(revision 15562)
@@ -9,6 +9,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-06-13 03:42:33 $
+ * @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
  */
@@ -29,4 +29,5 @@
     PM_DETREND_TYPE_FRINGE,
     PM_DETREND_TYPE_BACKGROUND,
+    PM_DETREND_TYPE_ASTROM,
 } pmDetrendType;
 
Index: /trunk/psModules/src/imcombine/pmStack.c
===================================================================
--- /trunk/psModules/src/imcombine/pmStack.c	(revision 15561)
+++ /trunk/psModules/src/imcombine/pmStack.c	(revision 15562)
@@ -8,7 +8,6 @@
  *  @author GLG, MHPCC
  *
- *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-10-26 23:15:06 $
- *
+ *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *  Copyright 2004-2007 Institute for Astronomy, University of Hawaii
  *
Index: /trunk/psModules/src/imcombine/pmSubtraction.h
===================================================================
--- /trunk/psModules/src/imcombine/pmSubtraction.h	(revision 15561)
+++ /trunk/psModules/src/imcombine/pmSubtraction.h	(revision 15562)
@@ -6,7 +6,6 @@
  * @author GLG, MHPCC
  *
- * @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-11-03 02:28:24 $
- *
+ * @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004-207 Institute for Astronomy, University of Hawaii
  */
Index: /trunk/psModules/src/objects/Makefile.am
===================================================================
--- /trunk/psModules/src/objects/Makefile.am	(revision 15561)
+++ /trunk/psModules/src/objects/Makefile.am	(revision 15562)
@@ -10,4 +10,5 @@
      pmModelUtils.c \
      pmSource.c \
+     pmSourceExtendedPars.c \
      pmSourceUtils.c \
      pmSourceSky.c \
@@ -50,4 +51,5 @@
      pmModelUtils.h \
      pmSource.h \
+     pmSourceExtendedPars.h \
      pmSourceUtils.h \
      pmSourceSky.h \
Index: /trunk/psModules/src/objects/pmGrowthCurve.h
===================================================================
--- /trunk/psModules/src/objects/pmGrowthCurve.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmGrowthCurve.h	(revision 15562)
@@ -4,6 +4,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-01-24 02:54:15 $
+ * @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2006 Institute for Astronomy, University of Hawaii
  */
@@ -27,4 +27,6 @@
 pmGrowthCurve;
 
+bool psMemCheckGrowthCurve(psPtr ptr);
+
 pmGrowthCurve *pmGrowthCurveAlloc (psF32 minRadius, psF32 maxRadius, psF32 refRadius);
 psF32 pmGrowthCurveCorrect (pmGrowthCurve *growth, psF32 radius);
Index: /trunk/psModules/src/objects/pmModel.c
===================================================================
--- /trunk/psModules/src/objects/pmModel.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmModel.c	(revision 15562)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:04:07 $
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -46,7 +46,4 @@
     psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
 
-    pmModel *tmp = (pmModel *) psAlloc(sizeof(pmModel));
-    psMemSetDeallocator(tmp, (psFreeFunc) modelFree);
-
     pmModelClass *class = pmModelClassSelect (type);
     if (class == NULL) {
@@ -54,4 +51,7 @@
         return(NULL);
     }
+
+    pmModel *tmp = (pmModel *) psAlloc(sizeof(pmModel));
+    psMemSetDeallocator(tmp, (psFreeFunc) modelFree);
 
     tmp->type = type;
@@ -89,7 +89,14 @@
 }
 
+bool psMemCheckModel(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) modelFree);
+}
+
 // copy model to a new structure
 pmModel *pmModelCopy (pmModel *model)
 {
+    PS_ASSERT_PTR_NON_NULL(model, NULL);
 
     pmModel *new = pmModelAlloc (model->type);
@@ -217,5 +224,5 @@
         Ro = psImageInterpolateOptionsAlloc(
             PS_INTERPOLATE_BILINEAR,
-            model->residuals->Ro, NULL, NULL, 0, 0.0, 0.0, 1, 0, 0.0);
+            model->residuals->Ro, NULL, mask, 0, 0.0, 0.0, 1, 0, 0.0);
         Rx = psImageInterpolateOptionsAlloc(
             PS_INTERPOLATE_BILINEAR,
@@ -257,6 +264,6 @@
                 float oy = yBin*(imageRow + 0.5 - yCenter) + yResidCenter;
 
+		psU8 mflux = 0;
                 if (mode & PM_MODEL_OP_RES0) {
-                    psU8 mflux = 0;
                     double Fo = 0.0;
                     psImageInterpolate (&Fo, NULL, &mflux, ox, oy, Ro);
@@ -265,6 +272,6 @@
                     }
                 }
-                if (mode & PM_MODEL_OP_RES1) {
-                    psU8 mflux = 0;
+		// skip Rx,Ry if Ro is masked
+                if (!mflux && (mode & PM_MODEL_OP_RES1)) {
                     double Fx = 0.0;
                     double Fy = 0.0;
Index: /trunk/psModules/src/objects/pmModel.h
===================================================================
--- /trunk/psModules/src/objects/pmModel.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmModel.h	(revision 15562)
@@ -5,6 +5,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-08-24 00:11:02 $
+ * @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  *
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -122,4 +122,5 @@
  */
 pmModel *pmModelAlloc(pmModelType type);
+bool psMemCheckModel(psPtr ptr);
 
 // copy model to a new structure
Index: /trunk/psModules/src/objects/pmModelClass.c
===================================================================
--- /trunk/psModules/src/objects/pmModelClass.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmModelClass.c	(revision 15562)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -57,5 +57,4 @@
 static void ModelClassFree (pmModelClass *modelClass)
 {
-
     if (modelClass == NULL)
         return;
@@ -70,8 +69,14 @@
 }
 
+bool psMemCheckModelClass(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) ModelClassFree);
+}
+
 void pmModelClassAdd (pmModelClass *model)
 {
     if (models == NULL) {
-        pmModelClassInit ();
+        pmModelClassInit();
     }
 
@@ -85,6 +90,7 @@
 {
     // if we do not need to init, return false;
-    if (models != NULL)
+    if (models != NULL) {
         return false;
+    }
 
     int Nnew = sizeof (defaultModels) / sizeof (pmModelClass);
@@ -100,4 +106,8 @@
 pmModelClass *pmModelClassSelect (pmModelType type)
 {
+    if (models == NULL) {
+        pmModelClassInit();
+    }
+
     if ((type < 0) || (type >= Nmodels)) {
         psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
@@ -111,4 +121,5 @@
     psFree (models);
     models = NULL;
+    Nmodels = 0;
     return;
 }
@@ -116,4 +127,8 @@
 psS32 pmModelClassParameterCount (pmModelType type)
 {
+    if (models == NULL) {
+        pmModelClassInit();
+    }
+
     if ((type < 0) || (type >= Nmodels)) {
         psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
@@ -125,4 +140,8 @@
 psS32 pmModelClassGetType (char *name)
 {
+    if (models == NULL) {
+        pmModelClassInit();
+    }
+
     for (int i = 0; i < Nmodels; i++) {
         if (!strcmp(models[i].name, name)) {
@@ -135,4 +154,8 @@
 char *pmModelClassGetName (pmModelType type)
 {
+    if (models == NULL) {
+        pmModelClassInit();
+    }
+
     if ((type < 0) || (type >= Nmodels)) {
         psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
Index: /trunk/psModules/src/objects/pmModelClass.h
===================================================================
--- /trunk/psModules/src/objects/pmModelClass.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmModelClass.h	(revision 15562)
@@ -21,6 +21,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-08-24 00:11:02 $
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -49,4 +49,7 @@
 pmModelClass *pmModelClassAlloc (int nModels);
 
+//
+bool psMemCheckModelClass(psPtr ptr);
+
 // initialize the internal (static) model class with the default models
 bool pmModelClassInit (void);
Index: /trunk/psModules/src/objects/pmModelGroup.c
===================================================================
--- /trunk/psModules/src/objects/pmModelGroup.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmModelGroup.c	(revision 15562)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-08-24 00:11:02 $
+ *  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -68,4 +68,10 @@
 }
 
+bool psMemCheckModelGroup(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) ModelGroupFree);
+}
+
 void pmModelGroupAdd (pmModelGroup *model)
 {
Index: /trunk/psModules/src/objects/pmModelGroup.h
===================================================================
--- /trunk/psModules/src/objects/pmModelGroup.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmModelGroup.h	(revision 15562)
@@ -21,6 +21,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-08-24 00:11:02 $
+ * @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -78,4 +78,6 @@
 pmModelGroup *pmModelGroupAlloc (int nModels);
 
+bool psMemCheckModelGroup(psPtr ptr);
+
 // initialize the internal (static) model group with the default models
 bool pmModelGroupInit (void);
Index: /trunk/psModules/src/objects/pmModelUtils.c
===================================================================
--- /trunk/psModules/src/objects/pmModelUtils.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmModelUtils.c	(revision 15562)
@@ -5,6 +5,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:04:30 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -36,4 +36,7 @@
 pmModel *pmModelFromPSF (pmModel *modelEXT, pmPSF *psf)
 {
+    PS_ASSERT_PTR_NON_NULL(psf, NULL);
+    PS_ASSERT_PTR_NON_NULL(modelEXT, NULL);
+
     // allocate a new pmModel to hold the PSF version
     pmModel *modelPSF = pmModelAlloc (psf->type);
@@ -53,7 +56,7 @@
 // instantiate a model for the PSF at this location with peak flux
 // NOTE: psf and (Xo,Yo) are defined wrt chip coordinates
-pmModel *pmModelFromPSFforXY (pmPSF *psf, float Xo, float Yo, float Io) {
-
-    assert (psf);
+pmModel *pmModelFromPSFforXY (pmPSF *psf, float Xo, float Yo, float Io)
+{
+    PS_ASSERT_PTR_NON_NULL(psf, NULL);
 
     // allocate a new pmModel to hold the PSF version
@@ -75,4 +78,6 @@
 // set this model to have the requested flux
 bool pmModelSetFlux (pmModel *model, float flux) {
+    PS_ASSERT_PTR_NON_NULL(model, NULL);
+    PS_ASSERT_PTR_NON_NULL(model->params, NULL);
 
     // set Io to be 1.0
Index: /trunk/psModules/src/objects/pmPSF.c
===================================================================
--- /trunk/psModules/src/objects/pmPSF.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmPSF.c	(revision 15562)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.32 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-29 00:15:32 $
+ *  @version $Revision: 1.33 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -76,4 +76,10 @@
 }
 
+bool psMemCheckPSFOptions(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmPSFOptionsFree);
+}
+
 /*****************************************************************************
 pmPSFFree(psf): function to free a pmPSF structure
@@ -81,7 +87,7 @@
 static void pmPSFFree (pmPSF *psf)
 {
-
-    if (psf == NULL)
+    if (psf == NULL) {
         return;
+    }
 
     psFree (psf->ChiTrend);
@@ -98,5 +104,6 @@
  pmPSFAlloc (type): allocate a pmPSF.
 
- NOTE: PSF model parameters which are not modeled on an image are set to NULL in psf->params.
+ NOTE: PSF model parameters which are not modeled on an image are set to NULL
+ in psf->params.
 
  These are normally:
@@ -109,4 +116,5 @@
 pmPSF *pmPSFAlloc (pmPSFOptions *options)
 {
+    PS_ASSERT_PTR_NON_NULL(options, NULL);
     int Nparams;
 
@@ -205,4 +213,10 @@
 }
 
+bool psMemCheckPSF(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmPSFFree);
+}
+
 // the PSF models the \sigma_{xy} variation of the elliptical contour as a function of position in the image with a
 // polynomial.  an individual object has a contour of the form (x^2/2sx^2) + (y^2/2sy^2) + sxy*x*y
@@ -217,4 +231,5 @@
 double pmPSF_SXYfromModel (psF32 *modelPar)
 {
+    PS_ASSERT_PTR_NON_NULL(modelPar, NAN);
 
     double SXX = modelPar[PM_PAR_SXX];
@@ -229,4 +244,5 @@
 double pmPSF_SXYtoModel (psF32 *fittedPar)
 {
+    PS_ASSERT_PTR_NON_NULL(fittedPar, NAN);
 
     double SXX = fittedPar[PM_PAR_SXX];
@@ -247,4 +263,6 @@
 bool pmPSF_FitToModel (psF32 *fittedPar, float minMinorAxis)
 {
+    PS_ASSERT_PTR_NON_NULL(fittedPar, false);
+
     psEllipsePol pol;
 
@@ -272,4 +290,7 @@
 psEllipsePol pmPSF_ModelToFit (psF32 *modelPar)
 {
+//   XXX: must assert non-NULL input parameter
+//    PS_ASSERT_PTR_NON_NULL(modelPar, NAN);
+
     psEllipseShape shape;
 
@@ -289,4 +310,6 @@
     psEllipseShape shape;
     psEllipseAxes axes;
+//   XXX: must assert non-NULL input parameter
+//    PS_ASSERT_PTR_NON_NULL(modelPar, axes);
 
     shape.sx  = modelPar[PM_PAR_SXX] / M_SQRT2;
@@ -310,4 +333,6 @@
 bool pmPSF_AxesToModel (psF32 *modelPar, psEllipseAxes axes)
 {
+    PS_ASSERT_PTR_NON_NULL(modelPar, false);
+
     if ((axes.major <= 0) || (axes.minor <= 0)) {
         modelPar[PM_PAR_SXX] = 0.0;
@@ -374,4 +399,6 @@
 bool pmGrowthCurveGenerate (pmReadout *readout, pmPSF *psf, bool ignore, psMaskType maskVal, psMaskType mark)
 {
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(readout->image, false);
 
     // bool status;
Index: /trunk/psModules/src/objects/pmPSF.h
===================================================================
--- /trunk/psModules/src/objects/pmPSF.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmPSF.h	(revision 15562)
@@ -6,6 +6,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-09-25 22:05:05 $
+ * @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -87,6 +87,9 @@
  *
  */
+
 pmPSF *pmPSFAlloc (pmPSFOptions *options);
-pmPSFOptions *pmPSFOptionsAlloc ();
+bool psMemCheckPSF(psPtr ptr);
+pmPSFOptions *pmPSFOptionsAlloc();
+bool psMemCheckPSFOptions(psPtr ptr);
 
 double pmPSF_SXYfromModel (psF32 *modelPar);
Index: /trunk/psModules/src/objects/pmPSF_IO.c
===================================================================
--- /trunk/psModules/src/objects/pmPSF_IO.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmPSF_IO.c	(revision 15562)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.27 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-10-09 19:26:25 $
+ *  @version $Revision: 1.28 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -50,4 +50,9 @@
 bool pmPSFmodelCheckDataStatusForView (const pmFPAview *view, const pmFPAfile *file)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa->chips, false);
+
     pmFPA *fpa = file->fpa;
 
@@ -61,4 +66,6 @@
     }
     pmChip *chip = fpa->chips->data[view->chip];
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->cells, false);
 
     if (view->cell == -1) {
@@ -75,4 +82,7 @@
 
 bool pmPSFmodelCheckDataStatusForFPA (const pmFPA *fpa) {
+
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, false);
 
     for (int i = 0; i < fpa->chips->n; i++) {
@@ -85,4 +95,5 @@
 
 bool pmPSFmodelCheckDataStatusForChip (const pmChip *chip) {
+    PS_ASSERT_PTR_NON_NULL(chip, false);
 
     bool status;
@@ -95,4 +106,8 @@
 bool pmPSFmodelWriteForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa->chips, false);
 
     pmFPA *fpa = file->fpa;
@@ -126,4 +141,7 @@
 bool pmPSFmodelWriteFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, false);
     pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
     *thisView = *view;
@@ -145,4 +163,7 @@
 bool pmPSFmodelWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+
     if (!pmPSFmodelWrite (chip->analysis, view, file, config)) {
         psError(PS_ERR_IO, false, "Failed to write PSF for chip");
@@ -162,4 +183,7 @@
 bool pmPSFmodelWrite (psMetadata *analysis, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
     bool status;
     pmHDU *hdu;
@@ -450,6 +474,9 @@
 
 // if this file needs to have a PHU written out, write one
-bool pmPSFmodelWritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config) {
-
+bool pmPSFmodelWritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
     // not needed if already written
     if (file->wrote_phu) return true;
@@ -494,4 +521,7 @@
 bool pmPSFmodelReadForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
 
     pmFPA *fpa = file->fpa;
@@ -517,4 +547,8 @@
 bool pmPSFmodelReadFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
     bool success = true;                // Was everything successful?
     for (int i = 0; i < fpa->chips->n; i++) {
@@ -528,4 +562,8 @@
 bool pmPSFmodelReadChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
     if (!pmPSFmodelRead (chip->analysis, view, file, config)) {
         psError(PS_ERR_IO, false, "Failed to write PSF for chip");
@@ -539,4 +577,8 @@
 bool pmPSFmodelRead (psMetadata *analysis, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
     bool status;
     char *rule = NULL;
@@ -763,4 +805,3 @@
 }
 
-// create a psMetadata representation (human-readable) of a psf model
 // XXX pmPSF to/from Metadata functions were defined for 1.22 and earlier, but were dropped
Index: /trunk/psModules/src/objects/pmPSFtry.c
===================================================================
--- /trunk/psModules/src/objects/pmPSFtry.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmPSFtry.c	(revision 15562)
@@ -5,6 +5,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.49 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-10-09 19:26:25 $
+ *  @version $Revision: 1.50 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -81,4 +81,11 @@
 }
 
+bool psMemCheckPSFtry(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmPSFtryFree);
+}
+
+
 // build a pmPSFtry for the given model:
 // - fit each source with the free-floating model
@@ -249,4 +256,7 @@
 bool pmPSFtryMetric (pmPSFtry *psfTry, float RADIUS)
 {
+    PS_ASSERT_PTR_NON_NULL(psfTry, false);
+    PS_ASSERT_PTR_NON_NULL(psfTry->sources, false);
+
     // the measured (aperture - fit) magnitudes (dA == psfTry->metric)
     //   depend on both the true ap-fit (dAo) and the bias in the sky measurement:
@@ -346,4 +356,7 @@
 bool pmPSFFromPSFtry (pmPSFtry *psfTry)
 {
+    PS_ASSERT_PTR_NON_NULL(psfTry, false);
+    PS_ASSERT_PTR_NON_NULL(psfTry->sources, false);
+
     pmPSF *psf = psfTry->psf;
 
Index: /trunk/psModules/src/objects/pmPSFtry.h
===================================================================
--- /trunk/psModules/src/objects/pmPSFtry.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmPSFtry.h	(revision 15562)
@@ -6,6 +6,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-09-25 22:05:05 $
+ * @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -78,5 +78,7 @@
  *
  */
+
 pmPSFtry *pmPSFtryAlloc (psArray *sources, pmPSFOptions *options);
+bool psMemCheckPSFtry(psPtr ptr);
 
 /** pmPSFtryModel()
Index: /trunk/psModules/src/objects/pmPeaks.c
===================================================================
--- /trunk/psModules/src/objects/pmPeaks.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmPeaks.c	(revision 15562)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA: significant modifications.
  *
- *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-27 03:35:29 $
+ *  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -150,4 +150,5 @@
 }
 
+// XXX: Get rid of this:
 bool pmPeakTest(const psPtr ptr)
 {
@@ -155,5 +156,13 @@
 }
 
+bool psMemCheckPeak(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) peakFree);
+}
+
+
 // psSort comparison function for peaks
+// XXX: Add error-checking for NULL args
 int pmPeaksCompareAscend (const void **a, const void **b)
 {
@@ -177,4 +186,5 @@
 
 // psSort comparison function for peaks
+// XXX: Add error-checking for NULL args
 int pmPeaksCompareDescend (const void **a, const void **b)
 {
Index: /trunk/psModules/src/objects/pmPeaks.h
===================================================================
--- /trunk/psModules/src/objects/pmPeaks.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmPeaks.h	(revision 15562)
@@ -10,6 +10,6 @@
  * @author GLG, MHPCC
  *
- * @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-09-27 03:35:29 $
+ * @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -75,4 +75,5 @@
 
 bool pmPeakTest(const psPtr ptr);
+bool psMemCheckPeak(psPtr ptr);
 
 /** pmPeaksInVector()
Index: /trunk/psModules/src/objects/pmResiduals.c
===================================================================
--- /trunk/psModules/src/objects/pmResiduals.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmResiduals.c	(revision 15562)
@@ -4,6 +4,6 @@
  *
  * @author EAM, IfA
- * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-04-21 19:47:14 $
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004 IfA, University of Hawaii
  */
@@ -51,2 +51,9 @@
     return resid;
 }
+
+bool psMemCheckResiduals(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmResidualsFree);
+}
+
Index: /trunk/psModules/src/objects/pmResiduals.h
===================================================================
--- /trunk/psModules/src/objects/pmResiduals.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmResiduals.h	(revision 15562)
@@ -4,6 +4,6 @@
  *
  * @author EAM, IfA
- * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-04-21 19:47:14 $
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004 IfA, University of Hawaii
  */
@@ -29,4 +29,5 @@
 
 pmResiduals *pmResidualsAlloc (int xSize, int ySize, int xBin, int yBin);
+bool psMemCheckResiduals(psPtr ptr);
 
 /// @}
Index: /trunk/psModules/src/objects/pmSource.c
===================================================================
--- /trunk/psModules/src/objects/pmSource.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSource.c	(revision 15562)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA: significant modifications.
  *
- *  @version $Revision: 1.40 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-10-06 02:29:47 $
+ *  @version $Revision: 1.41 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -77,8 +77,15 @@
 }
 
+bool psMemCheckSource(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) sourceFree);
+}
+
 /******************************************************************************
 pmSourceAlloc(): Allocate the pmSource structure and initialize its members
 to NULL.
 *****************************************************************************/
+
 pmSource *pmSourceAlloc()
 {
@@ -132,4 +139,7 @@
 pmSource *pmSourceCopy(pmSource *in)
 {
+    if (in == NULL) {
+        return(NULL);
+    }
     // this copy is used to allow multiple fit attempts on the
     // same object.  the pixels, weight, and mask arrays all point to
@@ -139,19 +149,23 @@
 
     // this is actually the same peak as the original, is this the correct way to handle this?
-    source->peak = pmPeakAlloc (in->peak->x, in->peak->y, in->peak->value, in->peak->type);
-    source->peak->xf = in->peak->xf;
-    source->peak->yf = in->peak->yf;
-    source->peak->flux = in->peak->flux;
-    source->peak->SN = in->peak->SN;
+    if (in->peak != NULL) {
+        source->peak = pmPeakAlloc (in->peak->x, in->peak->y, in->peak->value, in->peak->type);
+        source->peak->xf = in->peak->xf;
+        source->peak->yf = in->peak->yf;
+        source->peak->flux = in->peak->flux;
+        source->peak->SN = in->peak->SN;
+    }
 
     // copy the values in the moments structure
-    source->moments  =  pmMomentsAlloc();
-    *source->moments = *in->moments;
+    if (in->moments != NULL) {
+        source->moments  =  pmMomentsAlloc();
+        *source->moments = *in->moments;
+    }
 
     // These images are all views to the parent.
     // We want a new view, but pointing at the same pixels.
-    source->pixels   = psImageCopyView (NULL, in->pixels);
-    source->weight   = psImageCopyView (NULL, in->weight);
-    source->maskView = psImageCopyView (NULL, in->maskView);
+    source->pixels   = psImageCopyView(NULL, in->pixels);
+    source->weight   = psImageCopyView(NULL, in->weight);
+    source->maskView = psImageCopyView(NULL, in->maskView);
 
     // the maskObj is a unique mask array; create a new mask image
@@ -173,4 +187,9 @@
                           psF32 Radius)
 {
+    PS_ASSERT_PTR_NON_NULL(mySource, false);
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(readout->image, false);
+    PS_ASSERT_INT_POSITIVE(Radius, false);
+
     psRegion srcRegion;
 
@@ -200,9 +219,11 @@
                             psF32 Radius)
 {
+    PS_ASSERT_PTR_NON_NULL(mySource, false);
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(readout->image, false);
+    PS_ASSERT_INT_POSITIVE(Radius, false);
+
     bool extend;
     psRegion newRegion;
-
-    if (Radius == 0)
-        return false;
 
     // check to see if new region is completely contained within old region
@@ -814,6 +835,8 @@
 
 // should we call pmSourceCacheModel if it does not exist?
-bool pmSourceOp (pmSource *source, pmModelOpMode mode, bool add, psMaskType maskVal, int dx, int dy) {
-
+bool pmSourceOp (pmSource *source, pmModelOpMode mode, bool add, 
+                 psMaskType maskVal, int dx, int dy)
+{
+    PS_ASSERT_PTR_NON_NULL(source, false);
     bool status;
 
@@ -904,4 +927,5 @@
 pmModel *pmSourceGetModel (bool *isPSF, const pmSource *source)
 {
+    PS_ASSERT_PTR_NON_NULL(source, NULL);
 
     pmModel *model;
Index: /trunk/psModules/src/objects/pmSource.h
===================================================================
--- /trunk/psModules/src/objects/pmSource.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmSource.h	(revision 15562)
@@ -3,6 +3,6 @@
  * @author EAM, IfA; GLG, MHPCC
  *
- * @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-09-27 03:35:29 $
+ * @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -10,4 +10,6 @@
 # ifndef PM_SOURCE_H
 # define PM_SOURCE_H
+
+# include "pmSourceExtendedPars.h"
 
 /// @addtogroup Objects Object Detection / Analysis Functions
@@ -84,4 +86,5 @@
     psRegion region;                    ///< area on image covered by selected pixels
     float sky, skyErr;                  ///< The sky and its error at the center of the object
+    pmSourceExtendedPars *extpars;      ///< extended source parameters
 };
 
@@ -111,4 +114,7 @@
  *
  */
+
+bool psMemCheckSource(psPtr ptr);
+
 pmSource  *pmSourceCopy(pmSource *source);
 
@@ -178,8 +184,7 @@
  */
 pmPSFClump pmSourcePSFClump(
-    psArray *source,   ///< The input pmSource
-    psMetadata *metadata  ///< Contains classification parameters
-);
-
+    psArray *source,                    ///< The input pmSource
+    psMetadata *metadata                ///< Contains classification parameters
+);
 
 /** pmSourceRoughClass()
@@ -194,7 +199,7 @@
  */
 bool pmSourceRoughClass(
-    psArray *source,   ///< The input pmSource
-    psMetadata *metadata,  ///< Contains classification parameters
-    pmPSFClump clump,   ///< Statistics about the PSF clump
+    psArray *source,                    ///< The input pmSource
+    psMetadata *metadata,               ///< Contains classification parameters
+    pmPSFClump clump,                   ///< Statistics about the PSF clump
     psMaskType maskSat                  ///< Mask value for saturated pixels
 );
Index: /trunk/psModules/src/objects/pmSourceContour.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceContour.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceContour.c	(revision 15562)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA: significant modifications.
  *
- *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -220,4 +220,5 @@
 psArray *pmSourceContour (psImage *image, int xc, int yc, float threshold)
 {
+    PS_ASSERT_PTR_NON_NULL(image, NULL);
 
     int xR, yR, x0, x1, x0s, x1s;
Index: /trunk/psModules/src/objects/pmSourceExtendedPars.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceExtendedPars.c	(revision 15562)
+++ /trunk/psModules/src/objects/pmSourceExtendedPars.c	(revision 15562)
@@ -0,0 +1,155 @@
+/** @file  pmSourceExtendedPars.c
+ *
+ *  Functions to define and manipulate sources on images
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA: significant modifications.
+ *
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAMaskWeight.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+
+static void pmSourceExtendedParsFree (pmSourceExtendedPars *pars) {
+    if (!pars) return;
+
+    psFree(pars->profile);
+    psFree(pars->annuli);
+    psFree(pars->isophot);
+    psFree(pars->petrosian);
+    psFree(pars->kron);
+    return;
+}
+
+pmSourceExtendedPars *pmSourceExtendedParsAlloc () {
+    pmSourceExtendedPars *pars = (pmSourceExtendedPars *) psAlloc(sizeof(pmSourceExtendedPars));
+    psMemSetDeallocator(pars, (psFreeFunc) pmSourceExtendedParsFree);
+
+    pars->profile = NULL;
+    pars->annuli = NULL;
+    pars->isophot = NULL;
+    pars->petrosian = NULL;
+    pars->kron = NULL;
+
+    return pars;
+}
+
+static void pmSourceRadialProfileFree (pmSourceRadialProfile *profile) {
+    if (!profile) return;
+
+    psFree(profile->radius);
+    psFree(profile->flux);
+    psFree(profile->weight);
+    return;
+}
+
+pmSourceRadialProfile *pmSourceRadialProfileAlloc () {
+
+    pmSourceRadialProfile *profile = (pmSourceRadialProfile *) psAlloc(sizeof(pmSourceRadialProfile));
+    psMemSetDeallocator(profile, (psFreeFunc) pmSourceRadialProfileFree);
+
+    profile->radius = NULL;
+    profile->flux = NULL;
+    profile->weight = NULL;
+
+    return profile;
+}
+
+static void pmSourceIsophotalValuesFree (pmSourceIsophotalValues *isophot) {
+    if (!isophot) return;
+    return;
+}
+
+pmSourceIsophotalValues *pmSourceIsophotalValuesAlloc () {
+
+    pmSourceIsophotalValues *isophot = (pmSourceIsophotalValues *) psAlloc(sizeof(pmSourceIsophotalValues));
+    psMemSetDeallocator(isophot, (psFreeFunc) pmSourceIsophotalValuesFree);
+
+    isophot->mag = 0.0;
+    isophot->magErr = 0.0;
+    isophot->rad = 0.0;
+    isophot->radErr = 0.0;
+
+    return isophot;
+}
+
+static void pmSourcePetrosianValuesFree (pmSourcePetrosianValues *petrosian) {
+    if (!petrosian) return;
+    return;
+}
+
+pmSourcePetrosianValues *pmSourcePetrosianValuesAlloc () {
+
+    pmSourcePetrosianValues *petrosian = (pmSourcePetrosianValues *) psAlloc(sizeof(pmSourcePetrosianValues));
+    psMemSetDeallocator(petrosian, (psFreeFunc) pmSourcePetrosianValuesFree);
+
+    petrosian->mag = 0.0;
+    petrosian->magErr = 0.0;
+    petrosian->rad = 0.0;
+    petrosian->radErr = 0.0;
+
+    return petrosian;
+}
+
+static void pmSourceKronValuesFree (pmSourceKronValues *kron) {
+    if (!kron) return;
+    return;
+}
+
+pmSourceKronValues *pmSourceKronValuesAlloc () {
+
+    pmSourceKronValues *kron = (pmSourceKronValues *) psAlloc(sizeof(pmSourceKronValues));
+    psMemSetDeallocator(kron, (psFreeFunc) pmSourceKronValuesFree);
+
+    kron->mag = 0.0;
+    kron->magErr = 0.0;
+    kron->rad = 0.0;
+    kron->radErr = 0.0;
+
+    return kron;
+}
+
+static void pmSourceAnnuliFree (pmSourceAnnuli *annuli) {
+    if (!annuli) return;
+
+    psFree (annuli->flux);
+    psFree (annuli->fluxErr);
+    psFree (annuli->fluxVar);
+
+    return;
+}
+
+pmSourceAnnuli *pmSourceAnnuliAlloc () {
+
+    pmSourceAnnuli *annuli = (pmSourceAnnuli *) psAlloc(sizeof(pmSourceAnnuli));
+    psMemSetDeallocator(annuli, (psFreeFunc) pmSourceAnnuliFree);
+
+    annuli->flux = NULL;
+    annuli->fluxErr = NULL;
+    annuli->fluxVar = NULL;
+
+    return annuli;
+}
+
Index: /trunk/psModules/src/objects/pmSourceExtendedPars.h
===================================================================
--- /trunk/psModules/src/objects/pmSourceExtendedPars.h	(revision 15562)
+++ /trunk/psModules/src/objects/pmSourceExtendedPars.h	(revision 15562)
@@ -0,0 +1,65 @@
+/* @file  pmSourceExtendedPars.h
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_SOURCE_EXTENDED_PARS_H
+# define PM_SOURCE_EXTENDED_PARS_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+typedef struct {
+  psVector *radius;
+  psVector *flux;
+  psVector *weight;
+} pmSourceRadialProfile;
+
+typedef struct {
+  psVector *flux;
+  psVector *fluxErr;
+  psVector *fluxVar;
+} pmSourceAnnuli;
+
+typedef struct {
+  float mag;
+  float magErr;
+  float rad;
+  float radErr;
+} pmSourceIsophotalValues;
+
+typedef struct {
+  float mag;
+  float magErr;
+  float rad;
+  float radErr;
+} pmSourcePetrosianValues;
+
+typedef struct {
+  float mag;
+  float magErr;
+  float rad;
+  float radErr;
+} pmSourceKronValues;
+
+typedef struct {
+  pmSourceRadialProfile   *profile;
+  pmSourceAnnuli          *annuli;
+  pmSourceIsophotalValues *isophot;
+  pmSourcePetrosianValues *petrosian;
+  pmSourceKronValues      *kron;
+} pmSourceExtendedPars;
+
+pmSourceExtendedPars *pmSourceExtendedParsAlloc ();
+pmSourceRadialProfile *pmSourceRadialProfileAlloc ();
+pmSourceIsophotalValues *pmSourceIsophotalValuesAlloc ();
+pmSourcePetrosianValues *pmSourcePetrosianValuesAlloc ();
+pmSourceKronValues *pmSourceKronValuesAlloc ();
+pmSourceAnnuli *pmSourceAnnuliAlloc ();
+
+/// @}
+# endif /* PM_SOURCE_H */
Index: /trunk/psModules/src/objects/pmSourceFitSet.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceFitSet.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceFitSet.c	(revision 15562)
@@ -6,6 +6,6 @@
  *  @author GLG, MHPCC
  *
- *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-28 00:39:41 $
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -79,8 +79,16 @@
 }
 
+bool psMemCheckSourceFitSetData(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmSourceFitSetDataFree);
+}
+
+
 // this function is called with the full set of parameters and the beta values in a single vector
-bool pmSourceFitSetCheckLimits (psMinConstraintMode mode, int nParam, float *params, float *betas)
-{
-    assert (thisSet);
+bool pmSourceFitSetCheckLimits (psMinConstraintMode mode, int nParam, float *params,
+                                float *betas)
+{
+    PS_ASSERT_PTR_NON_NULL(thisSet, false);
 
     // nParam is the parameter in the full sequence.  determine which single model this comes from
@@ -109,7 +117,9 @@
 
 // merge parameters from FitSet models into single param and deriv vectors
-bool pmSourceFitSetJoin (psVector *deriv, psVector *param, pmSourceFitSetData *set) {
-
-    assert (set);
+bool pmSourceFitSetJoin (psVector *deriv, psVector *param, pmSourceFitSetData *set)
+{
+    PS_ASSERT_PTR_NON_NULL(set, false);
+    PS_ASSERT_PTR_NON_NULL(param, false);
+
     assert (set->paramSet->n == set->derivSet->n);
 
@@ -138,6 +148,7 @@
 // distribute parameters from single param and deriv vectors into FitSet models
 bool pmSourceFitSetSplit (pmSourceFitSetData *set, const psVector *deriv, const psVector *param) {
-
-    assert (set);
+    PS_ASSERT_PTR_NON_NULL(set, false);
+    PS_ASSERT_PTR_NON_NULL(param, false);
+
     assert (set->paramSet->n == set->derivSet->n);
 
@@ -159,9 +170,10 @@
 }
 
-bool pmSourceFitSetValues (pmSourceFitSetData *set, const psVector *dparam, const psVector *param, pmSource *source, psMinimization *myMin, int nPix, bool fitStatus) {
-
+bool pmSourceFitSetValues (pmSourceFitSetData *set, const psVector *dparam, 
+                           const psVector *param, pmSource *source,
+                           psMinimization *myMin, int nPix, bool fitStatus)
+{
+    PS_ASSERT_PTR_NON_NULL(set, false);
     bool onPic = true;
-
-    assert (set);
 
     int n = 0;
@@ -203,8 +215,7 @@
 psF32 pmSourceFitSetFunction(psVector *deriv, const psVector *param, const psVector *x)
 {
+    PS_ASSERT_PTR_NON_NULL(thisSet, NAN);
     float chisqSum = 0.0;
     float chisqOne = 0.0;
-
-    assert (thisSet);
     pmSourceFitSetSplit (thisSet, deriv, param);
 
@@ -225,5 +236,9 @@
 
 // XXX allow the mode to be a function of the object (eg, S/N)
-bool pmSourceFitSetMasks (psMinConstraint *constraint, pmSourceFitSetData *set, pmSourceFitMode mode) {
+bool pmSourceFitSetMasks (psMinConstraint *constraint, pmSourceFitSetData *set,
+                          pmSourceFitMode mode)
+{
+    PS_ASSERT_PTR_NON_NULL(set, false);
+    PS_ASSERT_PTR_NON_NULL(constraint, false);
 
     // unmask everyone
Index: /trunk/psModules/src/objects/pmSourceFitSet.h
===================================================================
--- /trunk/psModules/src/objects/pmSourceFitSet.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceFitSet.h	(revision 15562)
@@ -3,6 +3,6 @@
  * @author EAM, IfA; GLG, MHPCC
  *
- * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-09-28 00:39:47 $
+ * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -23,4 +23,5 @@
 // initialize data for a group of object models
 pmSourceFitSetData *pmSourceFitSetDataAlloc (psArray *modelSet);
+bool psMemCheckSourceFitSetData(psPtr ptr);
 
 // function used to set limits for a group of models
Index: /trunk/psModules/src/objects/pmSourceIO.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceIO.c	(revision 15562)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.52 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-10-05 22:46:34 $
+ *  @version $Revision: 1.53 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -47,4 +47,6 @@
 int pmSourceGetDophotType (pmSource *source)
 {
+    PS_ASSERT_PTR_NON_NULL(source, -1);
+
     switch (source->type) {
 
@@ -74,4 +76,6 @@
 bool pmSourceSetDophotType (pmSource *source, int type)
 {
+    PS_ASSERT_PTR_NON_NULL(source, false);
+
     if (type == 4) {
         source->mode |= PM_SOURCE_MODE_FAIL;
@@ -106,4 +110,7 @@
 bool pmFPAviewWriteObjects (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
 
     pmFPA *fpa = file->fpa;
@@ -165,4 +172,8 @@
 bool pmFPAWriteObjects (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, false);
+
     pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
     *thisView = *view;
@@ -184,4 +195,8 @@
 bool pmChipWriteObjects (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->cells, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
     pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
     *thisView = *view;
@@ -203,4 +218,8 @@
 bool pmCellWriteObjects (pmCell *cell, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(cell->readouts, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
     pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
     *thisView = *view;
@@ -222,12 +241,18 @@
 bool pmReadoutWriteObjects (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
 
     bool status;
-    char *exttype;
-    char *dataname;
-    char *headname;
     pmHDU *hdu;
     psMetadata *updates;
     psMetadata *outhead;
+
+    char *exttype  = NULL;
+    char *dataname = NULL;
+    char *xsrcname = NULL;
+    char *headname = NULL;
 
     // XXX if sources is NULL, skip the cell or write out empty tables?
@@ -284,4 +309,14 @@
         // get the current header
         hdu = pmFPAviewThisHDU (view, file->fpa);
+
+	// determine the output table format
+	psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, "PSPHOT");
+	if (!status) {
+	  psError(PS_ERR_UNKNOWN, true, "missing recipe PSPHOT in config data");
+	  return false;
+	}
+
+	// if this is not TRUE, the output files only contain the psf measurements.
+	bool XSRC_OUTPUT = psMetadataLookupBool(&status, recipe, "SAVE.XSRC");
 
         // define the EXTNAME values for the different data segments:
@@ -312,4 +347,14 @@
             }
             dataname = pmFPAfileNameFromRule (rule, file, view);
+
+	    if (XSRC_OUTPUT) {
+	      // EXTNAME for extended source data table
+	      rule = psMetadataLookupStr(&status, menu, "CMF.XSRC");
+	      if (!rule) {
+                psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XSRC in EXTNAME.RULES in camera.config");
+                return false;
+	      }
+	      xsrcname = pmFPAfileNameFromRule (rule, file, view);
+	    }
         }
 
@@ -350,10 +395,4 @@
             outhead = psMetadataAlloc ();
 
-            // determine the output table format
-            psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, "PSPHOT");
-            if (!status) {
-                psError(PS_ERR_UNKNOWN, true, "missing recipe PSPHOT in config data");
-                return false;
-            }
             exttype = psMemIncrRefCounter (psMetadataLookupStr(&status, recipe, "OUTPUT.FORMAT"));
             if (!exttype) {
@@ -375,7 +414,6 @@
             }
             if (!strcmp (exttype, "PS1_DEV_1")) {
-                status = pmSourcesWrite_PS1_DEV_1 (file->fits, sources, file->header, outhead, dataname);
+                status = pmSourcesWrite_PS1_DEV_1 (file->fits, sources, file->header, outhead, dataname, xsrcname);
             }
-
             if (!status) {
                 psError(PS_ERR_IO, false, "writing CMF data to %s with format %s\n", file->filename, exttype);
@@ -403,5 +441,8 @@
 
 // if this file needs to have a PHU written out, write one
-bool pmSource_CMF_WritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config) {
+bool pmSource_CMF_WritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
 
     bool status;
@@ -512,4 +553,8 @@
 bool pmFPAviewReadObjects (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
     pmFPA *fpa = file->fpa;
 
@@ -551,4 +596,9 @@
 bool pmFPAReadObjects (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa->chips, false);
+
     pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
     *thisView = *view;
@@ -572,4 +622,8 @@
 bool pmChipReadObjects (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->cells, false);
+
     pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
     *thisView = *view;
@@ -596,4 +650,8 @@
 bool pmCellReadObjects (pmCell *cell, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(cell->readouts, false);
+
     pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
     *thisView = *view;
@@ -637,4 +695,6 @@
 bool pmReadoutReadObjects (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
 
     bool status;
@@ -774,4 +834,8 @@
 bool pmFPAviewCheckDataStatusForSources (const pmFPAview *view, const pmFPAfile *file)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
     pmFPA *fpa = file->fpa;
 
@@ -811,5 +875,8 @@
 }
 
-bool pmFPACheckDataStatusForSources (const pmFPA *fpa) {
+bool pmFPACheckDataStatusForSources (const pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, false);
 
     for (int i = 0; i < fpa->chips->n; i++) {
@@ -821,5 +888,8 @@
 }
 
-bool pmChipCheckDataStatusForSources (const pmChip *chip) {
+bool pmChipCheckDataStatusForSources (const pmChip *chip)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->cells, false);
 
     for (int i = 0; i < chip->cells->n; i++) {
@@ -831,5 +901,8 @@
 }
 
-bool pmCellCheckDataStatusForSources (const pmCell *cell) {
+bool pmCellCheckDataStatusForSources (const pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(cell->readouts, false);
 
     for (int i = 0; i < cell->readouts->n; i++) {
@@ -841,5 +914,7 @@
 }
 
-bool pmReadoutCheckDataStatusForSources (const pmReadout *readout) {
+bool pmReadoutCheckDataStatusForSources (const pmReadout *readout)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
 
     bool status;
Index: /trunk/psModules/src/objects/pmSourceIO.h
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceIO.h	(revision 15562)
@@ -4,6 +4,6 @@
  * @author EAM, IfA; GLG, MHPCC
  *
- * @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-09-27 03:35:29 $
+ * @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  *
@@ -26,5 +26,6 @@
 bool pmSourcesWrite_SMPDATA (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
 bool pmSourcesWrite_PS1_DEV_0 (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
-bool pmSourcesWrite_PS1_DEV_1 (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
+bool pmSourcesWrite_PS1_DEV_1 (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, char *xsrcname);
+bool pmSourcesWrite_PS1_DEV_1_XSRC (psFits *fits, psArray *sources, char *extname);
 
 bool pmSource_CMF_WritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
Index: /trunk/psModules/src/objects/pmSourceIO_CMP.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO_CMP.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceIO_CMP.c	(revision 15562)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.31 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.32 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -48,4 +48,7 @@
 bool pmSourcesWriteCMP (psArray *sources, char *filename, psMetadata *header)
 {
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+    PS_ASSERT_PTR_NON_NULL(header, false);
 
     int i, type;
@@ -58,11 +61,13 @@
     // find config information for output header
     float ZERO_POINT = psMetadataLookupF32 (&status, header, "ZERO_PT");
-    if (!status)
+    if (!status) {
         ZERO_POINT = 25.0;
+    }
 
     // MEF elements have XTENSION, not SIMPLE: remove this (replace with SIMPLE)
     psMetadataLookupStr (&status, header, "XTENSION");
-    if (status)
+    if (status) {
         psMetadataRemoveKey (header, "XTENSION");
+    }
 
     // create file, write-out header
@@ -148,4 +153,6 @@
 psArray *pmSourcesReadCMP (char *filename, psMetadata *header)
 {
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+    PS_ASSERT_PTR_NON_NULL(header, false);
 
     bool status;
Index: /trunk/psModules/src/objects/pmSourceIO_OBJ.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO_OBJ.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceIO_OBJ.c	(revision 15562)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -42,4 +42,6 @@
 bool pmSourcesWriteOBJ (psArray *sources, char *filename)
 {
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
 
     int type;
Index: /trunk/psModules/src/objects/pmSourceIO_PS1_DEV_0.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO_PS1_DEV_0.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceIO_PS1_DEV_0.c	(revision 15562)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -46,7 +46,11 @@
 // values derived in the DVO database.
 // XXX how do I generate the source tables which I need to send to PSPS?
-
-bool pmSourcesWrite_PS1_DEV_0 (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
+// XXX: input parameter imageHeader is never used.
+bool pmSourcesWrite_PS1_DEV_0 (psFits *fits, psArray *sources, psMetadata *imageHeader,
+                               psMetadata *tableHeader, char *extname)
 {
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(extname, false);
 
     psArray *table;
@@ -147,4 +151,6 @@
 psArray *pmSourcesRead_PS1_DEV_0 (psFits *fits, psMetadata *header)
 {
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(header, false);
 
     bool status;
Index: /trunk/psModules/src/objects/pmSourceIO_PS1_DEV_1.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO_PS1_DEV_1.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceIO_PS1_DEV_1.c	(revision 15562)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-10-09 03:10:05 $
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -47,5 +47,5 @@
 // XXX how do I generate the source tables which I need to send to PSPS?
 
-bool pmSourcesWrite_PS1_DEV_1 (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
+bool pmSourcesWrite_PS1_DEV_1 (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, char *xsrcname)
 {
 
@@ -57,4 +57,9 @@
     psF32 xPos, yPos;
     psF32 xErr, yErr;
+
+    // if we request XSRC output, add the XSRC name to this header
+    if (xsrcname) {
+      psMetadataAddStr (tableHeader, PS_LIST_TAIL, "XSRCNAME", PS_META_REPLACE, "name of XSRC table extension", xsrcname);
+    }
 
     // let's write these out in S/N order
@@ -144,6 +149,10 @@
         return false;
     }
-
     psFree (table);
+
+    if (xsrcname) {
+      pmSourcesWrite_PS1_DEV_1_XSRC (fits, sources, xsrcname);
+    }
+
     return true;
 }
@@ -165,4 +174,6 @@
     }
     assert (modelType > -1);
+
+    // XXX need to look up the XSRCNAME entries
 
     // validate a single row of the table (must match SMP)
@@ -241,2 +252,85 @@
     return sources;
 }
+
+bool pmSourcesWrite_PS1_DEV_1_XSRC (psFits *fits, psArray *sources, char *extname)
+{
+
+    psArray *table;
+    psMetadata *row;
+    int i;
+    psF32 *PAR, *dPAR;
+    psEllipseAxes axes;
+    psF32 xPos, yPos;
+    psF32 xErr, yErr;
+
+    // create a header to hold the output data
+    psMetadata *outhead = psMetadataAlloc ();
+
+    // write the links to the image header
+    psMetadataAddStr (outhead, PS_LIST_TAIL, "EXTNAME", PS_META_REPLACE, "xsrc table extension", extname);
+
+    // let's write these out in S/N order
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    table = psArrayAllocEmpty (sources->n);
+
+    // we write out all sources, regardless of quality.  the source flags tell us the state
+    for (i = 0; i < sources->n; i++) {
+        pmSource *source = (pmSource *) sources->data[i];
+        source->seq = i;
+
+	// skip source if it is not a ext sourc
+
+        // no difference between PSF and non-PSF model
+	// XXX the PSF output should report the value for the psf, not the ext, model
+        pmModel *model = source->modelEXT;
+        if (model == NULL) continue;
+
+	PAR = model->params->data.F32;
+	dPAR = model->dparams->data.F32;
+	xPos = PAR[PM_PAR_XPOS];
+	yPos = PAR[PM_PAR_YPOS];
+	xErr = dPAR[PM_PAR_XPOS];
+	yErr = dPAR[PM_PAR_YPOS];
+
+	axes = pmPSF_ModelToAxes (PAR, 20.0);
+
+        row = psMetadataAlloc ();
+        // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
+        psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET",         PS_DATA_U32, "IPP detection identifier index",             source->seq);
+        psMetadataAdd (row, PS_LIST_TAIL, "X_EXT",            PS_DATA_F32, "PSF x coordinate",                           xPos);
+        psMetadataAdd (row, PS_LIST_TAIL, "Y_EXT",            PS_DATA_F32, "PSF y coordinate",                           yPos);
+        psMetadataAdd (row, PS_LIST_TAIL, "X_EXT_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  xErr);
+        psMetadataAdd (row, PS_LIST_TAIL, "Y_EXT_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  yErr);
+        psMetadataAdd (row, PS_LIST_TAIL, "EXT_INST_MAG",     PS_DATA_F32, "PSF fit instrumental magnitude",             PS_MIN (99.0, source->extMag));
+	// XXX need to calculate psfMag, psfMagErr, extMag, extMagErr...
+        psMetadataAdd (row, PS_LIST_TAIL, "EXT_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        PS_MIN (99.0, source->errMag));
+
+        // XXX these should be major and minor, not 'x' and 'y'
+        psMetadataAdd (row, PS_LIST_TAIL, "EXT_WIDTH_X",      PS_DATA_F32, "PSF width in x coordinate",                  axes.major);
+        psMetadataAdd (row, PS_LIST_TAIL, "EXT_WIDTH_Y",      PS_DATA_F32, "PSF width in y coordinate",                  axes.minor);
+        psMetadataAdd (row, PS_LIST_TAIL, "EXT_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
+
+	// other values that I need to report:
+	// R, Mag Petrosian, .....
+
+        psArrayAdd (table, 100, row);
+        psFree (row);
+    }
+
+    if (table->n == 0) {
+        psFitsWriteBlank (fits, outhead, extname);
+        psFree (table);
+        return true;
+    }
+
+    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
+    if (!psFitsWriteTable (fits, outhead, table, extname)) {
+        psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
+        psFree(table);
+        return false;
+    }
+    psFree (table);
+
+    return true;
+}
Index: /trunk/psModules/src/objects/pmSourceIO_RAW.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO_RAW.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceIO_RAW.c	(revision 15562)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -44,4 +44,7 @@
 {
 
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+
     char *name = (char *) psAlloc (strlen(filename) + 10);
 
@@ -65,4 +68,6 @@
 bool pmSourcesWritePSFs (psArray *sources, char *filename)
 {
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
 
     double dPos;
@@ -124,4 +129,6 @@
 bool pmSourcesWriteEXTs (psArray *sources, char *filename, bool requireEXT)
 {
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
 
     double dPos;
@@ -184,4 +191,6 @@
 bool pmSourcesWriteNULLs (psArray *sources, char *filename)
 {
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
 
     int i;
@@ -230,4 +239,6 @@
 bool pmMomentsWriteText (psArray *sources, char *filename)
 {
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
 
     int i;
Index: /trunk/psModules/src/objects/pmSourceIO_SMPDATA.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO_SMPDATA.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceIO_SMPDATA.c	(revision 15562)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -42,6 +42,11 @@
 // this format consists of a header derived from the image header
 // followed by a zero-size matrix, followed by the table data
-bool pmSourcesWrite_SMPDATA (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
+// XXX: input parameter imageHeader is never used
+bool pmSourcesWrite_SMPDATA (psFits *fits, psArray *sources, psMetadata *imageHeader,
+                             psMetadata *tableHeader, char *extname)
 {
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(extname, false);
 
     psArray *table;
@@ -126,4 +131,6 @@
 psArray *pmSourcesRead_SMPDATA (psFits *fits, psMetadata *header)
 {
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(header, false);
 
     bool status;
Index: /trunk/psModules/src/objects/pmSourceIO_SX.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO_SX.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceIO_SX.c	(revision 15562)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -42,4 +42,6 @@
 bool pmSourcesWriteSX (psArray *sources, char *filename)
 {
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
 
     psF32 *PAR, *dPAR;
Index: /trunk/psModules/src/objects/pmSourcePhotometry.c
===================================================================
--- /trunk/psModules/src/objects/pmSourcePhotometry.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourcePhotometry.c	(revision 15562)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA; GLG, MHPCC
  *
- *  @version $Revision: 1.36 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-29 03:14:55 $
+ *  @version $Revision: 1.37 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -39,5 +39,5 @@
 bool pmSourceMagnitudesInit (psMetadata *config)
 {
-
+    PS_ASSERT_PTR_NON_NULL(config, false);
     bool status;
 
@@ -64,6 +64,9 @@
 
 // XXX masked region should be (optionally) elliptical
-bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psMaskType maskVal, psMaskType mark)
-{
+bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode,
+                         psMaskType maskVal, psMaskType mark)
+{
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_PTR_NON_NULL(psf, false);
 
     int status = false;
@@ -269,11 +272,11 @@
 bool pmSourcePhotometryModel (float *fitMag, pmModel *model)
 {
+    PS_ASSERT_PTR_NON_NULL(fitMag, false);
+    if (model == NULL) {
+        return false;
+    }
 
     float fitSum = 0;
     *fitMag = NAN;
-
-    if (model == NULL) {
-        return false;
-    }
 
     // measure fitMag
@@ -289,14 +292,15 @@
 
 // return source aperture magnitude
-bool pmSourcePhotometryAper (float *apMag, pmModel *model, psImage *image, psImage *mask, psMaskType maskVal)
-{
+bool pmSourcePhotometryAper (float *apMag, pmModel *model, psImage *image, psImage *mask,
+                             psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(apMag, false);
+    PS_ASSERT_PTR_NON_NULL(image, false);
+    PS_ASSERT_PTR_NON_NULL(mask, false);
+    PS_ASSERT_PTR_NON_NULL(model, false);
+
     float apSum = 0;
     float sky = 0;
     *apMag = NAN;
-
-    if (model == NULL) {
-        psError(PM_ERR_OBJECTS, true, "Model is NULL");
-        return false;
-    }
 
     if (DO_SKY) {
@@ -327,6 +331,12 @@
 
 // return source aperture magnitude
-bool pmSourcePixelWeight (float *pixWeight, pmModel *model, psImage *image, psImage *mask, psMaskType maskVal)
-{
+bool pmSourcePixelWeight (float *pixWeight, pmModel *model, psImage *image, psImage *mask,
+                          psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(pixWeight, false);
+    PS_ASSERT_PTR_NON_NULL(image, false);
+    PS_ASSERT_PTR_NON_NULL(mask, false);
+    PS_ASSERT_PTR_NON_NULL(model, false);
+
     float modelSum = 0;
     float validSum = 0;
@@ -339,7 +349,4 @@
 
     *pixWeight = 0.0;
-
-    if (model == NULL)
-        return false;
 
     // we only care about the value of the object model, not the local sky
@@ -412,4 +419,6 @@
                              const bool unweighted_sum) // should the cross product be weighted?
 {
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
+    PS_ASSERT_PTR_NON_NULL(Mj, NAN);
 
     int Xs, Xe, Ys, Ye;
@@ -475,4 +484,6 @@
                            const bool unweighted_sum) // should the cross product be weighted?
 {
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
+    PS_ASSERT_PTR_NON_NULL(Mj, NAN);
 
     int Xs, Xe, Ys, Ye;
@@ -538,4 +549,5 @@
                       const bool unweighted_sum) // should the cross product be weighted?
 {
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
     double flux = 0, wt = 0, factor = 0;
 
@@ -587,6 +599,11 @@
 # endif
 
-bool pmSourceChisq (pmModel *model, psImage *image, psImage *mask, psImage *weight, psMaskType maskVal)
-{
+bool pmSourceChisq (pmModel *model, psImage *image, psImage *mask, psImage *weight,
+                    psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(model, false);
+    PS_ASSERT_PTR_NON_NULL(image, false);
+    PS_ASSERT_PTR_NON_NULL(mask, false);
+    PS_ASSERT_PTR_NON_NULL(weight, false);
 
     double dC = 0.0;
@@ -613,4 +630,5 @@
                       const bool unweighted_sum) // should the cross product be weighted?
 {
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
     double flux = 0, wt = 0, factor = 0;
 
@@ -662,4 +680,6 @@
                               const bool unweighted_sum) // should the cross product be weighted?
 {
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
+    PS_ASSERT_PTR_NON_NULL(Mj, NAN);
     int Xs, Xe, Ys, Ye;
     int xi, xj, yi, yj;
@@ -724,5 +744,6 @@
                              const bool unweighted_sum) // should the cross product be weighted?
 {
-
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
+    PS_ASSERT_PTR_NON_NULL(Mj, NAN);
     int Xs, Xe, Ys, Ye;
     int xi, xj, yi, yj;
Index: /trunk/psModules/src/objects/pmSourcePlotApResid.c
===================================================================
--- /trunk/psModules/src/objects/pmSourcePlotApResid.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourcePlotApResid.c	(revision 15562)
@@ -4,6 +4,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *  Copyright 2006 IfA, University of Hawaii
  */
@@ -40,9 +40,14 @@
     # include <kapa.h>
 
-    // plot the sx, sy, sxy as vector field,
-    // plot the PSF measured sx, sy, sxy as vector field
-    // pull the sources from the config / file?
-    bool pmSourcePlotApResid (const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout)
+// plot the sx, sy, sxy as vector field,
+// plot the PSF measured sx, sy, sxy as vector field
+// pull the sources from the config / file?
+bool pmSourcePlotApResid (const pmFPAview *view, pmFPAfile *file, const pmConfig *config,
+                          pmSourcePlotLayout *layout)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(layout, false);
 
     Graphdata graphdata;
@@ -150,5 +155,5 @@
 # else
 
-    bool pmSourcePlotApResid (const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout)
+bool pmSourcePlotApResid (const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout)
 {
     psLogMsg ("psphot", 3, "skipping ap-mag resid plot");
Index: /trunk/psModules/src/objects/pmSourcePlotMoments.c
===================================================================
--- /trunk/psModules/src/objects/pmSourcePlotMoments.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourcePlotMoments.c	(revision 15562)
@@ -5,6 +5,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2006 IfA, University of Hawaii
@@ -41,9 +41,14 @@
 // this variable is defined in psmodules.h if ohana-config is found
 # if (HAVE_KAPA)
-    # include <kapa.h>
+# include <kapa.h>
 
-    // plot the sx, sy moments plane (faint and bright sources)
-    bool pmSourcePlotMoments (const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout)
+// plot the sx, sy moments plane (faint and bright sources)
+bool pmSourcePlotMoments (const pmFPAview *view, pmFPAfile *file, const pmConfig *config,
+                          pmSourcePlotLayout *layout)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(layout, false);
 
     Graphdata graphdata;
Index: /trunk/psModules/src/objects/pmSourcePlotPSFModel.c
===================================================================
--- /trunk/psModules/src/objects/pmSourcePlotPSFModel.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourcePlotPSFModel.c	(revision 15562)
@@ -5,6 +5,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2006 IfA, University of Hawaii
@@ -41,11 +41,16 @@
 // this variable is defined in psmodules.h if ohana-config is found
 # if (HAVE_KAPA)
-    # include <kapa.h>
-
-    // plot the sx, sy, sxy as vector field,
-    // plot the PSF measured sx, sy, sxy as vector field
-    // pull the sources from the config / file?
-    bool pmSourcePlotPSFModel (const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout)
+# include <kapa.h>
+
+// plot the sx, sy, sxy as vector field,
+// plot the PSF measured sx, sy, sxy as vector field
+// pull the sources from the config / file?
+bool pmSourcePlotPSFModel (const pmFPAview *view, pmFPAfile *file, const pmConfig *config,
+                           pmSourcePlotLayout *layout)
 {
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(layout, false);
 
     Graphdata graphdata;
Index: /trunk/psModules/src/objects/pmSourcePlots.c
===================================================================
--- /trunk/psModules/src/objects/pmSourcePlots.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourcePlots.c	(revision 15562)
@@ -5,6 +5,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-05-04 00:54:09 $
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2006 IfA, University of Hawaii
@@ -36,4 +36,5 @@
     PS_ASSERT_PTR_NON_NULL(view, false);
     PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
 
     if ((view->readout != -1) || (view->cell != -1)) {
@@ -149,4 +150,11 @@
 }
 
+bool psMemCheckSourcePlotLayout(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmSourcePlotLayoutFree);
+}
+
+
 /* we have three types of plots to produce (maybe more?)
  * for each plot, we need to supply the following information:
Index: /trunk/psModules/src/objects/pmSourcePlots.h
===================================================================
--- /trunk/psModules/src/objects/pmSourcePlots.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourcePlots.h	(revision 15562)
@@ -4,6 +4,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-05-04 00:54:09 $
+ * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2006 Institute for Astronomy, University of Hawaii
  */
@@ -30,4 +30,5 @@
 
 pmSourcePlotLayout *pmSourcePlotLayoutAlloc();
+bool psMemCheckSourcePlotLayout(psPtr ptr);
 
 bool pmFPAviewWriteSourcePlot(const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
Index: /trunk/psModules/src/objects/pmSourceUtils.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceUtils.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmSourceUtils.c	(revision 15562)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA: significant modifications.
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-21 00:09:05 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -63,5 +63,9 @@
 }
 
-pmSource *pmSourceFromModel (pmModel *model, pmReadout *readout, float radius, pmSourceType type) {
+pmSource *pmSourceFromModel (pmModel *model, pmReadout *readout, float radius, 
+                             pmSourceType type)
+{
+    PS_ASSERT_PTR_NON_NULL(model, NULL);
+    PS_ASSERT_PTR_NON_NULL(readout, NULL);
 
     pmSource *source = pmSourceAlloc ();
Index: /trunk/psModules/src/objects/pmTrend2D.c
===================================================================
--- /trunk/psModules/src/objects/pmTrend2D.c	(revision 15561)
+++ /trunk/psModules/src/objects/pmTrend2D.c	(revision 15562)
@@ -3,7 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-10-30 00:50:00 $
- *
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
  *  Copyright 2004 Institute for Astronomy, University of Hawaii
  *
Index: /trunk/psModules/src/objects/pmTrend2D.h
===================================================================
--- /trunk/psModules/src/objects/pmTrend2D.h	(revision 15561)
+++ /trunk/psModules/src/objects/pmTrend2D.h	(revision 15562)
@@ -5,6 +5,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-09-24 21:27:58 $
+ * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -34,4 +34,6 @@
 pmTrend2D *pmTrend2DAlloc (pmTrend2DMode mode, psImage *image, int nXtrend, int nYtrend, psStats *stats);
 
+bool psMemCheckTrend2D(psPtr ptr);
+
 pmTrend2D *pmTrend2DNoImageAlloc (pmTrend2DMode mode, psImageBinning *binning, psStats *stats);
 
Index: /trunk/psastro/src/Makefile.am
===================================================================
--- /trunk/psastro/src/Makefile.am	(revision 15561)
+++ /trunk/psastro/src/Makefile.am	(revision 15562)
@@ -33,4 +33,5 @@
 	psastroLuminosityFunction.c \
 	psastroRefstarSubset.c      \
+	psastroEnforceChips.c       \
 	psastroMosaicAstrom.c       \
 	psastroMosaicGradients.c    \
Index: /trunk/psastro/src/psastro.h
===================================================================
--- /trunk/psastro/src/psastro.h	(revision 15561)
+++ /trunk/psastro/src/psastro.h	(revision 15562)
@@ -27,4 +27,5 @@
 bool              psastroDataSave (pmConfig *config);
 bool              psastroDefineFiles (pmConfig *config, pmFPAfile *input);
+bool              psastroDefineFile (pmConfig *config, pmFPA *input, char *filerule, char *argname, pmFPAfileType fileType, pmDetrendType detrendType);
 bool              psastroAnalysis (pmConfig *config);
 
@@ -74,7 +75,13 @@
 bool 		  psastroDumpStars (psArray *stars, char *filename);
 bool              psastroDumpMatchedStars (char *filename, psArray *rawstars, psArray *refstars, psArray *match);
+bool              psastroDumpGradients (psArray *gradients, char *filename);
 
 bool		  psastroMosaicSetAstrom_tmp (pmFPA *fpa);
 int 		  psastroSortByMag (const void *a, const void *b);
 
+bool              psastroEnforceChips (pmConfig *config, pmFPA *fpa, psMetadata *recipe);
+
+psArray *psastroReadGetstarCatalog (psFits *fits);
+psArray *psastroReadGetstar_PS1_DEV_0 (psFits *fits);
+
 # endif /* PSASTRO_H */
Index: /trunk/psastro/src/psastroAnalysis.c
===================================================================
--- /trunk/psastro/src/psastroAnalysis.c	(revision 15561)
+++ /trunk/psastro/src/psastroAnalysis.c	(revision 15562)
@@ -16,7 +16,4 @@
 	return true;
     }
-
-    // XXX test retrun
-    // return true;
 
     // load the reference stars overlapping the data stars
Index: /trunk/psastro/src/psastroArguments.c
===================================================================
--- /trunk/psastro/src/psastroArguments.c	(revision 15561)
+++ /trunk/psastro/src/psastroArguments.c	(revision 15562)
@@ -36,4 +36,16 @@
         psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CHIP_SELECTIONS", PS_META_REPLACE, "", argv[N]);
         psArgumentRemove (N, &argc, argv);
+    }
+    
+    // apply the chip correction based on the reference astrometry?
+    if ((N = psArgumentGet (argc, argv, "-fixchips"))) {
+        psArgumentRemove (N, &argc, argv);
+        psMetadataAddBool (config->arguments, PS_LIST_TAIL, "PSASTRO.FIX.CHIPS", PS_META_REPLACE, "", true);
+    }
+    // define the reference astrometry file
+    status = pmConfigFileSetsMD (config->arguments, &argc, argv, "REF.ASTROM", "-refastrom", "-refastromlist");
+    if (status) {
+	// if supplied, assume -fixchips is desired
+        psMetadataAddBool (config->arguments, PS_LIST_TAIL, "PSASTRO.FIX.CHIPS", PS_META_REPLACE, "", true);
     }
 
Index: /trunk/psastro/src/psastroDefineFiles.c
===================================================================
--- /trunk/psastro/src/psastroDefineFiles.c	(revision 15561)
+++ /trunk/psastro/src/psastroDefineFiles.c	(revision 15562)
@@ -4,7 +4,14 @@
 
     // these calls bind the I/O handle to the specified fpa
-    pmFPAfile *output = NULL;
+    bool status;
 
-    output = pmFPAfileDefineOutput (config, input->fpa, "PSASTRO.OUTPUT");
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSASTRO_RECIPE);
+    if (!recipe) {
+	psError(PSASTRO_ERR_CONFIG, false, "Can't find PSASTRO recipe!\n");
+	return false;
+    }
+
+    pmFPAfile *output = pmFPAfileDefineOutput (config, input->fpa, "PSASTRO.OUTPUT");
     if (!output) {
 	psError(PSASTRO_ERR_CONFIG, false, "Failed to build FPA from PSASTRO.INPUT");
@@ -12,4 +19,13 @@
     }
     output->save = true;
+
+    bool fixChips = psMetadataLookupBool (&status, recipe, "PSASTRO.FIX.CHIPS");
+
+    if (fixChips) {
+        if (!psastroDefineFile (config, input->fpa, "PSASTRO.REF.ASTROM", "REF.ASTROM", PM_FPA_FILE_ASTROM, PM_DETREND_TYPE_ASTROM)) {
+            psError (PS_ERR_IO, false, "Can't find a reference astrometry file");
+            return NULL;
+        }
+    }
 
 # if (0)
@@ -25,2 +41,52 @@
     return true;
 }
+
+bool psastroDefineFile (pmConfig *config, pmFPA *input, char *filerule, char *argname, pmFPAfileType fileType, pmDetrendType detrendType) {
+
+    bool status;
+    pmFPAfile *file;
+
+    // look for the file on the argument list
+    file = pmFPAfileDefineFromArgs  (&status, config, filerule, argname);
+    if (!status) {
+	psError (PS_ERR_UNKNOWN, false, "failed to load find definition");
+	return false;
+    }
+    if (file) {
+	if (file->type != fileType) {
+	    psError(PS_ERR_IO, true, "%s is not of type %s", filerule, pmFPAfileStringFromType (fileType));
+	    return false;
+	}
+	return true;
+    }
+
+    // look for the file in the camera config table
+    file = pmFPAfileDefineFromConf  (&status, config, filerule);
+    if (!status) {
+	psError (PS_ERR_UNKNOWN, false, "failed to load find definition");
+	return false;
+    }
+    if (file) {
+	if (file->type != fileType) {
+	    psError(PS_ERR_IO, true, "%s is not of type %s", filerule, pmFPAfileStringFromType (fileType));
+	    return false;
+	}
+	return true;
+    }
+
+    // look for the file to be loaded from the detrend database
+    file = pmFPAfileDefineFromDetDB (&status, config, filerule, input, detrendType);
+    if (!status) {
+	psError (PS_ERR_UNKNOWN, false, "failed to load file definition");
+	return false;
+    }
+    if (file) {
+	if (file->type != fileType) {
+	    psError(PS_ERR_IO, true, "%s is not of type %s", filerule, pmFPAfileStringFromType (fileType));
+	    return false;
+	}
+	return true;
+    }
+    return false;
+}
+
Index: /trunk/psastro/src/psastroDemoDump.c
===================================================================
--- /trunk/psastro/src/psastroDemoDump.c	(revision 15561)
+++ /trunk/psastro/src/psastroDemoDump.c	(revision 15562)
@@ -173,2 +173,22 @@
     return true;
 }
+
+// this function is used for test purposes (-trace psastro.dump 1)
+bool psastroDumpGradients (psArray *gradients, char *filename) {
+
+    FILE *f = fopen (filename, "w");
+
+    for (int i = 0; i < gradients->n; i++) {
+	pmAstromGradient *gradient = gradients->data[i];
+
+	// write out the refstar data
+	fprintf (f, "%d  %f %f   %f %f  %f %f\n", i,
+		 gradient->FP.x, gradient->FP.y, 
+		 gradient->dTPdL.x, gradient->dTPdL.y, 
+		 gradient->dTPdM.x, gradient->dTPdM.y);
+    }
+
+    fclose (f);
+    return true;
+}
+
Index: unk/psastro/src/psastroEnforceChip.c
===================================================================
--- /trunk/psastro/src/psastroEnforceChip.c	(revision 15561)
+++ 	(revision )
@@ -1,75 +1,0 @@
-# include "psastroInternal.h"
-
-bool psastroEnforceChips (pmFPA *fpa, psMetadata *recipe) {
-
-  pmChip *chip = NULL;
-  // identify reference astrometry table, stored as an fpa? better format?
-
-  pmFPAfile *refAstrom = psMetadataLookupPtr (NULL, config->files, "PSASTRO.REF.ASTROM");
-
-  pmFPAview *view = pmFPAviewAlloc (0);
-
-  // physical pixel scale in microns per pixel
-  double pixelTol = psMetadataLookupF32 (&status, recipe, "PSASTRO.PIXEL.TOLERANCE");
-  if (!status) {
-    psError(PS_ERR_IO, true, "Failed to lookup pixel tolerance"); 
-    return false; 
-  } 
-  double angleTol = psMetadataLookupF32 (&status, recipe, "PSASTRO.ANGLE.TOLERANCE");
-  if (!status) {
-    psError(PS_ERR_IO, true, "Failed to lookup angle tolerance"); 
-    return false; 
-  } 
-
-  // loop over all chips
-  while ((obsChip = pmFPAviewNextChip (view, fpa, 1)) != NULL) {
-    psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, obsChip->file_exists, obsChip->process);
-    if (!obsChip->process || !obsChip->file_exists || !obsChip->data_exists) { continue; }
-
-    // set the chip astrometry using the refAstrom file
-    pmChip *refChip = pmFPAviewThisChip (view, refAstrom->fpa);
-
-    // bad Astrometry test:  ref pixel or angle outside nominal
-
-    psPlane refPixel = {0.0, 0.0, 0.0, 0.0};
-    psPlane obsCoord, refCoord;
-
-    // find location of 0,0 pixel in focal plane coords for this chip
-    psPlaneTransformApply (&obsCoord, obsChip->toFPA, &refPixel);
-
-    // find location of 0,0 pixel in focal plane coords for ref chip
-    psPlaneTransformApply (&refCoord, refChip->toFPA, &refPixel);
-    
-    psPlane offPixel = {0.0, 0.0, 0.0, 0.0};
-    psPlane obsOffPt, refOffPt;
-
-    // find location of 0,0 pixel in focal plane coords for this chip
-    psPlaneTransformApply (&obsOffPt, obsChip->toFPA, &offPixel);
-
-    // find location of 0,0 pixel in focal plane coords for ref chip
-    psPlaneTransformApply (&refOffPt, refChip->toFPA, &offPixel);
-    
-    double obsAngle = atan2 (obsOffPt.y - obsCoord.y, obsOffPt.x - obsCoord.x);
-
-    badAstrom = false;
-    badAstrom |= fabs(obsCoord.x - refCoord.x) > pixelTol;
-    badAstrom |= fabs(obsCoord.y - refCoord.y) > pixelTol;
-    badAstrom |= fabs(obsAngle   - refAngle)   > angleTol;
-
-    if (!badAstrom) continue;
-
-    psFree (obsChip->toFPA);
-    psFree (obsChip->fromFPA);
-
-    // XXX can we do a straight copy?  I think so, but we may need to apply a scaling factor based
-    // on the toSky or toTPA values
-    obsChip->toFPA   = psMemIncrRefCounter (refChip->toFPA);
-    obsChip->fromFPA = psMemIncrRefCounter (refChip->fromFPA);
-  }
-  return true;
-}
-
-// XXX for this function to work, I need to:
-// 1 *) define badAstrom (ref pixel too far from nominal?) (ref angle too far off?)
-// 2) load the refAstrom fpa in the pmFPAfileIO stage 
-// 3) allow for this operation to be optional
Index: /trunk/psastro/src/psastroEnforceChips.c
===================================================================
--- /trunk/psastro/src/psastroEnforceChips.c	(revision 15562)
+++ /trunk/psastro/src/psastroEnforceChips.c	(revision 15562)
@@ -0,0 +1,80 @@
+# include "psastroInternal.h"
+
+bool psastroEnforceChips (pmConfig *config, pmFPA *fpa, psMetadata *recipe) {
+
+  bool status;
+
+  // identify reference astrometry table
+  // if not defined, correction was not requested; skip step
+  pmFPAfile *refAstrom = psMetadataLookupPtr (NULL, config->files, "REF.ASTROM");
+  if (!refAstrom) return true;
+
+  pmFPAview *view = pmFPAviewAlloc (0);
+
+  // physical pixel scale in microns per pixel
+  double pixelTol = psMetadataLookupF32 (&status, recipe, "PSASTRO.PIXEL.TOLERANCE");
+  if (!status) {
+    psError(PS_ERR_IO, true, "Failed to lookup pixel tolerance"); 
+    return false; 
+  } 
+  double angleTol = psMetadataLookupF32 (&status, recipe, "PSASTRO.ANGLE.TOLERANCE");
+  if (!status) {
+    psError(PS_ERR_IO, true, "Failed to lookup angle tolerance"); 
+    return false; 
+  } 
+
+  pmChip *obsChip = NULL;
+
+  // loop over all chips
+  while ((obsChip = pmFPAviewNextChip (view, fpa, 1)) != NULL) {
+    psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, obsChip->file_exists, obsChip->process);
+    if (!obsChip->process || !obsChip->file_exists || !obsChip->data_exists) { continue; }
+
+    // set the chip astrometry using the refAstrom file
+    pmChip *refChip = pmFPAviewThisChip (view, refAstrom->fpa);
+
+    // bad Astrometry test:  ref pixel or angle outside nominal
+
+    psPlane refPixel = {0.0, 0.0, 0.0, 0.0};
+    psPlane obsCoord, refCoord;
+
+    // find location of 0,0 pixel in focal plane coords for this chip
+    psPlaneTransformApply (&obsCoord, obsChip->toFPA, &refPixel);
+
+    // find location of 0,0 pixel in focal plane coords for ref chip
+    psPlaneTransformApply (&refCoord, refChip->toFPA, &refPixel);
+    
+    psPlane offPixel = {0.0, 0.0, 0.0, 0.0};
+    psPlane obsOffPt, refOffPt;
+
+    // find location of 0,0 pixel in focal plane coords for this chip
+    psPlaneTransformApply (&obsOffPt, obsChip->toFPA, &offPixel);
+
+    // find location of 0,0 pixel in focal plane coords for ref chip
+    psPlaneTransformApply (&refOffPt, refChip->toFPA, &offPixel);
+    
+    double obsAngle = atan2 (obsOffPt.y - obsCoord.y, obsOffPt.x - obsCoord.x);
+    double refAngle = atan2 (refOffPt.y - refCoord.y, refOffPt.x - refCoord.x);
+
+    bool badAstrom = false;
+    badAstrom |= fabs(obsCoord.x - refCoord.x) > pixelTol;
+    badAstrom |= fabs(obsCoord.y - refCoord.y) > pixelTol;
+    badAstrom |= fabs(obsAngle   - refAngle)   > angleTol;
+
+    if (!badAstrom) continue;
+
+    psFree (obsChip->toFPA);
+    psFree (obsChip->fromFPA);
+
+    // XXX can we do a straight copy?  I think so, but we may need to apply a scaling factor based
+    // on the toSky or toTPA values
+    obsChip->toFPA   = psMemIncrRefCounter (refChip->toFPA);
+    obsChip->fromFPA = psMemIncrRefCounter (refChip->fromFPA);
+  }
+  return true;
+}
+
+// XXX for this function to work, I need to:
+// 1 *) define badAstrom (ref pixel too far from nominal?) (ref angle too far off?)
+// 2) load the refAstrom fpa in the pmFPAfileIO stage 
+// 3) allow for this operation to be optional
Index: /trunk/psastro/src/psastroLoadRefstars.c
===================================================================
--- /trunk/psastro/src/psastroLoadRefstars.c	(revision 15561)
+++ /trunk/psastro/src/psastroLoadRefstars.c	(revision 15562)
@@ -15,5 +15,4 @@
     float DECmin = DEG_RAD*psMetadataLookupF32(NULL, recipe, "DEC_MIN");
     float DECmax = DEG_RAD*psMetadataLookupF32(NULL, recipe, "DEC_MAX");
-    // float MAGmax = psMetadataLookupF32(NULL, recipe, "MAG_MAX");
 
     // XXX CATDIR needs to look up abstracted name from psastro.config
@@ -25,4 +24,12 @@
     char *getstarCommand = psStringCopy(psMetadataLookupStr(NULL, recipe, "DVO.GETSTAR"));
     PS_ASSERT (getstarCommand, NULL);
+
+    char *outformat = psMetadataLookupStr(NULL, recipe, "DVO.GETSTAR.OUTFORMAT");
+    PS_ASSERT (outformat, NULL);
+
+    char *photcode = psMetadataLookupStr(NULL, recipe, "DVO.GETSTAR.PHOTCODE");
+    PS_ASSERT (photcode, NULL);
+
+    float MAGmax = psMetadataLookupF32(NULL, recipe, "DVO.GETSTAR.MAG.MAX");
 
     // issue the following command:
@@ -39,9 +46,9 @@
     psTimerStart ("psastro");
 
-    // use fork to add timeout capability
+    // supply a known output format (for CATALOG output) so the code below knows what to read
     if (ELIXIR_MODE) {
-        psStringAppend (&getstarCommand, " -D CATFORMAT elixir");
+        psStringAppend (&getstarCommand, " -D CATMODE mef -D CATFORMAT elixir");
     } else {
-        psStringAppend (&getstarCommand, " -D CATFORMAT panstarrs");
+        psStringAppend (&getstarCommand, " -D CATMODE mef -D CATFORMAT panstarrs");
     }
 
@@ -52,11 +59,13 @@
     psFree(CATDIR);
 
-    // psStringAppend (&getstarCommand, " -D CATMODE mef -maglim %f -region %f %f %f %f -o %s", MAGmax, RAmin, DECmin, RAmax, DECmax, tempFile);
-    // XXX TEST : no magnitude limit
-    // XXX need to specify the desired photometry system
-    psStringAppend (&getstarCommand, " -D CATMODE mef -region %f %f %f %f -o %s", RAmin, DECmin, RAmax, DECmax, tempFile);
+    // supply the max magnitude, the output format, and the photcode
+    psStringAppend (&getstarCommand, " -maglim %f -format %s -photcode %s", MAGmax, outformat, photcode);
+
+    // add region and output filename
+    psStringAppend (&getstarCommand, " -region %f %f %f %f -o %s", RAmin, DECmin, RAmax, DECmax, tempFile);
     psTrace ("psastro", 3, "%s\n", getstarCommand);
 
     // XXX use psPipe: catch stderr, stdout, allow for Nsec timeout...
+    // use fork to add timeout capability 
     status = system (getstarCommand);
     if (status) {
@@ -71,4 +80,41 @@
     psFits *fits = psFitsOpen (tempFile, "r");
 
+    psTimerStart ("psastro");
+
+    psArray *refstars = NULL;
+    if (!strcmp (outformat, "CATALOG")) {
+      refstars = psastroReadGetstarCatalog (fits);
+    }
+    if (!strcmp (outformat, "PS1_DEV_0")) {
+      refstars = psastroReadGetstar_PS1_DEV_0 (fits);
+    }
+    if (refstars == NULL) {
+        psError(PSASTRO_ERR_REFSTARS, true, "error reading reference data\n");
+        return NULL;
+    }
+    psLogMsg ("psastro", 3, "loaded %ld reference stars : %f sec\n", refstars->n, psTimerMark ("psastro"));
+
+    psTrace ("psastro", 3, "loaded %ld reference stars from (%10.6f,%10.6f) - (%10.6f,%10.6f)\n",
+             refstars->n, RAmin, DECmin, RAmax, DECmax);
+
+    psFitsClose (fits);
+    unlink (tempFile);
+
+    // dump or plot the available refstars
+    if (psTraceGetLevel("psastro.dump") > 0) {
+        psastroDumpRefstars (refstars, "refstars.dat");
+    }
+
+    if (psTraceGetLevel("psastro.plot") > 0) {
+        psastroPlotRefstars (refstars, recipe);
+    }
+
+    return refstars;
+}
+
+psArray *psastroReadGetstarCatalog (psFits *fits) {
+
+    bool status;
+
     if (ELIXIR_MODE) {
         psFitsMoveExtName (fits, "DVO_AVERAGE_ELIXIR");
@@ -77,5 +123,4 @@
     }
 
-    psTimerStart ("psastro");
     long numSources = psFitsTableSize(fits); // Number of sources in table
 
@@ -102,21 +147,30 @@
         psFree (row);
     }
-    psLogMsg ("psastro", 3, "loaded %ld reference stars : %f sec\n", refstars->n, psTimerMark ("psastro"));
-
-    psTrace ("psastro", 3, "loaded %ld reference stars from (%10.6f,%10.6f) - (%10.6f,%10.6f)\n",
-             refstars->n, RAmin, DECmin, RAmax, DECmax);
-
-    psFitsClose (fits);
-    unlink (tempFile);
-
-    // dump or plot the available refstars
-    if (psTraceGetLevel("psastro.dump") > 0) {
-        psastroDumpRefstars (refstars, "refstars.dat");
-    }
-
-    if (psTraceGetLevel("psastro.plot") > 0) {
-        psastroPlotRefstars (refstars, recipe);
-    }
-
     return refstars;
 }
+
+psArray *psastroReadGetstar_PS1_DEV_0 (psFits *fits) {
+
+    bool status;
+
+    psFitsMoveExtName (fits, "GETSTAR_PS1_DEV_0");
+
+    long numSources = psFitsTableSize(fits); // Number of sources in table
+
+    // convert the Average table to the pmAstromObj entries
+    psArray *refstars = psArrayAllocEmpty (numSources);
+    for (int i = 0; i < numSources; i++) {
+        pmAstromObj *ref = pmAstromObjAlloc ();
+
+        psMetadata *row = psFitsReadTableRow(fits, i); // Table row
+
+	ref->sky->r   = RAD_DEG*psMetadataLookupF32 (&status, row, "RA");
+	ref->sky->d   = RAD_DEG*psMetadataLookupF32 (&status, row, "DEC");
+	ref->Mag      = psMetadataLookupS32 (&status, row, "MAG");
+
+        psArrayAdd (refstars, 100, ref);
+        psFree (ref);
+        psFree (row);
+    }
+    return refstars;
+}
Index: /trunk/psastro/src/psastroMosaicAstrom.c
===================================================================
--- /trunk/psastro/src/psastroMosaicAstrom.c	(revision 15561)
+++ /trunk/psastro/src/psastroMosaicAstrom.c	(revision 15562)
@@ -21,7 +21,10 @@
     pmFPA *fpa = input->fpa;
 
-    // XXX before we do object matches, we need to fix failed chips
-    // compare chips with supplied mosaic model
-    // adjust significant outliers to match model
+    // before we do object matches, we need to (optionally) fix failed chips.  We compare chips with
+    // the supplied mosaic model.  Adjust significant outliers to match model.  
+    if (!psastroEnforceChips (config, fpa, recipe)) {
+	psError(PSASTRO_ERR_UNKNOWN, false, "failed to align problematic chips");
+	return false;
+    }
 
     // given the existing per-chip astrometry, determine matches between raw and ref stars
Index: /trunk/psastro/src/psastroMosaicGradients.c
===================================================================
--- /trunk/psastro/src/psastroMosaicGradients.c	(revision 15561)
+++ /trunk/psastro/src/psastroMosaicGradients.c	(revision 15562)
@@ -1,3 +1,4 @@
 # include "psastroInternal.h"
+static int nPass = 0;
 
 bool psastroMosaicGradients (pmFPA *fpa, psMetadata *recipe) {
@@ -50,4 +51,12 @@
     }
 
+    // if desired, dump the gradients to a file
+    if (psTraceGetLevel("psastro.dump") > 0) { 
+	char name[80];
+	sprintf (name, "gradients.%d.dat", nPass); 
+	psastroDumpGradients (gradients, name); 
+	nPass ++;
+    }
+
     // allocate mosaic-level polynomial transformation and set masks needed by DVO
     int order = psMetadataLookupF32 (&status, recipe, "PSASTRO.MOSAIC.ORDER");
Index: /trunk/psastro/src/psastroMosaicOneChip.c
===================================================================
--- /trunk/psastro/src/psastroMosaicOneChip.c	(revision 15561)
+++ /trunk/psastro/src/psastroMosaicOneChip.c	(revision 15562)
@@ -55,4 +55,6 @@
 	return false; 
     } 
+
+    psLogMsg ("psastro", PS_LOG_DETAIL, "mosaic fit chip order %d", order);
 
     // create output toFPA; set masks appropriate to the Elixir DVO astrometry format if we are
Index: /trunk/psastro/src/psastroMosaicSetMatch.c
===================================================================
--- /trunk/psastro/src/psastroMosaicSetMatch.c	(revision 15561)
+++ /trunk/psastro/src/psastroMosaicSetMatch.c	(revision 15562)
@@ -15,6 +15,15 @@
     if (!status) { 
 	psError(PS_ERR_IO, false, "Failed to lookup matching radius: %s", radiusWord); 
-	return NULL; 
+	return false; 
     } 
+
+    if (RADIUS <= 0.0) {
+	if (iteration == 0) {
+	    psError(PS_ERR_IO, false, "Invalid match radius for first iteration: %s", radiusWord); 
+	    return false; 
+	} 
+	psWarning ("skipping match for iteration %d\n", iteration);
+	return true;
+    }
 
     // this loop selects the matched stars for all chips
Index: /trunk/psphot/src/Makefile.am
===================================================================
--- /trunk/psphot/src/Makefile.am	(revision 15561)
+++ /trunk/psphot/src/Makefile.am	(revision 15562)
@@ -47,4 +47,5 @@
 	psphotModelWithPSF.c     \
 	psphotExtendedSources.c	 \
+	psphotRadialProfile.c	 \
 	psphotPetrosian.c	 \
 	psphotIsophotal.c	 \
Index: /trunk/psphot/src/psphot.h
===================================================================
--- /trunk/psphot/src/psphot.h	(revision 15561)
+++ /trunk/psphot/src/psphot.h	(revision 15562)
@@ -116,4 +116,5 @@
 psKernel       *psphotKernelFromPSF (pmSource *source, int nPix);
 
+bool            psphotRadialProfile (pmSource *source, psMetadata *recipe, psMaskType maskVal);
 bool 		psphotPetrosian (pmSource *source, psMetadata *recipe, psMaskType maskVal);
 bool 		psphotIsophotal (pmSource *source, psMetadata *recipe, psMaskType maskVal);
Index: /trunk/psphot/src/psphotAnnuli.c
===================================================================
--- /trunk/psphot/src/psphotAnnuli.c	(revision 15561)
+++ /trunk/psphot/src/psphotAnnuli.c	(revision 15562)
@@ -3,6 +3,57 @@
 bool psphotAnnuli (pmSource *source, psMetadata *recipe, psMaskType maskVal) {
 
-  psLogMsg ("psphot", PS_LOG_INFO, "not implemented\n");
+  assert (source->extpars);
+  assert (source->extpars->profile);
+  assert (source->extpars->profile->radius);
+  assert (source->extpars->profile->flux);
+
+  bool status;
+
+  psVector *radius = source->extpars->profile->radius;
+  psVector *weight = source->extpars->profile->weight;
+  psVector *flux = source->extpars->profile->flux;
+
+  // XXX how do I define the radii?  we can put a vector in the recipe...
+  // radialBins defines the bounds or start and stop (we can skip some that way...
+  psVector *radialBinsLower = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.LOWER");
+  psVector *radialBinsUpper = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.UPPER");
+  assert (radialBinsLower->n == radialBinsUpper->n);
+
+  psVector *fluxValues = psVectorAlloc (radialBinsLower->n, PS_TYPE_F32);
+  psVector *fluxSquare = psVectorAlloc (radialBinsLower->n, PS_TYPE_F32);
+  psVector *fluxWeight = psVectorAlloc (radialBinsLower->n, PS_TYPE_F32);
+  psVector *pixelCount = psVectorAlloc (radialBinsLower->n, PS_TYPE_F32);
+  psVectorInit (fluxValues, 0.0);
+  psVectorInit (fluxSquare, 0.0);
+  psVectorInit (fluxWeight, 0.0);
+  psVectorInit (pixelCount, 0.0);
+
+  // XXX this code assumes the radii are in pixels.  convert from arcsec with plate scale
+  // XXX assume the annulii above are not overlapping?  much faster...
+  // XXX this might be must faster in the reverse order: loop over annulii and use disection to 
+  // skip to the start of the annulus.
+  for (int i = 0; i < flux->n; i++) {
+    for (int j = 0; j < radialBinsLower->n; j++) {
+      if (radius->data.F32[i] < radialBinsLower->data.F32[j]) continue;
+      if (radius->data.F32[i] > radialBinsUpper->data.F32[j]) continue;
+      fluxValues->data.F32[j] += flux->data.F32[i];
+      fluxSquare->data.F32[j] += PS_SQR(flux->data.F32[i]);
+      fluxWeight->data.F32[j] += weight->data.F32[i];
+      pixelCount->data.F32[j] += 1.0;
+    }
+  }
+
+  for (int j = 0; j < radialBinsLower->n; j++) {
+    fluxValues->data.F32[j] /= pixelCount->data.F32[j];
+    fluxSquare->data.F32[j] /= pixelCount->data.F32[j];
+    fluxSquare->data.F32[j] -= PS_SQR(fluxValues->data.F32[j]);
+  }
+  
+  source->extpars->annuli = pmSourceAnnuliAlloc ();
+  source->extpars->annuli->flux    = fluxValues;
+  source->extpars->annuli->fluxErr = fluxWeight;
+  source->extpars->annuli->fluxVar = fluxSquare;
+
   return true;
+}
 
-}
Index: /trunk/psphot/src/psphotExtendedSources.c
===================================================================
--- /trunk/psphot/src/psphotExtendedSources.c	(revision 15561)
+++ /trunk/psphot/src/psphotExtendedSources.c	(revision 15562)
@@ -66,7 +66,18 @@
 	    return false;
 	} else {
+	  // XXX why am I caching the model?
 	    pmSourceCacheModel (source, maskVal); // XXX put this in the source model function?
 	    psTrace ("psphot", 5, "psf-convolved model for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
             Npsf ++;
+	}
+
+	// all of these below require the radial profile
+	// XXX push this as a test and call in each of the functions below?
+	// XXX this constructs a pmSourceExtendedParameters element
+	if (doPetrosian || doIsophotal || doAnnuli || doKron) {
+	  if (!psphotRadialProfile (source, recipe, maskVal)) {
+	    psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate radial profile");
+	    return false;
+	  }
 	}
 
Index: /trunk/psphot/src/psphotIsophotal.c
===================================================================
--- /trunk/psphot/src/psphotIsophotal.c	(revision 15561)
+++ /trunk/psphot/src/psphotIsophotal.c	(revision 15562)
@@ -3,5 +3,57 @@
 bool psphotIsophotal (pmSource *source, psMetadata *recipe, psMaskType maskVal) {
 
-  psLogMsg ("psphot", PS_LOG_INFO, "not implemented\n");
+  assert (source->extpars);
+  assert (source->extpars->profile);
+  assert (source->extpars->profile->radius);
+  assert (source->extpars->profile->flux);
+
+  bool status;
+
+  psVector *radius = source->extpars->profile->radius;
+  psVector *flux = source->extpars->profile->flux;
+
+  // flux at which to measure isophotal parameters
+  // XXX cache this?
+  float ISOPHOT_FLUX = psMetadataLookupF32 (&status, recipe, "ISOPHOTAL_FLUX");
+
+  // find the first bin below the flux level and the last above the level
+  // XXX can this be done faster with disection?
+  // XXX do I need to worry about crazy outliers?  
+  // XXX should i be smoothing or fitting the curve?
+  int firstBelow = -1;
+  int lastAbove = -1;
+  for (int i = 0; i < flux->n; i++) {
+    if (flux->data.F32[i] > ISOPHOT_FLUX) lastAbove = i;
+    if ((firstBelow < 0) && (flux->data.F32[i] < ISOPHOT_FLUX)) firstBelow = i;
+  }
+
+  // need to examine pixels in this vicinity
+  float isophotalFluxFirst = 0;
+  float isophotalFluxLast = 0;
+  for (int i = 0; i <= PS_MAX(firstBelow, lastAbove); i++) {
+    if (i <= firstBelow) {
+      isophotalFluxFirst += flux->data.F32[i];
+    }
+    if (i <= lastAbove) {
+      isophotalFluxLast += flux->data.F32[i];
+    }
+  }
+  float isophotalFlux    = 0.5*(isophotalFluxLast + isophotalFluxFirst);
+  float isophotalFluxErr = 0.5*fabs(isophotalFluxLast - isophotalFluxFirst);
+
+  float isophotalRad     = 0.5*(radius->data.F32[firstBelow] + radius->data.F32[lastAbove]);
+  float isophotalRadErr  = 0.5*fabs(radius->data.F32[firstBelow] - radius->data.F32[lastAbove]);
+
+  if (!source->extpars->isophot) {
+    source->extpars->isophot = pmSourceIsophotalValuesAlloc ();
+  }
+  
+  // these are uncalibrated: instrumental mags and pixel units
+  source->extpars->isophot->mag    = -2.5*log10(isophotalFlux);
+  source->extpars->isophot->magErr = isophotalFluxErr / isophotalFlux;
+
+  source->extpars->isophot->rad    = isophotalRad;
+  source->extpars->isophot->radErr = isophotalRadErr;
+
   return true;
 
Index: /trunk/psphot/src/psphotMakeResiduals.c
===================================================================
--- /trunk/psphot/src/psphotMakeResiduals.c	(revision 15561)
+++ /trunk/psphot/src/psphotMakeResiduals.c	(revision 15562)
@@ -28,4 +28,7 @@
 
     float nSigma = psMetadataLookupF32(&status, recipe, "PSF.RESIDUALS.NSIGMA");
+    PS_ASSERT (status, false);
+
+    float pixelSN = psMetadataLookupF32(&status, recipe, "PSF.RESIDUALS.PIX.SN");
     PS_ASSERT (status, false);
 
@@ -194,4 +197,9 @@
                 resid->Rx->data.F32[oy][ox] = resid->Ry->data.F32[oy][ox] = 0.0;
                 //resid->weight->data.F32[oy][ox] = fluxStats->sampleStdev;
+
+		if (resid->Ro->data.F32[oy][ox] < pixelSN*fluxStats->sampleStdev) {
+		  resid->mask->data.U8[oy][ox] = 1;
+		}
+
             } else {
                 assert (SPATIAL_ORDER == 1);
@@ -227,4 +235,9 @@
                 resid->Rx->data.F32[oy][ox] = B->data.F64[1];
                 resid->Ry->data.F32[oy][ox] = B->data.F64[2];
+
+		float dRo = sqrt(A->data.F32[0][0]);
+		if (resid->Ro->data.F32[oy][ox] < pixelSN*dRo) {
+		  resid->mask->data.U8[oy][ox] = 1;
+		}
                 //resid->weight->data.F32[oy][ox] = XXX;
             }
Index: /trunk/psphot/src/psphotPetrosian.c
===================================================================
--- /trunk/psphot/src/psphotPetrosian.c	(revision 15561)
+++ /trunk/psphot/src/psphotPetrosian.c	(revision 15562)
@@ -3,5 +3,79 @@
 bool psphotPetrosian (pmSource *source, psMetadata *recipe, psMaskType maskVal) {
 
-  psLogMsg ("psphot", PS_LOG_INFO, "not implemented\n");
+  bool status;
+
+  assert (source->extpars);
+  assert (source->extpars->profile);
+  assert (source->extpars->profile->radius);
+  assert (source->extpars->profile->flux);
+
+  psVector *radius = source->extpars->profile->radius;
+  psVector *flux = source->extpars->profile->flux;
+
+  // flux at which to measure isophotal parameters
+  // XXX cache this?
+  float PETROSIAN_R0 = psMetadataLookupF32 (&status, recipe, "PETROSIAN_R0");
+  float PETROSIAN_RF = psMetadataLookupF32 (&status, recipe, "PETROSIAN_FLUX_RATIO");
+
+  // first find flux at R0
+  int firstBelow = -1;
+  int lastAbove = -1;
+  for (int i = 0; i < radius->n; i++) {
+    if (radius->data.F32[i] > PETROSIAN_R0) lastAbove = i;
+    if ((firstBelow < 0) && (flux->data.F32[i] < PETROSIAN_R0)) firstBelow = i;
+  }
+
+  // average flux in this range
+  float fluxR0 = 0.0;
+  int fluxRn = 0;
+  for (int i = PS_MIN(firstBelow, lastAbove); i <= PS_MAX(firstBelow, lastAbove); i++) {
+    fluxR0 += flux->data.F32[i];
+    fluxRn ++;
+  }
+  fluxR0 /= (float)(fluxRn);
+  
+  // target flux for petrosian radius
+  float fluxRP = fluxR0 * PETROSIAN_RF;
+
+  // find the first bin below the flux level and the last above the level
+  // XXX can this be done faster with disection?
+  // XXX do I need to worry about crazy outliers?  
+  // XXX should i be smoothing or fitting the curve?
+  firstBelow = -1;
+  lastAbove = -1;
+  for (int i = 0; i < flux->n; i++) {
+    if (flux->data.F32[i] > fluxRP) lastAbove = i;
+    if ((firstBelow < 0) && (flux->data.F32[i] < fluxRP)) firstBelow = i;
+  }
+
+  // need to examine pixels in this vicinity
+  float fluxFirst = 0;
+  float fluxLast = 0;
+  for (int i = 0; i <= PS_MAX(firstBelow, lastAbove); i++) {
+    if (i <= firstBelow) {
+      fluxFirst += flux->data.F32[i];
+    }
+    if (i <= lastAbove) {
+      fluxLast += flux->data.F32[i];
+    }
+  }
+  float fluxRPSum    = 0.5*(fluxLast + fluxFirst);
+  float fluxRPSumErr = 0.5*fabs(fluxLast - fluxFirst);
+  // XXX need to use the weight appropriately here...
+
+  float rad     = 0.5*(radius->data.F32[firstBelow] + radius->data.F32[lastAbove]);
+  float radErr  = 0.5*fabs(radius->data.F32[firstBelow] - radius->data.F32[lastAbove]);
+
+  if (!source->extpars->petrosian) {
+    source->extpars->petrosian = pmSourcePetrosianValuesAlloc ();
+  }
+  
+  // these are uncalibrated: instrumental mags and pixel units
+  source->extpars->petrosian->mag    = -2.5*log10(fluxRPSum);
+  source->extpars->petrosian->magErr = fluxRPSumErr / fluxRPSum;
+
+  source->extpars->petrosian->rad    = rad;
+  source->extpars->petrosian->radErr = radErr;
+
   return true;
 
Index: /trunk/psphot/src/psphotRadialProfile.c
===================================================================
--- /trunk/psphot/src/psphotRadialProfile.c	(revision 15561)
+++ /trunk/psphot/src/psphotRadialProfile.c	(revision 15562)
@@ -5,9 +5,9 @@
     // allocate pmSourceExtendedParameters, if not already defined
     if (!source->extpars) {
-	source->extpars = pmSourceExtendedParametersAlloc ();
+	source->extpars = pmSourceExtendedParsAlloc ();
     }
 
     if (!source->extpars->profile) {
-	source->extpars->profile = pmSourceRadialProfile (); 
+	source->extpars->profile = pmSourceRadialProfileAlloc (); 
     }    
     
@@ -19,5 +19,5 @@
     psVector *radius = source->extpars->profile->radius;
     psVector *flux   = source->extpars->profile->flux;
-    psVector *weight = source->extpars->profile->radius;
+    psVector *weight = source->extpars->profile->weight;
 
     // XXX use the extended source model here for Xo, Yo?
@@ -40,5 +40,6 @@
     flux->n = n;
 
-    SortVectorsByRadius (radius, flux, weight);
+    // XXX need to sort here
+    // SortVectorsByRadius (radius, flux, weight);
 
     return true;
