Index: /trunk/psModules/src/camera/pmFPAMosaic.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAMosaic.c	(revision 13194)
+++ /trunk/psModules/src/camera/pmFPAMosaic.c	(revision 13195)
@@ -14,8 +14,11 @@
 #include "pmConceptsAverage.h"
 #include "pmHDUUtils.h"
+#include "pmConfig.h"
+#include "pmAstrometryWCS.h"
+
 #include "pmFPAMosaic.h"
-#include "pmConfig.h"
-
-#define CELL_LIST_BUFFER 50             // Buffer size for cell lists
+
+
+#define CELL_LIST_BUFFER 10             // Buffer size for cell lists
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -634,5 +637,5 @@
     if (!mdok || xBin->data.S32[index] == 0) {
         psError(PS_ERR_UNKNOWN, true, "CELL.XBIN for cell is not set.\n");
-	return false;
+        return false;
     } else if (xBin->data.S32[index] < *xBinMin) {
         *xBinMin = xBin->data.S32[index];
@@ -641,5 +644,5 @@
     if (!mdok || yBin->data.S32[index] == 0) {
         psError(PS_ERR_UNKNOWN, true, "CELL.YBIN for cell is not set.\n");
-	return false;
+        return false;
     } else if (yBin->data.S32[index] < *yBinMin) {
         *yBinMin = yBin->data.S32[index];
@@ -650,10 +653,10 @@
     if (!mdok || (xParityCell != 1 && xParityCell != -1)) {
         psError(PS_ERR_UNKNOWN, true, "CELL.XPARITY for cell is not set.\n");
-	return false;
+        return false;
     }
     int yParityCell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YPARITY");
     if (!mdok || (yParityCell != 1 && yParityCell != -1)) {
         psError(PS_ERR_UNKNOWN, true, "CELL.YPARITY for cell is not set.\n");
-	return false;
+        return false;
     }
 
@@ -665,10 +668,10 @@
         if (!mdok || (xParityChip != 1 && xParityChip != -1)) {
             psError(PS_ERR_UNKNOWN, true, "CHIP.XPARITY for chip is not set.\n");
-	    return false;
+            return false;
         }
         yParityChip = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.YPARITY");
         if (!mdok || (yParityChip != 1 && yParityChip != -1)) {
             psError(PS_ERR_UNKNOWN, true, "CHIP.YPARITY for chip is not set.\n");
-	    return false;
+            return false;
         }
     }
@@ -751,34 +754,16 @@
         FIX_CONCEPT(targetCell->concepts, "CELL.Y0", S32, 0);
     }
-    int xParityCellTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.XPARITY");
-    if (!mdok || (xParityCellTarget != -1 && xParityCellTarget != 1)) {
+    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");
         FIX_CONCEPT(targetCell->concepts, "CELL.XPARITY", S32, 1);
-        xParityCellTarget = 1;
-    }
-    int yParityCellTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.YPARITY");
-    if (!mdok || (yParityCellTarget != -1 && yParityCellTarget != 1)) {
+        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");
         FIX_CONCEPT(targetCell->concepts, "CELL.YPARITY", S32, 1);
-        yParityCellTarget = 1;
-    }
-    # if (0)
-    int xParityChipTarget = psMetadataLookupS32(&mdok, targetCell->parent->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");
-        FIX_CONCEPT(targetCell->parent->concepts, "CHIP.XPARITY", S32, 1);
-        xParityChipTarget = 1;
-    }
-    int yParityChipTarget = psMetadataLookupS32(&mdok, targetCell->parent->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");
-        FIX_CONCEPT(targetCell->parent->concepts, "CHIP.YPARITY", S32, 1);
-        yParityChipTarget = 1;
-    }
-    int xParityTarget = xParityChipTarget * xParityCellTarget;
-    int yParityTarget = yParityChipTarget * yParityCellTarget;
-    # endif
-    int xParityTarget = xParityCellTarget;
-    int yParityTarget = yParityCellTarget;
+        yParityTarget = 1;
+    }
 
     // Binning for the mosaicked chip is the minimum binning allowed by the cells
@@ -1105,11 +1090,11 @@
     }
     if (!targetPHU->header) {
-	// if we don't yet have a header, copy this one.
-	// XXX do we need to create an empty one if the levels do not match??
-	if (true) {
-	    targetPHU->header = psMetadataCopy(targetPHU->header, sourcePHU->header);
-	} else {
-	    targetPHU->header = psMetadataAlloc();
-	}
+        // if we don't yet have a header, copy this one.
+        // XXX do we need to create an empty one if the levels do not match??
+        if (true) {
+            targetPHU->header = psMetadataCopy(targetPHU->header, sourcePHU->header);
+        } else {
+            targetPHU->header = psMetadataAlloc();
+        }
     }
 
@@ -1118,43 +1103,84 @@
         return false;
     }
-    
-// this code extracts the WCS information from the header of one of the cells and applies it to
-// the mosaicked chip.  XXX EAM : I am leaving it at this point for PAP to get the binning, etc
-// from the concepts
-# if (0)
-    // if the cells contain the headers, we need to apply the WCS terms from (one of?) the cells
+
+    // If the cells contain the headers, we need to apply the WCS terms from (one of?) the cells
     for (int i = 0; i < source->cells->n; i++) {
-	pmCell *cell = source->cells->data[i];
-	if (cell == NULL) continue;
-	if (cell->hdu == NULL) continue;
-
-	// extract the WCS terms from this cell
-	pmAstromWCS *wcs = pmAstromWCSfromHeader (cell->hdu->header);
-
-	// modify the wcs terms for the cell offset, binning, and parity
-	xBinRatio = xBinCell / xBinChip;
-	if (xFlip) {
-	    wcs->crpix1 = xCell - wcs->crpix1*xBinRatio;
-	    wcs->cdelt1 *= -1;
-	} else {
-	    wcs->crpix1 = xCell + wcs->crpix1*xBinRatio;
-	}
-	wcs->cdelt1 *= xBinRatio;
-
-	yBinRatio = yBinCell / yBinChip;
-	if (yFlip) {
-	    wcs->crpix2 = yCell - wcs->crpix2*yBinRatio;
-	    wcs->cdelt2 *= -1;
-	} else {
-	    wcs->crpix2 = xCell + wcs->crpix2*yBinRatio;
-	}
-	wcs->cdelt2 *= yBinRatio;
-
-	pmAstromWCStoHeader (targetHDU->header);
-	break;
-	// XXX rather than quitting at this point, we could save this wcs structure and compare
-	// its values to the equivalent version from one of the other cells.
-    }
-# endif
+        pmCell *cell = source->cells->data[i];
+        if (!cell || !cell->hdu || !cell->hdu->header) {
+            continue;
+        }
+
+        pmAstromWCS *wcs = pmAstromWCSfromHeader(cell->hdu->header); // WCS terms for this cell
+        if (!wcs) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to read cell WCS to generate chip WCS.");
+            return false;
+        }
+
+        int xBinCell = psMetadataLookupS32(NULL, cell->concepts, "CELL.XBIN"); // Cell binning in x
+        if (xBinCell == 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CELL.XBIN is not set.");
+            return false;
+        }
+        int xParityCell = psMetadataLookupS32(NULL, cell->concepts, "CELL.XPARITY"); // Cell parity in x
+        if (xParityCell != -1 && xParityCell != 1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CELL.XPARITY is not set.");
+            return false;
+        }
+        int xParityChip = psMetadataLookupS32(NULL, cell->concepts, "CHIP.XPARITY"); // Chip parity in x
+        if (xParityChip != -1 && xParityChip != 1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CHIP.XPARITY is not set.");
+            return false;
+        }
+        bool xFlip = (xParityCell == xParityChip ? false : true); // Flip the x sense of the WCS?
+        int x0Cell = psMetadataLookupS32(NULL, cell->concepts, "CELL.X0"); // Cell offset in x
+
+        // Modify the wcs terms for the cell offset, binning, and parity
+        float xBinRatio = (float)xBinCell / (float)xBin;
+        if (xFlip) {
+            wcs->crpix1 = x0Cell - wcs->crpix1 * xBinRatio;
+            wcs->cdelt1 *= -1;
+        } else {
+            wcs->crpix1 = x0Cell + wcs->crpix1 * xBinRatio;
+        }
+        wcs->cdelt1 *= xBinRatio;
+
+        int yBinCell = psMetadataLookupS32(NULL, cell->concepts, "CELL.YBIN"); // Cell binning in y
+        if (yBinCell == 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CELL.YBIN is not set.");
+            return false;
+        }
+        int yParityCell = psMetadataLookupS32(NULL, cell->concepts, "CELL.YPARITY"); // Cell parity in y
+        if (yParityCell != -1 && yParityCell != 1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CELL.YPARITY is not set.");
+            return false;
+        }
+        int yParityChip = psMetadataLookupS32(NULL, cell->concepts, "CHIP.YPARITY"); // Chip parity in y
+        if (yParityChip != -1 && yParityChip != 1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CHIP.YPARITY is not set.");
+            return false;
+        }
+        bool yFlip = (yParityCell == yParityChip ? false : true); // Flip the y sense of the WCS?
+        int y0Cell = psMetadataLookupS32(NULL, cell->concepts, "CELL.Y0"); // Cell offset in y
+
+        float yBinRatio = (float)yBinCell / (float)yBin;
+        if (yFlip) {
+            wcs->crpix2 = y0Cell - wcs->crpix2 * yBinRatio;
+            wcs->cdelt2 *= -1;
+        } else {
+            wcs->crpix2 = y0Cell + wcs->crpix2 * yBinRatio;
+        }
+        wcs->cdelt2 *= yBinRatio;
+
+        if (!pmAstromWCStoHeader(targetHDU->header, wcs)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate chip WCS from cell WCS.");
+            psFree(wcs);
+            return false;
+        }
+        psFree(wcs);
+
+        // XXX rather than quitting at this point, we could save this wcs structure and compare
+        // its values to the equivalent version from one of the other cells.
+        break;
+    }
 
     return true;
