Index: trunk/ppImage/src/ppImageDetrendFringe.c
===================================================================
--- trunk/ppImage/src/ppImageDetrendFringe.c	(revision 9857)
+++ trunk/ppImage/src/ppImageDetrendFringe.c	(revision 9952)
@@ -5,16 +5,29 @@
 #include "ppImageDetrendFringe.h"
 
-bool ppImageDetrendFringeMeasure(pmFringeStats **science, // (Ptr to) science fringe measurements
-                                 psArray *references, // Array of reference fringe measurements
-                                 const pmReadout *readout, // Readout to measure
+bool ppImageDetrendFringeMeasure(pmReadout *readout, // Readout to measure
+                                 pmCell *fringe, // Fringe cell (each readout is a different component)
                                  const ppImageOptions *options // Options
                                  )
 {
-    assert(science);
-    PS_ASSERT_ARRAY_NON_NULL(references, false);
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(fringe, false);
+    PS_ASSERT_PTR_NON_NULL(options, false);
+
+    // Reference fringe measurements
+    psArray *references = psMemIncrRefCounter(psMetadataLookupPtr(NULL, fringe->analysis,
+                                                                  "FRINGE.MEASUREMENTS"));
+    if (!references) {
+        references = pmFringesParse(fringe); // Reference fringes
+        if (!references) {
+            psError(PS_ERR_IO, false, "Unable to find fringe references.\n");
+            return false;
+        }
+        psMetadataAdd(fringe->analysis, PS_LIST_TAIL, "FRINGE.MEASUREMENTS", PS_DATA_UNKNOWN,
+                      "Fringe measurements", references);
+    }
 
     pmFringeStats *reference = references->data[0]; // Take the first as representative
     pmFringeRegions *regions = reference->regions; // Regions to measure
-    pmFringeStats *fringe = pmFringeStatsMeasure(regions, readout, options->maskValue); // Fringe stats
+    pmFringeStats *measurements = pmFringeStatsMeasure(regions, readout, options->maskValue); // Fringe stats
 
     // Normalise measurements by the exposure time
@@ -23,5 +36,5 @@
     if (!mdok || !isfinite(expTime)) {
         psError(PS_ERR_UNKNOWN, false, "CELL.EXPOSURE is not set for --- can't normalise fringes\n");
-        psFree(fringe);
+        psFree(measurements);
         return false;
     }
@@ -30,22 +43,21 @@
         expTime = 1.0;
     }
-    psBinaryOp(fringe->f, fringe->f, "*", psScalarAlloc(1.0 / expTime, PS_TYPE_F32));
-    psBinaryOp(fringe->df, fringe->df, "*", psScalarAlloc(1.0 / expTime, PS_TYPE_F32));
+    psBinaryOp(measurements->f, measurements->f, "*", psScalarAlloc(1.0 / expTime, PS_TYPE_F32));
+    psBinaryOp(measurements->df, measurements->df, "*", psScalarAlloc(1.0 / expTime, PS_TYPE_F32));
 
-    if (!*science) {
-        // Only a single readout
-        *science = fringe;
-    } else {
+    // Science fringe measurements
+    pmFringeStats *previous = psMetadataLookupPtr(NULL, readout->parent->analysis, "FRINGE.MEASUREMENTS");
+    if (previous) {
         // Multiple readouts: concatenate
         psArray *concatenate = psArrayAlloc(2); // Array to hold fringes
 
         // Concatenate science measurements
-        concatenate->data[0] = *science;
-        concatenate->data[1] = fringe;
-        pmFringeStats *sciNew = pmFringeStatsConcatenate(concatenate, NULL, NULL); // New measurements
-        psFree(*science);
-        *science = sciNew;
+        concatenate->data[0] = previous;
+        concatenate->data[1] = measurements;
+        pmFringeStats *new = pmFringeStatsConcatenate(concatenate, NULL, NULL); // New measurements
+        psFree(measurements);
+        measurements = new;
 
-        // Concatenate reference measurements
+        // Concatenate reference measurements (duplication, so the science and reference line up)
         for (int i = 0; i < references->n; i++) {
             concatenate->data[0] = concatenate->data[1] = references->data[i];
@@ -54,8 +66,13 @@
             references->data[i] = refNew;
         }
-
         concatenate->data[0] = concatenate->data[1] = NULL;
         psFree(concatenate);
     }
+
+    psMetadataAdd(readout->parent->analysis, PS_LIST_TAIL, "FRINGE.MEASUREMENTS",
+                  PS_DATA_UNKNOWN | PS_META_REPLACE, "Fringe measurements", measurements);
+    psFree(measurements);
+
+    psFree(references);
 
     return true;
@@ -63,16 +80,38 @@
 
 
+// Pull the fringes out of the cell analysis FRINGE.MEASUREMENTS for a chip
+static psArray *getFringes(const pmChip *chip // Chip of interest
+    )
+{
+    psArray *cells = chip->cells;       // Component cells
+    psArray *fringes = psArrayAlloc(cells->n); // Fringes, to return
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];  // Cell of interest
+        fringes->data[i] = psMemIncrRefCounter(psMetadataLookupPtr(NULL, cell->analysis,
+                                                                   "FRINGE.MEASUREMENTS"));
+    }
+
+    return fringes;
+}
+
 
 // Solve the fringe system: we have science fringe measurements for each cell, and an array of reference
 // fringe measurements for each cell.  Need to concatenate these together first, and then solve.
-pmFringeScale *ppImageDetrendFringeSolve(psArray *science, // Science fringe measurements (per cell)
-                                         psArray *references, // Array of array of fringe measurements
-                                         const ppImageOptions *options // Options
+bool ppImageDetrendFringeSolve(pmChip *scienceChip, // Chip with science
+                               const pmChip *refChip, // Chip with reference fringes
+                               const ppImageOptions *options // Options
     )
 {
+    PS_ASSERT_PTR_NON_NULL(scienceChip, NULL);
+    PS_ASSERT_PTR_NON_NULL(refChip, NULL);
+    PS_ASSERT_PTR_NON_NULL(options, NULL);
+
+    psArray *science = getFringes(scienceChip); // Fringe measurements on science chip
     pmFringeStats *scienceCat = pmFringeStatsConcatenate(science, NULL, NULL); // Science fringes
+    psFree(science);
 
     // Need to transform the array of cells each with an array of fringes --> array of fringes for the chip as
     // a whole
+    psArray *references = getFringes(refChip); // Fringe measurements on reference chip
     int numRefs = ((psArray*)references->data[0])->n; // Number of reference fringes
     psArray *referencesCat = psArrayAlloc(numRefs); // Reference fringes
@@ -86,4 +125,5 @@
         psFree(refs);
     }
+    psFree(references);
 
     // Now we can solve
@@ -92,18 +132,22 @@
                                                    options->fringeIter, options->fringeKeep);
 
+    psMetadataAdd(scienceChip->analysis, PS_LIST_TAIL, "FRINGE.SOLUTION", PS_DATA_UNKNOWN,
+                  "Fringe solution", solution);
+    psFree(solution);
     psFree(scienceCat);
     psFree(referencesCat);
 
-    return solution;
+    return true;
 }
 
 
 psImage *ppImageDetrendFringeGenerate(pmCell *science, // Science cell
-                                      pmCell *fringes, // Fringe cell, one readout per fringe component
-                                      const pmFringeScale *solution // Fringe solution to apply
+                                      pmCell *fringes // Fringe cell, one readout per fringe component
     )
 {
     PS_ASSERT_PTR_NON_NULL(science, false);
-    PS_ASSERT_PTR_NON_NULL(solution, false);
+    PS_ASSERT_PTR_NON_NULL(fringes, false);
+
+    pmFringeScale *solution = psMetadataLookupPtr(NULL, science->parent->analysis, "FRINGE.SOLUTION");
     assert(fringes->readouts->n == solution->nFringeFrames);
 
