Index: trunk/pswarp/src/Makefile.am
===================================================================
--- trunk/pswarp/src/Makefile.am	(revision 12995)
+++ trunk/pswarp/src/Makefile.am	(revision 13104)
@@ -1,30 +1,23 @@
-
-lib_LTLIBRARIES = libpswarp.la
-libpswarp_la_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSWARP_CFLAGS)
-
 bin_PROGRAMS = pswarp
-pswarp_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSWARP_CFLAGS)
-pswarp_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) $(PSWARP_LIBS)
-pswarp_LDADD = libpswarp.la
+pswarp_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PPSTATS_CFLAGS) $(PSWARP_CFLAGS)
+pswarp_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) $(PPSTATS_LIBS) $(PSWARP_LIBS)
 
 pswarp_SOURCES = \
-	pswarp.c		
+	pswarp.c			\
+	pswarpArguments.c		\
+	pswarpCleanup.c			\
+	pswarpDataLoad.c		\
+	pswarpDataSave.c		\
+	pswarpDefine.c			\
+	pswarpDefineSkycell.c		\
+	pswarpErrorCodes.c		\
+	pswarpMapGrid.c			\
+	pswarpMatchRange.c		\
+	pswarpParseCamera.c		\
+	pswarpTransformReadout.c	\
+	pswarpTransformReadout_Opt.c	\
+	pswarpVersion.c            
 
-libpswarp_la_SOURCES = \
-pswarpArguments.c	   \
-pswarpCleanup.c            \
-pswarpDataLoad.c           \
-pswarpDataSave.c           \
-pswarpDefine.c             \
-pswarpDefineSkycell.c      \
-pswarpErrorCodes.c         \
-pswarpMapGrid.c            \
-pswarpMatchRange.c         \
-pswarpParseCamera.c   	   \
-pswarpTransformReadout.c   \
-pswarpTransformReadout_Opt.c \
-pswarpVersion.c            
-
-include_HEADERS = \
+noinst_HEADERS = \
 	pswarp.h \
 	pswarpErrorCodes.h
Index: trunk/pswarp/src/pswarpArguments.c
===================================================================
--- trunk/pswarp/src/pswarpArguments.c	(revision 12995)
+++ trunk/pswarp/src/pswarpArguments.c	(revision 13104)
@@ -26,8 +26,17 @@
 
     // chip selection is used to limit chips to be processed
-    if ((N = psArgumentGet (argc, argv, "-chip"))) {
-        psArgumentRemove (N, &argc, argv);
-        psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CHIP_SELECTIONS", PS_DATA_STRING, "", argv[N]);
-        psArgumentRemove (N, &argc, argv);
+    if ((N = psArgumentGet(argc, argv, "-chip"))) {
+        psArgumentRemove(N, &argc, argv);
+        psMetadataAddStr(config->arguments, PS_LIST_TAIL, "CHIP_SELECTIONS", PS_DATA_STRING,
+                         "Only process these chips", argv[N]);
+        psArgumentRemove(N, &argc, argv);
+    }
+
+    // Statistics file
+    if ((N = psArgumentGet(argc, argv, "-stat"))) {
+        psArgumentRemove(N, &argc, argv);
+        psMetadataAddStr(config->arguments, PS_LIST_TAIL, "STATS", PS_DATA_STRING,
+                         "Filename for statistics of output image", argv[N]);
+        psArgumentRemove(N, &argc, argv);
     }
 
Index: trunk/pswarp/src/pswarpDataSave.c
===================================================================
--- trunk/pswarp/src/pswarpDataSave.c	(revision 12995)
+++ 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;
 }
