Index: /trunk/psModules/src/detrend/pmFringeStats.c
===================================================================
--- /trunk/psModules/src/detrend/pmFringeStats.c	(revision 7827)
+++ /trunk/psModules/src/detrend/pmFringeStats.c	(revision 7828)
@@ -3,6 +3,6 @@
  *  @author Eugene Magnier, IfA
  *
- *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-21 03:21:16 $
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-07-06 03:29:28 $
  *
  *  Copyright 2004 IfA
@@ -14,7 +14,4 @@
 #include "pmFPA.h"
 #include "pmFringeStats.h"
-
-#define MAX(x,y) ((x) > (y) ? (x) : (y))
-#define MIN(x,y) ((x) < (y) ? (x) : (y))
 
 
@@ -191,5 +188,4 @@
     return measurements;
 }
-
 
 bool pmFringeStatsWriteFits(psFits *fits, const pmFringeStats *fringe, const char *extname)
@@ -353,4 +349,69 @@
 
 
+pmFringeStats *pmFringeStatsConcatenate(const psArray *fringes, const psVector *x0, const psVector *y0)
+{
+    PS_ASSERT_PTR_NON_NULL(fringes, NULL);
+    PS_ASSERT_PTR_NON_NULL(fringes->data, NULL);
+    PS_ASSERT_INT_POSITIVE(fringes->n, NULL);
+    if (x0 && y0) {
+        PS_ASSERT_VECTOR_NON_NULL(x0, NULL);
+        PS_ASSERT_VECTOR_NON_NULL(y0, NULL);
+        PS_ASSERT_VECTOR_TYPE(x0, PS_TYPE_S32, NULL);
+        PS_ASSERT_VECTOR_TYPE(y0, PS_TYPE_S32, NULL);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(x0, y0, NULL);
+        PS_ASSERT_VECTOR_SIZE(x0, fringes->n, NULL);
+        PS_ASSERT_VECTOR_SIZE(y0, fringes->n, NULL);
+    }
+
+    // Get the measurement parameters, and check they are consistent
+    int numPoints = 0;                  // Number of fringe points
+    int dX = 0, dY = 0;                 // Half-width and -height of fringe boxes
+    int nX = 0, nY = 0;                 // Smoothing scales
+    for (long i = 0; i < fringes->n; i++) {
+        pmFringeStats *fringe = fringes->data[i]; // The fringe of interest
+        pmFringeRegions *regions = fringe->regions; // The fringe regions
+        if (numPoints == 0) {
+            dX = regions->dX;
+            dY = regions->dY;
+            nX = regions->nX;
+            nY = regions->nY;
+        } else if (regions->dX != dX || regions->dY != dY || regions->nX != nX || regions->nY != nY) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Fringe %ld has different parameters (%d,%d,%d,%d) "
+                    "from the first (%d,%d,%d,%d).\n", i,
+                    regions->dX, regions->dY, regions->nX, regions->nY, dX, dY, nX, nY);
+            return NULL;
+        }
+        unsigned int num = regions->nRequested;  // Number of fringe points
+        if (regions->x->n != num || regions->y->n != num || regions->mask->n != num ||
+                fringe->f->n != num || fringe->df->n != num) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Length of region (%ld,%ld,%ld) and fringe vectors "
+                    "do not match (%ld,%ld) with the official value (%d).\n", regions->x->n, regions->y->n,
+                    regions->mask->n, fringe->f->n, fringe->df->n, num);
+            return NULL;
+        }
+        numPoints += regions->nRequested;
+    }
+
+    pmFringeRegions *newRegions = pmFringeRegionsAlloc(numPoints, dX, dY, nX, nY); // The new list of regions
+    pmFringeStats *newStats = pmFringeStatsAlloc(newRegions); // The new list of statistics
+
+    long offset = 0;                    // Offset from start of the list
+    for (long i = 0; i < fringes->n; i++) {
+        pmFringeStats *fringe = fringes->data[i]; // The fringe of interest
+        pmFringeRegions *regions = fringe->regions; // The fringe regions
+        // Copy the data over
+        memcpy(&newRegions->x->data.F32[offset], regions->x->data.F32, regions->x->n * sizeof(psF32));
+        memcpy(&newRegions->y->data.F32[offset], regions->y->data.F32, regions->y->n * sizeof(psF32));
+        memcpy(&newRegions->mask->data.U8[offset], regions->mask->data.U8, regions->mask->n * sizeof(psU8));
+        memcpy(&newStats->f->data.F32[offset], fringe->f->data.F32, fringe->f->n * sizeof(psF32));
+        memcpy(&newStats->df->data.F32[offset], fringe->f->data.F32, fringe->df->n * sizeof(psF32));
+        offset += regions->nRequested;
+    }
+
+    psFree(newRegions);                 // Drop reference
+    return newStats;
+}
+
+
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // pmFringeScale
Index: /trunk/psModules/src/detrend/pmFringeStats.h
===================================================================
--- /trunk/psModules/src/detrend/pmFringeStats.h	(revision 7827)
+++ /trunk/psModules/src/detrend/pmFringeStats.h	(revision 7828)
@@ -5,6 +5,6 @@
  *  @author Eugene Magnier, IfA
  *
- *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-14 22:04:40 $
+ *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-07-06 03:29:28 $
  *
  *  Copyright 2004 IfA, University of Hawaii
@@ -93,4 +93,12 @@
                                     );
 
+// Concatenate the fringe stats for several readouts into a single fringe stats.  The idea is that each
+// readout of each chip should be measured separately (so as to avoid any gaps, as in the case for GPC), but
+// then perform the fit to all the readouts belonging to a chip.  To do so, we need to concatenate.
+pmFringeStats *pmFringeStatsConcatenate(const psArray *fringes, // Array of pmFringeStats for the readouts
+                                        const psVector *x0, // Offset in x for the readout
+                                        const psVector *y0 // Offset in y for the readout
+                                       );
+
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // pmFringeScale
