Index: /trunk/psModules/src/camera/pmFPAMosaic.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAMosaic.c	(revision 7848)
+++ /trunk/psModules/src/camera/pmFPAMosaic.c	(revision 7849)
@@ -4,4 +4,5 @@
 #include "pmFPA.h"
 #include "pmHDU.h"
+#include "pmConceptsAverage.h"
 #include "pmHDUUtils.h"
 #include "pmFPAMosaic.h"
@@ -27,11 +28,4 @@
 if ((value) > (max)) { \
     (max) = (value); \
-}
-
-// Update a metadata entry directly
-#define MD_UPDATE(MD, NAME, TYPE, VALUE) \
-{ \
-    psMetadataItem *item = psMetadataLookup(MD, NAME); \
-    item->data.TYPE = VALUE; \
 }
 
@@ -529,108 +523,4 @@
 
     return mosaic;
-}
-
-
-// Set the concepts in the new cell, based on the values in the old one
-static bool cellConcepts(pmCell *target,// Target cell
-                         psList *sources, // Source cells
-                         int xBin, int yBin, // Binning
-                         psRegion *trimsec // The trim section
-                        )
-{
-    assert(target);
-    assert(sources);
-    assert(xBin > 0 && yBin > 0);
-    assert(trimsec);
-
-    bool success = true;                // Result of setting everything
-    float gain       = 0.0;             // Gain
-    float readnoise  = 0.0;             // Read noise
-    float saturation = INFINITY;        // Saturation level
-    float bad        = -INFINITY;       // Bad level
-    float exposure   = 0.0;             // Exposure time
-    float darktime   = 0.0;             // Dark time
-    double time      = 0.0;             // Time of observation
-    psTimeType timeSys = 0;             // Time system
-    int readdir      = 0;               // Cell read direction
-
-    int nCells = 0;                     // Number of cells;
-    psListIterator *sourcesIter = psListIteratorAlloc(sources, PS_LIST_HEAD, false); // Iterator for sources
-    pmCell *cell = NULL;                // Source cell from iteration
-    while ((cell = psListGetAndIncrement(sourcesIter))) {
-        if (!cell) {
-            continue;
-        }
-
-        nCells++;
-        gain       += psMetadataLookupF32(NULL, cell->concepts, "CELL.GAIN");
-        readnoise  += psMetadataLookupF32(NULL, cell->concepts, "CELL.READNOISE");
-        exposure   += psMetadataLookupF32(NULL, cell->concepts, "CELL.EXPOSURE");
-        darktime   += psMetadataLookupF32(NULL, cell->concepts, "CELL.DARKTIME");
-        psTime *cellTime = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TIME");
-        time       += psTimeToMJD(cellTime);
-        if (nCells == 1) {
-            timeSys = psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS");
-            readdir = psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR");
-        } else {
-            if (timeSys != psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS")) {
-                psLogMsg(__func__, PS_LOG_ERROR, "Differing time systems in use: %d vs %d\n", timeSys,
-                         psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS"));
-                success = false;
-            }
-            if (readdir != psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR")) {
-                psLogMsg(__func__, PS_LOG_ERROR, "Differing cell read directions in use: %d vs %d\n", readdir,
-                         psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR"));
-                success = false;
-            }
-        }
-
-        float cellSaturation = psMetadataLookupF32(NULL, cell->concepts, "CELL.SATURATION");
-        if (cellSaturation < saturation) {
-            saturation = cellSaturation;
-        }
-        float cellBad = psMetadataLookupF32(NULL, cell->concepts, "CELL.BAD");
-        if (cellBad > bad) {
-            bad = cellBad;
-        }
-    }
-    psFree(sourcesIter);
-
-    gain      /= (float)nCells;
-    readnoise /= (float)nCells;
-    exposure  /= (float)nCells;
-    darktime  /= (float)nCells;
-    time      /= (double)nCells;
-
-    MD_UPDATE(target->concepts, "CELL.GAIN", F32, gain);
-    MD_UPDATE(target->concepts, "CELL.READNOISE", F32, readnoise);
-    MD_UPDATE(target->concepts, "CELL.SATURATION", F32, saturation);
-    MD_UPDATE(target->concepts, "CELL.BAD", F32, bad);
-    MD_UPDATE(target->concepts, "CELL.EXPOSURE", F32, exposure);
-    MD_UPDATE(target->concepts, "CELL.DARKTIME", F32, darktime);
-    MD_UPDATE(target->concepts, "CELL.TIMESYS", S32, timeSys);
-    MD_UPDATE(target->concepts, "CELL.X0", S32, 0);
-    MD_UPDATE(target->concepts, "CELL.Y0", S32, 0);
-    MD_UPDATE(target->concepts, "CELL.XPARITY", S32, 1);
-    MD_UPDATE(target->concepts, "CELL.YPARITY", S32, 1);
-    MD_UPDATE(target->concepts, "CELL.XBIN", S32, xBin);
-    MD_UPDATE(target->concepts, "CELL.YBIN", S32, yBin);
-    MD_UPDATE(target->concepts, "CELL.READDIR", S32, readdir);
-
-    // CELL.TIME needs special care
-    {
-        psMetadataItem *timeItem = psMetadataLookup(target->concepts, "CELL.TIME");
-        psFree(timeItem->data.V);
-        timeItem->data.V = psTimeFromMJD(time);
-    }
-
-    // CELL.TRIMSEC needs special care
-    {
-        psMetadataItem *trimsecItem = psMetadataLookup(target->concepts, "CELL.TRIMSEC");
-        psFree(trimsecItem->data.V);
-        trimsecItem->data.V = psMemIncrRefCounter(trimsec);
-    }
-
-    return success;
 }
 
@@ -1105,5 +995,5 @@
     // Set the concepts for the target cell
     psList *sourceCells = psArrayToList(source->cells); // List of cells
-    cellConcepts(targetCell, sourceCells, xBin, yBin, chipRegion);
+    pmConceptsAverageCells(targetCell, sourceCells, xBin, yBin, chipRegion, NULL);
     psFree(sourceCells);
     psFree(chipRegion);
@@ -1211,5 +1101,5 @@
         }
     }
-    cellConcepts(targetCell, sourceCells, xBin, yBin, fpaRegion);
+    pmConceptsAverageCells(targetCell, sourceCells, xBin, yBin, fpaRegion, NULL);
     psFree(sourceCells);
     psFree(fpaRegion);
Index: /trunk/psModules/src/concepts/Makefile.am
===================================================================
--- /trunk/psModules/src/concepts/Makefile.am	(revision 7848)
+++ /trunk/psModules/src/concepts/Makefile.am	(revision 7849)
@@ -5,4 +5,5 @@
 libpsmoduleconcepts_la_SOURCES  = \
 	pmConcepts.c \
+	pmConceptsAverage.c \
 	pmConceptsRead.c \
 	pmConceptsWrite.c \
@@ -13,4 +14,5 @@
 psmoduleinclude_HEADERS = \
 	pmConcepts.h \
+	pmConceptsAverage.h \
 	pmConceptsRead.h \
 	pmConceptsWrite.h \
Index: /trunk/psModules/src/concepts/pmConceptsAverage.c
===================================================================
--- /trunk/psModules/src/concepts/pmConceptsAverage.c	(revision 7849)
+++ /trunk/psModules/src/concepts/pmConceptsAverage.c	(revision 7849)
@@ -0,0 +1,132 @@
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmConcepts.h"
+#include "pmFPA.h"
+
+#include "pmConceptsAverage.h"
+
+
+// Update a metadata entry directly
+#define MD_UPDATE(MD, NAME, TYPE, VALUE) \
+{ \
+    psMetadataItem *item = psMetadataLookup(MD, NAME); \
+    item->data.TYPE = VALUE; \
+}
+
+
+// Set a variety of concepts in a cell by averaging over several
+bool pmConceptsAverageCells(pmCell *target,// Target cell
+                            psList *sources, // List of source cells
+                            int xBin, int yBin, // Binning in x and y
+                            psRegion *trimsec, // The trim section
+                            psRegion *biassec // The bias section
+                           )
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_INT_POSITIVE(sources->n, false);
+    PS_ASSERT_INT_NONNEGATIVE(xBin, false);
+    PS_ASSERT_INT_NONNEGATIVE(yBin, false);
+    PS_ASSERT_PTR_NON_NULL(trimsec, false);
+
+    bool success = true;                // Result of setting everything
+    float gain       = 0.0;             // Gain
+    float readnoise  = 0.0;             // Read noise
+    float saturation = INFINITY;        // Saturation level
+    float bad        = -INFINITY;       // Bad level
+    float exposure   = 0.0;             // Exposure time
+    float darktime   = 0.0;             // Dark time
+    double time      = 0.0;             // Time of observation
+    psTimeType timeSys = 0;             // Time system
+    int readdir      = 0;               // Cell read direction
+
+    int nCells = 0;                     // Number of cells;
+    psListIterator *sourcesIter = psListIteratorAlloc(sources, PS_LIST_HEAD, false); // Iterator for sources
+    pmCell *cell = NULL;                // Source cell from iteration
+    while ((cell = psListGetAndIncrement(sourcesIter))) {
+        if (!cell) {
+            continue;
+        }
+
+        nCells++;
+        gain       += psMetadataLookupF32(NULL, cell->concepts, "CELL.GAIN");
+        readnoise  += psMetadataLookupF32(NULL, cell->concepts, "CELL.READNOISE");
+        exposure   += psMetadataLookupF32(NULL, cell->concepts, "CELL.EXPOSURE");
+        darktime   += psMetadataLookupF32(NULL, cell->concepts, "CELL.DARKTIME");
+        psTime *cellTime = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TIME");
+        time       += psTimeToMJD(cellTime);
+        if (nCells == 1) {
+            timeSys = psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS");
+            readdir = psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR");
+        } else {
+            if (timeSys != psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS")) {
+                psLogMsg(__func__, PS_LOG_ERROR, "Differing time systems in use: %d vs %d\n", timeSys,
+                         psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS"));
+                success = false;
+            }
+            if (readdir != psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR")) {
+                psLogMsg(__func__, PS_LOG_ERROR, "Differing cell read directions in use: %d vs %d\n", readdir,
+                         psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR"));
+                success = false;
+            }
+        }
+
+        float cellSaturation = psMetadataLookupF32(NULL, cell->concepts, "CELL.SATURATION");
+        if (cellSaturation < saturation) {
+            saturation = cellSaturation;
+        }
+        float cellBad = psMetadataLookupF32(NULL, cell->concepts, "CELL.BAD");
+        if (cellBad > bad) {
+            bad = cellBad;
+        }
+    }
+    psFree(sourcesIter);
+
+    gain      /= (float)nCells;
+    readnoise /= (float)nCells;
+    exposure  /= (float)nCells;
+    darktime  /= (float)nCells;
+    time      /= (double)nCells;
+
+    MD_UPDATE(target->concepts, "CELL.GAIN", F32, gain);
+    MD_UPDATE(target->concepts, "CELL.READNOISE", F32, readnoise);
+    MD_UPDATE(target->concepts, "CELL.SATURATION", F32, saturation);
+    MD_UPDATE(target->concepts, "CELL.BAD", F32, bad);
+    MD_UPDATE(target->concepts, "CELL.EXPOSURE", F32, exposure);
+    MD_UPDATE(target->concepts, "CELL.DARKTIME", F32, darktime);
+    MD_UPDATE(target->concepts, "CELL.TIMESYS", S32, timeSys);
+    MD_UPDATE(target->concepts, "CELL.X0", S32, 0);
+    MD_UPDATE(target->concepts, "CELL.Y0", S32, 0);
+    if (xBin > 0) {
+        MD_UPDATE(target->concepts, "CELL.XBIN", S32, xBin);
+    }
+    if (yBin > 0) {
+        MD_UPDATE(target->concepts, "CELL.YBIN", S32, yBin);
+    }
+    MD_UPDATE(target->concepts, "CELL.READDIR", S32, readdir);
+
+    // CELL.TIME needs special care
+    {
+        psMetadataItem *timeItem = psMetadataLookup(target->concepts, "CELL.TIME");
+        psFree(timeItem->data.V);
+        timeItem->data.V = psTimeFromMJD(time);
+    }
+
+    // CELL.TRIMSEC needs special care
+    if (trimsec) {
+        psMetadataItem *trimsecItem = psMetadataLookup(target->concepts, "CELL.TRIMSEC");
+        psFree(trimsecItem->data.V);
+        trimsecItem->data.V = psMemIncrRefCounter(trimsec);
+    }
+
+    // CELL.BIASSEC needs special care
+    if (biassec) {
+        psMetadataItem *biassecItem = psMetadataLookup(target->concepts, "CELL.BIASSEC");
+        psFree(biassecItem->data.V);
+        biassecItem->data.V = psMemIncrRefCounter(biassec);
+    }
+
+    return success;
+}
+
Index: /trunk/psModules/src/concepts/pmConceptsAverage.h
===================================================================
--- /trunk/psModules/src/concepts/pmConceptsAverage.h	(revision 7849)
+++ /trunk/psModules/src/concepts/pmConceptsAverage.h	(revision 7849)
@@ -0,0 +1,15 @@
+#ifndef PM_CONCEPTS_AVERAGE_H
+#define PM_CONCEPTS_AVERAGE_H
+
+#include <pslib.h>
+#include "pmFPA.h"
+
+// Set a variety of concepts in a cell by averaging over several
+bool pmConceptsAverageCells(pmCell *target,// Target cell
+                            psList *sources, // List of source cells
+                            int xBin, int yBin, // Binning in x and y
+                            psRegion *trimsec, // The trim section
+                            psRegion *biassec // The bias section
+                           );
+
+#endif
Index: /trunk/psModules/src/imcombine/pmReadoutCombine.c
===================================================================
--- /trunk/psModules/src/imcombine/pmReadoutCombine.c	(revision 7848)
+++ /trunk/psModules/src/imcombine/pmReadoutCombine.c	(revision 7849)
@@ -5,6 +5,6 @@
  *  @author GLG, MHPCC
  *
- *  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-07-04 00:19:11 $
+ *  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-07-08 05:21:12 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -18,4 +18,5 @@
 #include "pmFPA.h"
 #include "pmFPAMaskWeight.h"
+#include "pmConceptsAverage.h"
 
 #include "pmReadoutCombine.h"
@@ -396,6 +397,14 @@
     psFree(mask);
     psFree(weights);
-
     psFree(stats);
+
+    // Update the "concepts"
+    psList *inputCells = psListAlloc(NULL); // List of cells
+    for (long i = 0; i < inputs->n; i++) {
+        pmReadout *readout = inputs->data[i]; // Readout of interest
+        psListAdd(inputCells, PS_LIST_TAIL, readout->parent);
+    }
+    pmConceptsAverageCells(output->parent, inputCells, 0, 0, NULL, NULL);
+    psFree(inputCells);
 
     return true;
