Index: /branches/rel10_ifa/psModules/src/astrom/pmFPACopy.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPACopy.c	(revision 6827)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPACopy.c	(revision 6828)
@@ -273,5 +273,6 @@
 // Generate an HDU with the pixels
 static bool generateHDU(pmCell *target,  // The target cell
-                        pmCell *source // The source cell
+                        pmCell *source, // The source cell
+                        int xBin, int yBin // Binning in x and y
                        )
 {
@@ -315,4 +316,7 @@
     psFree(sourceCells);
 
+    xSize = (int)ceilf((float)xSize/(float)xBin);
+    ySize = (int)ceilf((float)ySize/(float)yBin);
+
     hdu->images = psArrayAlloc(numReadouts);
     for (int i = 0; i < numReadouts; i++) {
@@ -349,105 +353,34 @@
 }
 
+// Bin a region down by specified factors in x and y
+static void binRegion(psRegion *region, // Region to be binned
+                      int xBin, int yBin// Binning in x and y
+                     )
+{
+    // Want to include the lower bound: 1 binned by 4 --> 0; 3 binned by 4 --> 0; 4 binned by 4 --> 1
+    region->x0 = (int)(region->x0 / xBin);
+    region->y0 = (int)(region->y0 / yBin);
+    // Want to exclude the upper bound: 4 binned by 4 --> 1; 5 binned by 4 --> 2; 7 binned by 4 --> 2
+    region->x1 = (int)((region->x1 + xBin - 1) / xBin);
+    region->y1 = (int)((region->y1 + yBin - 1) / yBin);
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Public functions
+// File-static engine functions --- these do all the work.  Actually, cellCopy does all the work; the others
+// merely iterate on the higher-level components.
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-
-int pmFPACopy(pmFPA *target,            // The target FPA
-              pmFPA *source             // The source FPA, to be copied
-             )
+static int cellCopy(pmCell *target,          // The target cell
+                    pmCell *source,           // The source cell, to be copied
+                    bool pixels,             // Copy the pixels?
+                    int xBin, int yBin       // (Relative) binning factors in x and y
+                   )
 {
     assert(target);
     assert(source);
 
-    psArray *targetChips = target->chips; // The target chips
-    psArray *sourceChips = source->chips; // The source chips
-    if (targetChips->n != sourceChips->n) {
-        psError(PS_ERR_IO, true, "Number of source chips (%d) differs from the number of target chips (%d)\n",
-                sourceChips->n, targetChips->n);
-        return false;
-    }
-
-    #if 1
-    // Copy any headers
-    if (target->hdu && !target->hdu->phu) {
-        pmHDU *sourceHDU = pmHDUFromFPA(source);
-        target->hdu->header = psMetadataCopy(target->hdu->header, sourceHDU->header);
-    }
-    #endif
-
-    int numChips = 0;                   // Number of chips copied
-    for (int i = 0; i < targetChips->n; i++) {
-        pmChip *targetChip = targetChips->data[i]; // The target chip
-        const char *chipName = psMetadataLookupStr(NULL, targetChip->concepts, "CHIP.NAME"); // Name of chip
-        int chipNum = pmFPAFindChip(source, chipName); // Number of chip with that name
-        if (chipNum >= 0) {
-            pmChip *sourceChip = sourceChips->data[chipNum]; // The source chip
-            int numCells = pmChipCopy(targetChip, sourceChip); // Number of cells copied
-            psTrace(__func__, 5, "Copied %d cells for chip %s\n", numCells, chipName);
-            numChips++;
-        }
-    }
-
-    // Update the concepts
-    psMetadataCopy(target->concepts, source->concepts);
-
-    return numChips;
-}
-
-int pmChipCopy(pmChip *target,          // The target chip
-               pmChip *source           // The source chip, to be copied
-              )
-{
-    assert(target);
-    assert(source);
-
-    psArray *targetCells = target->cells; // The target cells
-    psArray *sourceCells = source->cells; // The source cells
-    if (targetCells->n != sourceCells->n) {
-        psError(PS_ERR_IO, true, "Number of source cells (%d) differs from the number of target cells (%d)\n",
-                sourceCells->n, targetCells->n);
-        return false;
-    }
-
-    #if 1
-    // Copy any headers
-    if (target->hdu && !target->hdu->phu) {
-        pmHDU *sourceHDU = pmHDUFromChip(source);
-        target->hdu->header = psMetadataCopy(target->hdu->header, sourceHDU->header);
-    }
-    #endif
-
-    int numCells = 0;                   // Number of cells copied
-    for (int i = 0; i < targetCells->n; i++) {
-        pmCell *targetCell = targetCells->data[i]; // The target cell
-        const char *cellName = psMetadataLookupStr(NULL, targetCell->concepts, "CELL.NAME"); // Name of cell
-        int cellNum = pmChipFindCell(source, cellName); // Number of cell with that name
-        if (cellNum >= 0) {
-            pmCell *sourceCell = sourceCells->data[cellNum]; // The source cell
-            int numReadouts = pmCellCopy(targetCell, sourceCell); // Number of readouts copied
-            psTrace(__func__, 5, "Copied %d readouts for cell %s\n", numReadouts, cellName);
-            numCells++;
-        }
-    }
-
-    // Update the concepts
-    psMetadataCopy(target->concepts, source->concepts);
-
-    return numCells;
-
-}
-
-int pmCellCopy(pmCell *target,          // The target cell
-               pmCell *source           // The source cell, to be copied
-              )
-{
-    assert(target);
-    assert(source);
-
     psArray *sourceReadouts = source->readouts; // The source readouts
     int numReadouts = sourceReadouts->n; // Number of readouts copied
 
-    #if 1
     // Copy any headers
     if (target->hdu && !target->hdu->phu) {
@@ -455,9 +388,8 @@
         target->hdu->header = psMetadataCopy(target->hdu->header, sourceHDU->header);
     }
-    #endif
 
     pmHDU *hdu = pmHDUFromCell(target); // The target HDU; we need to fix this up
     if (!hdu->images) {
-        generateHDU(target, source);
+        generateHDU(target, source, xBin, yBin);
     }
     if (!hdu->header) {
@@ -496,5 +428,8 @@
             psFree(trimsecString);
         } else {
-            copyPixels(hdu->images->data[i], sourceImage, *trimsec, xFlip, yFlip);
+            binRegion(trimsec, xBin, yBin);
+            if (pixels) {
+                copyPixels(hdu->images->data[i], sourceImage, *trimsec, xFlip, yFlip);
+            }
             targetReadout->image = psImageSubset(hdu->images->data[i], *trimsec);
         }
@@ -519,5 +454,8 @@
                 psFree(biassecString);
             } else {
-                copyPixels(hdu->images->data[i], bias, *biassec, xFlip, yFlip);
+                binRegion(biassec, xBin, yBin);
+                if (pixels) {
+                    copyPixels(hdu->images->data[i], bias, *biassec, xFlip, yFlip);
+                }
                 psImage *newBias = psImageSubset(hdu->images->data[i], *biassec);
                 psListAdd(targetReadout->bias, PS_LIST_TAIL, newBias);
@@ -565,4 +503,147 @@
     }
 
+    // Update the binning concepts
+    psMetadataItem *binItem = psMetadataLookup(target->concepts, "CELL.XBIN");
+    binItem->data.S32 *= xBin;
+    binItem = psMetadataLookup(target->concepts, "CELL.YBIN");
+    binItem->data.S32 *= yBin;
+
     return numReadouts;
 }
+
+static int chipCopy(pmChip *target,          // The target chip
+                    pmChip *source,          // The source chip, to be copied
+                    bool pixels,             // Copy the pixels?
+                    int xBin, int yBin       // (Relative) binning factors in x and y
+                   )
+{
+    assert(target);
+    assert(source);
+
+    psArray *targetCells = target->cells; // The target cells
+    psArray *sourceCells = source->cells; // The source cells
+    if (targetCells->n != sourceCells->n) {
+        psError(PS_ERR_IO, true, "Number of source cells (%d) differs from the number of target cells (%d)\n",
+                sourceCells->n, targetCells->n);
+        return false;
+    }
+
+    // Copy any headers
+    if (target->hdu && !target->hdu->phu) {
+        pmHDU *sourceHDU = pmHDUFromChip(source);
+        target->hdu->header = psMetadataCopy(target->hdu->header, sourceHDU->header);
+    }
+
+    int numCells = 0;                   // Number of cells copied
+    for (int i = 0; i < targetCells->n; i++) {
+        pmCell *targetCell = targetCells->data[i]; // The target cell
+        const char *cellName = psMetadataLookupStr(NULL, targetCell->concepts, "CELL.NAME"); // Name of cell
+        int cellNum = pmChipFindCell(source, cellName); // Number of cell with that name
+        if (cellNum >= 0) {
+            pmCell *sourceCell = sourceCells->data[cellNum]; // The source cell
+            int numReadouts = cellCopy(targetCell, sourceCell, pixels, xBin, yBin); // Number of readouts
+            // copied
+            psTrace(__func__, 5, "Copied %d readouts for cell %s\n", numReadouts, cellName);
+            numCells++;
+        }
+    }
+
+    // Update the concepts
+    psMetadataCopy(target->concepts, source->concepts);
+
+    return numCells;
+
+}
+
+static int fpaCopy(pmFPA *target,            // The target FPA
+                   pmFPA *source,            // The source FPA, to be copied
+                   bool pixels,              // Copy the pixels?
+                   int xBin, int yBin        // (Relative) binning factors in x and y
+                  )
+{
+    assert(target);
+    assert(source);
+
+    psArray *targetChips = target->chips; // The target chips
+    psArray *sourceChips = source->chips; // The source chips
+    if (targetChips->n != sourceChips->n) {
+        psError(PS_ERR_IO, true, "Number of source chips (%d) differs from the number of target chips (%d)\n",
+                sourceChips->n, targetChips->n);
+        return false;
+    }
+
+    // Copy any headers
+    if (target->hdu && !target->hdu->phu) {
+        pmHDU *sourceHDU = pmHDUFromFPA(source);
+        target->hdu->header = psMetadataCopy(target->hdu->header, sourceHDU->header);
+    }
+
+    int numChips = 0;                   // Number of chips copied
+    for (int i = 0; i < targetChips->n; i++) {
+        pmChip *targetChip = targetChips->data[i]; // The target chip
+        const char *chipName = psMetadataLookupStr(NULL, targetChip->concepts, "CHIP.NAME"); // Name of chip
+        int chipNum = pmFPAFindChip(source, chipName); // Number of chip with that name
+        if (chipNum >= 0) {
+            pmChip *sourceChip = sourceChips->data[chipNum]; // The source chip
+            int numCells = chipCopy(targetChip, sourceChip, pixels, xBin, yBin); // Number of cells copied
+            psTrace(__func__, 5, "Copied %d cells for chip %s\n", numCells, chipName);
+            numChips++;
+        }
+    }
+
+    // Update the concepts
+    psMetadataCopy(target->concepts, source->concepts);
+
+    return numChips;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+int pmFPACopy(pmFPA *target,            // The target FPA
+              pmFPA *source             // The source FPA, to be copied
+             )
+{
+    return fpaCopy(target, source, true, 1, 1);
+}
+
+int pmChipCopy(pmChip *target,          // The target chip
+               pmChip *source           // The source chip, to be copied
+              )
+{
+    return chipCopy(target, source, true, 1, 1);
+}
+
+int pmCellCopy(pmCell *target,          // The target cell
+               pmCell *source           // The source cell, to be copied
+              )
+{
+    return cellCopy(target, source, true, 1, 1);
+}
+
+
+int pmFPACopyStructure(pmFPA *target,   // The target FPA
+                       pmFPA *source,   // The source FPA, to be copied
+                       int xBin, int yBin // Binning factors in x and y
+                      )
+{
+    return fpaCopy(target, source, false, xBin, yBin);
+}
+
+int pmChipCopyStructure(pmChip *target, // The target chip
+                        pmChip *source, // The source chip, to be copied
+                        int xBin, int yBin // Binning factors in x and y
+                       )
+{
+    return chipCopy(target, source, false, xBin, yBin);
+}
+
+int pmCellCopyStructure(pmCell *target, // The target cell
+                        pmCell *source, // The source cell, to be copied
+                        int xBin, int yBin // Binning factors in x and y
+                       )
+{
+    return cellCopy(target, source, false, xBin, yBin);
+}
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPACopy.h
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPACopy.h	(revision 6827)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPACopy.h	(revision 6828)
@@ -2,4 +2,5 @@
 #define PM_FPA_COPY_H
 
+// Copy the FPA components, including the pixels
 int pmFPACopy(pmFPA *target,            // The target FPA
               pmFPA *source             // The source FPA, to be copied
@@ -12,3 +13,18 @@
               );
 
+// Versions that copy the structure and not the pixels; they also allow binning
+int pmFPACopyStructure(pmFPA *target,   // The target FPA
+                       pmFPA *source,   // The source FPA, to be copied
+                       int xBin, int yBin     // Binning factors in x and y
+                      );
+int pmChipCopyStructure(pmChip *target, // The target chip
+                        pmChip *source, // The source chip, to be copied
+                        int xBin, int yBin   // Binning factors in x and y
+                       );
+int pmCellCopyStructure(pmCell *target, // The target cell
+                        pmCell *source, // The source cell, to be copied
+                        int xBin, int yBin // Binning factors in x and y
+                       );
+
+
 #endif
