Index: trunk/psModules/src/camera/pmFPAMosaic.c
===================================================================
--- trunk/psModules/src/camera/pmFPAMosaic.c	(revision 7605)
+++ trunk/psModules/src/camera/pmFPAMosaic.c	(revision 7606)
@@ -447,9 +447,9 @@
     // Set up the image
     // Since both upper and lower values are inclusive, we need to add one to the size
-    float xSize = (float)(xMax - xMin + 1) / (float)xBinTarget;
+    float xSize = (float)(xMax + 1) / (float)xBinTarget;
     if (xSize - (int)xSize > 0) {
         xSize += 1;
     }
-    float ySize = (float)(yMax - yMin + 1) / (float)yBinTarget;
+    float ySize = (float)(yMax + 1) / (float)yBinTarget;
     if (ySize - (int)ySize > 0) {
         ySize += 1;
@@ -629,5 +629,7 @@
                     int *xBinMin,       // The minimum x binning, returned
                     int *yBinMin,       // The minimum y binning, returned
-                    bool chipStuff      // Worry about chip stuff as well?
+                    bool chipStuff,      // Worry about chip stuff as well?
+                    int x0Target, int y0Target, // Target x0 and y0 offsets
+                    int xParityTarget, int yParityTarget // Target parities
                    )
 {
@@ -743,17 +745,17 @@
 
     // Set the flips on the basis of the parity
-    if (xParityCell * xParityChip == -1) {
+    if (xParityCell * xParityChip == xParityTarget) {
+        xFlip->data.U8[index] = 0;
+    } else {
         xFlip->data.U8[index] = 1;
+    }
+    if (yParityCell * yParityChip == yParityTarget) {
+        yFlip->data.U8[index] = 0;
     } else {
-        xFlip->data.U8[index] = 0;
-    }
-    if (yParityCell * yParityChip == -1) {
         yFlip->data.U8[index] = 1;
-    } else {
-        yFlip->data.U8[index] = 0;
-    }
-
-    x0->data.S32[index] = x0Chip + x0Cell;
-    y0->data.S32[index] = y0Chip + y0Cell;
+    }
+
+    x0->data.S32[index] = x0Chip + x0Cell - x0Target;
+    y0->data.S32[index] = y0Chip + y0Cell - y0Target;
 
     // Add the readout to the array of images to be mosaicked
@@ -783,5 +785,6 @@
                        psImage **mosaicWeights, // The mosaic weights, to be returned
                        int *xBinChip, int *yBinChip, // The binning in x and y, to be returned
-                       const pmChip *chip // Chip to mosaic
+                       const pmChip *chip, // Chip to mosaic
+                       const pmCell *targetCell // Cell to which to mosaic
                       )
 {
@@ -789,5 +792,8 @@
     assert(mosaicMask);
     assert(mosaicWeights);
+    assert(xBinChip);
+    assert(yBinChip);
     assert(chip);
+    assert(targetCell);
 
     psArray *images = psArrayAlloc(0); // Array of images that will be mosaicked
@@ -801,4 +807,25 @@
     psVector *yFlip = psVectorAlloc(0, PS_TYPE_U8); // Flip in y?
 
+    // Get the target characteristics
+    bool mdok = true;                   // Status of MD lookup
+    int x0Target = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.X0");
+    if (!mdok) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.X0 is not set for the target cell; assuming 0.\n");
+    }
+    int y0Target = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.Y0");
+    if (!mdok) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.Y0 is not set for the target cell; assuming 0.\n");
+    }
+    int xParityTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.XPARITY");
+    if (!mdok || (xParityTarget != -1 && xParityTarget != 1)) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.XPARITY is not set for the target cell; assuming 1.\n");
+        xParityTarget = 1;
+    }
+    int yParityTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.YPARITY");
+    if (!mdok || (yParityTarget != -1 && yParityTarget != 1)) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.YPARITY is not set for the target cell; assuming 1.\n");
+        yParityTarget = 1;
+    }
+
     // Binning for the mosaicked chip is the minimum binning allowed by the cells
     *xBinChip = INT_MAX;
@@ -814,5 +841,20 @@
         }
         allGood |= addCell(images, masks, weights, x0, y0, xBin, yBin, xFlip, yFlip,
-                           cell, xBinChip, yBinChip, false);
+                           cell, xBinChip, yBinChip, false, x0Target, y0Target,
+                           xParityTarget, yParityTarget);
+    }
+
+    // Check to see if the target has a smaller binning in mind
+    int xBinTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.XBIN");
+    if (!mdok || xBinTarget == 0) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.XBIN is not set for the target cell; assuming %d.\n",*xBinChip);
+    } else {
+        *xBinChip = xBinTarget;
+    }
+    int yBinTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.YBIN");
+    if (!mdok || yBinTarget == 0) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.YBIN is not set for the target cell; assuming %d.\n",*yBinChip);
+    } else {
+        *yBinChip = yBinTarget;
     }
 
@@ -843,5 +885,7 @@
                       psImage **mosaicWeights, // The mosaic weights, to be returned
                       int *xBinFPA, int *yBinFPA, // The binning in x and y, to be returned
-                      const pmFPA *fpa  // FPA to mosaic
+                      const pmFPA *fpa,  // FPA to mosaic
+                      const pmChip *targetChip, // Chip to which to mosaic
+                      const pmCell *targetCell // Cell to which to mosaic
                      )
 {
@@ -849,5 +893,9 @@
     assert(mosaicMask);
     assert(mosaicWeights);
+    assert(xBinFPA);
+    assert(yBinFPA);
     assert(fpa);
+    assert(targetChip);
+    assert(targetCell);
 
     psArray *images = psArrayAlloc(0); // Array of images that will be mosaicked
@@ -861,4 +909,45 @@
     psVector *yFlip = psVectorAlloc(0, PS_TYPE_U8); // Flip in y?
 
+    // Get the target characteristics
+    bool mdok = true;                   // Status of MD lookup
+    int x0Target = psMetadataLookupS32(&mdok, targetChip->concepts, "CHIP.X0");
+    if (!mdok) {
+        psLogMsg(__func__, PS_LOG_WARN, "CHIP.X0 is not set for the target chip; assuming 0.\n");
+    }
+    int y0Target = psMetadataLookupS32(&mdok, targetChip->concepts, "CHIP.Y0");
+    if (!mdok) {
+        psLogMsg(__func__, PS_LOG_WARN, "CHIP.Y0 is not set for the target chip; assuming 0.\n");
+    }
+    x0Target += psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.X0");
+    if (!mdok) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.X0 is not set for the target cell; assuming 0.\n");
+    }
+    y0Target += psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.Y0");
+    if (!mdok) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.Y0 is not set for the target cell; assuming 0.\n");
+    }
+    int xParityChipTarget = psMetadataLookupS32(&mdok, targetChip->concepts, "CHIP.XPARITY");
+    if (!mdok || (xParityChipTarget != -1 && xParityChipTarget != 1)) {
+        psLogMsg(__func__, PS_LOG_WARN, "CHIP.XPARITY is not set for the target chip; assuming 1.\n");
+        xParityChipTarget = 1;
+    }
+    int yParityChipTarget = psMetadataLookupS32(&mdok, targetChip->concepts, "CHIP.YPARITY");
+    if (!mdok || (yParityChipTarget != -1 && yParityChipTarget != 1)) {
+        psLogMsg(__func__, PS_LOG_WARN, "CHIP.YPARITY is not set for the target chip; assuming 1.\n");
+        yParityChipTarget = 1;
+    }
+    int xParityCellTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.XPARITY");
+    if (!mdok || (xParityCellTarget != -1 && xParityCellTarget != 1)) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.XPARITY is not set for the target cell; assuming 1.\n");
+        xParityCellTarget = 1;
+    }
+    int yParityCellTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.YPARITY");
+    if (!mdok || (yParityCellTarget != -1 && yParityCellTarget != 1)) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.YPARITY is not set for the target cell; assuming 1.\n");
+        yParityCellTarget = 1;
+    }
+    int xParityTarget = xParityChipTarget * xParityCellTarget;
+    int yParityTarget = yParityChipTarget * yParityCellTarget;
+
     // Binning for the mosaicked chip is the minimum binning allowed by the cells
     *xBinFPA = INT_MAX;
@@ -880,6 +969,21 @@
             }
             allGood |= addCell(images, masks, weights, x0, y0, xBin, yBin, xFlip, yFlip,
-                               cell, xBinFPA, yBinFPA, true);
-        }
+                               cell, xBinFPA, yBinFPA, true, x0Target, y0Target,
+                               xParityTarget, yParityTarget);
+        }
+    }
+
+    // Check to see if the target has a smaller binning in mind
+    int xBinTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.XBIN");
+    if (!mdok || xBinTarget == 0) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.XBIN is not set for the target cell; assuming %d.\n", *xBinFPA);
+    } else {
+        *xBinFPA = xBinTarget;
+    }
+    int yBinTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.YBIN");
+    if (!mdok || yBinTarget == 0) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.YBIN is not set for the target cell; assuming %d.\n", *yBinFPA);
+    } else {
+        *yBinFPA = yBinTarget;
     }
 
@@ -975,5 +1079,5 @@
         // Case 2 --- we need to mosaic by cut and paste
         psTrace(__func__, 1, "Case 2 mosaicking: cut and paste.\n");
-        if (!chipMosaic(&mosaicImage, &mosaicMask, &mosaicWeights, &xBin, &yBin, source)) {
+        if (!chipMosaic(&mosaicImage, &mosaicMask, &mosaicWeights, &xBin, &yBin, source, targetCell)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to mosaic cells.\n");
             return false;
@@ -1056,5 +1160,6 @@
         // Case 2 --- we need to mosaic by cut and paste
         psTrace(__func__, 1, "Case 2 mosaicking: cut and paste.\n");
-        if (!fpaMosaic(&mosaicImage, &mosaicMask, &mosaicWeights, &xBin, &yBin, source)) {
+        if (!fpaMosaic(&mosaicImage, &mosaicMask, &mosaicWeights, &xBin, &yBin, source,
+                       targetChip, targetCell)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to mosaic chips.\n");
             return false;
