Index: trunk/ppFringe/src/ppFringeLoop.c
===================================================================
--- trunk/ppFringe/src/ppFringeLoop.c	(revision 7838)
+++ trunk/ppFringe/src/ppFringeLoop.c	(revision 7889)
@@ -9,6 +9,28 @@
     )
 {
-    psFitsWriteBlank(data->outFile, NULL);
+    psRandom *rng = NULL; // Random number generator
 
+    // Set up output header
+    const char *detId = psMetadataLookupStr(NULL, config->arguments, "-detid"); // Detector ID, for header
+    const char *classId = psMetadataLookupStr(NULL, config->arguments, "-classid"); // Class ID, for header
+    psMetadata *outHeader = psMetadataAlloc(); // Header for output
+    if (detId && strlen(detId) > 0) {
+        psMetadataAddStr(outHeader, PS_LIST_TAIL, "DETID", 0, "Detector ID for this image.", detId);
+    }
+    if (classId && strlen(classId) > 0) {
+        psMetadataAddStr(outHeader, PS_LIST_TAIL, "CLASSID", 0, "Class ID for this image.", classId);
+    }
+
+    // Get table of contents for the output FITS file
+    psMetadata *contents = psFitsReadHeaderSet(NULL, data->outFile);
+#if 0
+    psMetadataPrint(stdout, contents, 0);
+    exit(EXIT_FAILURE);
+#endif
+    if (!contents || contents->list->n == 0) {
+        psFitsWriteBlank(data->outFile, NULL);
+    }
+
+    // Iterate through the FPA
     pmFPA *fpa = data->inFPA;           // The FPA of interest
     psArray *chips = fpa->chips;        // Array of component chips
@@ -50,39 +72,89 @@
             }
 
-            // Create points to measure fringes
-            pmFringeRegions *regions = pmFringeRegionsAlloc(data->numPoints, data->xWidth, data->yWidth,
-                                                            data->xSmooth, data->ySmooth);
-            if (!pmFringeRegionsCreatePoints(regions, readout->image)) {
-                psLogMsg(__func__, PS_LOG_WARN, "Unable to create fringe regions for chip %s cell %s --- "
+            // Look for this chip/cell in the output file
+            pmFringeRegions *regions = NULL; // Points at which to measure fringes
+            bool preDefined = false;    // Are the regions defined in the output file?
+            psString extname = NULL;
+            psStringAppend(&extname, "%s_%s", chipName, cellName);
+            if (contents && contents->list->n > 0) {
+                bool mdok;              // Status of MD lookup
+                psMetadata *header = psMetadataLookupMD(&mdok, contents, extname); // Header
+                if (mdok && header) {
+                    regions = pmFringeRegionsReadFits(NULL, data->outFile, extname);
+                    if (regions) {
+                        preDefined = true;
+                    } else {
+                        psLogMsg(__func__, PS_LOG_WARN, "Unable to read fringe regions for chip %s cell %s "
+                                 " --- will generate new regions.\n", chipName, cellName);
+                    }
+                }
+            }
+
+            // Otherwise, generate one ourselves
+            if (!regions) {
+                if (!rng) {
+                    rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+                }
+                // Create points to measure fringes
+                regions = pmFringeRegionsAlloc(data->numPoints, data->xWidth, data->yWidth,
+                                               data->xSmooth, data->ySmooth);
+                if (!pmFringeRegionsCreatePoints(regions, readout->image, rng)) {
+                    psLogMsg(__func__, PS_LOG_WARN, "Unable to create fringe regions for chip %s cell %s --- "
+                             "ignored.\n", chipName, cellName);
+                    psFree(extname);
+                    psFree(regions);
+                    pmCellFreeData(cell);
+                    continue;
+                }
+            }
+
+            // Measure fringes
+            pmFringeStats *fringeStats = pmFringeStatsMeasure(regions, readout, data->maskVal);
+            psFree(regions);            // Drop reference
+            if (!fringeStats) {
+                psLogMsg(__func__, PS_LOG_WARN, "Unable to measure fringes for chip %s cell %s --- "
                          "ignored.\n", chipName, cellName);
-                psFree(regions);
                 pmCellFreeData(cell);
                 continue;
             }
 
-            // Measure fringes
-            pmFringeStats *fringeStats = pmFringeStatsMeasure(regions, readout, data->maskVal);
-            if (!fringeStats) {
-                psLogMsg(__func__, PS_LOG_WARN, "Unable to measure fringes for chip %s cell %s --- "
+            // Write fringe regions
+            if (!preDefined &&
+                !pmFringeRegionsWriteFits(data->outFile, NULL, fringeStats->regions, extname)) {
+                psLogMsg(__func__, PS_LOG_WARN, "Unable to write fringe regions for chip %s cell %s --- "
                          "ignored.\n", chipName, cellName);
-                psFree(regions);
+                psFree(fringeStats);
+                psFree(extname);
                 pmCellFreeData(cell);
                 continue;
             }
 
+            int version = 0;            // Version number
+            if (preDefined) {
+                // Find the lowest possible version number that isn't already taken
+                psMetadata *header = NULL; // Header from the table of contents
+                bool mdok = true;       // Status of MD lookup
+                do {
+                    version++;
+                    psString checkName = NULL; // Extension name to check
+                    psStringAppend(&checkName, "%s:%d", extname, version);
+                    header = psMetadataLookupMD(&mdok, contents, checkName);
+                    psFree(checkName);
+                } while (mdok && header);
+            }
+
             // Write fringe measurements
-            psString extname = NULL;
-            psStringAppend(&extname, "%s_%s", chipName, cellName);
-            if (!pmFringeStatsWriteFits(data->outFile, fringeStats, extname)) {
+            psStringAppend(&extname, ":%d", version);
+            if (!pmFringeStatsWriteFits(data->outFile, outHeader, fringeStats, extname)) {
                 psLogMsg(__func__, PS_LOG_WARN, "Unable to write fringe measurements for chip %s cell %s --- "
                          "ignored.\n", chipName, cellName);
-                psFree(regions);
                 psFree(fringeStats);
+                psFree(extname);
                 pmCellFreeData(cell);
                 continue;
             }
 
-            psFree(regions);
             psFree(fringeStats);
+            psFree(extname);
             pmCellFreeData(cell);
         }
@@ -90,3 +162,9 @@
     }
     pmFPAFreeData(fpa);
+
+    psFree(rng);
+    psFree(contents);
+    psFree(outHeader);
+
+    return;
 }
