Index: /trunk/psModules/src/astrom/pmFPAConstruct.c
===================================================================
--- /trunk/psModules/src/astrom/pmFPAConstruct.c	(revision 6893)
+++ /trunk/psModules/src/astrom/pmFPAConstruct.c	(revision 6894)
@@ -755,4 +755,5 @@
             for (int k = 0; k < readouts->n; k++) {
                 pmReadout *readout = readouts->data[k]; // The readout
+                psTrace(__func__, 8, "row0: %d\n", readout->row0);
                 psImage *image = readout->image; // The image
                 psList *bias = readout->bias; // The list of bias images
Index: /trunk/psModules/src/astrom/pmFPARead.c
===================================================================
--- /trunk/psModules/src/astrom/pmFPARead.c	(revision 6893)
+++ /trunk/psModules/src/astrom/pmFPARead.c	(revision 6894)
@@ -12,4 +12,7 @@
 #include "pmHDUUtils.h"
 
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // File-static functions
@@ -17,12 +20,10 @@
 
 // Carve a readout from the image pixels
-static pmReadout *readoutCarve(pmCell *cell, // Cell into which the new readout will be placed
-                               psImage *image, // Image that will be carved
-                               const psRegion *trimsec, // Trim section
-                               const psList *biassecs // Bias sections
-                              )
-{
-    pmReadout *readout = pmReadoutAlloc(cell);
-
+static bool readoutCarve(pmReadout *readout, // Readout to be carved up
+                         psImage *image, // Image that will be carved
+                         const psRegion *trimsec, // Trim section
+                         const psList *biassecs // Bias sections
+                        )
+{
     // The image corresponding to the trim region
     if (psRegionIsBad(*trimsec)) {
@@ -33,7 +34,17 @@
         return NULL;
     }
-    readout->image = psMemIncrRefCounter(psImageSubset(image, *trimsec));
+    psRegion region = psRegionSet(trimsec->x0, trimsec->x1, MAX(trimsec->y0 - readout->row0, 0),
+                                  MIN(trimsec->y1 - readout->row0, image->numRows));
+    if (readout->image) {
+        psFree(readout->image);         // Make way!
+    }
+    readout->image = psMemIncrRefCounter(psImageSubset(image, region));
 
     // Get the list of overscans
+    if (readout->bias->n != 0) {
+        // Make way!
+        psFree(readout->bias);
+        readout->bias = psListAlloc(NULL);
+    }
     psListIterator *iter = psListIteratorAlloc((psList*)biassecs, PS_LIST_HEAD, false); // Iterator
     psRegion *biassec = NULL;       // A BIASSEC region from the list
@@ -46,5 +57,7 @@
             return NULL;
         }
-        psImage *overscan = psMemIncrRefCounter(psImageSubset(image, *biassec));
+        psRegion region = psRegionSet(biassec->x0, biassec->x1, MAX(biassec->y0 - readout->row0, 0),
+                                      MIN(biassec->y1 - readout->row0, image->numRows));
+        psImage *overscan = psMemIncrRefCounter(psImageSubset(image, region));
         psListAdd(readout->bias, PS_LIST_TAIL, overscan);
         psFree(overscan);
@@ -73,11 +86,26 @@
     }
 
-    if (!pmHDUReadHeader(hdu, fits)) {
-        psError(PS_ERR_IO, false, "Unable to read HDU header!\n");
+    if (!hdu->header) {
+        if (!pmHDUReadHeader(hdu, fits)) {
+            psError(PS_ERR_IO, false, "Unable to read HDU header!\n");
+            return false;
+        }
+        pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER, false, NULL);
+    }
+
+    // Get the trim and bias sections
+    bool mdok = true;                   // Status of MD lookup
+    psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC");
+    if (!mdok || !trimsec || psRegionIsBad(*trimsec)) {
+        psError(PS_ERR_IO, true, "CELL.TRIMSEC is not set.\n");
+        return false;
+    }
+    psList *biassecs = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.BIASSEC");
+    if (!mdok || !biassecs) {
+        psError(PS_ERR_IO, true, "CELL.BIASSEC is not set.\n");
         return false;
     }
 
     // Check the third dimension
-    bool mdok = true;                   // Status of MD lookup
     int naxis = psMetadataLookupS32(&mdok, hdu->header, "NAXIS"); // The number of axes
     if (!mdok) {
@@ -134,7 +162,4 @@
     psRegion region = psRegionSet(0, naxis1, offset, upper); // Region to be read
     psImage *image = psFitsReadImage(fits, region, z); // The image
-    if (readout->image) {
-        psFree(readout->image);
-    }
 
     // Stick the image into the HDU and the readout
@@ -151,6 +176,6 @@
     }
     hdu->images->data[z] = image;
-    readout->image = psImageSubset(hdu->images->data[z], psRegionSet(0,0,0,0));
     readout->row0 = region.y0;
+    readoutCarve(readout, image, trimsec, biassecs);
 
     return true;
@@ -191,5 +216,6 @@
         }
 
-        pmReadout *readout = readoutCarve(cell, image, trimsec, biassecs);
+        pmReadout *readout = pmReadoutAlloc(cell);
+        readoutCarve(readout, image, trimsec, biassecs);
         readout->mask = NULL;
         readout->weight = NULL;
