Index: /trunk/ppMerge/src/ppMerge.h
===================================================================
--- /trunk/ppMerge/src/ppMerge.h	(revision 42784)
+++ /trunk/ppMerge/src/ppMerge.h	(revision 42785)
@@ -117,10 +117,11 @@
     );
 
+bool ppMergeFileFreeInput(pmConfig *config, const pmFPAview *view, int num);
+
 /**
  * Set the data level for files specified by name; return an array of the files
  */
 psArray *ppMergeFileDataLevel(const pmConfig *config, ///< Configuration
-                              const char *name, ///< Name of files
-                              pmFPALevel level ///< Level for file data level
+                              const char *name ///< Name of files
     );
 
Index: /trunk/ppMerge/src/ppMergeFiles.c
===================================================================
--- /trunk/ppMerge/src/ppMergeFiles.c	(revision 42784)
+++ /trunk/ppMerge/src/ppMergeFiles.c	(revision 42785)
@@ -105,5 +105,38 @@
 }
 
-psArray *ppMergeFileDataLevel(const pmConfig *config, const char *name, pmFPALevel level)
+bool ppMergeFileFreeInput(pmConfig *config, const pmFPAview *view, int num)
+{
+    {
+        pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", num);
+        if (!pmFPAfileFreeData(input, view)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to free data for image file %d", num);
+            return false;
+        }
+    }
+    bool mdok;          // Status of MD lookup
+    if (psMetadataLookupBool(&mdok, config->arguments, "INPUTS.MASKS")) {
+        pmFPAfile *mask = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT.MASK", num); // Mask file
+        if (!pmFPAfileFreeData(mask, view)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to free data for mask file %d", num);
+            return false;
+        }
+    }
+    if (psMetadataLookupBool(&mdok, config->arguments, "INPUTS.VARIANCES")) {
+        pmFPAfile *variance = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT.VARIANCE", num); // Variance file
+        if (!pmFPAfileFreeData(variance, view)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to free data for variance file %d", num);
+            return false;
+        }
+    }
+    return true;
+}
+
+// Select the specified input files and assign the dataLevel and freeLevel,
+// saving a pointer on output array.
+// This function takes the argument pmFPALevel and sets the dataLevel based on that value.
+// However, this is only used with the value PM_FPA_LEVEL_READOUT, and it must be set
+// to that level for the rest of ppMerge to work correctly.  Furthermore, the freeLevel
+// must be set to Cell.  Remove the (false) option.
+psArray *ppMergeFileDataLevel(const pmConfig *config, const char *name)
 {
     assert(config);
@@ -115,6 +148,6 @@
     for (int i = 0; i < numFiles; i++) {
         pmFPAfile *file = pmFPAfileSelectSingle(config->files, name, i); // Image file
-        file->dataLevel = level;
-        file->freeLevel = level;
+        file->dataLevel = PM_FPA_LEVEL_READOUT;
+        file->freeLevel = PM_FPA_LEVEL_CELL;
         files->data[i] = psMemIncrRefCounter(file);
     }
Index: /trunk/ppMerge/src/ppMergeLoop.c
===================================================================
--- /trunk/ppMerge/src/ppMergeLoop.c	(revision 42784)
+++ /trunk/ppMerge/src/ppMergeLoop.c	(revision 42785)
@@ -39,12 +39,7 @@
     bool haveVariances = psMetadataLookupBool(&mdok, arguments, "INPUTS.VARIANCES"); // Do we have variances?
 
-    psArray *inputs = ppMergeFileDataLevel(config, "PPMERGE.INPUT", PM_FPA_LEVEL_READOUT); // Input images
-    psArray *masks = NULL, *variances = NULL; // Input masks and variances
-    if (haveMasks) {
-        masks = ppMergeFileDataLevel(config, "PPMERGE.INPUT.MASK", PM_FPA_LEVEL_READOUT);
-    }
-    if (haveVariances) {
-        variances = ppMergeFileDataLevel(config, "PPMERGE.INPUT.VARIANCE", PM_FPA_LEVEL_READOUT);
-    }
+    psArray *inputs    = ppMergeFileDataLevel(config, "PPMERGE.INPUT"); // Input images
+    psArray *masks     = haveMasks ? ppMergeFileDataLevel(config, "PPMERGE.INPUT.MASK") : NULL; // Input masks 
+    psArray *variances = haveVariances ? ppMergeFileDataLevel(config, "PPMERGE.INPUT.VARIANCE") : NULL; // Input variances
 
     int nThreads = psMetadataLookupS32 (&mdok, arguments, "NTHREADS");
@@ -135,5 +130,4 @@
     psString darkNorm = psMetadataLookupStr(&mdok, arguments, "DARK.NORM"); ///< Dark normalisation
 
-
     if (!ppMergeFileActivate(config, PPMERGE_FILES_ALL, true)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to activate files.");
@@ -152,5 +146,4 @@
     }
 
-
     // Average concepts across inputs
     {
@@ -180,5 +173,5 @@
         {
             psList *inChips = psListAlloc(NULL);
-            for (int i=0; i < numFiles; i++) {
+            for (int i = 0; i < numFiles; i++) {
                 pmChip *chip = pmFPAviewThisChip(view, ((pmFPAfile *)inputs->data[i])->fpa);
                 psListAdd(inChips, PS_LIST_TAIL, chip);
@@ -193,7 +186,4 @@
 
         pmCell *outCell;                ///< Cell of interest
-
-        // XXX TEST : force a single loop
-        // outCell = pmFPAviewNextCell(view, outFPA, 1); {
 
         while ((outCell = pmFPAviewNextCell(view, outFPA, 1))) {
@@ -291,4 +281,5 @@
                 psAssert (fileGroups->n > 0, "no valid file groups defined");
                 fileGroup = fileGroups->data[0];
+
                 if (!pmDarkCombinePrepare(outCell, fileGroup->readouts, darkOrdinates, darkNorm)) {
                     goto ERROR;
@@ -305,4 +296,6 @@
                 psAbort("Should never get here.");
             }
+	    fprintf (stderr, "after pmDarkCombinePrepare / pmReadoutCombinePrepare:\n");
+	    psMemStats(true, NULL, NULL);
 
             // Read input data by chunks
@@ -357,6 +350,8 @@
                       // call: pmDarkCombine(outCell, fileGroup->readouts, iter, rej, maskVal);
                       if (!psThreadJobAddPending(job)) {
-			//                          goto ERROR;
-			// continue; // I don't care.
+			// CZW commented this out with a note that this was needed to allow ppMerge to work even if some inputs are invalid.
+			// EAM thinks pmDarkCombine will only return FALSE if there is a programming or setup error (see pmDark.c:pmDarkCombine)
+			// if so, we should raise an error here.
+			// goto ERROR;
                       }
                       break;
@@ -400,5 +395,4 @@
 
             psFree(fileGroups);
-	    //            psFree(zeros);
 
             // XXX eventually need to keep both the shutter and the pattern, as we do with dark
@@ -541,4 +535,12 @@
             }
 
+            // free the data used by the input files (we need to do the work ourselves)
+            for (int i = 0; i < numFiles; i++) {
+                if (!ppMergeFileFreeInput(config, view, i)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to open file %d", i);
+                    goto ERROR;
+                }
+            }
+
             psFree(outRO);
             cellNum++;
@@ -547,4 +549,6 @@
                 goto ERROR;
             }
+
+	    // pmFPAfileIOList (config);
         }
 
@@ -564,4 +568,5 @@
     psFree(variances);
     psFree(stats);
+    psFree(zeros);
     return true;
 
@@ -573,4 +578,5 @@
     psFree(variances);
     psFree(stats);
+    psFree(zeros);
     return false;
 }
Index: /trunk/ppMerge/src/ppMergeMask.c
===================================================================
--- /trunk/ppMerge/src/ppMergeMask.c	(revision 42784)
+++ /trunk/ppMerge/src/ppMergeMask.c	(revision 42785)
@@ -427,12 +427,12 @@
     }
 
-    psArray *inputs = ppMergeFileDataLevel(config, "PPMERGE.INPUT", PM_FPA_LEVEL_READOUT); ///< Input images
+    psArray *inputs = ppMergeFileDataLevel(config, "PPMERGE.INPUT"); ///< Input images
     psFree(inputs);
     if (haveMasks) {
-        psArray *masks = ppMergeFileDataLevel(config, "PPMERGE.INPUT.MASK", PM_FPA_LEVEL_READOUT);
+        psArray *masks = ppMergeFileDataLevel(config, "PPMERGE.INPUT.MASK");
         psFree(masks);
     }
     if (haveVariances) {
-        psArray *variances = ppMergeFileDataLevel(config, "PPMERGE.INPUT.VARIANCE", PM_FPA_LEVEL_READOUT);
+        psArray *variances = ppMergeFileDataLevel(config, "PPMERGE.INPUT.VARIANCE");
         psFree(variances);
     }
Index: /trunk/ppMerge/src/ppMergeScaleZero.c
===================================================================
--- /trunk/ppMerge/src/ppMergeScaleZero.c	(revision 42784)
+++ /trunk/ppMerge/src/ppMergeScaleZero.c	(revision 42785)
@@ -232,4 +232,5 @@
     }
 
+    psFree(gains);
     psFree(background);
     psFree(shutters);
