Index: trunk/ppMerge/src/ppMergeLoop_Threaded.c
===================================================================
--- trunk/ppMerge/src/ppMergeLoop_Threaded.c	(revision 18862)
+++ trunk/ppMerge/src/ppMergeLoop_Threaded.c	(revision 18967)
@@ -12,5 +12,5 @@
 #include "ppMerge.h"
 
-// XXX this function is now sufficiently different for the major types, it would make sense to just 
+// XXX this function is now sufficiently different for the major types, it would make sense to just
 // split it into three: BASIC, SHUTTER, DARK
 
@@ -57,6 +57,6 @@
     psMaskType markVal;
     if (!pmConfigMaskSetBits (&maskVal, &markVal, config)) {
-	psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
-	return false;
+        psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
+        return false;
     }
 
@@ -151,10 +151,10 @@
             if (type == PPMERGE_TYPE_SHUTTER) {
                 shutterRef = pmShutterCorrectionReference(shutters->data[cellNum]);
-		pattern = pmReadoutAlloc(NULL);
+                pattern = pmReadoutAlloc(NULL);
             }
 
             pmReadout *outRO = pmReadoutAlloc(outCell);
 
-	    // open the input files (we need to do the work ourselves)
+            // open the input files (we need to do the work ourselves)
             for (int i = 0; i < numFiles; i++) {
                 if (!ppMergeFileOpenInput(config, view, i)) {
@@ -162,122 +162,127 @@
                     goto ERROR;
                 }
-	    }
-
-	    ppMergeFileGroup *fileGroup = NULL;
-	    psArray *fileGroups = psArrayAlloc (nThreads + 1);
-
-	    // generate readouts for each input file in each file group
-	    for (int i = 0; i < fileGroups->n; i++) {
-		psArray *readouts = psArrayAlloc(numFiles); // Input readouts
-		for (int j = 0; j < numFiles; j++) {
-		    pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i);
-		    pmCell *inCell = pmFPAviewThisCell(view, input->fpa); // Input cell
-		    readouts->data[j] = pmReadoutAlloc(inCell);
-		}
-
-		fileGroup = ppMergeFileGroupAlloc();
-		fileGroup->readouts = readouts;
-		fileGroup->read = false;
-		fileGroup->busy = false;
-		fileGroup->lastScan = 0;
-		fileGroup->firstScan = 0;
-		fileGroups->data[i] = fileGroup;
-            }
-
-	    // call the init functions
-	    switch (type) {
-	      case PPMERGE_TYPE_BIAS:
-	      case PPMERGE_TYPE_FLAT:
-	      case PPMERGE_TYPE_FRINGE: 
-		psAssert (fileGroups->n > 0, "no valid file groups defined");
-		fileGroup = fileGroups->data[0];
-		if (!pmReadoutCombinePrepare(outRO, fileGroup->readouts, combination)) {
-		    goto ERROR;
-		}
-		break;
-	      case PPMERGE_TYPE_DARK:
-		psAssert (fileGroups->n > 0, "no valid file groups defined");
-		fileGroup = fileGroups->data[0];
-		if (!pmDarkCombinePrepare(outCell, fileGroup->readouts, darkOrdinates, darkNorm)) {
-		    goto ERROR;
-		}
-		break;
-	      case PPMERGE_TYPE_SHUTTER:
-		psAssert (fileGroups->n > 0, "no valid file groups defined");
-		fileGroup = fileGroups->data[0];
-		if (!pmShutterCorrectionGeneratePrepare(outRO, pattern, fileGroup->readouts, maskVal)) {
-		    goto ERROR;
-		}
-		break;
-	      default:
-		fprintf (stderr, "not yet ready");
-		goto ERROR;
-	    }
+            }
+
+            ppMergeFileGroup *fileGroup = NULL;
+            psArray *fileGroups = psArrayAlloc(nThreads + 1);
+
+            // Generate readouts for each input file in each file group
+            for (int i = 0; i < fileGroups->n; i++) {
+                psArray *readouts = psArrayAlloc(numFiles); // Input readouts
+                for (int j = 0; j < numFiles; j++) {
+                    pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i);
+                    pmCell *inCell = pmFPAviewThisCell(view, input->fpa); // Input cell
+                    readouts->data[j] = pmReadoutAlloc(inCell);
+                }
+
+                fileGroup = ppMergeFileGroupAlloc();
+                fileGroup->readouts = readouts;
+                fileGroup->read = false;
+                fileGroup->busy = false;
+                fileGroup->lastScan = 0;
+                fileGroup->firstScan = 0;
+                fileGroups->data[i] = fileGroup;
+            }
+
+            // call the init functions
+            switch (type) {
+              case PPMERGE_TYPE_BIAS:
+              case PPMERGE_TYPE_FLAT:
+              case PPMERGE_TYPE_FRINGE:
+                psAssert (fileGroups->n > 0, "no valid file groups defined");
+                fileGroup = fileGroups->data[0];
+                if (!pmReadoutCombinePrepare(outRO, fileGroup->readouts, combination)) {
+                    goto ERROR;
+                }
+                break;
+              case PPMERGE_TYPE_DARK:
+                psAssert (fileGroups->n > 0, "no valid file groups defined");
+                fileGroup = fileGroups->data[0];
+                if (!pmDarkCombinePrepare(outCell, fileGroup->readouts, darkOrdinates, darkNorm)) {
+                    goto ERROR;
+                }
+                break;
+              case PPMERGE_TYPE_SHUTTER:
+                psAssert (fileGroups->n > 0, "no valid file groups defined");
+                fileGroup = fileGroups->data[0];
+                if (!pmShutterCorrectionGeneratePrepare(outRO, pattern, fileGroup->readouts, maskVal)) {
+                    goto ERROR;
+                }
+                break;
+              default:
+                psAbort("Should never get here.");
+            }
 
             // Read input data by chunks
-	    psTimerStart ("ppMergeLoop");
+            psTimerStart("ppMergeLoop");
             for (int numChunk = 0; true; numChunk++) {
 
-		bool status = false;
-		fileGroup = ppMergeReadChunk (&status, fileGroups, config, numChunk);
-		if (!status) goto ERROR;
-		if (!fileGroup) break;
-
-		psThreadJob *job = NULL;
-
+                bool status = false;
+                fileGroup = ppMergeReadChunk(&status, fileGroups, config, numChunk);
+                if (!status) {
+                    // Something went wrong
+                    goto ERROR;
+                }
+                if (!fileGroup) {
+                    // Nothing more to read
+                    break;
+                }
+
+                // Start a job
                 switch (type) {
                   case PPMERGE_TYPE_BIAS:
                   case PPMERGE_TYPE_FLAT:
-                  case PPMERGE_TYPE_FRINGE:
-		    // allocate a job
-		    job = psThreadJobAlloc ("PPMERGE_READOUT_COMBINE");
-
-		    // construct the arguments for this job
-		    psArrayAdd (job->args, 1, outRO);
-		    psArrayAdd (job->args, 1, fileGroup);
-		    psArrayAdd (job->args, 1, zeros);
-		    psArrayAdd (job->args, 1, scales);
-		    psArrayAdd (job->args, 1, combination);
-
-		    // call: pmReadoutCombine(outRO, fileGroup->readouts, zeros, scales, combination);
-		    if (!psThreadJobAddPending (job)) {
-			goto ERROR;
-		    }
-                    break;
-                  case PPMERGE_TYPE_DARK:
-		    // allocate a job
-		    job = psThreadJobAlloc ("PPMERGE_DARK_COMBINE");
-
-		    // construct the arguments for this job
-		    psArrayAdd (job->args, 1, outCell);
-		    psArrayAdd (job->args, 1, fileGroup);
-		    psArrayAdd (job->args, 1, psScalarAlloc(iter, PS_TYPE_S32));
-		    psArrayAdd (job->args, 1, psScalarAlloc(rej, PS_TYPE_F32));
-		    psArrayAdd (job->args, 1, psScalarAlloc(maskVal, PS_TYPE_U8));
-
-		    // call: pmDarkCombine(outCell, fileGroup->readouts, iter, rej, maskVal);
-		    if (!psThreadJobAddPending (job)) {			
-			goto ERROR;
-		    }
-                    break;
-                  case PPMERGE_TYPE_SHUTTER:
-		    // allocate a job
-		    job = psThreadJobAlloc ("PPMERGE_SHUTTER_CORRECTION");
-
-		    // construct the arguments for this job
-		    psArrayAdd (job->args, 1, outRO);
-		    psArrayAdd (job->args, 1, pattern);
-		    psArrayAdd (job->args, 1, fileGroup);
-		    psArrayAdd (job->args, 1, psScalarAlloc(shutterRef, PS_TYPE_F32));
-		    psArrayAdd (job->args, 1, shutters->data[cellNum]);
-		    psArrayAdd (job->args, 1, psScalarAlloc(iter, PS_TYPE_S32));
-		    psArrayAdd (job->args, 1, psScalarAlloc(rej, PS_TYPE_F32));
-		    psArrayAdd (job->args, 1, psScalarAlloc(maskVal, PS_TYPE_U8));
-
-		    // call: pmShutterCorrectionGenerate(outRO, pattern, fileGroup->readouts, shutterRef, shutters->data[cellNum], iter, rej, maskVal)
-		    if (!psThreadJobAddPending (job)) {
-			goto ERROR;
-		    }
-                    break;
+                  case PPMERGE_TYPE_FRINGE: {
+                      psThreadJob *job = psThreadJobAlloc("PPMERGE_READOUT_COMBINE"); // Job to start
+
+                      // Construct the arguments for this job
+                      psArrayAdd(job->args, 1, outRO);
+                      psArrayAdd(job->args, 1, fileGroup);
+                      psArrayAdd(job->args, 1, zeros);
+                      psArrayAdd(job->args, 1, scales);
+                      psArrayAdd(job->args, 1, combination);
+
+                      // call: pmReadoutCombine(outRO, fileGroup->readouts, zeros, scales, combination);
+                      if (!psThreadJobAddPending(job)) {
+                          goto ERROR;
+                      }
+                      break;
+                  }
+                  case PPMERGE_TYPE_DARK: {
+                      psThreadJob *job = psThreadJobAlloc ("PPMERGE_DARK_COMBINE"); // Job to start
+
+                      // construct the arguments for this job
+                      psArrayAdd(job->args, 1, outCell);
+                      psArrayAdd(job->args, 1, fileGroup);
+                      psArrayAdd(job->args, 1, psScalarAlloc(iter, PS_TYPE_S32));
+                      psArrayAdd(job->args, 1, psScalarAlloc(rej, PS_TYPE_F32));
+                      psArrayAdd(job->args, 1, psScalarAlloc(maskVal, PS_TYPE_U8));
+
+                      // call: pmDarkCombine(outCell, fileGroup->readouts, iter, rej, maskVal);
+                      if (!psThreadJobAddPending(job)) {
+                          goto ERROR;
+                      }
+                      break;
+                  }
+                  case PPMERGE_TYPE_SHUTTER: {
+                      psThreadJob *job = psThreadJobAlloc ("PPMERGE_SHUTTER_CORRECTION");
+
+                      // construct the arguments for this job
+                      psArrayAdd(job->args, 1, outRO);
+                      psArrayAdd(job->args, 1, pattern);
+                      psArrayAdd(job->args, 1, fileGroup);
+                      psArrayAdd(job->args, 1, psScalarAlloc(shutterRef, PS_TYPE_F32));
+                      psArrayAdd(job->args, 1, shutters->data[cellNum]);
+                      psArrayAdd(job->args, 1, psScalarAlloc(iter, PS_TYPE_S32));
+                      psArrayAdd(job->args, 1, psScalarAlloc(rej, PS_TYPE_F32));
+                      psArrayAdd(job->args, 1, psScalarAlloc(maskVal, PS_TYPE_U8));
+
+                      // call: pmShutterCorrectionGenerate(outRO, pattern, fileGroup->readouts, shutterRef,
+                      //                                   shutters->data[cellNum], iter, rej, maskVal);
+                      if (!psThreadJobAddPending (job)) {
+                          goto ERROR;
+                      }
+                      break;
+                  }
                   default:
                     psAbort("Should never get here.");
@@ -285,19 +290,19 @@
             }
 
-	    // wait for the threads to finish and manage results
-	    if (!psThreadPoolWait ()) {
-		psError(PS_ERR_UNKNOWN, false, "Unable to combine images.");
-		return false;
-	    }
-
-	    // we don't care about the results, just dump the done queue jobs
-	    psThreadJob *job = NULL;
-	    while ((job = psThreadJobGetDone()) != NULL) {
-		psFree (job);
-	    }
+            // Wait for the threads to finish and manage results
+            if (!psThreadPoolWait(false)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to combine images.");
+                return false;
+            }
+
+            // we don't care about the results, just dump the done queue jobs
+            psThreadJob *job = NULL;    // Job to dump
+            while ((job = psThreadJobGetDone())) {
+                psFree (job);
+            }
 
             psFree(fileGroups);
 
-	    // XXX eventually need to keep both the shutter and the pattern, as we do with dark 
+            // XXX eventually need to keep both the shutter and the pattern, as we do with dark
             psFree(pattern);
 
@@ -305,6 +310,6 @@
             psList *inCells = psListAlloc(NULL); // List of cells
             for (int i = 0; i < numFiles; i++) {
-		pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i);
-		pmCell *inCell = pmFPAviewThisCell(view, input->fpa); // Input cell
+                pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i);
+                pmCell *inCell = pmFPAviewThisCell(view, input->fpa); // Input cell
                 psListAdd(inCells, PS_LIST_TAIL, inCell);
             }
@@ -316,5 +321,4 @@
             }
             psFree(inCells);
-	    fprintf (stdout, "done ppMergeLoop for cell : %f\n", psTimerMark ("ppMergeLoop"));
 
             // Plug supplementary images into their own FPAs
@@ -364,5 +368,5 @@
             }
 
-            if (!ppStatsFPA(stats, outFPA, view, maskVal, config)) {
+            if (stats && !ppStatsFPA(stats, outFPA, view, maskVal, config)) {
                 psError(PS_ERR_UNKNOWN, true, "Unable to generate stats for image.");
                 goto ERROR;
