Index: /trunk/psModules/src/camera/pmFPAConstruct.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAConstruct.c	(revision 7310)
+++ /trunk/psModules/src/camera/pmFPAConstruct.c	(revision 7311)
@@ -26,6 +26,6 @@
     bool status = true;                 // Result of MD lookup
     psMetadata *cells = psMetadataLookupMD(&status, format, "CELLS"); // The CELLS
-    if (! status) {
-        psError(PS_ERR_IO, false, "Unable to determine CELLS of camera.\n");
+    if (!status || !cells) {
+        psError(PS_ERR_IO, true, "Unable to determine CELLS of camera.\n");
         return NULL;
     }
@@ -114,6 +114,6 @@
     }
     psMetadataItem *resultItem = psMetadataLookup(header, keyword);
-    if (! resultItem) {
-        psError(PS_ERR_IO, false, "Unable to find %s in primary header to identify %s.\n", keyword, name);
+    if (!resultItem) {
+        psError(PS_ERR_IO, true, "Unable to find %s in primary header to identify %s.\n", keyword, name);
         return NULL;
     }
@@ -138,5 +138,8 @@
     fpa->hdu = psMemIncrRefCounter(hdu);
     if (hdu->header) {
-        pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_HEADER, NULL);
+        if (!pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_HEADER, NULL)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to read concepts for FPA");
+            return false;
+        }
     }
     pmFPASetFileStatus(fpa, true);
@@ -256,5 +259,8 @@
 
     if (hdu && level == PM_FPA_LEVEL_FPA) {
-        addHDUtoFPA(fpa, hdu);
+        if (!addHDUtoFPA(fpa, hdu)) {
+            psError(PS_ERR_UNKNOWN, false, "Adding HDU to FPA (%s)", contents);
+            return -1;
+        }
     }
 
@@ -333,5 +339,8 @@
         }
         newCell->config = psMemIncrRefCounter(cellData);
-        pmConceptsReadCell(newCell, PM_CONCEPT_SOURCE_CAMERA | PM_CONCEPT_SOURCE_DEFAULTS, false, NULL);
+        if (!pmConceptsReadCell(newCell, PM_CONCEPT_SOURCE_CAMERA | PM_CONCEPT_SOURCE_DEFAULTS, false, NULL)) {
+            psError(PS_ERR_IO, false, "Reading concepts for cell %d", numCells);
+            return -1;
+        }
         numCells++;
     }
@@ -388,4 +397,9 @@
     bool mdok = true;                   // Status from MD lookups
     psMetadata *components = psMetadataLookupMD(&mdok, camera, "FPA"); // FPA components
+    if (!mdok || !components) {
+        psError(PS_ERR_IO, true, "Failed to lookup \"FPA\"");
+        psFree(fpa);
+        return NULL;
+    }
     psMetadataIterator *componentsIter = psMetadataIteratorAlloc(components, PS_LIST_HEAD, NULL);
     psMetadataItem *componentsItem = NULL; // Item from components
@@ -500,5 +514,11 @@
         hdu->format = psMemIncrRefCounter(format);
         const char *content = contentsItem->data.V; // The content data
-        processContents(fpa, chip, cell, hdu, level, content, format);
+        if (processContents(fpa, chip, cell, hdu, level, content, format) < 0) {
+            psError(PS_ERR_IO, false, "Error setting contents for %s", contentsItem->name);
+            psFree(hdu);
+            psFree(contentsIter);
+
+            return false;
+        }
         psFree(hdu);
     }
@@ -568,9 +588,17 @@
         if (!mdok || !contents || strlen(contents) == 0) {
             psError(PS_ERR_IO, true, "Unable to find CONTENTS in the camera format configuration.\n");
+            psFree(phdu);
             psFree(view);
             return NULL;
         }
 
-        processContents(fpa, NULL, NULL, phdu, PM_FPA_LEVEL_FPA, contents, format);
+        if (processContents(fpa, NULL, NULL, phdu, PM_FPA_LEVEL_FPA, contents, format) < 0) {
+            psError(PS_ERR_IO, false, "Error setting CONTENTS");
+            psFree(phdu);
+            psFree(view);
+
+            return NULL;
+        }
+
         psFree(phdu);
         return view;
@@ -581,5 +609,14 @@
     psMetadata *contents = psMetadataLookupMD(&mdok, format, "CONTENTS"); // The contents of the FITS file
     if (!mdok || !contents) {
-        psError(PS_ERR_IO, false, "Unable to find CONTENTS in the camera format configuration.\n");
+        if (mdok && !contents) {
+            psError(PS_ERR_IO, true, "CONTENTS metadata is NULL in the camera format configuration.");
+        } else {
+            if(psMetadataLookup(format, "CONTENTS") != NULL) {
+                psError(PS_ERR_IO, true, "CONTENTS is of wrong type in camera format configuration");
+            } else {
+                psError(PS_ERR_IO, true, "Unable to find CONTENTS in the camera format configuration.");
+            }
+        }
+
         psFree(view);
         return NULL;
Index: /trunk/psModules/src/camera/pmFPARead.c
===================================================================
--- /trunk/psModules/src/camera/pmFPARead.c	(revision 7310)
+++ /trunk/psModules/src/camera/pmFPARead.c	(revision 7311)
@@ -35,5 +35,5 @@
     if (psRegionIsBad(*trimsec)) {
         psString regionString = psRegionToString(*trimsec);
-        psError(PS_ERR_IO, true, "Invalid trim section: %s\n", regionString);
+        psError(PS_ERR_UNKNOWN, true, "Invalid trim section: %s\n", regionString);
         psFree(regionString);
         psFree(readout);
@@ -319,9 +319,12 @@
     }
     if (!hdu->images && !pmHDURead(hdu, fits)) {
-        psError(PS_ERR_IO, false, "Unable to read HDU for cell.\n");
-        return false;
-    }
-
-    pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER, false, NULL);
+        psError(PS_ERR_UNKNOWN, false, "Unable to read HDU for cell.\n");
+        return false;
+    }
+
+    if (!pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER, false, NULL)) {
+        psError(PS_ERR_UNKNOWN, false, "Failed to read concepts for cell");
+        return false;
+    }
 
     // Having read the cell, we now have to cut it up
@@ -397,5 +400,5 @@
         pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_HEADER, NULL);
     } else {
-        psLogMsg(__func__, PS_LOG_WARN, "Unable to read any chips in FPA.\n");
+        psError(PS_ERR_UNKNOWN, false, "Unable to read any chips in FPA");
     }
 
Index: /trunk/psModules/src/camera/pmFPA_JPEG.c
===================================================================
--- /trunk/psModules/src/camera/pmFPA_JPEG.c	(revision 7310)
+++ /trunk/psModules/src/camera/pmFPA_JPEG.c	(revision 7311)
@@ -5,6 +5,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-02 00:55:22 $
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -141,5 +141,6 @@
 
         // XXX we need to decide where the scale will come from in the long term
-        psImageClippedStatsInit (10000);
+        unsigned long seed = 0;
+        psImageClippedStatsInit (10000, seed);
 
         psStats *stats = psImageClippedStats (readout->image, NULL, 0, 0.25, 0.75);
Index: /trunk/psModules/src/camera/pmFPAfile.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfile.c	(revision 7310)
+++ /trunk/psModules/src/camera/pmFPAfile.c	(revision 7311)
@@ -21,4 +21,5 @@
 #include "pmPSF_IO.h"
 #include "pmFPA_JPEG.h"
+#define WERROR 0                        // if true, warnings in this file are treated as errors
 
 static void pmFPAfileFree(pmFPAfile *file)
@@ -84,4 +85,53 @@
     return file;
 }
+
+static const char *depthEnumToName(pmFPAdepth depth)
+{
+    const char *val = NULL;
+
+    switch (depth) {
+    case PM_FPA_DEPTH_NONE:
+        val = "NONE";
+        break;
+    case PM_FPA_DEPTH_FPA:
+        val = "FPA";
+        break;
+    case PM_FPA_DEPTH_CHIP:
+        val = "CHIP";
+        break;
+    case PM_FPA_DEPTH_CELL:
+        val = "CELL";
+        break;
+    case PM_FPA_DEPTH_READOUT:
+        val = "READOUT";
+        break;
+    default:
+        psAbort(PS_FILE_LINE, "You can't get here; depth = %d", depth);
+    }
+
+    return val;
+}
+
+static pmFPAdepth depthNameToEnum(const char *name)
+{
+    pmFPAdepth val;
+
+    if (name == NULL) {
+        val = PM_FPA_DEPTH_NONE;
+    } else if (!strcasecmp(name, "FPA"))     {
+        val = PM_FPA_DEPTH_FPA;
+    } else if (!strcasecmp(name, "CHIP"))    {
+        val = PM_FPA_DEPTH_CHIP;
+    } else if (!strcasecmp(name, "CELL"))    {
+        val = PM_FPA_DEPTH_CELL;
+    } else if (!strcasecmp(name, "READOUT")) {
+        val = PM_FPA_DEPTH_READOUT;
+    } else {
+        val = PM_FPA_DEPTH_NONE;
+    }
+
+    return val;
+}
+
 
 pmFPAfile *pmFPAfileDefine(psMetadata *files, psMetadata *camera, pmFPA *fpa, char *name)
@@ -94,5 +144,4 @@
 
     bool status;
-    char *depth;
     char *type;
 
@@ -100,5 +149,5 @@
     psMetadata *filerules = psMetadataLookupPtr (&status, camera, "FILERULES");
     if (filerules == NULL) {
-        psErrorStackPrint(stderr, "Can't find FILERULES in the CAMERA configuration!\n");
+        psError(PS_ERR_IO, true, "Can't find FILERULES in the CAMERA configuration!");
         return NULL;
     }
@@ -107,10 +156,11 @@
     // check for alias name (type == STR, name is aliased name)
     char *realname = psMetadataLookupStr (&status, filerules, name);
-    if (realname == NULL)
+    if (!realname || strlen(realname) == 0) {
         realname = name;
+    }
 
     psMetadata *data = psMetadataLookupPtr (&status, filerules, realname);
     if (data == NULL) {
-        psErrorStackPrint(stderr, "Can't find file concept %s!\n", name);
+        psError(PS_ERR_IO, true, "Can't find file concept %s!", name);
         return NULL;
     }
@@ -126,40 +176,10 @@
     file->extxtra  = psMemIncrRefCounter(psMetadataLookupStr (&status, data, "EXTNAME.XTRA"));
 
-    file->fileDepth = PM_FPA_DEPTH_NONE;
-    depth = psMetadataLookupStr (&status, data, "FILE.DEPTH");
-    if (depth != NULL) {
-        if (!strcasecmp (depth, "FPA"))     {
-            file->fileDepth = PM_FPA_DEPTH_FPA;
-        }
-        if (!strcasecmp (depth, "CHIP"))    {
-            file->fileDepth = PM_FPA_DEPTH_CHIP;
-        }
-        if (!strcasecmp (depth, "CELL"))    {
-            file->fileDepth = PM_FPA_DEPTH_CELL;
-        }
-        if (!strcasecmp (depth, "READOUT")) {
-            file->fileDepth = PM_FPA_DEPTH_READOUT;
-        }
-    }
+    file->fileDepth = depthNameToEnum(psMetadataLookupStr(&status, data, "FILE.DEPTH"));
     if (file->fileDepth == PM_FPA_DEPTH_NONE) {
         psLogMsg (__func__, 3, "warning: FILE.DEPTH is not set for %s\n", name);
     }
 
-    file->dataDepth = PM_FPA_DEPTH_NONE;
-    depth = psMetadataLookupStr (&status, data, "DATA.DEPTH");
-    if (depth != NULL) {
-        if (!strcasecmp (depth, "FPA"))     {
-            file->dataDepth = PM_FPA_DEPTH_FPA;
-        }
-        if (!strcasecmp (depth, "CHIP"))    {
-            file->dataDepth = PM_FPA_DEPTH_CHIP;
-        }
-        if (!strcasecmp (depth, "CELL"))    {
-            file->dataDepth = PM_FPA_DEPTH_CELL;
-        }
-        if (!strcasecmp (depth, "READOUT")) {
-            file->dataDepth = PM_FPA_DEPTH_READOUT;
-        }
-    }
+    file->dataDepth = depthNameToEnum(psMetadataLookupStr (&status, data, "DATA.DEPTH"));
     if (file->dataDepth == PM_FPA_DEPTH_NONE) {
         psLogMsg (__func__, 3, "warning: DATA.DEPTH is not set for %s\n", name);
@@ -240,4 +260,8 @@
     pmFPAfile *file = pmFPAfileDefine (files, format, fpa, name);
     psFree (fpa);
+    if (!file) {
+        psErrorStackPrint(stderr, "file %s not defined\n", name);
+        return NULL;
+    }
     return file;
 }
@@ -257,4 +281,5 @@
 
     if (file->state & PM_FPA_STATE_INACTIVE) {
+        psError(PS_ERR_IO, true, "Atempted to read an inactive file");
         return false;
     }
@@ -265,7 +290,9 @@
 
     if (file->mode == PM_FPA_MODE_NONE) {
+        psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_NONE");
         return false;
     }
     if (file->mode == PM_FPA_MODE_INTERNAL) {
+        psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_INTERNAL");
         return false;
     }
@@ -279,6 +306,8 @@
     // determine the file name
     file->filename = pmFPAfileNameFromRule (file->filerule, file, view);
-    if (file->filename == NULL)
-        return false;
+    if (file->filename == NULL) {
+        psError(PS_ERR_IO, true, "Filename is NULL");
+        return false;
+    }
 
     // indirect filenames
@@ -288,6 +317,7 @@
         file->filename = psMetadataLookupStr (&status, file->names, extra);
         psFree (extra);
-        if (file->filename == NULL)
+        if (file->filename == NULL) {
             psAbort ("pmFPAfile", "no file specified");
+        }
         // psMetadataLookupStr just returns a view, file->filename must be protected
         psMemIncrRefCounter (file->filename);
@@ -298,6 +328,7 @@
         // file->filename = pmDetrendSelect (extra);
         psFree (extra);
-        if (file->filename == NULL)
+        if (file->filename == NULL) {
             psAbort ("pmFPAfile", "no file specified");
+        }
         psMemIncrRefCounter (file->filename);
     }
@@ -309,6 +340,8 @@
         psTrace ("pmFPAfile", 5, "opening %s (type: %d)\n", file->filename, file->type);
         file->fits = psFitsOpen (file->filename, mode);
-        if (file->fits == NULL)
-            psAbort (__func__, "error opening file %s\n", file->filename);
+        if (file->fits == NULL) {
+            psError(PS_ERR_IO, false, "error opening file %s\n", file->filename);
+            return false;
+        }
         file->state = PM_FPA_STATE_OPEN;
         break;
@@ -325,5 +358,5 @@
 
     default:
-        fprintf (stderr, "warning: type mismatch for %s : %d\n", file->filename, file->type);
+        psError(PS_ERR_IO, true, "type mismatch for %s : %d\n", file->filename, file->type);
         return false;
     }
@@ -336,9 +369,13 @@
     PS_ASSERT_PTR_NON_NULL(view, false);
 
-    if (file->state & PM_FPA_STATE_INACTIVE)
-        return false;
-
-    if (file->mode != PM_FPA_MODE_READ)
-        return false;
+    if (file->state & PM_FPA_STATE_INACTIVE) {
+        psError(PS_ERR_IO, true, "Atempted to read an inactive file");
+        return false;
+    }
+
+    if (file->mode != PM_FPA_MODE_READ) {
+        psError(PS_ERR_IO, true, "File isn't mode PM_FPA_MODE_READ");
+        return false;
+    }
 
     // get the current depth
@@ -347,10 +384,22 @@
     // do we need to open this file?
     if (depth == file->fileDepth) {
-        pmFPAfileOpen (file, view);
+        if (!pmFPAfileOpen (file, view)) {
+            psError(PS_ERR_IO, false, "Opening file");
+            return false;
+        }
     }
 
     // do we need to read this file?
-    if (depth != file->dataDepth)
-        return false;
+    if (depth != file->dataDepth) {
+        #if WERROR
+        psError(PS_ERR_IO, true, "Desired depth %s doesn't match dataDepth %s",
+                depthEnumToName(depth), depthEnumToName(file->dataDepth));
+        return false;
+        #else
+
+        return true;
+        #endif
+
+    }
 
     switch (file->type) {
@@ -359,5 +408,6 @@
             psTrace ("pmFPAfile", 5, "reading %s (type: %d)\n", file->filename, file->type);
         } else {
-            psTrace ("pmFPAfile", 5, "skipping %s (type: %d)\n", file->filename, file->type);
+            psError(PS_ERR_UNKNOWN, false, "skipping %s (type: %d)\n", file->filename, file->type);
+            return false;
         }
         break;
@@ -381,5 +431,5 @@
 
     default:
-        fprintf (stderr, "warning: type mismatch\n");
+        psError(PS_ERR_IO, true, "warning: type mismatch; saw type %d", file->type);
         return false;
     }
@@ -393,8 +443,10 @@
 
     if (file->state & PM_FPA_STATE_INACTIVE) {
+        psError(PS_ERR_IO, true, "Atempted to write an inactive file");
         return false;
     }
 
     if (file->mode != PM_FPA_MODE_WRITE) {
+        psError(PS_ERR_IO, true, "File isn't mode PM_FPA_MODE_WRITE");
         return false;
     }
@@ -404,10 +456,22 @@
 
     // do we need to write this file?
-    if (depth != file->dataDepth)
-        return false;
+    if (depth != file->dataDepth) {
+        #if WERROR
+        psError(PS_ERR_IO, true, "Desired depth %s doesn't match dataDepth %s",
+                depthEnumToName(depth), depthEnumToName(file->dataDepth));
+        return false;
+        #else
+
+        return true;
+        #endif
+
+    }
 
     // do we need to open this file?
     if (depth >= file->fileDepth) {
-        pmFPAfileOpen (file, view);
+        if (!pmFPAfileOpen (file, view)) {
+            psError(PS_ERR_IO, false, "failed to open %s", file->filename);
+            return false;
+        }
     }
 
@@ -423,6 +487,10 @@
     case PM_FPA_FILE_CMP:
     case PM_FPA_FILE_CMF:
-        pmFPAviewWriteObjects (view, file);
-        psTrace ("pmFPAfile", 5, "wrote object %s (fpa: %p)\n", file->filename, file->fpa);
+        psTrace ("pmFPAfile", 5, "writing object %s (fpa: %p)\n", file->filename, file->fpa);
+        if (!pmFPAviewWriteObjects (view, file)) {
+            psError(PS_ERR_IO, false, "Failed to write object %s", file->filename);
+            return false;
+        }
+
         break;
 
@@ -451,19 +519,33 @@
 
     if (file->state & PM_FPA_STATE_INACTIVE) {
-        return false;
-    }
-    if (file->mode != PM_FPA_MODE_WRITE)
-        return false;
+        psError(PS_ERR_IO, true, "Atempted to create an inactive file");
+        return false;
+    }
+    if (file->mode != PM_FPA_MODE_WRITE) {
+        psError(PS_ERR_IO, true, "File isn't mode PM_FPA_MODE_WRITE");
+        return false;
+    }
 
     // get the current depth
     pmFPAdepth depth = pmFPAviewDepth (view);
 
+    // XXX is this a sufficient check to avoid creating elements?
+    if (file->src == NULL) {
+        #if WERROR
+        psError(PS_ERR_IO, true, "file->src is NULL");
+        return false;
+        #else
+
+        return true;
+        #endif
+
+    }
+
     // do we need to write this file?
-    if (depth != file->dataDepth)
-        return false;
-
-    // XXX is this a sufficient check to avoid creating elements?
-    if (file->src == NULL)
-        return false;
+    if (depth != file->dataDepth) {
+        psError(PS_ERR_IO, true, "Desired depth %s doesn't match dataDepth %s",
+                depthEnumToName(depth), depthEnumToName(file->dataDepth));
+        return false;
+    }
 
     switch (file->type) {
@@ -484,5 +566,5 @@
 
     default:
-        fprintf (stderr, "warning: type mismatch\n");
+        psError(PS_ERR_IO, true, "Unsupported type: %d", file->type);
         return false;
     }
@@ -496,4 +578,5 @@
 
     if (file->state & PM_FPA_STATE_INACTIVE) {
+        psError(PS_ERR_IO, true, "Atempted to close an inactive file");
         return false;
     }
@@ -505,5 +588,13 @@
     pmFPAdepth depth = pmFPAviewDepth (view);
     if (file->fileDepth != depth) {
-        return false;
+        #if WERROR
+        psError(PS_ERR_IO, true, "Desired depth %s doesn't match fileDepth %s",
+                depthEnumToName(depth), depthEnumToName(file->fileDepth));
+        return false;
+        #else
+
+        return true;
+        #endif
+
     }
 
@@ -531,5 +622,5 @@
 
     default:
-        fprintf (stderr, "warning: type mismatch\n");
+        psError(PS_ERR_IO, true, "type mismatch: %d", file->type);
         return false;
     }
@@ -560,5 +651,10 @@
     bool status = false;
     pmFPAfile *file = psMetadataLookupPtr (&status, files, name);
+    if (!status) {
+        psError(PS_ERR_IO, true, "Failed to look up file %s", name);
+        return false;
+    }
     if (!file) {
+        psError(PS_ERR_IO, true, "file %s is NULL", name);
         return false;
     }
@@ -583,13 +679,35 @@
         pmFPAfile *file = item->data.V;
 
-        if (place == PM_FPA_BEFORE) {
-            pmFPAfileRead (file, view);
-            pmFPAfileCreate (file, view);
-        } else {
-            pmFPAfileWrite (file, view);
-            pmFPAfileClose (file, view);
+        switch (place) {
+        case PM_FPA_BEFORE:
+            if (file->mode == PM_FPA_MODE_READ && !pmFPAfileRead (file, view)) {
+                psError(PS_ERR_IO, false, "failed in FPA_BEFORE block for %s", file->name);
+                psFree(iter);
+                return false;
+            }
+            if (file->mode == PM_FPA_MODE_WRITE && !pmFPAfileCreate(file, view)) {
+                psError(PS_ERR_IO, false, "failed in FPA_BEFORE block for %s", file->name);
+                psFree(iter);
+                return false;
+            }
+            break;
+        case PM_FPA_AFTER:
+            if (file->mode == PM_FPA_MODE_WRITE && !pmFPAfileWrite (file, view)) {
+                psError(PS_ERR_IO, false, "failed in FPA_AFTER block for %s", file->name);
+                psFree(iter);
+                return false;
+            }
+            if (!pmFPAfileClose(file, view)) {
+                psError(PS_ERR_IO, false, "failed in FPA_AFTER block for %s", file->name);
+                psFree(iter);
+                return false;
+            }
+            break;
+        default:
+            psAbort(PS_FILE_LINE, "You can't get here");
         }
     }
     psFree (iter);
+
     return true;
 }
@@ -627,9 +745,13 @@
 
     pmFPAfile *file = psMetadataLookupPtr (&status, files, name);
-    if (file == NULL)
-        return false;
-
-    if (file->mode != PM_FPA_MODE_INTERNAL)
-        return false;
+    if (file == NULL) {
+        psError(PS_ERR_IO, true, "Failed to lookup %s", name);
+        return false;
+    }
+
+    if (file->mode != PM_FPA_MODE_INTERNAL) {
+        psError(PS_ERR_IO, true, "File %s has mode %d != PM_FPA_MODE_INTERNAL", name, file->mode);
+        return false;
+    }
 
     psMetadataRemoveKey (files, name);
@@ -648,6 +770,7 @@
 
     pmFPAfile *file = psMetadataLookupPtr (&status, files, name);
-    if (file == NULL)
-        return NULL;
+    if (file == NULL) {
+        return NULL;
+    }
 
     // internal files have the readout as a separate element:
@@ -677,4 +800,5 @@
 
     if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %d", view->chip, fpa->chips->n);
         return false;
     }
@@ -687,4 +811,5 @@
 
     if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %d", view->cell, chip->cells->n);
         return false;
     }
@@ -695,12 +820,15 @@
         return status;
     }
+    psError(PS_ERR_UNKNOWN, true, "Returning false");
     return false;
 
     // XXX pmReadoutRead, pmReadoutReadSegement disabled for now
-    # if (0)
-
-        if (view->readout >= cell->readouts->n) {
-            return false;
-        }
+    #if 0
+
+    if (view->readout >= cell->readouts->n) {
+        psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouts->n == %d",
+                view->readout, cell->readouts->n);
+        return false;
+    }
     pmReadout *readout = cell->readouts->data[view->readout];
 
@@ -711,5 +839,5 @@
     }
     return true;
-    # endif
+    #endif
 }
 
@@ -731,4 +859,5 @@
 
     if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %d", view->chip, fpa->chips->n);
         return false;
     }
@@ -757,4 +886,5 @@
 
     if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %d", view->cell, chip->cells->n);
         return false;
     }
@@ -762,15 +892,17 @@
 
     if (view->readout == -1) {
-        pmCellWrite (cell, fits, NULL, true);
-        return true;
-    }
+        return pmCellWrite (cell, fits, NULL, true);
+    }
+    psError(PS_ERR_UNKNOWN, true, "Returning false");
     return false;
 
     // XXX disable readout write for now
-    # if (0)
-
-        if (view->readout >= cell->readouts->n) {
-            return false;
-        }
+    #if 0
+
+    if (view->readout >= cell->readouts->n) {
+        psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouts->n == %d",
+                view->readout, cell->readouts->n);
+        return false;
+    }
     pmReadout *readout = cell->readouts->data[view->readout];
 
@@ -781,5 +913,5 @@
     }
     return true;
-    # endif
+    #endif
 }
 
@@ -808,7 +940,9 @@
     psArray *infiles = psMetadataLookupPtr(&status, config->arguments, argname);
     if (!status) {
+        psError(PS_ERR_IO, false, "Failed to read %s from metadata\n", argname);
         return NULL;
     }
     if (infiles->n < 1) {
+        psError(PS_ERR_IO, false, "Found n == %d files in %s from metadata\n", infiles->n, argname);
         return NULL;
     }
@@ -819,8 +953,17 @@
     phu = psFitsReadHeader (NULL, fits);
     format = pmConfigCameraFormatFromHeader (config, phu);
-    psFitsClose (fits);
+    psFitsClose (fits);                        // don't close phu; we'll use it below
+    if (!format) {
+        psError(PS_ERR_IO, false, "Failed to read CCD format from %s\n", infiles->data[0]);
+        psFree(phu);
+        return NULL;
+    }
 
     // build the template fpa, set up the basic view
     fpa = pmFPAConstruct (config->camera);
+    if (!fpa) {
+        psError(PS_ERR_IO, false, "Failed to construct FPA from %s", infiles->data[0]);
+        return NULL;
+    }
 
     // load the given filerule (from config->camera) and associate it with the fpa
@@ -828,5 +971,6 @@
     file = pmFPAfileDefine (config->files, config->camera, fpa, filename);
     if (!file) {
-        psErrorStackPrint(stderr, "file %s not defined\n", filename);
+        psError(PS_ERR_IO, false, "file %s not defined", filename);
+        psFree(phu);
         psFree (fpa);
         psFree (format);
@@ -854,4 +998,11 @@
         // set the view to the corresponding entry for this phu
         pmFPAview *view = pmFPAAddSourceFromHeader (fpa, phu, format);
+        if (!view) {
+            psError(PS_ERR_IO, false, "Failed to set view from file %s", infiles->data[i]);
+            psFree(phu);
+            psFree (fpa);
+            psFree (format);
+            return NULL;
+        }
 
         // XXX is this the correct psMD to save the filename?
@@ -871,5 +1022,5 @@
 
 // XXX this this function through, then finish
-# if 0
+#if 0
 // look for the given name on the argument list.
 // returns the file (a view to the one saved on config->files)
@@ -925,5 +1076,5 @@
     file = pmFPAfileDefine (config->files, config->camera, fpa, filename);
     if (!file) {
-        psErrorStackPrint(stderr, "file %s not defined\n", filename);
+        psError(PS_ERR_IO, false, "file %s not defined", filename);
         psFree (fpa);
         psFree (format);
@@ -966,5 +1117,5 @@
     return file;
 }
-# endif
+#endif
 
 // create a new output pmFPAfile based on an existing FPA
@@ -979,4 +1130,8 @@
     pmFPA *fpa = pmFPAConstruct (config->camera);
     pmFPAfile *file = pmFPAfileDefine (config->files, config->camera, fpa, filename);
+    if (!file) {
+        psErrorStackPrint(stderr, "file %s not defined\n", filename);
+        return NULL;
+    }
     file->src = src; // inherit output elements from this source pmFPA
     file->xBin = xBin;
@@ -1014,5 +1169,5 @@
     file = pmFPAfileDefine (config->files, config->camera, NULL, filename);
     if (!file) {
-        psErrorStackPrint(stderr, "file %s not defined\n", filename);
+        psError(PS_ERR_IO, false, "file %s not defined\n", filename);
         return NULL;
     }
@@ -1120,4 +1275,10 @@
     newName = psStringCopy (rule);
 
+    if (strstr (newName, "{OUTPUT}") != NULL) {
+        char *name = psMetadataLookupStr (NULL, file->names, "OUTPUT");
+        if (name != NULL) {
+            newName = psStringSubstitute (newName, name, "{OUTPUT}");
+        }
+    }
     if (strstr (newName, "{CHIP.NAME}") != NULL) {
         pmChip *chip = pmFPAviewThisChip (view, file->fpa);
@@ -1144,10 +1305,4 @@
         }
     }
-    if (strstr (newName, "{OUTPUT}") != NULL) {
-        char *name = psMetadataLookupStr (NULL, file->names, "OUTPUT");
-        if (name != NULL) {
-            newName = psStringSubstitute (newName, name, "{OUTPUT}");
-        }
-    }
     return newName;
 }
@@ -1167,4 +1322,5 @@
     }
     if (view->chip >= in->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= in->chips->n == %d", view->chip, in->chips->n);
         return false;
     }
@@ -1177,4 +1333,6 @@
     }
     if (view->cell >= inChip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d>= inChip->cells->n == %d",
+                view->cell, inChip->cells->n);
         return false;
     }
@@ -1186,4 +1344,5 @@
         return true;
     }
+    psError(PS_ERR_UNKNOWN, true, "Returning false");
     return false;
 
@@ -1203,8 +1362,8 @@
     if (view->chip == -1) {
         pmFPAAddSourceFromView (out, view, format);
-        pmFPACopyStructure (out, in, xBin, yBin);
-        return true;
+        return pmFPACopyStructure (out, in, xBin, yBin);
     }
     if (view->chip >= in->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= in->chips->n == %d", view->chip, in->chips->n);
         return false;
     }
@@ -1214,8 +1373,9 @@
     if (view->cell == -1) {
         pmFPAAddSourceFromView (out, view, format);
-        pmChipCopyStructure (outChip, inChip, xBin, yBin);
-        return true;
+        return pmChipCopyStructure (outChip, inChip, xBin, yBin);
     }
     if (view->cell >= inChip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d>= inChip->cells->n == %d",
+                view->cell, inChip->cells->n);
         return false;
     }
@@ -1225,7 +1385,7 @@
     if (view->readout == -1) {
         pmFPAAddSourceFromView (out, view, format);
-        pmCellCopyStructure (outCell, inCell, xBin, yBin);
-        return true;
-    }
+        return pmCellCopyStructure (outCell, inCell, xBin, yBin);
+    }
+    psError(PS_ERR_UNKNOWN, true, "Returning false");
     return false;
 
Index: /trunk/psModules/src/camera/pmReadout.c
===================================================================
--- /trunk/psModules/src/camera/pmReadout.c	(revision 7310)
+++ /trunk/psModules/src/camera/pmReadout.c	(revision 7311)
@@ -76,4 +76,8 @@
             readout->mask = psMemIncrRefCounter(psImageSubset(masks->data[i], *trimsec));
         }
+        if (readout->weight == NULL || readout->mask == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "Trimming readout %d", i);
+            return false;
+        }
 
         // Set up the mask
Index: /trunk/psModules/src/concepts/pmConcepts.c
===================================================================
--- /trunk/psModules/src/concepts/pmConcepts.c	(revision 7310)
+++ /trunk/psModules/src/concepts/pmConcepts.c	(revision 7311)
@@ -131,25 +131,44 @@
     }
 
+    bool success = true;                // Success in reading concepts?
     if (source & PM_CONCEPT_SOURCE_CAMERA && !(*read & PM_CONCEPT_SOURCE_CAMERA)) {
-        pmConceptsReadFromCamera(*specs, cell, target);
-        *read |= PM_CONCEPT_SOURCE_CAMERA;
+        if (pmConceptsReadFromCamera(*specs, cell, target)) {
+            *read |= PM_CONCEPT_SOURCE_CAMERA;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from camera configuration.\n");
+            success = false;
+        }
     }
 
     if (source & PM_CONCEPT_SOURCE_DEFAULTS && !(*read & PM_CONCEPT_SOURCE_DEFAULTS)) {
-        pmConceptsReadFromDefaults(*specs, fpa, chip, cell, target);
-        *read |= PM_CONCEPT_SOURCE_DEFAULTS;
+        if (pmConceptsReadFromDefaults(*specs, fpa, chip, cell, target)) {
+            *read |= PM_CONCEPT_SOURCE_DEFAULTS;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from defaults.\n");
+            success = false;
+        }
     }
 
     if (source & PM_CONCEPT_SOURCE_HEADER && !(*read & PM_CONCEPT_SOURCE_HEADER)) {
-        pmConceptsReadFromHeader(*specs, fpa, chip, cell, target);
-        *read |= PM_CONCEPT_SOURCE_HEADER;
-    }
-
+        if (pmConceptsReadFromHeader(*specs, fpa, chip, cell, target)) {
+            *read |= PM_CONCEPT_SOURCE_HEADER;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from header.\n");
+            success = false;
+        }
+    }
+
+    #ifndef OMIT_PSDB
     if (source & PM_CONCEPT_SOURCE_DATABASE && !(*read & PM_CONCEPT_SOURCE_DATABASE)) {
-        pmConceptsReadFromDatabase(*specs, fpa, chip, cell, db, target);
-        *read |= PM_CONCEPT_SOURCE_DATABASE;
-    }
-
-    return true;
+        if (pmConceptsReadFromDatabase(*specs, fpa, chip, cell, db, target)) {
+            *read |= PM_CONCEPT_SOURCE_DATABASE;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from database.\n");
+            success = false;
+        }
+    }
+    #endif
+
+    return success;
 }
 
Index: /trunk/psModules/src/concepts/pmConcepts.h
===================================================================
--- /trunk/psModules/src/concepts/pmConcepts.h	(revision 7310)
+++ /trunk/psModules/src/concepts/pmConcepts.h	(revision 7311)
@@ -6,7 +6,7 @@
 
 // Function to call to parse a concept once it has been read
-typedef psMetadataItem* (*pmConceptParseFunc)(psMetadataItem *concept, psMetadataItem *pattern, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
+typedef psMetadataItem* (*pmConceptParseFunc)(const psMetadataItem *concept, const psMetadataItem *pattern, const psMetadata *cameraFormat, const pmFPA *fpa, const pmChip *chip, const pmCell *cell);
 // Function to call to format a concept for writing
-typedef psMetadataItem* (*pmConceptFormatFunc)(psMetadataItem *concept, psMetadata *cameraFormat, pmFPA *fpa, pmChip *chip, pmCell *cell);
+typedef psMetadataItem* (*pmConceptFormatFunc)(const psMetadataItem *concept, const psMetadata *cameraFormat, const pmFPA *fpa, const pmChip *chip, const pmCell *cell);
 
 // A "concept" specification
Index: /trunk/psModules/src/concepts/pmConceptsRead.c
===================================================================
--- /trunk/psModules/src/concepts/pmConceptsRead.c	(revision 7310)
+++ /trunk/psModules/src/concepts/pmConceptsRead.c	(revision 7311)
@@ -71,6 +71,8 @@
         parsed = parsePlain(concept, spec->blank);
     }
-    if (!parsed)
-        return false;
+    if (!parsed) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s\n", spec->blank->name);
+        return false;
+    }
 
     // Plug the parsed concept into a new psMetadataItem, so each "concept" has its own version that can
@@ -117,5 +119,5 @@
 
     pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
-    if (! hdu) {
+    if (!hdu) {
         return false;
     }
@@ -124,9 +126,9 @@
     psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
     while ((specItem = psMetadataGetAndIncrement(specsIter))) {
         pmConceptSpec *spec = specItem->data.V; // The specification
         psString name = specItem->name; // The concept name
         psMetadataItem *conceptItem = psMetadataLookup(cellConfig, name); // The concept, or NULL
-        psMetadataItem *value = NULL; // The value of the concept
         if (conceptItem) {
             if (conceptItem->type == PS_DATA_STRING) {
@@ -138,6 +140,9 @@
                 psFree(nameSource);
                 if (mdok && strlen(source) > 0 && strcasecmp(source, "VALUE") == 0) {
-                    value = conceptItem;
-                    conceptParse(spec, value, cameraFormat, target, NULL, NULL, cell);
+                    if (!conceptParse(spec, conceptItem, cameraFormat, target, NULL, NULL, cell)) {
+                        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from camera "
+                                "configuration\n", name);
+                        status = false;
+                    }
                 } else if (source && (strlen(source) == 0 || strcasecmp(source, "HEADER") != 0)) {
                     // We leave "HEADER" to pmConceptsReadFromHeader
@@ -148,10 +153,14 @@
             } else {
                 // Another type --- should be OK
-                conceptParse(spec, conceptItem, cameraFormat, target, NULL, NULL, cell);
+                if (!conceptParse(spec, conceptItem, cameraFormat, target, NULL, NULL, cell)) {
+                    psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from camera "
+                            "configuration.  It has a weird %s.SOURCE: %s\n", name, name);
+                    status = false;
+                }
             }
         }
     }
     psFree(specsIter);
-    return true;
+    return status;
 }
 
@@ -179,12 +188,16 @@
     psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
     while ((specItem = psMetadataGetAndIncrement(specsIter))) {
         pmConceptSpec *spec = specItem->data.V; // The specification
         psString name = specItem->name; // The concept name
         psMetadataItem *conceptItem = psMetadataLookup(defaults, name); // The concept, or NULL
-        conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell);
+        if (conceptItem && !conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell)) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from DEFAULTS.\n", name);
+            status = false;
+        }
     }
     psFree(specsIter);
-    return true;
+    return status;
 }
 
@@ -213,4 +226,5 @@
     psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
     while ((specItem = psMetadataGetAndIncrement(specsIter))) {
         pmConceptSpec *spec = specItem->data.V; // The specification
@@ -257,8 +271,11 @@
 
         // This will also clean up the name
-        conceptParse(spec, headerItem, cameraFormat, target, fpa, chip, cell);
+        if (headerItem && !conceptParse(spec, headerItem, cameraFormat, target, fpa, chip, cell)) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from header.\n", name);
+            status = false;
+        }
     }
     psFree(specsIter);
-    return true;
+    return status;
 }
 
@@ -294,4 +311,5 @@
     psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
     psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
     while ((specItem = psMetadataGetAndIncrement(specsIter))) {
         pmConceptSpec *spec = specItem->data.V; // The specification
@@ -374,5 +392,9 @@
 
                     // Now we have the result
-                    conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell);
+                    if (!conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell)) {
+                        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from database.\n",
+                                name);
+                        status = false;
+                    }
 
                 }
@@ -385,5 +407,5 @@
     psFree(specsIter);
 
-    return true;
+    return status;
     #endif
 }
Index: /trunk/psModules/src/concepts/pmConceptsStandard.c
===================================================================
--- /trunk/psModules/src/concepts/pmConceptsStandard.c	(revision 7310)
+++ /trunk/psModules/src/concepts/pmConceptsStandard.c	(revision 7311)
@@ -69,5 +69,5 @@
                     sscanf(concept->data.V, "%d %d %f", &big, &medium, &small) != 3)
             {
-                psError(PS_ERR_IO, true, "Cannot interpret FPA.RA: %s\n", concept->data.V);
+                psError(PS_ERR_UNKNOWN, true, "Cannot interpret FPA.RA: %s\n", concept->data.V);
                 break;
             }
@@ -80,5 +80,5 @@
         break;
     default:
-        psError(PS_ERR_IO, true, "%s concept is of an unexpected type: %x\n", pattern->name, concept->type);
+        psError(PS_ERR_UNKNOWN, true, "%s concept is of an unexpected type: %x\n", pattern->name, concept->type);
         return NULL;
     }
@@ -171,9 +171,8 @@
     assert(pattern);
 
-    psRegion *trimsec = psAlloc(sizeof(psRegion)); // Make space for a psRegion (usually passed by value)
+    psRegion *trimsec = psRegionAlloc(0, 0, 0, 0);
 
     if (concept->type != PS_DATA_STRING) {
-        psError(PS_ERR_IO, true, "CELL.TRIMSEC after read is not of type STR (%x)\n", concept->type);
-        *trimsec = psRegionSet(0.0, 0.0, 0.0, 0.0);
+        psError(PS_ERR_UNKNOWN, true, "CELL.TRIMSEC after read is not of type STR (%x)\n", concept->type);
     } else {
         *trimsec = psRegionFromString(concept->data.V);
@@ -231,5 +230,5 @@
         }
     default:
-        psError(PS_ERR_IO, true, "CELL.BIASSEC after read is not of type STRING or LIST --- assuming "
+        psError(PS_ERR_UNKNOWN, true, "CELL.BIASSEC after read is not of type STRING or LIST --- assuming "
                 "blank.\n");
     }
@@ -259,5 +258,5 @@
                     (strcmp(pattern->name, "CELL.YBIN") == 0 && sscanf(binString, "%*d %d", &binning) != 1 &&
                      sscanf(binString, "%*d,%d", &binning) != 1)) {
-                psError(PS_ERR_IO, true, "Unable to parse string to get %s: %s\n", pattern->name, binString);
+                psError(PS_ERR_UNKNOWN, true, "Unable to parse string to get %s: %s\n", pattern->name, binString);
             }
         }
@@ -269,5 +268,5 @@
         TYPE_CASE(binning, concept, S32);
     default:
-        psError(PS_ERR_IO, true, "Note sure how to parse %s of type %x --- assuming 1.\n", pattern->name,
+        psError(PS_ERR_UNKNOWN, true, "Note sure how to parse %s of type %x --- assuming 1.\n", pattern->name,
                 concept->type);
     }
@@ -290,5 +289,5 @@
     psString sys = concept->data.V;     // The time system string
     if (concept->type != PS_DATA_STRING || strlen(sys) <= 0) {
-        psError(PS_ERR_IO, true, "Can't interpret CELL.TIMESYS --- assuming UTC.\n");
+        psError(PS_ERR_UNKNOWN, true, "Can't interpret CELL.TIMESYS --- assuming UTC.\n");
     } else if (strcasecmp(sys, "TAI") == 0) {
         timeSys = PS_TIME_TAI;
@@ -300,5 +299,5 @@
         timeSys = PS_TIME_TT;
     } else {
-        psError(PS_ERR_IO, true, "Can't interpret CELL.TIMESYS --- assuming UTC.\n");
+        psError(PS_ERR_UNKNOWN, true, "Can't interpret CELL.TIMESYS --- assuming UTC.\n");
     }
 
@@ -334,10 +333,14 @@
     // Get format
     psMetadata *formats = psMetadataLookupMD(&mdok, cameraFormat, "FORMATS");
-    if (!mdok || !formats)
+    if (!mdok || !formats) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find FORMATS in camera configuration.\n");
         return NULL;
+    }
 
     psString timeFormat = psMetadataLookupStr(&mdok, formats, "CELL.TIME");
-    if (!mdok || !timeFormat || !strlen(timeFormat))
+    if (!mdok || !timeFormat || !strlen(timeFormat)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find CELL.TIME in FORMATS.\n");
         return NULL;
+    }
 
     // Parse the time format
@@ -385,5 +388,5 @@
             psMetadataItem *timeItem = psListGet(dateTime, PS_LIST_HEAD + 1); // Item containing the time
             if (dateItem->type != PS_DATA_STRING) {
-                psError(PS_ERR_IO, true, "Date is not of type STR.\n");
+                psError(PS_ERR_UNKNOWN, true, "Date is not of type STR.\n");
                 return NULL;
             }
@@ -392,5 +395,5 @@
             if (sscanf(dateString, "%d-%d-%d", &year, &month, &day) != 3 &&
                     sscanf(dateString, "%d/%d/%d", &year, &month, &day) != 3) {
-                psError(PS_ERR_IO, true, "Unable to read date: %s\n", dateString);
+                psError(PS_ERR_UNKNOWN, true, "Unable to read date: %s\n", dateString);
                 return NULL;
             }
@@ -408,7 +411,13 @@
                 year = temp;
             }
-            if (pre2000Time || year < 2000) {
-                year += 2000;
-            }
+            if (year < 100) {
+                if (pre2000Time) {
+                    year += 1900;
+                } else {
+                    year += 2000;
+                }
+            }
+            sprintf(dateString,"%04d-%02d-%02d", year, month, day);
+
             psString timeString = NULL; // The string with the time
             if (timeItem->type == PS_DATA_STRING) {
@@ -427,5 +436,5 @@
                     TYPE_CASE(seconds, timeItem, F64);
                 default:
-                    psError(PS_ERR_IO, true, "Time is not of an expected type: %x\n", timeItem->type);
+                    psError(PS_ERR_UNKNOWN, true, "Time is not of an expected type: %x\n", timeItem->type);
                     return NULL;
                 }
@@ -440,4 +449,5 @@
             psStringAppend(&dateTimeString, "%sT%s", dateString, timeString);
             time = psTimeFromISO(dateTimeString, timeSys);
+            psFree(dateTimeString);
             break;
         }
@@ -463,5 +473,6 @@
                 time = psTimeFromMJD(timeValue);
             } else {
-                psError(PS_ERR_IO, true, "Not sure how to parse CELL.TIME (%f) --- trying JD\n", timeValue);
+                psError(PS_ERR_UNKNOWN, true, "Not sure how to parse CELL.TIME (%f) --- trying JD\n",
+                        timeValue);
                 time = psTimeFromJD(timeValue);
             }
@@ -475,5 +486,6 @@
                 time = psTimeFromMJD(timeValue);
             } else {
-                psError(PS_ERR_IO, true, "Not sure how to parse CELL.TIME (%f) --- trying JD\n", timeValue);
+                psError(PS_ERR_UNKNOWN, true, "Not sure how to parse CELL.TIME (%f) --- trying JD\n",
+                        timeValue);
                 time = psTimeFromJD(timeValue);
             }
@@ -481,5 +493,5 @@
         }
     default:
-        psError(PS_ERR_IO, true, "Unable to parse CELL.TIME.\n");
+        psError(PS_ERR_UNKNOWN, true, "Unable to parse CELL.TIME.\n");
         return NULL;
     }
@@ -526,5 +538,5 @@
         TYPE_CASE(offset, concept, S32);
     default:
-        psError(PS_ERR_IO, true, "Concept %s is not of integer type, as expected.\n", pattern->name);
+        psError(PS_ERR_UNKNOWN, true, "Concept %s is not of integer type, as expected.\n", pattern->name);
         return NULL;
     }
@@ -724,13 +736,13 @@
         // XXX: Couldn't be bothered doing these right now
         if (pre2000Time) {
-            psError(PS_ERR_IO, true, "Don't you realise it's the twenty-first century?\n");
+            psError(PS_ERR_UNKNOWN, true, "Don't you realise it's the twenty-first century?\n");
             return NULL;
         }
         if (backwardsTime) {
-            psError(PS_ERR_IO, true, "You want it BACKWARDS?  Not right now, thanks.\n");
+            psError(PS_ERR_UNKNOWN, true, "You want it BACKWARDS?  Not right now, thanks.\n");
             return NULL;
         }
         if (usaTime) {
-            psError(PS_ERR_IO, true, "USA?  No OK --- yet.\n");
+            psError(PS_ERR_UNKNOWN, true, "USA?  No OK.\n");
             return NULL;
         }
@@ -778,5 +790,5 @@
 
     if (concept->type != PS_TYPE_S32) {
-        psError(PS_ERR_IO, true, "Concept %s is not of type S32, as expected.\n", concept->name);
+        psError(PS_ERR_UNKNOWN, true, "Concept %s is not of type S32, as expected.\n", concept->name);
         return NULL;
     }
Index: /trunk/psModules/src/config/pmConfig.c
===================================================================
--- /trunk/psModules/src/config/pmConfig.c	(revision 7310)
+++ /trunk/psModules/src/config/pmConfig.c	(revision 7311)
@@ -3,6 +3,6 @@
  *  @author PAP, IfA
  *
- *  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-02 00:55:22 $
+ *  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -12,4 +12,5 @@
 #include <string.h>
 #include <unistd.h>
+#include <libgen.h>
 #include <assert.h>
 #include <sys/types.h>
@@ -52,7 +53,17 @@
 }
 
+void pmConfigSet(const char *path)
+{
+    pmConfigDone();
+
+    psList *list = psStringSplit(path, ":", false);
+    configPath = psListToArray(list);
+    psFree(list);
+}
+
 void pmConfigDone(void)
 {
     psFree(configPath);
+    configPath = NULL;
 }
 
@@ -100,5 +111,5 @@
 
     if (configPath == NULL) {
-        psError(PS_ERR_IO, false, "Cannot find %s configuration file (%s) in path\n", description, name);
+        psError(PS_ERR_IO, true, "Cannot find %s configuration file (%s) in path\n", description, name);
         return false;
     }
@@ -121,5 +132,5 @@
     }
 
-    psError(PS_ERR_IO, false, "Cannot find %s configuration file %s in path\n", description, name);
+    psError(PS_ERR_IO, true, "Cannot find %s configuration file %s in path\n", description, name);
     return false;
 
@@ -127,9 +138,12 @@
     *config = psMetadataConfigParse(NULL, &numBadLines, realName, true);
     if (numBadLines > 0) {
-        psLogMsg(__func__, PS_LOG_WARN, "%d bad lines in %s configuration file (%s)\n",
-                 description, realName);
+        psError(PS_ERR_IO, false, "%d bad lines in %s configuration file (%s)",
+                numBadLines, description, realName);
+        psFree (realName);
+
+        return false;
     }
     if (!*config) {
-        psError(PS_ERR_IO, false, "Unable to read %s configuration from %s\n",
+        psError(PS_ERR_IO, true, "Unable to read %s configuration from %s",
                 description, realName);
         psFree (realName);
@@ -214,17 +228,23 @@
         return NULL;
     }
+
+    // define the config-file search path (configPath).  Ensure that
+    // it contains the directory where we found the config file in
+    // the first place
+    if (configPath) {
+        pmConfigDone();
+    }
+
+    psString siteNameDir = psStringCopy(dirname(siteName));
     psFree(siteName);
 
-    // define the config-file search path (configPath)
-    if (configPath) {
-        psFree(configPath);
-        configPath = NULL;
-    }
-    char *path = psMetadataLookupStr(NULL, config->site, "PATH");
+    psString path = psMetadataLookupStr(NULL, config->site, "PATH");
     if (path) {
-        psList *list = psStringSplit(path, ":", false);
-        configPath = psListToArray(list);
-        psFree(list);
-    }
+        psStringAppend(&path, ":%s", siteNameDir);
+    } else {
+        path = psMemIncrRefCounter(siteNameDir);
+    }
+    pmConfigSet(path);
+    psFree(siteNameDir);
 
     // Next, we do a similar thing for the camera configuration file.  The
@@ -349,4 +369,6 @@
     }
 
+    psErrorClear();   // we may have failed to find some items in the metadata
+
     return config;
 }
@@ -468,5 +490,5 @@
         psMetadata *cameras = psMetadataLookupMD(&mdok, config->site, "CAMERAS");
         if (! mdok) {
-            psError(PS_ERR_IO, false, "Unable to find CAMERAS in the configuration.\n");
+            psError(PS_ERR_IO, true, "Unable to find CAMERAS in the configuration.");
             return false;
         }
@@ -502,5 +524,5 @@
 
         if (! config->camera) {
-            psError(PS_ERR_IO, true, "Unable to find a camera that matches input FITS header!\n");
+            psError(PS_ERR_IO, false, "Unable to find a camera that matches input FITS header!");
             return NULL;
         }
@@ -611,5 +633,5 @@
     psMetadata *rules = psMetadataLookupMD(&mdok, format, "RULE"); // How to identify this format
     if (!mdok || !rules) {
-        psError(PS_ERR_IO, false, "Unable to find RULE in camera format.\n");
+        psError(PS_ERR_IO, true, "Unable to find RULE in camera format.\n");
         return false;
     }
@@ -651,4 +673,10 @@
         globList.gl_offs = 0;
         glob (argv[Narg], 0, NULL, &globList);
+
+        if (globList.gl_pathc == 0) {
+            psError(PS_ERR_IO, true, "No match for %s", argv[Narg]);
+            return input;
+        }
+
         for (int i = 0; i < globList.gl_pathc; i++) {
             char *filename = psStringCopy (globList.gl_pathv[i]);
@@ -706,6 +734,9 @@
     PS_ASSERT_INT_POSITIVE(strlen(list), NULL);
 
+    psErrorClear();   // pmConfigFileSets may or may not call psError, so
+    // if files->n == 0 we'll want to call psError(..., false, ...)
     psArray *files = pmConfigFileSets (argc, argv, file, list);
     if (files->n == 0) {
+        psError(PS_ERR_IO, false, "pmConfigFileSets failed to find desired files in metadata");
         psFree (files);
         return false;
Index: /trunk/psModules/src/config/pmConfig.h
===================================================================
--- /trunk/psModules/src/config/pmConfig.h	(revision 7310)
+++ /trunk/psModules/src/config/pmConfig.h	(revision 7311)
@@ -3,6 +3,6 @@
  *  @author PAP, IfA
  *
- *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-05-02 00:47:01 $
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -28,4 +28,6 @@
 
 pmConfig *pmConfigAlloc(void);
+
+void pmConfigSet(const char *path); // set the configPath
 
 // Free static variables
Index: /trunk/psModules/src/objects/pmPSF.c
===================================================================
--- /trunk/psModules/src/objects/pmPSF.c	(revision 7310)
+++ /trunk/psModules/src/objects/pmPSF.c	(revision 7311)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-04-23 01:07:51 $
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -97,5 +97,5 @@
     // the ApTrend components are (x, y, r2rflux, flux)
     psf->ApTrend = psPolynomial4DAlloc (PS_POLYNOMIAL_ORD, 2, 2, 1, 1);
-    pmPSF_MaskApTrend (psf, PM_PSF_SKYBIAS);
+    pmPSF_MaskApTrend (psf->ApTrend, PM_PSF_SKYBIAS);
 
     if (psf->poissonErrors) {
@@ -239,76 +239,77 @@
  * to enable the specific subset of the coefficients
  **********************************************/
-bool pmPSF_MaskApTrend (pmPSF *psf, pmPSF_ApTrendOptions option)
+bool pmPSF_MaskApTrend (psPolynomial4D *trend,
+                        pmPSF_ApTrendOptions option)
 {
 
     switch (option) {
     case PM_PSF_NONE:
-        maskAllTerms (psf->ApTrend);
+        maskAllTerms (trend);
         return true;
 
     case PM_PSF_CONSTANT:
-        maskAllTerms (psf->ApTrend);
-        psf->ApTrend->mask[0][0][0][0] = 0;  // unmask constant
+        maskAllTerms (trend);
+        trend->mask[0][0][0][0] = 0;  // unmask constant
         return true;
 
     case PM_PSF_SKYBIAS:
-        maskAllTerms (psf->ApTrend);
-        psf->ApTrend->mask[0][0][0][0] = 0;  // unmask constant
-        psf->ApTrend->mask[0][0][1][0] = 0;  // unmask skybias
+        maskAllTerms (trend);
+        trend->mask[0][0][0][0] = 0;  // unmask constant
+        trend->mask[0][0][1][0] = 0;  // unmask skybias
         return true;
 
     case PM_PSF_SKYSAT:
-        maskAllTerms (psf->ApTrend);
-        psf->ApTrend->mask[0][0][0][0] = 0;  // unmask constant
-        psf->ApTrend->mask[0][0][1][0] = 0;  // unmask skybias
-        psf->ApTrend->mask[0][0][0][1] = 0;  // unmask skybias
+        maskAllTerms (trend);
+        trend->mask[0][0][0][0] = 0;  // unmask constant
+        trend->mask[0][0][1][0] = 0;  // unmask skybias
+        trend->mask[0][0][0][1] = 0;  // unmask skysat
         return true;
 
     case PM_PSF_XY_LIN:
-        maskAllTerms (psf->ApTrend);
-        psf->ApTrend->mask[0][0][0][0] = 0;  // unmask constant
-        psf->ApTrend->mask[1][0][0][0] = 0;  // unmask x
-        psf->ApTrend->mask[0][1][0][0] = 0;  // unmask y
+        maskAllTerms (trend);
+        trend->mask[0][0][0][0] = 0;  // unmask constant
+        trend->mask[1][0][0][0] = 0;  // unmask x
+        trend->mask[0][1][0][0] = 0;  // unmask y
         return true;
 
     case PM_PSF_XY_QUAD:
-        maskAllTerms (psf->ApTrend);
-        psf->ApTrend->mask[0][0][0][0] = 0;  // unmask constant
-        psf->ApTrend->mask[1][0][0][0] = 0;  // unmask x
-        psf->ApTrend->mask[2][0][0][0] = 0;  // unmask x^2
-        psf->ApTrend->mask[1][1][0][0] = 0;  // unmask x y
-        psf->ApTrend->mask[0][1][0][0] = 0;  // unmask y
-        psf->ApTrend->mask[0][2][0][0] = 0;  // unmask y^2
+        maskAllTerms (trend);
+        trend->mask[0][0][0][0] = 0;  // unmask constant
+        trend->mask[1][0][0][0] = 0;  // unmask x
+        trend->mask[2][0][0][0] = 0;  // unmask x^2
+        trend->mask[1][1][0][0] = 0;  // unmask x y
+        trend->mask[0][1][0][0] = 0;  // unmask y
+        trend->mask[0][2][0][0] = 0;  // unmask y^2
         return true;
 
     case PM_PSF_SKY_XY_LIN:
-        maskAllTerms (psf->ApTrend);
-        psf->ApTrend->mask[0][0][0][0] = 0;  // unmask constant
-        psf->ApTrend->mask[1][0][0][0] = 0;  // unmask x
-        psf->ApTrend->mask[0][1][0][0] = 0;  // unmask y
-        psf->ApTrend->mask[0][0][1][0] = 0;  // unmask skybias
+        maskAllTerms (trend);
+        trend->mask[0][0][0][0] = 0;  // unmask constant
+        trend->mask[1][0][0][0] = 0;  // unmask x
+        trend->mask[0][1][0][0] = 0;  // unmask y
+        trend->mask[0][0][1][0] = 0;  // unmask skybias
         return true;
 
     case PM_PSF_SKYSAT_XY_LIN:
-        maskAllTerms (psf->ApTrend);
-        psf->ApTrend->mask[0][0][0][0] = 0;  // unmask constant
-        psf->ApTrend->mask[1][0][0][0] = 0;  // unmask x
-        psf->ApTrend->mask[0][1][0][0] = 0;  // unmask y
-        psf->ApTrend->mask[0][0][1][0] = 0;  // unmask skybias
-        psf->ApTrend->mask[0][0][0][1] = 0;  // unmask skysat
+        maskAllTerms (trend);
+        trend->mask[0][0][0][0] = 0;  // unmask constant
+        trend->mask[1][0][0][0] = 0;  // unmask x
+        trend->mask[0][1][0][0] = 0;  // unmask y
+        trend->mask[0][0][1][0] = 0;  // unmask skybias
+        trend->mask[0][0][0][1] = 0;  // unmask skysat
         return true;
 
     case PM_PSF_ALL:
     default:
-        maskAllTerms (psf->ApTrend);
-        psf->ApTrend->mask[0][0][0][0] = 0;  // unmask constant
-        psf->ApTrend->mask[0][0][1][0] = 0;  // unmask skybias
-        psf->ApTrend->mask[0][0][0][1] = 0;  // unmask skysat
-
-        psf->ApTrend->mask[1][0][0][0] = 0;  // unmask x
-        psf->ApTrend->mask[2][0][0][0] = 0;  // unmask x^2
-        psf->ApTrend->mask[1][1][0][0] = 0;  // unmask x y
-        psf->ApTrend->mask[0][1][0][0] = 0;  // unmask y
-        psf->ApTrend->mask[0][2][0][0] = 0;  // unmask y^2
+        maskAllTerms (trend);
+        trend->mask[0][0][0][0] = 0;  // unmask constant
+        trend->mask[0][0][1][0] = 0;  // unmask skybias
+        trend->mask[0][0][0][1] = 0;  // unmask skysat
+
+        trend->mask[1][0][0][0] = 0;  // unmask x
+        trend->mask[2][0][0][0] = 0;  // unmask x^2
+        trend->mask[1][1][0][0] = 0;  // unmask x y
+        trend->mask[0][1][0][0] = 0;  // unmask y
+        trend->mask[0][2][0][0] = 0;  // unmask y^2
         return true;
     }
Index: /trunk/psModules/src/objects/pmPSF.h
===================================================================
--- /trunk/psModules/src/objects/pmPSF.h	(revision 7310)
+++ /trunk/psModules/src/objects/pmPSF.h	(revision 7311)
@@ -31,6 +31,6 @@
     psArray *params;   ///< Model parameters (psPolynomial2D)
     psPolynomial1D *ChiTrend;  ///< Chisq vs flux fit (correction for systematic errors)
-    psPolynomial4D *ApTrend;  ///< ApResid vs (x,y,rflux) (rflux = ten(0.4*mInst)
-    pmGrowthCurve *growth;  ///< apMag vs Radius
+    psPolynomial4D *ApTrend;  ///< ApResid vs (x,y,rflux) (rflux = ten(0.4*mInst))
+    //pmGrowthCurve *growth;  ///< apMag vs Radius // move to end as gdb is confused by it here
     float ApResid;   ///< apMag - psfMag (for PSF stars)
     float dApResid;   ///< scatter of ApResid
@@ -41,4 +41,5 @@
     int nApResid;   ///< number of stars used to measure ApResid
     bool poissonErrors;
+    pmGrowthCurve *growth;  ///< apMag vs Radius
 }
 pmPSF;
@@ -100,5 +101,5 @@
 );
 
-bool pmPSF_MaskApTrend (pmPSF *psf, pmPSF_ApTrendOptions option);
+bool pmPSF_MaskApTrend (psPolynomial4D *trend, pmPSF_ApTrendOptions option);
 
 # endif
Index: /trunk/psModules/src/objects/pmPSF_IO.c
===================================================================
--- /trunk/psModules/src/objects/pmPSF_IO.c	(revision 7310)
+++ /trunk/psModules/src/objects/pmPSF_IO.c	(revision 7311)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-04-17 18:01:05 $
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -287,5 +287,5 @@
 {
 
-    int Nfail;
+    unsigned int Nfail;
     char *filename;
 
Index: /trunk/psModules/src/objects/pmPSFtry.c
===================================================================
--- /trunk/psModules/src/objects/pmPSFtry.c	(revision 7310)
+++ /trunk/psModules/src/objects/pmPSFtry.c	(revision 7311)
@@ -5,6 +5,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-02 02:16:05 $
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -263,5 +263,5 @@
     psLogMsg ("pmPSFtryMetric", 4, "fit stats: %f +/- %f\n", stats->sampleMedian, stats->sampleStdev);
 
-    pmPSF_MaskApTrend (psfTry->psf, PM_PSF_SKYBIAS);
+    pmPSF_MaskApTrend (psfTry->psf->ApTrend, PM_PSF_SKYBIAS);
     psfTry->psf->ApTrend->coeff[0][0][0][0] = poly->coeff[0];
     psfTry->psf->ApTrend->coeff[0][0][1][0] = 0;
Index: /trunk/psModules/src/objects/pmPSFtry.h
===================================================================
--- /trunk/psModules/src/objects/pmPSFtry.h	(revision 7310)
+++ /trunk/psModules/src/objects/pmPSFtry.h	(revision 7311)
@@ -6,4 +6,6 @@
  *  @author EAM, IfA
  *
+ *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -76,10 +78,5 @@
  * 
  */
-pmPSFtry *pmPSFtryAlloc(
-    psArray *stars,                     ///< Add comment.
-    char *modelName,                     ///< Add comment.
-    bool poissonErrors   // use poissonian or constant errors?
-);
-
+pmPSFtry *pmPSFtryAlloc (psArray *sources, char *modelName, bool poissonErrors);
 
 /** pmPSFtryModel()
@@ -90,11 +87,5 @@
  * 
  */
-pmPSFtry *pmPSFtryModel(
-    psArray *sources,                   ///< Add comment.
-    char *modelName,                    ///< Add comment.
-    float radius,                     ///< Add comment.
-    bool poissonErrors   // use poissonian or constant errors?
-);
-
+pmPSFtry *pmPSFtryModel (psArray *sources, char *modelName, float RADIUS, bool poissonErrors);
 
 /** pmPSFtryMetric()
Index: /trunk/psModules/src/objects/pmPeaks.c
===================================================================
--- /trunk/psModules/src/objects/pmPeaks.c	(revision 7310)
+++ /trunk/psModules/src/objects/pmPeaks.c	(revision 7311)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA: significant modifications.
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-04-21 21:26:44 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -94,4 +94,7 @@
 pmPeakAlloc(): Allocate the pmPeak data structure and set appropriate members.
 *****************************************************************************/
+static void peakFree(pmPeak *tmp)
+{} // used by pmIsPeak()
+
 pmPeak *pmPeakAlloc(psS32 x,
                     psS32 y,
@@ -100,5 +103,7 @@
 {
     psTrace(__func__, 3, "---- %s() begin ----\n", __func__);
+    static int id = 1;
     pmPeak *tmp = (pmPeak *) psAlloc(sizeof(pmPeak));
+    *(int *)&tmp->id = id++;
     tmp->x = x;
     tmp->y = y;
@@ -106,6 +111,13 @@
     tmp->type = type;
 
+    psMemSetDeallocator(tmp, (psFreeFunc) peakFree);
+
     psTrace(__func__, 3, "---- %s() end ----\n", __func__);
     return(tmp);
+}
+
+bool pmIsPeak(const psPtr ptr)
+{
+    return (psMemGetDeallocator(ptr) == (psFreeFunc)peakFree);
 }
 
Index: /trunk/psModules/src/objects/pmPeaks.h
===================================================================
--- /trunk/psModules/src/objects/pmPeaks.h	(revision 7310)
+++ /trunk/psModules/src/objects/pmPeaks.h	(revision 7311)
@@ -10,6 +10,6 @@
  *  @author GLG, MHPCC
  *
- *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-04-17 18:01:05 $
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -47,4 +47,5 @@
 typedef struct
 {
+    const int id;   ///< Unique ID for object
     int x;                              ///< X-coordinate of peak pixel.
     int y;                              ///< Y-coordinate of peak pixel.
@@ -66,4 +67,5 @@
 );
 
+bool pmIsPeak(const psPtr ptr);
 
 /** pmFindVectorPeaks()
Index: /trunk/psModules/src/objects/pmSource.c
===================================================================
--- /trunk/psModules/src/objects/pmSource.c	(revision 7310)
+++ /trunk/psModules/src/objects/pmSource.c	(revision 7311)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA: significant modifications.
  *
- *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-02 02:16:05 $
+ *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -46,5 +46,7 @@
 {
     psTrace(__func__, 3, "---- %s() begin ----\n", __func__);
+    static int id = 1;
     pmSource *tmp = (pmSource *) psAlloc(sizeof(pmSource));
+    *(int *)&tmp->id = id++;
     tmp->peak = NULL;
     tmp->pixels = NULL;
@@ -69,4 +71,9 @@
 }
 
+bool pmIsSource(const psPtr ptr)
+{
+    return (psMemGetDeallocator(ptr) == (psFreeFunc)sourceFree);
+}
+
 // x,y are defined in the parent image coords of readout->image
 bool pmSourceDefinePixels(pmSource *mySource,
@@ -82,7 +89,7 @@
     srcRegion = psRegionForImage (readout->image, srcRegion);
 
-    mySource->pixels = psImageSubset(readout->image, srcRegion);
-    mySource->weight = psImageSubset(readout->weight, srcRegion);
-    mySource->mask   = psImageSubset(readout->mask,  srcRegion);
+    mySource->pixels = psMemIncrRefCounter(psImageSubset(readout->image, srcRegion));
+    mySource->weight = psMemIncrRefCounter(psImageSubset(readout->weight, srcRegion));
+    mySource->mask   = psMemIncrRefCounter(psImageSubset(readout->mask,  srcRegion));
     mySource->region = srcRegion;
 
@@ -123,7 +130,7 @@
         psFree (mySource->mask);
 
-        mySource->pixels = psImageSubset(readout->image,  newRegion);
-        mySource->weight = psImageSubset(readout->weight, newRegion);
-        mySource->mask   = psImageSubset(readout->mask,   newRegion);
+        mySource->pixels = psMemIncrRefCounter(psImageSubset(readout->image,  newRegion));
+        mySource->weight = psMemIncrRefCounter(psImageSubset(readout->weight, newRegion));
+        mySource->mask   = psMemIncrRefCounter(psImageSubset(readout->mask,   newRegion));
         mySource->region = newRegion;
     }
Index: /trunk/psModules/src/objects/pmSource.h
===================================================================
--- /trunk/psModules/src/objects/pmSource.h	(revision 7310)
+++ /trunk/psModules/src/objects/pmSource.h	(revision 7311)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA; GLG, MHPCC
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-04-19 20:29:57 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -73,4 +73,5 @@
 typedef struct
 {
+    const int id;   ///< Unique ID for object
     pmPeak *peak;   ///< Description of peak pixel.
     psImage *pixels;   ///< Rectangular region including object pixels.
@@ -114,4 +115,5 @@
 pmSource  *pmSourceAlloc();
 
+bool pmIsSource(const psPtr ptr);
 
 /** pmSourceDefinePixels()
Index: /trunk/psModules/src/objects/pmSourceFitModel.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceFitModel.c	(revision 7310)
+++ /trunk/psModules/src/objects/pmSourceFitModel.c	(revision 7311)
@@ -6,6 +6,6 @@
  *  @author GLG, MHPCC
  *
- *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-04-23 01:07:51 $
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -515,4 +515,7 @@
     psTrace (__func__, 5, "fitting function\n");
     fitStatus = psMinimizeLMChi2(myMin, covar, params, constrain, x, y, yErr, pmModelFitSet);
+    if (!fitStatus) {
+        psError(PS_ERR_UNKNOWN, false, "Failed to fit model\n");
+    }
 
     // parameter errors from the covariance matrix
Index: /trunk/psModules/src/objects/pmSourceIO.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO.c	(revision 7310)
+++ /trunk/psModules/src/objects/pmSourceIO.c	(revision 7311)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-03 00:40:28 $
+ *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -57,5 +57,5 @@
 }
 
-// Given a FITS file pointer, read the table of object data
+// Given a FITS file pointer, write the table of object data
 bool pmFPAviewWriteObjects (const pmFPAview *view, pmFPAfile *file)
 {
@@ -64,9 +64,13 @@
 
     if (view->chip == -1) {
-        pmFPAWriteObjects (fpa, view, file);
+        if (!pmFPAWriteObjects (fpa, view, file)) {
+            psError(PS_ERR_IO, false, "Failed to write objects from fpa");
+            return false;
+        }
         return true;
     }
 
     if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_UNKNOWN, false, "Writing chip == %d (>= chips->n == %d)", view->chip, fpa->chips->n);
         return false;
     }
@@ -74,9 +78,14 @@
 
     if (view->cell == -1) {
-        pmChipWriteObjects (chip, view, file);
+        if (!pmChipWriteObjects (chip, view, file)) {
+            psError(PS_ERR_IO, false, "Failed to write objects from chip");
+            return false;
+        }
         return true;
     }
 
     if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_UNKNOWN, false, "Writing cell == %d (>= cells->n == %d)",
+                view->cell, chip->cells->n);
         return false;
     }
@@ -84,14 +93,24 @@
 
     if (view->readout == -1) {
-        pmCellWriteObjects (cell, view, file);
+        if (!pmCellWriteObjects (cell, view, file)) {
+            psError(PS_ERR_IO, false, "Failed to write objects from cell");
+            return false;
+        }
+
         return true;
     }
 
     if (view->readout >= cell->readouts->n) {
+        psError(PS_ERR_UNKNOWN, false, "Writing readout == %d (>= readouts->n == %d)",
+                view->readout, cell->readouts->n);
         return false;
     }
     pmReadout *readout = cell->readouts->data[view->readout];
 
-    pmReadoutWriteObjects (readout, view, file);
+    if (!pmReadoutWriteObjects (readout, view, file)) {
+        psError(PS_ERR_IO, false, "Failed to write objects from readout %d", view->readout);
+        return false;
+    }
+
     return true;
 }
@@ -104,5 +123,8 @@
 
         pmChip *chip = fpa->chips->data[i];
-        pmChipWriteObjects (chip, view, file);
+        if (!pmChipWriteObjects (chip, view, file)) {
+            psError(PS_ERR_IO, false, "Failed to write %dth chip", i);
+            return false;
+        }
     }
     return true;
@@ -116,5 +138,8 @@
 
         pmCell *cell = chip->cells->data[i];
-        pmCellWriteObjects (cell, view, file);
+        if (!pmCellWriteObjects (cell, view, file)) {
+            psError(PS_ERR_IO, false, "Failed to write %dth cell", i);
+            return false;
+        }
     }
     return true;
@@ -128,5 +153,8 @@
 
         pmReadout *readout = cell->readouts->data[i];
-        pmReadoutWriteObjects (readout, view, file);
+        if (!pmReadoutWriteObjects (readout, view, file)) {
+            psError(PS_ERR_IO, false, "Failed to write %dth readout", i);
+            return false;
+        }
     }
     return true;
@@ -181,7 +209,12 @@
         psMetadataCopy (outhead, updates);
 
-        pmSourcesWriteCMP (sources, filename, outhead);
+        bool status = pmSourcesWriteCMP (sources, filename, outhead);
         psFree (outhead);
         psFree (filename);
+
+        if (!status) {
+            psError(PS_ERR_IO, false, "Failed to write CMP file\n");
+            return false;
+        }
         break;
 
Index: /trunk/psModules/src/objects/pmSourceIO_CMP.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO_CMP.c	(revision 7310)
+++ /trunk/psModules/src/objects/pmSourceIO_CMP.c	(revision 7311)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-03 00:40:46 $
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-03 01:02:08 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -69,11 +69,29 @@
 
     psFits *fits = psFitsOpen (filename, "w");
-    psFitsWriteBlank(fits, header);
-    psFitsClose (fits);
+    if (fits == NULL) {
+        psError(PS_ERR_IO, false, "can't open output file for write %s\n", filename);
+        return false;
+    }
+    if (!psFitsWriteBlank(fits, header)) {
+        psError(PS_ERR_IO, false, "Writing header to %s\n", filename);
+        (void)psFitsClose(fits);
+        return false;
+    }
+    if (!psFitsClose(fits)) {
+        const psErrorCode code = psErrorCodeLast();
+
+        if (code == PS_ERR_BAD_FITS) {
+            psErrorClear();
+        } else {
+            psError(PS_ERR_IO, false, "Closing %s\n", filename);
+            return false;
+        }
+    }
 
     // re-open, add data to end of file
     FILE *f = fopen (filename, "a+");
     if (f == NULL) {
-        psLogMsg ("WriteSourceOBJ", 3, "can't open output file for output %s\n", filename);
+        psLogMsg ("WriteSourceOBJ", 3, "can't reopen output file for append %s\n", filename);
+        psError(PS_ERR_IO, false, "can't open output file for output %s\n", filename);
         return false;
     }
Index: /trunk/psModules/src/pslib/psAdditionals.c
===================================================================
--- /trunk/psModules/src/pslib/psAdditionals.c	(revision 7310)
+++ /trunk/psModules/src/pslib/psAdditionals.c	(revision 7311)
@@ -68,5 +68,5 @@
         fits_get_errstatus (status, fitsErr);
         psError (PS_ERR_IO, true, PS_ERRORTEXT_psFits_WRITE_FAILED, fitsErr);
-        exit (2);
+        return false;
     }
 
Index: /trunk/psModules/src/pslib/psImageUnbin.c
===================================================================
--- /trunk/psModules/src/pslib/psImageUnbin.c	(revision 7310)
+++ /trunk/psModules/src/pslib/psImageUnbin.c	(revision 7311)
@@ -143,5 +143,5 @@
         }
         // Nx,Ny
-        V = vIn[nx-1][ny-1];
+        V = vIn[ny-1][nx-1];
         for (int iy = ny*DY - dy; iy < Ny; iy++)
         {
@@ -161,11 +161,15 @@
 static int MAX_SAMPLE_PIXELS;
 
-void psImageClippedStatsInit (int nMax)
+void psImageClippedStatsInit (int nMax, unsigned long seed)
 {
 
     MAX_SAMPLE_PIXELS = nMax;
 
+    if (rnd && seed) {
+        psFree(rnd);
+        rnd = NULL;
+    }
     if (!rnd) {
-        rnd = psRandomAlloc (PS_RANDOM_TAUS, 0);
+        rnd = psRandomAlloc (PS_RANDOM_TAUS, seed);
     }
     return;
Index: /trunk/psModules/src/pslib/psImageUnbin.h
===================================================================
--- /trunk/psModules/src/pslib/psImageUnbin.h	(revision 7310)
+++ /trunk/psModules/src/pslib/psImageUnbin.h	(revision 7311)
@@ -7,5 +7,5 @@
 psImage *psImageUnbin (psImage *out, psImage *in, int DX, int DY, int dx, int dy);
 
-void psImageClippedStatsInit (int nMax);
+void psImageClippedStatsInit (int nMax, unsigned long seed);
 void psImageClippedStatsCleanup ();
 
Index: /trunk/psModules/src/pslib/psMetadataItemParse.c
===================================================================
--- /trunk/psModules/src/pslib/psMetadataItemParse.c	(revision 7310)
+++ /trunk/psModules/src/pslib/psMetadataItemParse.c	(revision 7311)
@@ -228,5 +228,5 @@
     return value; } \
 
-psString psMetadataItemParseString(psMetadataItem *item
+psString psMetadataItemParseString(const psMetadataItem *item
                                   )
 {
Index: /trunk/psModules/src/pslib/psMetadataItemParse.h
===================================================================
--- /trunk/psModules/src/pslib/psMetadataItemParse.h	(revision 7310)
+++ /trunk/psModules/src/pslib/psMetadataItemParse.h	(revision 7311)
@@ -4,18 +4,18 @@
 #include "pslib.h"
 
-psBool psMetadataItemParseBool(psMetadataItem *item);
+psBool psMetadataItemParseBool(const psMetadataItem *item);
 
-psF32 psMetadataItemParseF32(psMetadataItem *item);
-psF64 psMetadataItemParseF64(psMetadataItem *item);
+psF32 psMetadataItemParseF32(const psMetadataItem *item);
+psF64 psMetadataItemParseF64(const psMetadataItem *item);
 
-psS8  psMetadataItemParseS8 (psMetadataItem *item);
-psS16 psMetadataItemParseS16(psMetadataItem *item);
-psS32 psMetadataItemParseS32(psMetadataItem *item);
+psS8  psMetadataItemParseS8 (const psMetadataItem *item);
+psS16 psMetadataItemParseS16(const psMetadataItem *item);
+psS32 psMetadataItemParseS32(const psMetadataItem *item);
 
-psU8  psMetadataItemParseU8 (psMetadataItem *item);
-psU16 psMetadataItemParseU16(psMetadataItem *item);
-psU32 psMetadataItemParseU32(psMetadataItem *item);
+psU8  psMetadataItemParseU8 (const psMetadataItem *item);
+psU16 psMetadataItemParseU16(const psMetadataItem *item);
+psU32 psMetadataItemParseU32(const psMetadataItem *item);
 
-psString psMetadataItemParseString(psMetadataItem *item);
+psString psMetadataItemParseString(const psMetadataItem *item);
 
 #endif
