Index: trunk/ppImage/src/ppImageLoop.c
===================================================================
--- trunk/ppImage/src/ppImageLoop.c	(revision 9657)
+++ trunk/ppImage/src/ppImageLoop.c	(revision 9857)
@@ -5,4 +5,5 @@
 #include <ppStats.h>
 #include "ppImage.h"
+#include "ppImageDetrendFringe.h"
 
 bool ppImageLoop (pmConfig *config, ppImageOptions *options) {
@@ -44,8 +45,30 @@
         if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) return false;
 
+        const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME"); // Name of chip
+        psArray *fringeRef = NULL;      // Array of array of fringe statistics for reference --- for each cell
+        psArray *fringeSci = NULL;      // Array of fringe statistics for science --- for each cell
+        if (options->doFringe) {
+            fringeRef = psArrayAlloc(chip->cells->n);
+            fringeSci = psArrayAlloc(chip->cells->n);
+        }
+
         while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
             psLogMsg ("ppImageLoop", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
             if (!cell->process || !cell->file_exists) { continue; }
             if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) return false;
+            const char *cellName = psMetadataLookupStr(NULL, cell->concepts, "CELL.NAME"); // Name of cell
+
+            if (options->doFringe) {
+                pmFPAfile *fringeFile = psMetadataLookupPtr(&status, config->files, "PPIMAGE.FRINGE");
+                if (!status || !fringeFile) {
+                    psErrorStackPrint(stderr, "Can't find fringe data!\n");
+                    exit(EXIT_FAILURE);
+                }
+
+                psString fringeExt = NULL; // Fringe extension name
+                psStringAppend(&fringeExt, "FRINGE_%s_%s", chipName, cellName);
+                fringeRef->data[view->cell] = pmFringesReadFits(NULL, fringeFile->fits, fringeExt);
+                psFree(fringeExt);
+            }
 
             // process each of the readouts
@@ -57,6 +80,40 @@
                 if (!ppImageDetrendReadout (config, options, view)) return false;
 
+                if (options->doFringe) {
+                    ppImageDetrendFringeMeasure((pmFringeStats**)(&fringeSci->data[view->cell]),
+                                                fringeRef->data[view->cell], readout, options);
+                }
+            }
+        }
+
+        // Solve the fringe system
+        pmFringeScale *fringeSoln = NULL; // Solution for the fringes
+        if (options->doFringe) {
+            fringeSoln = ppImageDetrendFringeSolve(fringeSci, fringeRef, options);
+            psFree(fringeSci);
+            psFree(fringeRef);
+        }
+
+        // Go back over the cells to apply the fringe and do statistics
+        view->cell = view->readout = -1;
+        while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
+            if (!cell->process || !cell->file_exists) { continue; }
+
+            // Apply the fringe correction
+            psTrace("ppImage", 3, "Applying fringe correction...\n");
+            bool mdok;                          // Status of MD lookup
+            pmFPAfile *fringeFile = psMetadataLookupPtr(&mdok, config->files, "PPIMAGE.FRINGE");
+            pmCell *fringeCell = pmFPAviewThisCell(view, fringeFile->fpa);
+            psImage *fringe = ppImageDetrendFringeGenerate(cell, fringeCell, fringeSoln);
+            while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
+                if (!readout->data_exists) { continue; }
+
+                // XXX: Make generic, so subregions may be subtracted as well
+                psBinaryOp(readout->image, readout->image, "-", fringe);
+
                 if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) return false;
             }
+            psFree(fringe);
+
 
             // Perform statistics on the detrended cell
@@ -67,4 +124,5 @@
             if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) return false;
         }
+        psFree(fringeSoln);
 
         ppImageMosaicChip (config, view, "PPIMAGE.OUTPUT.CHIP", "PPIMAGE.OUTPUT");
