Index: trunk/ppStats/src/ppStatsLoop.c
===================================================================
--- trunk/ppStats/src/ppStatsLoop.c	(revision 13607)
+++ trunk/ppStats/src/ppStatsLoop.c	(revision 13640)
@@ -68,13 +68,14 @@
 
 
-static void cellStats(psMetadata *chipResults, // Metadata holding the chip results
-                      pmCell *cell,     // Cell for which to get statistics
-                      psFits *fits,     // FITS file handle
-                      ppStatsData *data,// The data
-                      const pmConfig *config // Configuration
+static psExit cellStats(psMetadata *chipResults, // Metadata holding the chip results
+			pmCell *cell,     // Cell for which to get statistics
+			psFits *fits,     // FITS file handle
+			ppStatsData *data,// The data
+			const pmConfig *config // Configuration
     )
 {
     assert(chipResults);
     assert(cell);
+    assert(fits);
     assert(data);
     assert(config);
@@ -84,5 +85,5 @@
     // Check to see if this is a cell of interest
     if (!doThis(data->cells, cellName)) {
-        return;
+        return PS_EXIT_SUCCESS;
     }
 
@@ -95,6 +96,7 @@
 
     if (psListLength(data->headers) > 0 && cell->hdu) {
-        if (fits && !pmCellReadHeader(cell, fits)) {
-            goto cellDone;
+        if (!pmCellReadHeader(cell, fits)) {
+            psError (PS_ERR_IO, false, "trouble reading cell header\n");
+	    return PS_EXIT_DATA_ERROR;
         }
         pmHDU *hdu = cell->hdu;     // HDU for headers
@@ -102,6 +104,7 @@
     }
     if (psListLength(data->concepts) > 0) {
-        if (fits && !pmCellReadHeader(cell, fits)) {
-            goto cellDone;
+        if (!pmCellReadHeader(cell, fits)) {
+            psError (PS_ERR_IO, false, "trouble reading cell header\n");
+	    return PS_EXIT_DATA_ERROR;
         }
         pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_ALL, false, config->database);
@@ -120,14 +123,16 @@
     pmHDU *hdu = pmHDUFromCell(cell); // HDU for cell
     if (!hdu || hdu->blankPHU) {
-        goto cellDone;
-    }
-
-    if (fits && !pmCellRead(cell, fits, config->database)) {
-        psLogMsg(__func__, PS_LOG_WARN, "Unable to read cell %s\n", cellName);
-        goto cellDone;
+	psError (PS_ERR_UNKNOWN, false, "trouble finding HDU for cell\n");
+	return PS_EXIT_CONFIG_ERROR;
+    }
+
+    if (!pmCellRead(cell, fits, config->database)) {
+	psError (PS_ERR_IO, false, "trouble reading cell data\n");
+	return PS_EXIT_DATA_ERROR;
     }
 
     psArray *readouts = cell->readouts; // Array of component readouts
     if (readouts->n == 0) {
+        psLogMsg(__func__, PS_LOG_WARN, "No readouts present in cell %s --- skipping\n", cellName);
         goto cellDone;
     }
@@ -138,6 +143,5 @@
     pmReadout *readout = readouts->data[0]; // The readout of interest
     if (!readout->image) {
-        psLogMsg(__func__, PS_LOG_WARN, "No image associated with readout in cell %s --- "
-                 "ignored.\n", cellName);
+        psLogMsg(__func__, PS_LOG_WARN, "No image associated with readout in cell %s --- ignored.\n", cellName);
         goto cellDone;
     }
@@ -146,6 +150,5 @@
     if (data->sample <= 0.0) {
         if (!psImageStats(data->stats, readout->image, readout->mask, data->maskVal)) {
-            psLogMsg(__func__, PS_LOG_WARN, "Unable to perform statistics on cell %s --- "
-                     "ignored.\n", cellName);
+            psLogMsg(__func__, PS_LOG_WARN, "Unable to perform statistics on cell %s --- ignored.\n", cellName);
             goto statsDone;
         }
@@ -216,5 +219,7 @@
         }
 
-	if (!get_nSatPixels && !get_fSatPixels) goto cellDone;
+	if (!get_nSatPixels && !get_fSatPixels) {
+	    goto cellDone;
+	}
 
 	// Get the "concepts" of interest
@@ -222,4 +227,6 @@
 	if (!mdok || isnan(saturation)) {
 	    psLogMsg(__func__, PS_LOG_WARN, "CELL.SATURATION is not set --- unable to measure N_SAT_PIXELS.\n");
+	    if (get_nSatPixels) psMetadataAddS32(cellResults, PS_LIST_TAIL, "SAT_PIXEL_NUM", 0, NULL, 0);
+	    if (get_fSatPixels) psMetadataAddF32(cellResults, PS_LIST_TAIL, "SAT_PIXEL_FRAC", 0, NULL, NAN);
 	    goto cellDone;
 	}
@@ -240,29 +247,30 @@
     // Add the cell results to the chip
     addToHierarchy(cellResults, chipResults, cellName, "Results for cell");
-    if (fits) {
-        pmCellFreeData(cell);
-    }
-    return;
-}
-
-static bool chipStats(psMetadata *fpaResults, // Metadata holding the fpa results
-                      pmChip *chip,     // Chip for which to get statistics
-                      psFits *fits,     // FITS file handle
-                      pmFPAview *view,  // View for analysis
-                      ppStatsData *data,// The data
-                      const pmConfig *config // Configuration
+    pmCellFreeData(cell);
+    return PS_EXIT_SUCCESS;
+}
+
+static psExit chipStats(psMetadata *fpaResults, // Metadata holding the fpa results
+			pmChip *chip,     // Chip for which to get statistics
+			psFits *fits,     // FITS file handle
+			pmFPAview *view,  // View for analysis
+			ppStatsData *data,// The data
+			const pmConfig *config // Configuration
     )
 {
     assert(fpaResults);
     assert(chip);
+    assert(fits);
     assert(view);
     assert(data);
     assert(config);
 
+    psExit result = PS_EXIT_SUCCESS;
+
     const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME"); // Name of chip
 
     // Check to see if this is a chip of interest
     if (!doThis(data->chips, chipName)) {
-        return true;
+        return PS_EXIT_SUCCESS;
     }
 
@@ -271,5 +279,5 @@
         psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Desired cell view (%d) doesn't match "
                 "number of cells (%ld)\n", view->cell, cells->n);
-        return false;
+	return PS_EXIT_CONFIG_ERROR;
     }
 
@@ -282,6 +290,7 @@
 
     if (psListLength(data->headers) > 0 && chip->hdu) {
-        if (fits && !pmChipReadHeader(chip, fits)) {
-            goto chipDone;
+        if (!pmChipReadHeader(chip, fits)) {
+            psError (PS_ERR_IO, false, "trouble reading chip header\n");
+	    return PS_EXIT_DATA_ERROR;
         }
         pmHDU *hdu = chip->hdu;     // HDU for headers
@@ -289,6 +298,7 @@
     }
     if (psListLength(data->concepts) > 0) {
-        if (fits && !pmChipReadHeader(chip, fits)) {
-            goto chipDone;
+        if (!pmChipReadHeader(chip, fits)) {
+            psError (PS_ERR_IO, false, "trouble reading chip header\n");
+	    return PS_EXIT_DATA_ERROR;
         }
         pmConceptsReadChip(chip, PM_CONCEPT_SOURCE_ALL, false, false, config->database);
@@ -298,6 +308,13 @@
     if (view->cell >= 0) {
         pmCell *cell = cells->data[view->cell]; // Cell of interest
-        cellStats(chipResults, cell, fits, data, config);
-        goto chipDone;
+        result = cellStats(chipResults, cell, fits, data, config);
+	if (result != PS_EXIT_SUCCESS) {
+	    psError (PS_ERR_IO, false, "trouble with cell stats for %d\n", view->cell);
+	    pmChipFreeData(chip);
+	    return result;
+	}
+	addToHierarchy(chipResults, fpaResults, chipName, "Results for chip");
+	pmChipFreeData(chip);
+	return PS_EXIT_SUCCESS;
     }
 
@@ -305,18 +322,19 @@
     for (int i = 0; i < cells->n; i++) {
         pmCell *cell = cells->data[i];  // Cell of interest
-        cellStats(chipResults, cell, fits, data, config);
-    }
-
-chipDone:
+        result = cellStats(chipResults, cell, fits, data, config);
+	if (result != PS_EXIT_SUCCESS) {
+	    psError (PS_ERR_IO, false, "trouble with cell stats for %d\n", i);
+	    pmChipFreeData(chip);
+	    return result;
+	}
+    }
+
     addToHierarchy(chipResults, fpaResults, chipName, "Results for chip");
-    if (fits) {
-        pmChipFreeData(chip);
-    }
-
-    return true;
-}
-
-
-psMetadata *ppStatsLoop(psMetadata *fpaResults, // Metadata to hold the FPA results
+    pmChipFreeData(chip);
+    return PS_EXIT_SUCCESS;
+}
+
+psMetadata *ppStatsLoop(psExit *result,
+			psMetadata *fpaResults, // Metadata to hold the FPA results
                         ppStatsData *data, // The data
                         const pmConfig *config // Configuration
@@ -327,28 +345,27 @@
     psFits *fits = data->fits;          // FITS file handle
     PS_ASSERT_PTR_NON_NULL(fpa, NULL);
-
-    pmFPAview *view = psMemIncrRefCounter(data->view); // View for analysis
-    if (!view) {
-        view = pmFPAviewAlloc(0);
-    }
-
-    if (!fpaResults) {
-        fpaResults = psMetadataAlloc();
+    PS_ASSERT_PTR_NON_NULL(fits, NULL);
+
+    *result = PS_EXIT_SUCCESS;
+
+    // allocate or bump the ref counter (so we can just free below)
+    pmFPAview *view = (data->view) ? psMemIncrRefCounter(data->view) : pmFPAviewAlloc(0);
+
+    // allocate a new one if needed
+    psMetadata *newResults = psMemIncrRefCounter(fpaResults);
+    if (!newResults) {
+	newResults = psMetadataAlloc();
     }
 
     // Iterate through the FPA
     if (psListLength(data->headers) > 0 && fpa->hdu) {
-        if (fits) {
-            pmFPAReadHeader(fpa, fits);
-        }
+	pmFPAReadHeader(fpa, fits);
         pmHDU *hdu = fpa->hdu;          // HDU for headers
-        getMetadata(fpaResults, hdu->header, data->headers);
+        getMetadata(newResults, hdu->header, data->headers);
     }
     if (psListLength(data->concepts) > 0) {
-        if (fits) {
-            pmFPAReadHeader(fpa, fits);
-        }
+	pmFPAReadHeader(fpa, fits);
         pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_ALL, false, config->database);
-        getMetadata(fpaResults, fpa->concepts, data->concepts);
+        getMetadata(newResults, fpa->concepts, data->concepts);
     }
 
@@ -356,6 +373,14 @@
     if (view->chip >= 0) {
         pmChip *chip = chips->data[view->chip]; // Chip of interest
-        chipStats(fpaResults, chip, fits, view, data, config);
-        goto fpaDone;
+	*result = chipStats(newResults, chip, fits, view, data, config);
+        if (*result != PS_EXIT_SUCCESS) {
+	    psError(PS_ERR_UNKNOWN, false, "trouble with stats for cell %d\n", view->cell);
+	    psFree (view);
+	    psFree (newResults);
+	    return NULL;
+	}
+	pmFPAFreeData(fpa);
+	psFree(view);
+	return newResults;
     }
 
@@ -363,13 +388,15 @@
     for (int i = 0; i < chips->n; i++) {
         pmChip *chip = chips->data[i];  // Chip of interest
-        chipStats(fpaResults, chip, fits, view, data, config);
-    }
-
-fpaDone:
-    if (fits) {
-        pmFPAFreeData(fpa);
-    }
+        *result = chipStats(newResults, chip, fits, view, data, config);
+	if (*result != PS_EXIT_SUCCESS) {
+	    psError(PS_ERR_UNKNOWN, false, "trouble with stats for chip %d\n", i);
+	    psFree (view);
+	    psFree (newResults);
+	    return NULL;
+	}
+    }
+
+    pmFPAFreeData(fpa);
     psFree(view);
-
-    return fpaResults;
-}
+    return newResults;
+}
