Index: branches/simmosaic_branches/pswarp/src/pswarp.c
===================================================================
--- branches/simmosaic_branches/pswarp/src/pswarp.c	(revision 24860)
+++ branches/simmosaic_branches/pswarp/src/pswarp.c	(revision 27839)
@@ -11,15 +11,6 @@
  */
 
-# include "pswarp.h"
-
-static void usage (void) {
-    fprintf(stderr, "USAGE: pswarp [-file image(s)] [-list imagelist] [options] (output) (skycell)\n");
-    fprintf(stderr, "  options:\n");
-    fprintf(stderr, "    [-astrom astrom.cmp] : provide an alternative astrometry calibration\n");
-    fprintf(stderr, "    [-mask mask.fits] : provide a corresponding mask image\n");
-    fprintf(stderr, "    [-variance variance.fits] : provide a corresponding variance image\n");
-    psErrorStackPrint(stderr, "\n");
-    exit (2);
-}
+#include "pswarp.h"
+#include "pswarpFileNames.h"
 
 int main (int argc, char **argv)
@@ -28,14 +19,15 @@
 
     psLibInit(NULL);
-
-    // model inits are needed in pmSourceIO
-    // models defined in psphot/src/models are not available in psastro
     pmModelClassInit();
-
-    // init various psphot pieces (errors, models, threads)
     psphotInit();
 
+    const char *statsName = NULL;       // Filename for statistics
+    psMetadata *stats = NULL;           // Container for statistics
+    FILE *statsFile = NULL;             // File stream for statistics
+
     pmConfig *config = pswarpArguments(argc, argv);
-    if (!config) usage();
+    if (!config) {
+        goto DIE;
+    }
 
     pswarpVersionPrint();
@@ -43,28 +35,100 @@
     // load identify the data sources
     if (!pswarpParseCamera(config)) {
-        psErrorStackPrint(stderr, "error setting up the camera\n");
-        exit(PS_EXIT_CONFIG_ERROR);
+        goto DIE;
     }
 
     if (!pswarpOptions(config)) {
-        psErrorStackPrint(stderr, "error parsing options\n");
-        exit(PS_EXIT_SYS_ERROR);
+        goto DIE;
     }
 
     // load the skycell layout information
     if (!pswarpDefine(config)) {
-        psErrorStackPrint(stderr, "error loading output definition\n");
-        exit(PS_EXIT_CONFIG_ERROR);
+        goto DIE;
+    }
+
+    // Open the statistics file
+    bool mdok;                          ///< Status of MD lookup
+    statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS"); ///< Filename for statistics
+    if (mdok && statsName && strlen(statsName) > 0) {
+        psString resolved = pmConfigConvertFilename(statsName, config, true, true);
+        statsFile = fopen(resolved, "w");
+        if (!statsFile) {
+            psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.\n", resolved);
+            psFree(resolved);
+            goto DIE;
+        }
+        psFree(resolved);
+        stats = psMetadataAlloc();
+        psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", 0, "No problems", 0);
     }
 
     // load and warp
-    if (!pswarpLoop(config)) {
-        psErrorStackPrint(stderr, "error warping data\n");
-        exit(PS_EXIT_DATA_ERROR);
+    if (!pswarpLoop(config, stats)) {
+        goto DIE;
     }
 
-    psLogMsg("pswarp", 3, "complete pswarp run: %f sec\n", psTimerMark("pswarp"));
-    pswarpCleanup(config);
-    psLibFinalize();
-    exit(PS_EXIT_SUCCESS);
+    psLogMsg("pswarp", PS_LOG_INFO, "complete pswarp run: %f sec\n", psTimerMark("pswarp"));
+
+DIE:
+    {
+        psExit exitValue = pswarpExitCode(PS_EXIT_SUCCESS); // Exit code
+
+        // Ensure everything is written out, at every level
+        pswarpFileActivation(config, detectorFiles, true);
+        pswarpFileActivation(config, skycellFiles, true);
+        pswarpFileActivation(config, photFiles, true);
+        pswarpFileActivation(config, independentFiles, true);
+        if (!pswarpIOChecksAfter(config)) {
+            psError(psErrorCodeLast(), false, "Unable to write files.");
+            exitValue = pswarpExitCode(exitValue);
+            pmFPAfileFreeSetStrict(false);
+        }
+
+        // Write out summary statistics
+        if (stats) {
+            psMetadataAddF32(stats, PS_LIST_TAIL, "DT_WARP", 0, "Time for warp completion",
+                             psTimerMark("pswarp"));
+
+            const char *statsMDC = psMetadataConfigFormat(stats);
+            if (!statsMDC) {
+                psError(psErrorCodeLast(), false, "Unable to get statistics file.");
+                exitValue = pswarpExitCode(exitValue);
+            }
+            psFree(stats);
+            if (fprintf(statsFile, "%s", statsMDC) != strlen(statsMDC)) {
+                psError(PSWARP_ERR_IO, true, "Unable to write statistics file.");
+                exitValue = pswarpExitCode(exitValue);
+            }
+            psFree(statsMDC);
+            if (fclose(statsFile) == EOF) {
+                psError(PSWARP_ERR_IO, true, "Unable to close statistics file.");
+                exitValue = pswarpExitCode(exitValue);
+            }
+            pmConfigRunFilenameAddWrite(config, "STATS", statsName);
+        }
+
+        // Dump configuration
+        psString dump_file = psMetadataLookupStr(&mdok, config->arguments, "DUMP_CONFIG");
+        if (dump_file) {
+            if (!pmConfigDump(config, dump_file)) {
+                psError(psErrorCodeLast(), false, "Unable to dump configuration");
+                exitValue = pswarpExitCode(exitValue);
+            }
+        }
+
+        psThreadPoolFinalize();
+        psMemCheckCorruption(stderr, true);
+
+        psFree(config);
+
+        psTimerStop();
+        pmVisualClose();
+        pmModelClassCleanup();
+        pmConceptsDone();
+        pmConfigDone();
+        psLibFinalize();
+
+        exitValue = pswarpExitCode(exitValue);
+        return exitValue;
+    }
 }
