Index: trunk/pswarp/src/pswarpDataSave.c
===================================================================
--- trunk/pswarp/src/pswarpDataSave.c	(revision 12771)
+++ trunk/pswarp/src/pswarpDataSave.c	(revision 13104)
@@ -1,3 +1,4 @@
-# include "pswarp.h"
+#include <ppStats.h>
+#include "pswarp.h"
 
 // this loop loads the data from the input files and selects the
@@ -7,5 +8,5 @@
 
 // all of the different astrometry analysis modes use the same data load loop
-bool pswarpDataSave (pmConfig *config) {
+bool pswarpDataSave(pmConfig *config) {
 
     pmChip *chip;
@@ -18,4 +19,17 @@
         psError(PSWARP_ERR_CONFIG, true, "Can't find input data!\n");
         return false;
+    }
+
+    bool mdok;                          // Status of MD lookup
+    const char *statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS"); // Filename for statistics
+    psMetadata *stats = NULL;           // Container for statistics
+    FILE *statsFile = NULL;             // File stream for statistics
+    if (mdok && statsName && strlen(statsName) > 0) {
+        statsFile = fopen(statsName, "w");
+        if (!statsFile) {
+            psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.\n", statsName);
+            return false;
+        }
+        stats = psMetadataAlloc();
     }
 
@@ -40,10 +54,40 @@
             pmFPAfileIOChecks (config, view, PM_FPA_BEFORE);
 
-            // process each of the readouts
-            while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
+            // Perform statistics on the cell
+            if (stats) {
+                bool mdok;              // Status of MD lookup
+                pmFPAfile *output = psMetadataLookupPtr(&mdok, config->files, "PSWARP.OUTPUT");
+                if (!mdok || !output) {
+                    psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find file PSWARP.OUTPUT.\n");
+                    psFree(view);
+                    psFree(stats);
+                    return false;
+                }
+                ppStats(stats, output->fpa, view, config);
+            }
+
+            pmHDU *hdu = pmHDUFromCell(cell); // HDU that owns the cell
+
+            // Process readouts
+            while ((readout = pmFPAviewNextReadout(view, input->fpa, 1)) != NULL) {
                 pmFPAfileIOChecks (config, view, PM_FPA_BEFORE);
-                if (! readout->data_exists) { continue; }
+                if (!readout->data_exists) {
+                    continue;
+                }
 
                 // pswarpConvertReadout (readout, config);
+
+                // Add MD5 information for readout
+                const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME");
+                const char *cellName = psMetadataLookupStr(NULL, cell->concepts, "CELL.NAME");
+                psString headerName = NULL; // Header name for MD5
+                psStringAppend(&headerName, "MD5_%s_%s_%d", chipName, cellName, view->readout);
+                psVector *md5 = psImageMD5(readout->image); // md5 hash
+                psString md5string = psMD5toString(md5); // String
+                psFree(md5);
+                psMetadataAddStr(hdu->header, PS_LIST_TAIL, headerName, PS_META_REPLACE,
+                                 "Image MD5", md5string);
+                psFree(md5string);
+                psFree(headerName);
 
                 pmFPAfileIOChecks (config, view, PM_FPA_AFTER);
@@ -59,4 +103,20 @@
     pmFPAfileActivate (config->files, true, NULL);
 
+    // Write out summary statistics
+    if (stats) {
+        const char *statsMDC = psMetadataConfigFormat(stats);
+        if (!statsMDC || strlen(statsMDC) == 0) {
+            psError(PS_ERR_IO, false, "Unable to get statistics MDC file.\n");
+            psFree(stats);
+            fclose(statsFile);
+            return false;
+        }
+        fprintf(statsFile, "%s", statsMDC);
+        psFree((void*)statsMDC);
+        fclose(statsFile);
+
+        psFree(stats);
+    }
+
     return true;
 }
