Index: /trunk/ppMerge/src/Makefile.am
===================================================================
--- /trunk/ppMerge/src/Makefile.am	(revision 7259)
+++ /trunk/ppMerge/src/Makefile.am	(revision 7260)
@@ -1,6 +1,10 @@
 bin_PROGRAMS = ppMerge
 
-ppMerge_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(ppMerge_CFLAGS)
-ppMerge_LDADD = $(PSLIB_LIBS) $(PSMODULE_LIBS)
+ppMerge_CFLAGS += -g $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
+ppMerge_LDFLAGS = $(PSMODULE_LIBS) $(PSLIB_LIBS)
+### For profiling:
+#ppMerge_CFLAGS += -g -pg -fprofile-arcs $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
+#ppMerge_LDFLAGS = -pg -Wl,--start-group -Wl,-Bstatic $(PSMODULE_LIBS) $(PSLIB_LIBS) -Wl,-Bdynamic
+
 ppMerge_SOURCES =		\
 	ppMerge.c		\
@@ -22,4 +26,6 @@
 	ppMergeOptions.h
 
+CLEANFILES = *~
+
 clean-local:
 	-rm -f TAGS
Index: /trunk/ppMerge/src/ppMerge.c
===================================================================
--- /trunk/ppMerge/src/ppMerge.c	(revision 7259)
+++ /trunk/ppMerge/src/ppMerge.c	(revision 7260)
@@ -21,4 +21,5 @@
 int main(int argc, char **argv)
 {
+    psMemThreadSafety(false);           // Turn off thread safety, for more
     psTimerStart(TIMERNAME);
 
@@ -47,4 +48,6 @@
     ppMergeCombine(scale, zero, data, options, config);
 
+    pmFPAPrint(data->out, true, true);
+
     // Cleaning up
     psFree(data);
Index: /trunk/ppMerge/src/ppMergeBackground.c
===================================================================
--- /trunk/ppMerge/src/ppMergeBackground.c	(revision 7259)
+++ /trunk/ppMerge/src/ppMergeBackground.c	(revision 7260)
@@ -49,13 +49,13 @@
     // Sanity checks
     assert(!options->scale || scales);
-    assert(!scales || !*scales || ((*scales)->type.type == PS_TYPE_F64 &&
+    assert(!scales || !*scales || ((*scales)->type.type == PS_TYPE_F32 &&
                                    (*scales)->numCols == data->numCells &&
                                    (*scales)->numRows == filenames->n));
     assert(!options->zero || zeros);
-    assert(!zeros || !*zeros || ((*zeros)->type.type == PS_TYPE_F64 &&
+    assert(!zeros || !*zeros || ((*zeros)->type.type == PS_TYPE_F32 &&
                                  (*zeros)->numCols == data->numCells &&
                                  (*zeros)->numRows == filenames->n));
 
-    psImage *background = psImageAlloc(filenames->n, data->numCells, PS_TYPE_F64); // Background measurements
+    psImage *background = psImageAlloc(data->numCells, filenames->n, PS_TYPE_F32); // Background measurements
     psImageInit(background, NAN);
     psStats *bgStats = psStatsAlloc(options->background); // Statistic to measure the background
@@ -63,8 +63,9 @@
     psImage *exptime = NULL;            // The exposure time for each integration of each cell
     if (options->scale) {
-        gains = psVectorAlloc(data->numCells, PS_TYPE_F64);
+        gains = psVectorAlloc(data->numCells, PS_TYPE_F32);
+        gains->n = data->numCells;
     }
     if (options->exptime) {
-        exptime = psImageAlloc(filenames->n, data->numCells, PS_TYPE_F64);
+        exptime = psImageAlloc(filenames->n, data->numCells, PS_TYPE_F32);
     }
 
@@ -75,4 +76,5 @@
             continue;
         }
+        psTrace(__func__, 9, "Opening %s to get background...\n", name);
         psFits *inFile = psFitsOpen(filenames->data[i], "r"); // The FITS file to read
         if (!inFile) {
@@ -107,10 +109,10 @@
                 if (options->exptime) {
                     bool mdok = true;   // Status of MD lookup
-                    exptime->data.F64[i][cellNum] = psMetadataLookupF32(&mdok, cell->concepts,
+                    exptime->data.F32[i][cellNum] = psMetadataLookupF32(&mdok, cell->concepts,
                                                                         "CELL.EXPOSURE");
-                    if (!mdok || isnan(exptime->data.F64[i][cellNum])) {
+                    if (!mdok || isnan(exptime->data.F32[i][cellNum])) {
                         psLogMsg(__func__, PS_LOG_WARN, "CELL.EXPOSURE for file %s chip %d cell %d is not "
                                  "set.\n", name, j, k);
-                        exptime->data.F64[i][cellNum] = NAN;
+                        exptime->data.F32[i][cellNum] = NAN;
                         status = false;
                     }
@@ -151,6 +153,28 @@
 
                     // Get the background
-                    psImageStats(bgStats, image, readout->mask, options->combine->maskVal);
-                    background->data.F64[i][cellNum] = getStat(bgStats, options->background);
+                    int sampleSize = (image->numCols * image->numRows) / options->sample; // Size of sample
+                    psVector *sample = psVectorAlloc(sampleSize, PS_TYPE_F32); // Sample of the image
+                    sample->n = sampleSize;
+                    psVector *sampleMask = NULL; // Mask for sample
+                    if (readout->mask) {
+                        sampleMask = psVectorAlloc(sampleSize, PS_TYPE_U8);
+                        sampleMask->n = sampleSize;
+                    }
+                    psImage *mask = readout->mask; // The mask image
+                    for (long i = 0; i < sampleSize; i++) {
+                        int j = i * options->sample; // Index into image
+                        int x = j % image->numCols; // x index
+                        int y = j / image->numCols; // y index
+                        sample->data.F32[i] = image->data.F32[y][x];
+                        if (readout->mask) {
+                            sampleMask->data.U8[i] = mask->data.U8[y][x];
+                        }
+                    }
+                    psVectorStats(bgStats, sample, sampleMask, NULL, options->combine->maskVal);
+                    psFree(sample);
+                    psFree(sampleMask);
+                    background->data.F32[i][cellNum] = getStat(bgStats, options->background);
+                    psTrace(__func__, 3, "Background for %s, cell %d is %f\n", name, cellNum,
+                            background->data.F32[i][cellNum]);
                 }
 
@@ -167,4 +191,9 @@
         // Need to normalize over the focal plane
         bool converge = true;           // Did we converge?
+        if (psTraceGetLevel(__func__) > 9) {
+            for (int i = 0; i < gains->n; i++) {
+                psTrace(__func__, 10, "Gain for cell %d is %f\n", i, gains->data.F32[i]);
+            }
+        }
         psVector *fluxes = pmFlatNormalize(&converge, gains, background, MAX_ITER, TOLERANCE);
         if (!converge || !fluxes) {
@@ -174,11 +203,11 @@
         psFree(gains);
 
-        *scales = psImageCopy(*scales, background, PS_TYPE_F64);
+        *scales = psImageCopy(*scales, background, PS_TYPE_F32);
         psImage *scalesDeref = *scales; // Dereference the pointer
 
         for (int i = 0; i < scalesDeref->numRows; i++) {
-            psF64 bg = fluxes->data.F64[i];
+            psF32 bg = fluxes->data.F32[i];
             for (int j = 0; j < scalesDeref->numCols; j++) {
-                scalesDeref->data.F64[i][j] = bg;
+                scalesDeref->data.F32[i][j] = bg;
             }
         }
@@ -188,5 +217,5 @@
         if (!options->scale) {
             // Copy over the exposure times
-            psImageCopy(*scales, exptime, PS_TYPE_F64);
+            psImageCopy(*scales, exptime, PS_TYPE_F32);
         } else {
             psBinaryOp(*scales, *scales, "*", exptime);
@@ -199,5 +228,25 @@
             *zeros = psMemIncrRefCounter(background);
         } else {
-            *zeros = psImageCopy(*zeros, background, PS_TYPE_F64);
+            *zeros = psImageCopy(*zeros, background, PS_TYPE_F32);
+        }
+    }
+
+    // Diagnostic stuff
+    if (scales && *scales && psTraceGetLevel(__func__) > 9) {
+        psImage *scalesDeref = *scales; // Dereference the pointer
+        for (int i = 0; i < scalesDeref->numRows; i++) {
+            for (int j = 0; j < scalesDeref->numCols; j++) {
+                psTrace(__func__, 9, "Scale for exposure %d, cell %d is: %f\n", i, j,
+                        scalesDeref->data.F32[i][j]);
+            }
+        }
+    }
+    if (zeros && *zeros && psTraceGetLevel(__func__) > 9) {
+        psImage *zerosDeref = *zeros; // Dereference the pointer
+        for (int i = 0; i < zerosDeref->numRows; i++) {
+            for (int j = 0; j < zerosDeref->numCols; j++) {
+                psTrace(__func__, 9, "Zero for exposure %d, cell %d is: %f\n", i, j,
+                        zerosDeref->data.F32[i][j]);
+            }
         }
     }
Index: /trunk/ppMerge/src/ppMergeCheckInputs.c
===================================================================
--- /trunk/ppMerge/src/ppMergeCheckInputs.c	(revision 7259)
+++ /trunk/ppMerge/src/ppMergeCheckInputs.c	(revision 7260)
@@ -27,4 +27,8 @@
     psArray *filenames = psMetadataLookupPtr(NULL, config->arguments, "INPUT"); // The input file names
     assert(filenames);
+    if (!data->in) {
+        data->in = psArrayAlloc(filenames->n);
+        data->in->n = filenames->n;
+    }
     int numGood = 0;                    // Number of good files
     for (int i = 0; i < filenames->n; i++) {
@@ -33,4 +37,5 @@
             continue;
         }
+        psTrace(__func__, 1, "Checking input file %s....\n", name);
         psFits *inFile = psFitsOpen(filenames->data[i], "r"); // The FITS file to read
         if (!inFile) {
@@ -42,4 +47,8 @@
         }
         psMetadata *header = psFitsReadHeader(NULL, inFile); // The FITS (primary) header
+        if (psTraceGetLevel(__func__) > 9) {
+            psTrace(__func__, 9, "Primary header:\n");
+            psMetadataPrint(header, 9);
+        }
         psFitsClose(inFile);
 
@@ -74,9 +83,14 @@
         // Use the first valid input as the basis for the output --- including the header
         if (!data->out) {
+            psTrace(__func__, 5, "Constructing output using %s as a template.\n", name);
             data->out = pmFPAConstruct(config->camera);
             pmFPAview *view = pmFPAAddSourceFromHeader(data->out, header, options->format);
             psFree(view);
+#if 0
+            pmFPACopyStructure(data->out, data->in->data[i], 1, 1);
+#endif
         }
 
+        psTrace(__func__, 3, "%s checks out.\n", name);
         numGood++;
     }
@@ -99,5 +113,7 @@
     }
     data->numCells = numCells;
+    psTrace(__func__, 3, "Output has %d cells.\n", numCells);
 
+    psTrace(__func__, 3, "We have %d good inputs.\n", numGood);
     if (numGood > 1) {
         return data;
Index: /trunk/ppMerge/src/ppMergeCombine.c
===================================================================
--- /trunk/ppMerge/src/ppMergeCombine.c	(revision 7259)
+++ /trunk/ppMerge/src/ppMergeCombine.c	(revision 7260)
@@ -7,4 +7,5 @@
 #include "ppMergeData.h"
 #include "ppMergeCombine.h"
+
 
 // Combine the inputs
@@ -22,9 +23,9 @@
     // Sanity checks
     assert(!options->scale || scales);
-    assert(!scales || (scales->type.type == PS_TYPE_F64 &&
+    assert(!scales || (scales->type.type == PS_TYPE_F32 &&
                        scales->numCols == data->numCells &&
                        scales->numRows == filenames->n));
     assert(!options->zero || zeros);
-    assert(!zeros || (zeros->type.type == PS_TYPE_F64 &&
+    assert(!zeros || (zeros->type.type == PS_TYPE_F32 &&
                       zeros->numCols == data->numCells &&
                       zeros->numRows == filenames->n));
@@ -32,5 +33,5 @@
     // Iterate over the FPA
     int cellNum = -1;                   // Cell number
-    pmFPAWrite(data->out, data->outFile, config->database, false);
+    pmFPAWrite(data->out, data->outFile, config->database, false, false); // Write header only
     psArray *chips = data->out->chips;  // Array of output chips
     for (int i = 0; i < chips->n; i++) {
@@ -39,5 +40,5 @@
             continue;
         }
-        pmChipWrite(chip, data->outFile, config->database, false);
+        pmChipWrite(chip, data->outFile, config->database, false, false); // Write header only
         psArray *cells = chip->cells;   // Array of output cells
         for (int j = 0; j < cells->n; j++) {
@@ -47,7 +48,8 @@
             }
             cellNum++;
-            pmCellWrite(cell, data->outFile, config->database, false);
+            pmCellWrite(cell, data->outFile, config->database, false); // Write header only
             pmReadout *readout = pmReadoutAlloc(cell); // Output readout of interest
             psArray *stack = psArrayAlloc(filenames->n); // Stack of readouts to combine
+            stack->n = filenames->n;
             psVector *cellScales = NULL; // Scales for this cell
             if (scales) {
@@ -59,7 +61,7 @@
             }
 
-            bool stillReadingRows = false;  // Still reading rows from any of the files?
-
+            int numRead;  // Number of inputs read
             do {
+                numRead = 0;
                 for (int k = 0; k < filenames->n; k++) {
                     if (! filenames->data[k] || strlen(filenames->data[k]) == 0) {
@@ -82,15 +84,17 @@
 
                     // Only reading and writing the first readout in each cell (plane 0)
-                    stillReadingRows |= pmReadoutReadNext(stack->data[k], fits, 0, options->rows);
+                    if (pmReadoutReadNext(stack->data[k], fits, 0, options->rows)) {
+                        numRead++;
+                    }
                     psFitsClose(fits);
                 }
 
-                pmReadoutCombine(readout, stack, cellZeros, cellScales, options->combine);
-                pmReadoutWriteNext(readout, data->outFile, 0);
+                if (numRead > 0) {
+                    pmReadoutCombine(readout, stack, cellZeros, cellScales, options->combine);
+                    psTrace(__func__, 5, "Chip %d, cell %d, readout size %dx%d\n", i, j,
+                            readout->image->numCols, readout->image->numRows);
+                }
 
-            } while (stillReadingRows);
-
-            // Write the pixels
-            pmCellWrite(cell, data->outFile, config->database, true);
+            } while (numRead > 0);
 
             // Blow away the cell data
@@ -101,9 +105,12 @@
                 pmCellFreeData(cellIn);
             }
-            pmCellFreeData(cell);
+
+            // Write the pixels
+            if (cell->hdu) {
+                psTrace(__func__, 5, "Writing out cell HDU.\n");
+                pmCellWrite(cell, data->outFile, config->database, true);
+                pmCellFreeData(cell);
+            }
         }
-
-        // Write the pixels
-        pmChipWrite(chip, data->outFile, config->database, true);
 
         // Blow away the chip data
@@ -113,10 +120,18 @@
             pmChipFreeData(chipIn);
         }
-        pmChipFreeData(chip);
 
+        // Write the pixels
+        if (chip->hdu) {
+            psTrace(__func__, 5, "Writing out chip HDU.\n");
+            pmChipWrite(chip, data->outFile, config->database, true, false);
+            pmChipFreeData(chip);
+        }
     }
 
-    // Write the pixels
-    pmFPAWrite(data->out, data->outFile, config->database, true);
+    if (data->out->hdu) {
+        // Write the pixels
+        psTrace(__func__, 5, "Writing out FPA HDU.\n");
+        pmFPAWrite(data->out, data->outFile, config->database, true, false);
+    }
 
     // Blow away the FPA data
Index: /trunk/ppMerge/src/ppMergeOptions.c
===================================================================
--- /trunk/ppMerge/src/ppMergeOptions.c	(revision 7259)
+++ /trunk/ppMerge/src/ppMergeOptions.c	(revision 7260)
@@ -137,5 +137,5 @@
     OPTION_PARSE(options->combine->fracLow,  recipe, "FRACLOW",   F32 );
     OPTION_PARSE(options->combine->nKeep,    recipe, "NKEEP",     S32 );
-    OPTION_PARSE(options->combine->maskVal,  recipe, "MASKVAL",   U8  );
+    OPTION_PARSE(options->combine->maskVal,  recipe, "MASKVAL",   S32 );
     options->combine->combine = parseStat(recipe, "COMBINE");
     options->background       = parseStat(recipe, "BACKGROUND");
@@ -145,28 +145,41 @@
     // Set options based on the type of calibration frame
     const char *type = psMetadataLookupStr(NULL, config->arguments, "-type"); // The type of calibration frame
-    if (strcasecmp(type, "BIAS") == 0) {
+    if (strlen(type) > 0) {
+        if (strcasecmp(type, "BIAS") == 0) {
+            options->zero = false;
+            options->scale = false;
+            options->exptime = false;
+        } else if (strcasecmp(type, "DARK") == 0) {
+            options->zero = false;
+            options->scale = false;
+            options->exptime = true;
+        } else if (strcasecmp(type, "FLAT") == 0) {
+            options->zero = false;
+            options->scale = true;
+            options->exptime = false;
+        } else if (strcasecmp(type, "FRINGE") == 0) {
+            options->zero = true;
+            options->scale = true;
+            options->exptime = false;
+        } else {
+            psLogMsg(__func__, PS_LOG_WARN, "Unrecognised image type: %s --- assuming BIAS.\n", type);
+            options->zero = false;
+            options->scale = false;
+            options->exptime = false;
+        }
+    } else {
+        psLogMsg(__func__, PS_LOG_WARN, "No calibration type specified; assuming BIAS.\n");
         options->zero = false;
         options->scale = false;
         options->exptime = false;
-    } else if (strcasecmp(type, "DARK") == 0) {
-        options->zero = false;
-        options->scale = false;
-        options->exptime = true;
-    } else if (strcasecmp(type, "FLAT") == 0) {
-        options->zero = false;
-        options->scale = true;
-        options->exptime = false;
-    } else if (strcasecmp(type, "FRINGE") == 0) {
-        options->zero = true;
-        options->scale = true;
-        options->exptime = false;
-    } else {
-        psLogMsg(__func__, PS_LOG_WARN, "Unrecognised image type: %s --- ignored.\n", type);
     }
 
+
+#if 0
     // Or you can set them individually
     OPTION_PARSE(options->zero,    config->arguments, "-zero",    Bool);
     OPTION_PARSE(options->scale,   config->arguments, "-scale",   Bool);
     OPTION_PARSE(options->exptime, config->arguments, "-exptime", Bool);
+#endif
 
     // Number of on/off images
