Index: /trunk/psModules/src/astrom/pmConceptsWrite.c
===================================================================
--- /trunk/psModules/src/astrom/pmConceptsWrite.c	(revision 6895)
+++ /trunk/psModules/src/astrom/pmConceptsWrite.c	(revision 6896)
@@ -129,4 +129,7 @@
                              )
 {
+    if (!hdu->header) {
+        return false;
+    }
     switch (item->type) {
     case PS_DATA_STRING:
@@ -166,4 +169,8 @@
     if (item->type == PS_DATA_LIST) {
         psList *values = item->data.V;  // List of outputs
+        if (values->n == 0) {
+            // Nothing to write
+            return false;
+        }
         psList *keys = psStringSplit(keywords, " ,;"); // List of keywords
         if (keys->n != values->n) {
Index: /trunk/psModules/src/astrom/pmFPA.c
===================================================================
--- /trunk/psModules/src/astrom/pmFPA.c	(revision 6895)
+++ /trunk/psModules/src/astrom/pmFPA.c	(revision 6896)
@@ -12,6 +12,6 @@
 * XXX: Should we implement non-linear cell->chip transforms?
 *
-*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2006-04-17 18:01:04 $
+*  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-04-19 03:24:09 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -231,4 +231,5 @@
     pmReadout *tmpReadout = (pmReadout *) psAlloc(sizeof(pmReadout));
     tmpReadout->row0 = 0;
+    tmpReadout->col0 = 0;
 
     tmpReadout->image = NULL;
Index: /trunk/psModules/src/astrom/pmFPA.h
===================================================================
--- /trunk/psModules/src/astrom/pmFPA.h	(revision 6895)
+++ /trunk/psModules/src/astrom/pmFPA.h	(revision 6896)
@@ -7,6 +7,6 @@
 *  @author GLG, MHPCC
 *
-*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2006-04-17 18:01:04 $
+*  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-04-19 03:24:09 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -129,5 +129,6 @@
 typedef struct
 {
-    int row0;                           ///< Row offset; non-zero if reading in bit by bit
+    int col0;                           ///< Column offset; non-zero if reading in columns bit by bit
+    int row0;                           ///< Row offset; non-zero if reading in rows bit by bit
     psImage *image;                     ///< Imaging area of readout
     psImage *mask;                      ///< Mask of input image
Index: /trunk/psModules/src/astrom/pmFPARead.c
===================================================================
--- /trunk/psModules/src/astrom/pmFPARead.c	(revision 6895)
+++ /trunk/psModules/src/astrom/pmFPARead.c	(revision 6896)
@@ -34,6 +34,9 @@
         return NULL;
     }
-    psRegion region = psRegionSet(trimsec->x0, trimsec->x1, MAX(trimsec->y0 - readout->row0, 0),
-                                  MIN(trimsec->y1 - readout->row0, image->numRows));
+    psRegion region = psRegionSet(MAX(trimsec->x0 - readout->col0, 0), // x0
+                                  MIN(trimsec->x1 - readout->col0, image->numCols), // x1
+                                  MAX(trimsec->y0 - readout->row0, 0), // y0
+                                  MIN(trimsec->y1 - readout->row0, image->numRows) // y1
+                                 );
     if (readout->image) {
         psFree(readout->image);         // Make way!
@@ -57,6 +60,9 @@
             return NULL;
         }
-        psRegion region = psRegionSet(biassec->x0, biassec->x1, MAX(biassec->y0 - readout->row0, 0),
-                                      MIN(biassec->y1 - readout->row0, image->numRows));
+        psRegion region = psRegionSet(MAX(biassec->x0 - readout->col0, 0), // x0
+                                      MIN(biassec->x1 - readout->col0, image->numCols), // x1
+                                      MAX(biassec->y0 - readout->row0, 0), // y0
+                                      MIN(biassec->y1 - readout->row0, image->numRows) // y1
+                                     );
         psImage *overscan = psMemIncrRefCounter(psImageSubset(image, region));
         psListAdd(readout->bias, PS_LIST_TAIL, overscan);
@@ -76,5 +82,5 @@
                        psFits *fits,    // FITS file from which to read
                        int z,           // Readout number/plane; zero-offset indexing
-                       int numRows      // The number of rows to read
+                       int numScans     // The number of scans to read
                       )
 {
@@ -96,12 +102,17 @@
     // Get the trim and bias sections
     bool mdok = true;                   // Status of MD lookup
-    psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC");
+    psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim sections
     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");
+    psList *biassecs = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.BIASSEC"); // Bias sections
     if (!mdok || !biassecs) {
         psError(PS_ERR_IO, true, "CELL.BIASSEC is not set.\n");
+        return false;
+    }
+    int readdir = psMetadataLookupS32(&mdok, cell->concepts, "CELL.READDIR"); // Read direction
+    if (!mdok || readdir == 0 || (readdir != -1 && readdir != 1)) {
+        psError(PS_ERR_IO, true, "CELL.READDIR is not set to -1 or +1.\n");
         return false;
     }
@@ -150,15 +161,28 @@
     int offset = readout->row0;         // The row number to read
     if (readout->image) {
-        offset += readout->image->numRows;
-    }
-    if (offset >= naxis2) {
+        if (readdir > 0) {
+            // Reading rows
+            offset += readout->image->numRows;
+        } else {
+            // Reading columns
+            offset += readout->image->numCols;
+        }
+    }
+    if ((readdir > 0 && offset >= naxis2) || (readdir < 0 && offset > naxis1)) {
         // We've read everything there is
         return false;
     }
-    int upper = offset + numRows;       // The upper limit for the pixel read
-    if (upper > naxis2) {
+    int upper = offset + numScans;      // The upper limit for the pixel read
+    if (readdir > 0 && upper > naxis2) {
         upper = naxis2;
-    }
-    psRegion region = psRegionSet(0, naxis1, offset, upper); // Region to be read
+    } else if (readdir < 0 && upper > naxis1) {
+        upper = naxis1;
+    }
+    psRegion region = {0, 0, 0, 0};     // Region to be read
+    if (readdir > 0) {
+        region = psRegionSet(0, naxis1, offset, upper); // Read rows
+    } else {
+        region = psRegionSet(offset, upper, 0, naxis2); // Read columns
+    }
     psImage *image = psFitsReadImage(fits, region, z); // The image
 
@@ -177,4 +201,5 @@
     hdu->images->data[z] = image;
     readout->row0 = region.y0;
+    readout->col0 = region.x0;
     readoutCarve(readout, image, trimsec, biassecs);
 
Index: /trunk/psModules/src/astrom/pmFPAWrite.c
===================================================================
--- /trunk/psModules/src/astrom/pmFPAWrite.c	(revision 6895)
+++ /trunk/psModules/src/astrom/pmFPAWrite.c	(revision 6896)
@@ -5,10 +5,73 @@
 #include "pmFPA.h"
 #include "pmHDU.h"
+#include "pmHDUUtils.h"
 #include "pmConcepts.h"
+
+
+bool pmReadoutWriteNext(pmReadout *readout, // Readout to write
+                        psFits *fits,   // FITS file to which to write
+                        int z           // Image plane to write
+                       )
+{
+    pmHDU *hdu = pmHDUFromReadout(readout); // The HDU to which to write
+    psMetadata *header = hdu->header;   // The FITS header
+    if (!header) {
+        psError(PS_ERR_IO, true, "No FITS header available in the HDU.\n");
+        return false;
+    }
+
+    // We have to rely to a great extent on the FITS header, because otherwise we simply don't know how many
+    // image planes there are (NAXIS3) or the size of the original image (NAXIS1, NAXIS2).
+    bool mdok = true;                   // Status of MD lookup
+    int naxis1 = psMetadataLookupS32(&mdok, header, "NAXIS1"); // Number of columns
+    if (!mdok || naxis1 <= 0) {
+        psError(PS_ERR_IO, true, "Can't find NAXIS1 in header.\n");
+        return false;
+    }
+    int naxis2 = psMetadataLookupS32(&mdok, header, "NAXIS2"); // Number of rows
+    if (!mdok || naxis2 <= 0) {
+        psError(PS_ERR_IO, true, "Can't find NAXIS2 in header.\n");
+        return false;
+    }
+    int naxis3 = psMetadataLookupS32(&mdok, header, "NAXIS3"); // Number of image planes
+    if (!mdok || naxis3 <= 0) {
+        naxis3 = 1;
+    }
+    if (z >= naxis3) {
+        psError(PS_ERR_IO, true, "Specified a plane number (%d) greater than NAXIS3 allows.\n", z);
+        return false;
+    }
+
+    psImage *image = hdu->images->data[z]; // The image from the HDU to write
+    if (readout->row0 == 0 && readout->col0 == 0 && z == 0) {
+        // Then we can assume that nothing has been written to the FITS file for now
+        if (naxis1 == image->numCols && naxis2 == image->numRows) {
+            // We can write the whole lot at once
+            return psFitsWriteImage(fits, header, image, z, hdu->extname);
+        }
+        // Create a dummy image so we can write something larger than we actually have
+        psImage *dummy = psImageAlloc(naxis1, naxis2, image->type.type); // Dummy image
+        psImageInit(dummy, 0);
+        psImageOverlaySection(dummy, image, 0, 0, "=");
+        bool result = psFitsWriteImage(fits, header, dummy, z, hdu->extname);
+        psFree(dummy);
+        return result;
+    }
+
+    // We can simply update an existing HDU
+    if (!psFitsMoveExtName(fits, hdu->extname)) {
+        psError(PS_ERR_IO, false, "Unable to move to extension %s\n", hdu->extname);
+        return false;
+    }
+    return psFitsUpdateImage(fits, image, readout->col0, readout->row0, z);
+}
+
+
 
 
 bool pmCellWrite(pmCell *cell,          // Cell to write
                  psFits *fits,          // FITS file to which to write
-                 psDB *db               // Database handle for "concepts" update
+                 psDB *db,              // Database handle for "concepts" update
+                 bool pixels            // Write the pixels?
                 )
 {
@@ -17,5 +80,5 @@
 
     pmHDU *hdu = cell->hdu;             // The HDU
-    if (hdu && !pmHDUWrite(hdu, fits)) {
+    if (hdu && ((!pixels && hdu->phu) || pixels) && !pmHDUWrite(hdu, fits)) {
         psError(PS_ERR_IO, false, "Unable to write HDU for Chip.\n");
         return false;
@@ -28,5 +91,6 @@
 bool pmChipWrite(pmChip *chip,          // Chip to write
                  psFits *fits,          // FITS file to which to write
-                 psDB *db               // Database handle for "concepts" update
+                 psDB *db,              // Database handle for "concepts" update
+                 bool pixels            // Write the pixels?
                 )
 {
@@ -35,5 +99,5 @@
 
     pmHDU *hdu = chip->hdu;             // The HDU
-    if (hdu && !pmHDUWrite(hdu, fits)) {
+    if (hdu && ((!pixels && hdu->phu) || pixels) && !pmHDUWrite(hdu, fits)) {
         psError(PS_ERR_IO, false, "Unable to write HDU for Chip.\n");
         return false;
@@ -41,8 +105,10 @@
 
     bool success = true;                // Success of writing
-    psArray *cells = chip->cells;       // Array of cells
-    for (int i = 0; i < cells->n; i++) {
-        pmCell *cell = cells->data[i];  // The cell of interest
-        success |= pmCellWrite(cell, fits, db);
+    if (pixels) {
+        psArray *cells = chip->cells;       // Array of cells
+        for (int i = 0; i < cells->n; i++) {
+            pmCell *cell = cells->data[i];  // The cell of interest
+            success |= pmCellWrite(cell, fits, db, true);
+        }
     }
 
@@ -55,5 +121,6 @@
 bool pmFPAWrite(pmFPA *fpa,             // FPA to write
                 psFits *fits,           // FITS file to which to write
-                psDB *db                // Database handle for "concepts" update
+                psDB *db,               // Database handle for "concepts" update
+                bool pixels             // Write the pixels?
                )
 {
@@ -62,5 +129,5 @@
 
     pmHDU *hdu = fpa->hdu;              // The HDU
-    if (hdu && !pmHDUWrite(hdu, fits)) {
+    if (hdu && ((!pixels && hdu->phu) || pixels) && !pmHDUWrite(hdu, fits)) {
         psError(PS_ERR_IO, false, "Unable to write HDU for FPA.\n");
         return false;
@@ -68,8 +135,10 @@
 
     bool success = true;                // Success of writing
-    psArray *chips = fpa->chips;        // Array of chips
-    for (int i = 0; i < chips->n; i++) {
-        pmChip *chip = chips->data[i];  // The chip of interest
-        success |= pmChipWrite(chip, fits, db);
+    if (pixels) {
+        psArray *chips = fpa->chips;        // Array of chips
+        for (int i = 0; i < chips->n; i++) {
+            pmChip *chip = chips->data[i];  // The chip of interest
+            success |= pmChipWrite(chip, fits, db, true);
+        }
     }
 
Index: /trunk/psModules/src/astrom/pmFPAWrite.h
===================================================================
--- /trunk/psModules/src/astrom/pmFPAWrite.h	(revision 6895)
+++ /trunk/psModules/src/astrom/pmFPAWrite.h	(revision 6896)
@@ -5,16 +5,23 @@
 #include "pmFPA.h"
 
+bool pmReadoutWriteNext(pmReadout *readout, // Readout to write
+                        psFits *fits,   // FITS file to which to write
+                        int z           // Image plane to write
+                       );
 
 bool pmCellWrite(pmCell *cell,          // Cell to write
                  psFits *fits,          // FITS file to which to write
-                 psDB *db               // Database handle for "concepts" update
+                 psDB *db,              // Database handle for "concepts" update
+                 bool pixels            // Write the pixels?
                 );
 bool pmChipWrite(pmChip *chip,          // Chip to write
                  psFits *fits,          // FITS file to which to write
-                 psDB *db               // Database handle for "concepts" update
+                 psDB *db,              // Database handle for "concepts" update
+                 bool pixels            // Write the pixels?
                 );
 bool pmFPAWrite(pmFPA *fpa,             // FPA to write
                 psFits *fits,           // FITS file to which to write
-                psDB *db                // Database handle for "concepts" update
+                psDB *db,               // Database handle for "concepts" update
+                bool pixels             // Write the pixels?
                );
 
Index: /trunk/psModules/src/astrom/pmFPAfile.c
===================================================================
--- /trunk/psModules/src/astrom/pmFPAfile.c	(revision 6895)
+++ /trunk/psModules/src/astrom/pmFPAfile.c	(revision 6896)
@@ -634,5 +634,5 @@
     // pmFPAWrite takes care of all PHUs as needed
     if (view->chip == -1) {
-        pmFPAWrite (fpa, fits, NULL);
+        pmFPAWrite (fpa, fits, NULL, true);
         return true;
     }
@@ -660,5 +660,5 @@
 
     if (view->cell == -1) {
-        pmChipWrite (chip, fits, NULL);
+        pmChipWrite (chip, fits, NULL, true);
         return true;
     }
@@ -670,5 +670,5 @@
 
     if (view->readout == -1) {
-        pmCellWrite (cell, fits, NULL);
+        pmCellWrite (cell, fits, NULL, true);
         return true;
     }
