Index: /branches/eam_rel9_p0/psModules/src/astrom/pmChipMosaic.c
===================================================================
--- /branches/eam_rel9_p0/psModules/src/astrom/pmChipMosaic.c	(revision 6079)
+++ /branches/eam_rel9_p0/psModules/src/astrom/pmChipMosaic.c	(revision 6080)
@@ -37,4 +37,5 @@
     int yMin = INT_MAX;
     int yMax = - INT_MAX;
+    psElemType type = 0;
     for (int i = 0; i < source->n; i++) {
         psImage *image = source->data[i]; // The image of interest
@@ -43,5 +44,11 @@
         }
 
-        assert(image->type.type == PS_TYPE_F32); // Only implemented for F32 images so far.
+        // Only implemented for F32 and U8 images so far.
+        assert(image->type.type == PS_TYPE_F32 || image->type.type == PS_TYPE_U8);
+        // All input types must be the same
+        if (type == 0) {
+            type = image->type.type;
+        }
+        assert(type == image->type.type);
 
         // Size of cell in x and y
@@ -71,5 +78,5 @@
 
     psTrace(__func__, 3, "Spliced image will be %dx%d\n", (int)xSize, (int)ySize);
-    psImage *mosaic = psImageAlloc((int)xSize, (int)ySize, PS_TYPE_F32); // The mosaic image
+    psImage *mosaic = psImageAlloc((int)xSize, (int)ySize, type); // The mosaic image
     psImageInit(mosaic, 0.0);
 
@@ -96,12 +103,24 @@
                     // In case the original image is binned but the mosaic is not, we need to fill in the
                     // values in the mosaic.
-                    for (int j = 0; j < yBinSource->data.S32[i]; j++) {
-                        int yTarget = (int)(yTargetBase + yParity * (float)j / (float)yBinTarget);
-                        for (int i = 0; i < xBinSource->data.S32[i]; i++) {
-                            int xTarget = (int)(xTargetBase + xParity * (float)i / (float)xBinTarget);
-
-                            mosaic->data.F32[yTarget][xTarget] += image->data.F32[y][x];
-                        }
-                    } // Iterating over mosaic image for binned input image
+                    #define FILL_IN(TYPE)                                                                    \
+                    for (int j = 0; j < yBinSource->data.S32[i]; j++) {                                      \
+                        int yTarget = (int)(yTargetBase + yParity * (float)j / (float)yBinTarget);           \
+                        for (int i = 0; i < xBinSource->data.S32[i]; i++) {                                  \
+                            int xTarget = (int)(xTargetBase + xParity * (float)i / (float)xBinTarget);       \
+                            mosaic->data.TYPE[yTarget][xTarget] += image->data.TYPE[y][x];                   \
+                        }                                                                                    \
+                    }
+
+                    switch (type) {
+                    case PS_TYPE_F32:
+                        FILL_IN(F32);
+                        break;
+                    case PS_TYPE_U8:
+                        FILL_IN(U8);
+                        break;
+                    default:
+                        psAbort(__func__, "Should never get here.\n");
+                    }
+
                 }
             } // Iterating over input image
@@ -158,8 +177,4 @@
         }
 
-        // Trim the image to get rid of the overscan
-        psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC");
-        psTrace(__func__, 7, "Cell %d trimsec: [%.0f:%.0f,%.0f:%.0f]\n", i, trimsec->x0, trimsec->x1,
-                trimsec->y0, trimsec->y1);
         psArray *readouts = cell->readouts; // The array of readouts
         if (readouts->n > 1) {
@@ -167,10 +182,10 @@
                      "be mosaicked.\n", i);
         }
-        psImage *image = ((pmReadout*)readouts->data[0])->image; // The image to put into the mosaic
-        psImage *weight = ((pmReadout*)readouts->data[0])->weight;
-        psImage *mask = ((pmReadout*)readouts->data[0])->weight;
-        images->data[i] = psImageSubset(image, *trimsec); // Trimmed image
-        weights->data[i] = weight ? psImageSubset(weight, *trimsec) : NULL;
-        masks->data[i] = mask ? psImageSubset(mask, *trimsec) : NULL;
+        pmReadout *readout = readouts->data[0]; // The only readout we'll bother with
+
+        // The images to put into the mosaic
+        images->data[i]  = readout->image;
+        weights->data[i] = readout->weight;
+        masks->data[i]   = readout->mask;
     }
     // Mosaic the images together and we're done
Index: /branches/eam_rel9_p0/psModules/src/astrom/pmConcepts.c
===================================================================
--- /branches/eam_rel9_p0/psModules/src/astrom/pmConcepts.c	(revision 6079)
+++ /branches/eam_rel9_p0/psModules/src/astrom/pmConcepts.c	(revision 6080)
@@ -160,4 +160,8 @@
     while ((item = psMetadataGetAndIncrement(iter))) {
         const char *name = item->name;  // Name of the concept
+        if (!strcmp(name, "CELL.NAME") || !strcmp(name, "CHIP.NAME")) {
+            // These concepts are not written out; they are set from things like the FITS extname
+            continue;
+        }
         psMetadataItem *specItem = psMetadataLookup(*specs, name); // Specification for the concept
         if (specItem) {
Index: /branches/eam_rel9_p0/psModules/src/astrom/pmFPA.c
===================================================================
--- /branches/eam_rel9_p0/psModules/src/astrom/pmFPA.c	(revision 6079)
+++ /branches/eam_rel9_p0/psModules/src/astrom/pmFPA.c	(revision 6080)
@@ -12,6 +12,6 @@
 * XXX: Should we implement non-linear cell->chip transforms?
 *
-*  @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2006-01-20 02:36:41 $
+*  @version $Revision: 1.1.2.2 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-01-20 09:47:06 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -23,8 +23,10 @@
 #include <string.h>
 #include <math.h>
+#include <assert.h>
 #include "pslib.h"
 
 #include "pmFPA.h"
 #include "pmConcepts.h"
+#include "pmMaskBadPixels.h"
 
 /******************************************************************************
@@ -163,4 +165,5 @@
     tmpReadout->mask = NULL;
     tmpReadout->weight = NULL;
+    tmpReadout->bias = psListAlloc(NULL);
     tmpReadout->analysis = psMetadataAlloc();
     tmpReadout->parent = cell;
@@ -390,4 +393,25 @@
 }
 
+bool pmChipSelectCell(pmChip *chip,
+                      int cellNum
+                     )
+{
+    assert(chip);
+
+    psArray *cells = chip->cells;       // Component cells
+    if (!cells || cellNum > cells->n) {
+        return false;
+    }
+
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];
+        if (!cell) {
+            continue;
+        }
+        cell->process = (i == cellNum);
+    }
+
+    return true;
+}
 
 /*****************************************************************************
@@ -437,4 +461,31 @@
 }
 
+int pmChipExcludeCell(pmChip *chip,
+                      int cellNum
+                     )
+{
+    assert(chip);
+
+    psArray *cells = chip->cells;       // The component cells
+    if (!cells || cellNum > cells->n) {
+        return 0;
+    }
+
+    int numCells = 0;                   // Number of cells to be processed
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];
+        if (!cell) {
+            continue;
+        }
+        if (i == cellNum) {
+            cell->process = false;
+        } else {
+            numCells++;
+        }
+    }
+
+    return numCells;
+}
+
 
 bool pmCellSetWeights(pmCell *cell // Cell for which to set weights
@@ -444,4 +495,6 @@
     float readnoise = psMetadataLookupF32(NULL, cell->concepts, "CELL.READNOISE"); // Cell read noise
     psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC"); // Trim section
+    float saturation = psMetadataLookupF32(NULL, cell->concepts, "CELL.SATURATION"); // Saturation level
+    float bad = psMetadataLookupF32(NULL, cell->concepts, "CELL.BAD"); // Bad level
 
     p_pmHDU *hdu = cell->hdu;           // The data unit, containing the weight and mask originals
@@ -478,5 +531,4 @@
             psImage *image = pixels->data[i];
             masks->data[i] = psImageAlloc(image->numCols, image->numRows, PS_TYPE_U8);
-            psImageInit(masks->data[i], 0);
         }
         hdu->masks = masks;
@@ -489,17 +541,27 @@
 
         if (! readout->weight) {
-            readout->weight = weights->data[i];
+            readout->weight = psImageSubset(weights->data[i], *trimsec);
         }
         if (! readout->mask) {
-            readout->mask = masks->data[i];
-        }
-
-        // Mask is already set to 0
+            readout->mask = psImageSubset(masks->data[i], *trimsec);
+        }
+
+        // Set up the mask
+        psImage *image = readout->image;// Pixels
+        psImage *mask = readout->mask;  // Mask image
+        for (int i = 0; i < image->numRows; i++) {
+            for (int j = 0; j < image->numCols; j++) {
+                if (image->data.F32[i][j] > saturation) {
+                    mask->data.F32[i][j] = PM_MASK_SAT;
+                }
+                if (image->data.F32[i][j] < bad) {
+                    mask->data.F32[i][j] = PM_MASK_BAD;
+                }
+            }
+        }
 
         // Set weight image to the variance = g*f + rn^2
-        psImage *image = psImageSubset(readout->image, *trimsec); // The pixels
-        psImage *weight = psImageSubset(readout->weight, *trimsec); // The weight map
-        psBinaryOp(weight, image, "*", psScalarAlloc(gain, PS_TYPE_F32));
-        psBinaryOp(weight, weight, "+", psScalarAlloc(readnoise*readnoise, PS_TYPE_F32));
+        psBinaryOp(readout->weight, image, "*", psScalarAlloc(gain, PS_TYPE_F32));
+        psBinaryOp(readout->weight, readout->weight, "+", psScalarAlloc(readnoise*readnoise, PS_TYPE_F32));
     }
 
Index: /branches/eam_rel9_p0/psModules/src/astrom/pmFPA.h
===================================================================
--- /branches/eam_rel9_p0/psModules/src/astrom/pmFPA.h	(revision 6079)
+++ /branches/eam_rel9_p0/psModules/src/astrom/pmFPA.h	(revision 6080)
@@ -7,6 +7,6 @@
 *  @author GLG, MHPCC
 *
-*  @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2006-01-20 02:36:41 $
+*  @version $Revision: 1.1.2.2 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-01-20 09:47:06 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -153,4 +153,5 @@
     psImage *mask;                      ///< Mask of input image
     psImage *weight;                    ///< Weight of input image
+    psList *bias;                       ///< Overscan images
     psMetadata *analysis;               ///< Readout-level analysis metadata
     pmCell *parent;                     ///< Parent cell
@@ -261,4 +262,8 @@
 );
 
+bool pmChipSelectCell(pmChip *chip,
+                      int cellNum
+                     );
+
 /**
  *
@@ -275,4 +280,7 @@
 );
 
+int pmChipExcludeCell(pmChip *chip,
+                      int cellNum
+                     );
 
 // Set the weights and masks within a cell, based on the gain and RN
Index: /branches/eam_rel9_p0/psModules/src/astrom/pmFPARead.c
===================================================================
--- /branches/eam_rel9_p0/psModules/src/astrom/pmFPARead.c	(revision 6079)
+++ /branches/eam_rel9_p0/psModules/src/astrom/pmFPARead.c	(revision 6080)
@@ -1,4 +1,5 @@
 #include <stdio.h>
 #include <strings.h>
+#include <assert.h>
 #include "pslib.h"
 
@@ -105,17 +106,29 @@
 {
     psArray *images = hdu->images;      // Array of images (each of which is a readout)
-    psArray *masks = hdu->masks;        // Array of masks (one for each readout)
+
+    psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC");
+    psList *biassecs = psMetadataLookupPtr(NULL, cell->concepts, "CELL.BIASSEC");
+
     // Iterate over each of the image planes
     for (int i = 0; i < images->n; i++) {
         psImage *image = images->data[i]; // The i-th plane
-        psImage *mask = NULL;           // The mask
-        if (masks) {
-            mask = masks->data[i];
-        }
-
         pmReadout *readout = pmReadoutAlloc(cell);
-        readout->image = image;
-        readout->mask = mask;
-        psFree(readout);
+
+        readout->image = psImageSubset(image, *trimsec); // The image corresponding to the trim region
+
+        // Get the list of overscans
+        psListIterator *iter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, false); // Iterator
+        psRegion *biassec = NULL;       // A BIASSEC region from the list
+        while ((biassec = psListGetAndIncrement(iter))) {
+            psImage *overscan = psImageSubset(image, *biassec);
+            psListAdd(readout->bias, PS_LIST_TAIL, overscan);
+            psFree(overscan);
+        }
+        psFree(iter);
+
+        readout->mask = NULL;
+        readout->weight = NULL;
+
+        psFree(readout);                // Drop reference
     }
 
@@ -164,6 +177,6 @@
         pmChip *chip = chips->data[i]; // The chip
 
-        // Only read chips marked to "process"
-        if (! chip->process) {
+        // Only read chips marked to "read"
+        if (! chip->process || chip->exists) {
             psTrace(__func__, 2, "Ignoring chip %d...\n", i);
             continue;
@@ -187,6 +200,6 @@
             pmCell *cell = cells->data[j]; // The cell
 
-            // Only read cells marked to "process"
-            if (! cell->process) {
+            // Only read cells marked to "read"
+            if (! cell->process || cell->exists) {
                 psTrace(__func__, 3, "Ignoring chip %d...\n", i);
                 continue;
@@ -400,5 +413,5 @@
     for (int chipNum = 0; chipNum < chips->n; chipNum++) {
         pmChip *chip = chips->data[chipNum]; // The current chip of interest
-        if (chip->process) {
+        if (chip->process && !chip->exists) {
             if (chip->hdu) {
                 hdu = chip->hdu;
@@ -407,5 +420,5 @@
             for (int cellNum = 0; cellNum < cells->n; cellNum++) {
                 pmCell *cell = cells->data[cellNum]; // The current cell of interest
-                if (cell->process) {
+                if (cell->process && !cell->exists) {
                     if (cell->hdu) {
                         hdu = cell->hdu;
@@ -538,5 +551,5 @@
     for (int chipNum = 0; chipNum < chips->n; chipNum++) {
         pmChip *chip = chips->data[chipNum]; // The current chip of interest
-        if (chip->process) {
+        if (chip->process && !chip->exists) {
             if (chip->hdu) {
                 hdu = chip->hdu;
@@ -545,5 +558,5 @@
             for (int cellNum = 0; cellNum < cells->n; cellNum++) {
                 pmCell *cell = cells->data[cellNum]; // The current cell of interest
-                if (cell->process) {
+                if (cell->process && !cell->exists) {
                     if (cell->hdu) {
                         hdu = cell->hdu;
Index: /branches/eam_rel9_p0/psModules/src/detrend/pmFlatField.c
===================================================================
--- /branches/eam_rel9_p0/psModules/src/detrend/pmFlatField.c	(revision 6079)
+++ /branches/eam_rel9_p0/psModules/src/detrend/pmFlatField.c	(revision 6080)
@@ -24,6 +24,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.4.8.1.2.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-01-20 06:01:02 $
+ *  @version $Revision: 1.4.8.1.2.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-01-20 09:47:06 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -53,8 +53,4 @@
     psElemType flatType;
     psElemType maskType;
-    psImage *inImage = NULL;
-    psImage *inMask = NULL;
-    psImage *flatImage = NULL;
-
 
     // Check for nulls
@@ -67,11 +63,13 @@
     }
 
-    // Get the TRIMSEC of each image
-    {
-        psRegion *trimsec = psMetadataLookupPtr(NULL, in->parent->concepts, "CELL.TRIMSEC");
-        inImage = psImageSubset(in->image, *trimsec);
-        trimsec = psMetadataLookupPtr(NULL, flat->parent->concepts, "CELL.TRIMSEC");
-        flatImage = psImageSubset(flat->image, *trimsec);
-    }
+    psImage *inImage   = in->image;     // Input image
+    psImage *inMask    = in->mask;      // Mask for input image
+    psImage *flatImage = flat->image;   // Flat-field image
+
+    // Offsets on the chip
+    int x0in = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.X0");
+    int y0in = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.Y0");
+    int x0flat = psMetadataLookupS32(NULL, flat->parent->concepts, "CELL.X0");
+    int y0flat = psMetadataLookupS32(NULL, flat->parent->concepts, "CELL.Y0");
 
     if (inImage == NULL) {
@@ -84,5 +82,4 @@
         return false;
     }
-    inMask = in->mask;
 
     // Check input image and its mask are not larger than flat image
@@ -102,6 +99,6 @@
 
     // Determine total offset based on image offset with chip offset
-    totOffCol = inImage->col0 + in->col0;
-    totOffRow = inImage->row0 + in->row0;
+    totOffCol = inImage->col0 + y0in - flatImage->col0 - y0flat;
+    totOffRow = inImage->row0 + x0in - flatImage->row0 - x0flat;
 
     // Check that offsets are within image limits
Index: /branches/eam_rel9_p0/psModules/src/detrend/pmMaskBadPixels.h
===================================================================
--- /branches/eam_rel9_p0/psModules/src/detrend/pmMaskBadPixels.h	(revision 6079)
+++ /branches/eam_rel9_p0/psModules/src/detrend/pmMaskBadPixels.h	(revision 6080)
@@ -24,6 +24,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.2.8.1.2.1 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-01-20 02:38:28 $
+ *  @version $Revision: 1.2.8.1.2.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-01-20 09:47:06 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -38,5 +38,6 @@
     PM_MASK_BADCOL  = 0x0002,   ///< The pixel is a bad column.
     PM_MASK_SAT     = 0x0004,   ///< The pixel is saturated.
-    PM_MASK_FLAT    = 0x0008    ///< The pixel is non-positive in the flat-field.
+    PM_MASK_BAD     = 0x0008,   ///< The pixel is low
+    PM_MASK_FLAT    = 0x0010    ///< The pixel is non-positive in the flat-field.
 } pmMaskValue;
 
Index: /branches/eam_rel9_p0/psModules/src/imsubtract/pmSubtractBias.c
===================================================================
--- /branches/eam_rel9_p0/psModules/src/imsubtract/pmSubtractBias.c	(revision 6079)
+++ /branches/eam_rel9_p0/psModules/src/imsubtract/pmSubtractBias.c	(revision 6080)
@@ -11,6 +11,6 @@
  *  @author GLG, MHPCC
  *
- *  @version $Revision: 1.6.8.1.2.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-01-20 06:03:29 $
+ *  @version $Revision: 1.6.8.1.2.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-01-20 09:47:06 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -102,11 +102,8 @@
     assert(sub);
 
-    // Get the trim sections
-    psRegion *inTrimsec = psMetadataLookupPtr(NULL, in->parent->concepts, "CELL.TRIMSEC");
-    psRegion *subTrimsec = psMetadataLookupPtr(NULL, sub->parent->concepts, "CELL.TRIMSEC");
-    psImage *inImage = psImageSubset(in->image, *inTrimsec); // The input image
-    psImage *subImage = psImageSubset(sub->image, *subTrimsec); // The image to be subtracted
-    psImage *inMask = in->mask ? psImageSubset(in->mask, *inTrimsec) : NULL; // The input mask
-    psImage *subMask = sub->mask ? psImageSubset(sub->mask, *subTrimsec) : NULL; // The input mask
+    psImage *inImage  = in->image;      // The input image
+    psImage *inMask   = in->mask;       // The input mask
+    psImage *subImage = sub->image;     // The image to be subtracted
+    psImage *subMask  = sub->mask;      // The mask for the subtraction image
 
     // Offsets of the cells
@@ -425,7 +422,5 @@
     PS_ASSERT_READOUT_TYPE(in, PS_TYPE_F32, NULL);
 
-    pmCell *cell = in->parent;      // The parent cell
-    psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC"); // The trim region
-    psImage *image = psImageSubset(in->image, *trimsec); // The image corresponding to the trim region
+    psImage *image = in->image;         // The input image
 
     // Overscan processing
@@ -438,15 +433,5 @@
         }
 
-        // Get the list of overscans
-        psList *overscanRegions = psMetadataLookupPtr(NULL, cell->concepts, "CELL.BIASSEC");
-        psList *overscans = psListAlloc(NULL); // List of the overscan images
-        psListIterator *iter = psListIteratorAlloc(overscanRegions, PS_LIST_HEAD, false); // Iterator
-        psRegion *biassec = NULL;       // A BIASSEC region from the list
-        while ((biassec = psListGetAndIncrement(iter))) {
-            psImage *overscan = psImageSubset(in->image, *biassec);
-            psListAdd(overscans, PS_LIST_TAIL, overscan);
-            psFree(overscan);
-        }
-        psFree(iter);
+        psList *overscans = in->bias; // List of the overscan images
 
         psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN); // A new psStats, to avoid clobbering original
@@ -482,5 +467,6 @@
 
             // We do the regular overscan subtraction
-            bool readRows = psMetadataLookupBool(NULL, cell->concepts, "CELL.READDIR"); // Read direction
+
+            bool readRows = psMetadataLookupBool(NULL, in->parent->concepts, "CELL.READDIR");// Read direction
 
             if (readRows) {
