Index: /trunk/ppMerge/src/ppMerge.c
===================================================================
--- /trunk/ppMerge/src/ppMerge.c	(revision 13872)
+++ /trunk/ppMerge/src/ppMerge.c	(revision 13873)
@@ -46,16 +46,22 @@
     }
 
-    psImage *scale = NULL;              // The scalings
-    psImage *zero = NULL;               // The zeros
-
     if (options->mask) {
         // Generate a mask
         ppMergeMask(data, options, config);
     } else {
+
+        psImage *scale = NULL;              // The scalings
+        psImage *zero = NULL;               // The zeros
+        psArray *shutters = NULL;           // The shutter correction data
+
         // Measure the background in each image
-        ppMergeScaleZero(&scale, &zero, data, options, config);
+        ppMergeScaleZero(&scale, &zero, &shutters, data, options, config);
 
         // Do the combination and write
-        ppMergeCombine(scale, zero, data, options, config);
+        ppMergeCombine(scale, zero, shutters, data, options, config);
+
+        psFree(scale);
+        psFree(zero);
+        psFree(shutters);
     }
 
@@ -73,6 +79,4 @@
     // Cleaning up
     psFree(data);
-    psFree(scale);
-    psFree(zero);
     psFree(options);
     psFree(config);
Index: /trunk/ppMerge/src/ppMergeCombine.c
===================================================================
--- /trunk/ppMerge/src/ppMergeCombine.c	(revision 13872)
+++ /trunk/ppMerge/src/ppMergeCombine.c	(revision 13873)
@@ -83,4 +83,5 @@
 bool ppMergeCombine(psImage *scales,    // Scales for each cell of each integration, or NULL
                     psImage *zeros,     // Zeros for each cell of each integration, or NULL
+                    psArray *shutters, // Shutter correction data for each cell, or NULL
                     ppMergeData *data,  // Data
                     ppMergeOptions *options, // Options
@@ -100,4 +101,6 @@
                       zeros->numCols == data->numCells &&
                       zeros->numRows == filenames->n));
+    assert(!options->shutter || shutters);
+    assert(!shutters || (shutters->n == data->numCells));
 
     // Iterate over the FPA
@@ -143,4 +146,9 @@
             }
 
+            float shutterRef;           // Reference shutter correction
+            if (options->shutter) {
+                shutterRef = pmShutterCorrectionReference(shutters->data[cellNum]);
+            }
+
             do {
                 numRead = 0;
@@ -162,11 +170,11 @@
 
                     // Only reading and writing the first readout in each cell (plane 0)
-		    bool readOK;
+                    bool readOK;
                     if (pmReadoutReadNext(&readOK, stack->data[i], fits, 0, options->rows)) {
-			if (!readOK) {
-			    psError(PS_ERR_IO, false, "Failed to read concepts for cell.\n");
-			    psErrorStackPrint(stderr, "trouble reading data!\n");
-			    exit (1);
-			}
+                        if (!readOK) {
+                            psError(PS_ERR_IO, false, "Failed to read concepts for cell.\n");
+                            psErrorStackPrint(stderr, "trouble reading data!\n");
+                            exit (1);
+                        }
                         // If we're creating a bias or a dark, we don't want to generate a mask
                         if ((options->zero || options->scale || options->shutter || options->mask) &&
@@ -198,9 +206,7 @@
 
                     if (options->shutter) {
-                        pmShutterCorrectionMeasure(readout, stack, options->shutterSize,
-                                                   options->mean, options->stdev,
-                                                   options->shutterIter,
-                                                   options->shutterRej,
-                                                   options->combine->maskVal);
+                        pmShutterCorrectionGenerate(readout, NULL, stack, shutterRef, shutters->data[cellNum],
+                                                    options->shutterIter, options->shutterRej,
+                                                    options->combine->maskVal);
                     } else {
                         pmReadoutCombine(readout, stack, cellZeros, cellScales, options->combine);
@@ -271,16 +277,12 @@
             // Statistics on the merged cell
             if (data->statsFile) {
-		if (!data->stats) {
-		    data->stats = psMetadataAlloc();
-		}
-                if (!ppStats(data->stats, 
-			     data->out, 
-			     view, 
-			     options->combine->maskVal,
-			     config)) {
+                if (!data->stats) {
+                    data->stats = psMetadataAlloc();
+                }
+                if (!ppStats(data->stats, data->out, view, options->combine->maskVal, config)) {
                     psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to generate stats for image.\n");
-		    return false;
-		}
-	    }
+                    return false;
+                }
+            }
 
             // We threw away the bias sections --- record this
Index: /trunk/ppMerge/src/ppMergeCombine.h
===================================================================
--- /trunk/ppMerge/src/ppMergeCombine.h	(revision 13872)
+++ /trunk/ppMerge/src/ppMergeCombine.h	(revision 13873)
@@ -11,4 +11,5 @@
 bool ppMergeCombine(psImage *scales,    // Scales for each cell of each integration, or NULL
                     psImage *zeros,     // Zeros for each cell of each integration, or NULL
+                    psArray *shutters, // Shutter correction data for each cell, or NULL
                     ppMergeData *data,  // Data
                     ppMergeOptions *options, // Options
Index: /trunk/ppMerge/src/ppMergeOptions.c
===================================================================
--- /trunk/ppMerge/src/ppMergeOptions.c	(revision 13872)
+++ /trunk/ppMerge/src/ppMergeOptions.c	(revision 13873)
@@ -61,5 +61,4 @@
     options->satMask = 0x00;
     options->badMask = 0x00;
-
     return options;
 }
@@ -135,5 +134,5 @@
 
     // First, deal with the recipe.  These are parameters that will typically be constant for a camera.
-    OPTION_PARSE(options->rows,              recipe, "ROWS",           U16);
+    OPTION_PARSE(options->rows,              recipe, "ROWS",           S32);
     OPTION_PARSE(options->minElectrons,      recipe, "ELECTRONS",      F32);
     OPTION_PARSE(options->sample,            recipe, "SAMPLE",         S32);
@@ -215,5 +214,4 @@
             options->shutter = true;
             options->mask = false;
-            options->rows = 0;          // Read the whole image at once
         } else if (strcasecmp(type, "MASK") == 0) {
             options->zero = false;
Index: /trunk/ppMerge/src/ppMergeScaleZero.c
===================================================================
--- /trunk/ppMerge/src/ppMergeScaleZero.c	(revision 13872)
+++ /trunk/ppMerge/src/ppMergeScaleZero.c	(revision 13873)
@@ -15,4 +15,5 @@
 bool ppMergeScaleZero(psImage **scales, // The scales for each integration/cell
                       psImage **zeros, // The zeroes for each integration/cell
+                      psArray **shutters, // The shutter correction data for each cell
                       ppMergeData *data,// The data
                       const ppMergeOptions *options, // The options
@@ -24,5 +25,5 @@
     assert(config);
 
-    if (!options->scale && !options->zero && !options->darktime) {
+    if (!options->scale && !options->zero && !options->darktime && !options->shutter) {
         return true;                    // We did everything we were asked for
     }
@@ -43,4 +44,6 @@
                                  (*zeros)->numCols == data->numCells &&
                                  (*zeros)->numRows == filenames->n));
+    assert(!options->shutter || shutters);
+    assert(!shutters || !*shutters || (*shutters)->n == data->numCells);
 
     // Allocate the outputs
@@ -57,6 +60,14 @@
         *zeros = psImageAlloc(data->numCells, filenames->n, PS_TYPE_F32);
     }
-
-    bool fromConcepts = false;          // Do we get the scale and zero points from the concepts
+    psRandom *rng = NULL;               // Random number generator
+    if (options->shutter) {
+        if (*shutters) {
+            psFree(*shutters);
+        }
+        *shutters = psArrayAlloc(data->numCells);
+        rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+    }
+
+    bool fromConcepts = false;          // Do we get the scale and zero points from the concepts?
     bool first = true;                  // Are we on the first cell (that sets the standard for the rest)?
     bool done = false;                  // Are we done going through the list?
@@ -86,5 +97,5 @@
                     if (mdok && !isnan(scale)) {
                         if (!first && !fromConcepts) {
-                            psLogMsg(__func__, PS_LOG_WARN, "PPMERGE.SCALE and PPMERGE.ZERO have been set "
+                            psWarning("PPMERGE.SCALE and PPMERGE.ZERO have been set "
                                      "for some, but not all cells --- we will re-measure it for all cells.");
                             done = true;
@@ -93,7 +104,8 @@
                         fromConcepts = true;
                         (*scales)->data.F32[i][cellNum] = scale;
-                        psTrace("ppMerge", 9, "Scale for input %ld, chip %ld, cell %ld: %f\n", i, j, k, scale);
+                        psTrace("ppMerge", 9, "Scale for input %ld, chip %ld, cell %ld: %f\n",
+                                i, j, k, scale);
                     } else if (!first && fromConcepts) {
-                        psLogMsg(__func__, PS_LOG_WARN, "PPMERGE.SCALE and PPMERGE.ZERO have been set "
+                        psWarning("PPMERGE.SCALE and PPMERGE.ZERO have been set "
                                  "for some, but not all cells --- we will re-measure it for all cells.");
                         fromConcepts = false;
@@ -107,5 +119,5 @@
                     if (mdok && !isnan(zero)) {
                         if (!first && !fromConcepts) {
-                            psLogMsg(__func__, PS_LOG_WARN, "PPMERGE.SCALE and PPMERGE.ZERO have been set "
+                            psWarning("PPMERGE.SCALE and PPMERGE.ZERO have been set "
                                      "for some, but not all cells --- we will re-measure it for all cells.");
                             done = true;
@@ -116,5 +128,5 @@
                         psTrace("ppMerge", 9, "Zero for input %ld, chip %ld, cell %ld: %f\n", i, j, k, zero);
                     } else if (!first && fromConcepts) {
-                        psLogMsg(__func__, PS_LOG_WARN, "PPMERGE.SCALE and PPMERGE.ZERO have been set "
+                        psWarning("PPMERGE.SCALE and PPMERGE.ZERO have been set "
                                  "for some, but not all cells --- we will re-measure it for all cells.");
                         fromConcepts = false;
@@ -131,4 +143,5 @@
     if (fromConcepts) {
         // We've already done everything we need to
+        psFree(rng);
         return true;
     }
@@ -205,5 +218,5 @@
 
                     if (cell->readouts->n > 1) {
-                        psLogMsg(__func__, PS_LOG_WARN, "File %s chip %d cell %d contains more than one "
+                        psWarning("File %s chip %d cell %d contains more than one "
                                  "readout --- ignoring all but the first.\n", name, j, k);
                         status = false;
@@ -222,5 +235,5 @@
                         gains->data.F32[cellNum] = psMetadataLookupF32(&mdok, cell->concepts, "CELL.GAIN");
                         if (!mdok || isnan(gains->data.F32[cellNum])) {
-                            psLogMsg(__func__, PS_LOG_WARN, "CELL.GAIN for file %s chip %d cell %d is not "
+                            psWarning("CELL.GAIN for file %s chip %d cell %d is not "
                                      "set.\n", name, j, k);
                             gains->data.F32[cellNum] = NAN;
@@ -259,4 +272,35 @@
                 }
 
+                // Shutter correction
+                if (options->shutter) {
+                    if (!pmCellRead(cell, inFile, config->database)) {
+                        // Nothing here
+                        pmCellFreeData(cell);
+                        continue;
+                    }
+
+                    if (cell->readouts->n > 1) {
+                        psWarning("File %s chip %d cell %d contains more than one "
+                                  "readout --- ignoring all but the first.\n", name, j, k);
+                        status = false;
+                    }
+                    pmReadout *readout = cell->readouts->data[0]; // The readout of interest
+
+                    pmShutterCorrectionData *shutter = (*shutters)->data[cellNum]; // Shutter correction data
+                    if (!shutter) {
+                        shutter = pmShutterCorrectionDataAlloc(readout->image->numCols,
+                                                               readout->image->numRows,
+                                                               options->shutterSize);
+                        (*shutters)->data[cellNum] = shutter;
+                    }
+                    if (!pmShutterCorrectionAddReadout(shutter, readout, options->mean, options->stdev,
+                                                       options->combine->maskVal, rng)) {
+                        psWarning("Can't add file %s chip %d cell %d to shutter correction --- ignored.",
+                                  name, j, k);
+                        status = false;
+                    }
+                }
+
+
                 pmCellFreeData(cell);
             }
@@ -265,4 +309,5 @@
         pmFPAFreeData(fpa);
     }
+    psFree(rng);
     psFree(bgStats);
     psFree(view);
@@ -277,5 +322,5 @@
         psVector *fluxes = NULL;        // Solution to fluxes
         if (!pmFlatNormalize(&fluxes, &gains, background)) {
-            psLogMsg(__func__, PS_LOG_WARN, "Normalisation failed to converge --- continuing anyway.\n");
+            psWarning("Normalisation failed to converge --- continuing anyway.\n");
             status = false;
         }
Index: /trunk/ppMerge/src/ppMergeScaleZero.h
===================================================================
--- /trunk/ppMerge/src/ppMergeScaleZero.h	(revision 13872)
+++ /trunk/ppMerge/src/ppMergeScaleZero.h	(revision 13873)
@@ -11,4 +11,5 @@
 bool ppMergeScaleZero(psImage **scales, // The scales for each integration/cell
                       psImage **zeros, // The zeroes for each integration/cell
+                      psArray **shutter,// The shutter correction data for each cell
                       ppMergeData *data,// The data
                       const ppMergeOptions *options, // The options
