Index: /branches/pap_branch_070920/psLib/src/fits/psFits.c
===================================================================
--- /branches/pap_branch_070920/psLib/src/fits/psFits.c	(revision 15167)
+++ /branches/pap_branch_070920/psLib/src/fits/psFits.c	(revision 15168)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.71.2.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-29 21:55:41 $
+ *  @version $Revision: 1.71.2.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-10-03 03:01:45 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -81,9 +81,5 @@
 bool psFitsClose(psFits* fits)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
 
     bool status = fitsClose(fits);
@@ -95,12 +91,8 @@
 psFits* psFitsOpen(const char* name, const char* mode)
 {
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+
     int status = 0;
     fitsfile *fptr = NULL;      /* Pointer to the FITS file */
-
-    if (name == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("Specified filename can not be NULL."));
-        return NULL;
-    }
 
     /* check the mode to determine how to open/create file */
@@ -131,6 +123,5 @@
         if (access(name, F_OK) == 0) {
             // file exists, delete old one first
-            remove
-                (name);
+            remove(name);
         }
 
@@ -140,7 +131,5 @@
         (void)fits_create_file
         #endif
-        (&fptr,
-         name,
-         &status);
+        (&fptr, name, &status);
         if (fptr == NULL || status != 0) {
             char fitsErr[MAX_STRING_LENGTH];
@@ -157,8 +146,5 @@
         (void)fits_open_file
         #endif
-        (&fptr,
-         name,
-         iomode,
-         &status);
+        (&fptr, name, iomode, &status);
         if (fptr == NULL || status != 0) {
             char fitsErr[MAX_STRING_LENGTH];
@@ -175,4 +161,5 @@
     fits->writable = (iomode == READWRITE);
     fits->extword = NULL;
+    fits->compression = true;
     psMemSetDeallocator(fits,(psFreeFunc)fitsFree);
 
@@ -180,12 +167,6 @@
 }
 
-psErrorCode p_psFitsError(const char* filename,
-                          unsigned int lineno,
-                          const char* func,
-                          int status,
-                          bool new,
-                          const char *errorMsg,
-                          ...
-                          )
+psErrorCode p_psFitsError(const char* filename, unsigned int lineno, const char* func, int status,
+                          bool new, const char *errorMsg, ...)
 {
     if (status == 0) {
@@ -211,4 +192,5 @@
 static void psFitsCompressionFree(psFitsCompression *comp)
 {
+    PS_ASSERT_PTR_NON_NULL(comp,);
     psFree(comp->tilesize);
 }
@@ -256,5 +238,5 @@
                                  const char *extword)
 {
-    PS_ASSERT_PTR_NON_NULL(fits,    false);
+    PS_ASSERT_FITS_NON_NULL(fits,   false);
     PS_ASSERT_PTR_NON_NULL(extname, false);
     PS_ASSERT_PTR_NON_NULL(extword, false);
@@ -301,17 +283,8 @@
                        const char* extname)
 {
-    int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return false;
-    }
-
-    if (extname == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("Specified extension name can not be NULL."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_STRING_NON_EMPTY(extname, false);
+
+    int status = 0;
 
     if (fits->extword != NULL) {
@@ -336,9 +309,5 @@
                       bool relative)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
 
     int status = 0;
@@ -372,9 +341,6 @@
 bool psFitsMoveLast(psFits* fits)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
     int size = psFitsGetSize(fits);
     if (size == 0) { // empty file -- no action needed
@@ -387,13 +353,6 @@
 int psFitsGetExtNum(const psFits* fits)
 {
+    PS_ASSERT_FITS_NON_NULL(fits, false);
     int hdunum;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return PS_FITS_TYPE_NONE;
-    }
-
-
     return fits_get_hdu_num(fits->fd,&hdunum) - 1;
 }
@@ -401,9 +360,5 @@
 psString psFitsGetExtName(const psFits* fits)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return NULL;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
 
     int status = 0;
@@ -422,15 +377,6 @@
 bool psFitsSetExtName(psFits* fits, const char* name)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return false;
-    }
-
-    if (name == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("Specified extension name can not be NULL."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, false);
 
     int status = 0;
@@ -454,9 +400,5 @@
                         bool relative)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
 
     if (! fits->writable) {
@@ -492,9 +434,6 @@
                          const char* extname)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_STRING_NON_EMPTY(extname, false);
 
     if (! fits->writable) {
@@ -530,9 +469,5 @@
 int psFitsGetSize(const psFits* fits)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return 0;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, 0);
 
     int num = 0;
@@ -553,9 +488,5 @@
 psFitsType psFitsGetExtType(const psFits* fits)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return PS_FITS_TYPE_NONE;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, PS_FITS_TYPE_NONE);
 
     int status = 0;
@@ -582,9 +513,5 @@
 bool psFitsTruncate(psFits* fits)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return PS_FITS_TYPE_NONE;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
 
     if (! fits->writable) {
@@ -623,4 +550,6 @@
 )
 {
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
     // convert psFitsCompressionType to cfitsio compression types
     int comptype;
@@ -708,4 +637,96 @@
 }
 
+psFitsCompression *psFitsCompressionGet(psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    int status = 0;                     // cfitsio status
+
+    psFitsCompressionType type = psFitsCompressionGetType(fits);
+    if (type < 0) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to get compression type.");
+        return NULL;
+    }
+
+    psElemType tileType;                // Type corresponding to "long"
+    if (sizeof(long) == sizeof(psS64)) {
+        tileType = PS_TYPE_S64;
+    } else if (sizeof(long) == sizeof(psS32)) {
+        tileType = PS_TYPE_S32;
+    } else {
+        psAbort("can't map (long) type to a psLib type");
+    }
+
+    psVector *tiles = psVectorAlloc(3, tileType); // Tile sizes
+    if (fits_get_tile_dim(fits->fd, 3, (long*)tiles->data.U8, &status)) {
+        psFitsError(status, true, "Unable to get compression tile sizes.");
+        psFree(tiles);
+        return NULL;
+    }
+
+    int noisebits;                      // Noise bits for compression
+    if (fits_get_noise_bits(fits->fd, &noisebits, &status)) {
+        psFitsError(status, true, "Unable to get compression noise bits.");
+        psFree(tiles);
+        return NULL;
+    }
+
+    int hscale = 0, hsmooth = 0;        // Scaling and smoothing for HCOMPRESS
+
+#if FITS_HCOMP
+    if (fits_get_hcomp_scale(fits->fd, &hscale, &status)) {
+        psFitsError(status, true, "Unable to get HCOMPRESS scaling.");
+        psFree(tiles);
+        return NULL;
+    }
+    if (fits_get_hcomp_smooth(fits->fd, &hsmooth, &status)) {
+        psFitsError(status, true, "Unable to get HCOMPRESS smoothing.");
+        psFree(tiles);
+        return NULL;
+    }
+#endif // FITS_HCOMP
+
+    psFitsCompression *compress = psFitsCompressionAlloc(type, tiles, noisebits, hscale, hsmooth);
+    psFree(tiles);                      // Drop reference
+
+    return compress;
+}
+
+psFitsCompressionType psFitsCompressionGetType(psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, -1);
+
+    int status = 0;                     // cfitsio status
+    int comptype = 0;                   // cfitsio compression type
+    if (fits_get_compression_type(fits->fd, &comptype, &status)) {
+        psFitsError(status, true, "Unable to get compression type.");
+        return -1;
+    }
+
+    psFitsCompressionType type;
+    switch (comptype) {
+      case 0:
+        type = PS_FITS_COMPRESS_NONE;
+        break;
+      case GZIP_1:
+        type = PS_FITS_COMPRESS_GZIP;
+        break;
+      case RICE_1:
+        type = PS_FITS_COMPRESS_RICE;
+        break;
+      case HCOMPRESS_1:
+        type = PS_FITS_COMPRESS_HCOMPRESS;
+        break;
+      case PLIO_1:
+        type = PS_FITS_COMPRESS_PLIO;
+        break;
+      default:
+        psError(PS_ERR_UNKNOWN, true, "cfitsio reports unknown compression type.");
+        return -1;
+    }
+
+    return type;
+}
+
 
 bool psFitsCompressionApply(
Index: /branches/pap_branch_070920/psLib/src/fits/psFits.h
===================================================================
--- /branches/pap_branch_070920/psLib/src/fits/psFits.h	(revision 15167)
+++ /branches/pap_branch_070920/psLib/src/fits/psFits.h	(revision 15168)
@@ -4,6 +4,6 @@
  * @author Robert DeSonia, MHPCC
  *
- * @version $Revision: 1.31.2.2 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-09-29 21:55:41 $
+ * @version $Revision: 1.31.2.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-10-03 03:01:45 $
  * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
  */
@@ -55,4 +55,5 @@
     bool writable;                      ///< Is the file writable?
     char *extword;                      ///< user-specified word to name extensions (NULL implies EXTNAME)
+    bool compression;                   ///< Treat compressed images automatically?
 } psFits;
 
@@ -140,5 +141,5 @@
  */
 bool psFitsSetCompression(
-    psFits* fits,                       ///< psFits object to close
+    psFits* fits,                       ///< psFits object for which to set compression
     psFitsCompressionType type,         ///< type of compression
     psVector *tilesize,                 ///< vector defining compression tile size
@@ -148,4 +149,14 @@
 );
 
+/// Get the compression options for a file handle
+psFitsCompression *psFitsCompressionGet(
+    psFits* fits                        ///< psFits object for which to get compression
+);
+
+/// Get the compression type for a file handle
+psFitsCompressionType psFitsCompressionGetType(
+    psFits* fits                        ///< psFits object for which to get compression type
+    );
+
 /** Sets FITS write options
  *
@@ -153,5 +164,5 @@
  */
 bool psFitsCompressionApply(
-    psFits* fits,                       ///< psFits object to close
+    psFits* fits,                       ///< psFits object for which to set compression
     psFitsCompression *compress         ///< options object
 );
@@ -290,4 +301,10 @@
                           );
 
+#define PS_ASSERT_FITS_NON_NULL(NAME, RVAL) \
+if (!(NAME) || !(NAME)->fd) { \
+    psError(PS_ERR_UNEXPECTED_NULL, true, "Error: FITS file pointer %s is NULL", #NAME); \
+    return RVAL; \
+}
+
 /// @}
 #endif // #ifndef PS_FITS_H
Index: /branches/pap_branch_070920/psLib/src/fits/psFitsHeader.c
===================================================================
--- /branches/pap_branch_070920/psLib/src/fits/psFitsHeader.c	(revision 15167)
+++ /branches/pap_branch_070920/psLib/src/fits/psFitsHeader.c	(revision 15168)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.34.4.4 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-10-01 21:51:42 $
+ *  @version $Revision: 1.34.4.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-10-03 03:01:45 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -68,46 +68,85 @@
 
 
-bool psFitsEmptyPHU(const psFits *fits, const psMetadata *header)
-{
-    PS_ASSERT_PTR_NON_NULL(fits, false);
-    PS_ASSERT_METADATA_NON_NULL(header, false);
+bool psFitsCheckSingleCompressedImagePHU(const psFits *fits, psMetadata *header)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    if (!fits->compression) {
+        // User has turned off compression conventions; doesn't want any nasty surprises
+        return false;
+    }
 
     if (psFitsGetExtNum(fits) != 0) {
-        // It's not the PHU, so it can't be an empty PHU!
-        return false;
-    }
-
-    if (header->list->n == 0) {
-        // There's nothing in the list
+        // It's not the PHU, so it can't be the PHU for a single compressed image!
+        return false;
+    }
+
+    if (psFitsGetSize(fits) != 2) {
+        // No second extension, or multiple extensions
+        return false;
+    }
+
+    int numKeys;                        // Number of keywords in the header
+    int status = 0;                     // CFITSIO status
+    fits_get_hdrspace(fits->fd, &numKeys, 0, &status);
+    if (numKeys >= NUM_EMPTY_KEYS) {
+        return false;
+    }
+
+    int bitpix, naxis;                  // Bits per pixel and number of axes
+    long naxes[MAX_COMPRESS_DIM];       // Dimensions
+    fits_get_img_param(fits->fd, MAX_COMPRESS_DIM, &bitpix, &naxis, naxes, &status);
+    if (naxis != 0) {
+        return false;
+    }
+
+    if (!header) {
+        for (int i = 1; i <= numKeys; i++) {
+            // Just want to read the keyword names, without parsing the values and stuffing into a metadata
+            char keyName[MAX_STRING_LENGTH];// Keyword name
+            char keyValue[MAX_STRING_LENGTH]; // Corresponding value
+            char keyComment[MAX_STRING_LENGTH]; // Corresponding comment
+            fits_read_keyn(fits->fd, i, keyName, keyValue, keyComment, &status);
+            if (!keywordInList(keyName, emptyKeys)) {
+                return false;
+            }
+        }
+    } else {
+        psMetadataIterator *iter = psMetadataIteratorAlloc(header, PS_LIST_HEAD, NULL); // Iterator
+        psMetadataItem *item;           // Item from iteration
+        while ((item = psMetadataGetAndIncrement(iter))) {
+            if (!keywordInList(item->name, emptyKeys)) {
+                psFree(iter);
+                return false;
+            }
+        }
+        psFree(iter);
+    }
+
+    if (!psFitsMoveExtNum(fits, 1, false)) {
+        psWarning("Unable to examine first extension as suspect compressed image.");
+        return false;
+    }
+
+    if (fits_is_compressed_image(fits->fd, &status)) {
         return true;
     }
 
-    // Check if it's got any keywords of potential interest
-    psMetadataIterator *iter = psMetadataIteratorAlloc(header, PS_LIST_HEAD, NULL); // Iterator
-    psMetadataItem *item;               // Item from iteration
-    while ((item = psMetadataGetAndIncrement(iter))) {
-        if (!keywordInList(item->name, emptyKeys)) {
-            psFree(iter);
-            return false;
-        }
-    }
-    psFree(iter);
-
-    return true;
-}
-
-
-psMetadata* psFitsReadHeader(psMetadata* out,
-                             const psFits* fits)
-{
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return NULL;
-    }
-
-    if (out == NULL) {
-        out = psMetadataAlloc();
-    }
+    // It's not a single compressed image PHU --- move back to the PHU for the user
+    if (!psFitsMoveExtNum(fits, 0, false)) {
+        psWarning("Unable to examine first extension as suspect compressed image.");
+        return false;
+    }
+
+    return false;
+}
+
+// Read the header
+static psMetadata *readHeader(const psFits *fits // FITS file from which to read header
+                              )
+{
+    assert(fits);
+
+    psMetadata *header = psMetadataAlloc(); // Header, to return
 
     // Get number of key names
@@ -150,5 +189,5 @@
         case 'X': // bit
         case 'B': // byte
-            success = psMetadataAddS8(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));
+            success = psMetadataAddS8(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));
             break;
         case 'I': // short int.
@@ -156,23 +195,24 @@
             // Trap NAN, INF and -INF, which cfitsio doesn't handle.
             if (strncasecmp(keyValue, "NAN", 3) == 0) {
-                success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN);
+                success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN);
             } else if (strncasecmp(keyValue, "INF", 3) == 0) {
-                success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY);
+                success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY);
             } else if (strncasecmp(keyValue, "-INF", 4) == 0) {
-                success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY);
+                success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY);
             } else {
-                success = psMetadataAddS32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));
+                success = psMetadataAddS32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment,
+                                           atoi(keyValue));
             }
             break;
         case 'J': // int.
-            success = psMetadataAddS32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));
+            success = psMetadataAddS32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));
             break;
         case 'U': // unsigned int.
-            success = psMetadataAddU32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atol(keyValue));
+            success = psMetadataAddU32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atol(keyValue));
             break;
 
         case 'K': // long int. can't all fit in a psS32, put in psF64
         case 'F':
-            success = psMetadataAddF64(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atof(keyValue));
+            success = psMetadataAddF64(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atof(keyValue));
             break;
         case 'C': {
@@ -195,11 +235,11 @@
                 // cfitsio won't write these, so we write them as strings, and then have to trap them on read.
                 if (strcasecmp(keyValueFixed, "NAN") == 0) {
-                    success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN);
+                    success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN);
                 } else if (strcasecmp(keyValueFixed, "INF") == 0) {
-                    success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY);
+                    success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY);
                 } else if (strcasecmp(keyValueFixed, "-INF") == 0) {
-                    success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY);
+                    success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY);
                 } else {
-                    success = psMetadataAddStr(out, PS_LIST_TAIL, keyName, dupFlag, keyComment,
+                    success = psMetadataAddStr(header, PS_LIST_TAIL, keyName, dupFlag, keyComment,
                                                keyValueFixed);
                 }
@@ -208,15 +248,17 @@
         case 'L': {
                 bool temp = (keyValue[0] == 'T') ? 1 : 0;
-                success = psMetadataAddBool(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, temp);
+                success = psMetadataAddBool(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, temp);
                 break;
             }
         default:
             psError(PS_ERR_IO, true, _("Specified FITS metadata type, %c, is not supported."), keyType);
-            return out;
+            psFree(header);
+            return NULL;
         }
 
         if (!success) {
             psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s."), keyName);
-            return out;
+            psFree(header);
+            return NULL;
         }
 
@@ -227,7 +269,60 @@
         (void)fits_get_errstatus(status, fitsErr);
         psError(PS_ERR_IO, true, _("Failed to add metadata item, %s."), fitsErr);
-        return false;
-    }
-
+        psFree(header);
+        return false;
+    }
+
+    return header;
+}
+
+
+psMetadata* psFitsReadHeader(psMetadata* out,
+                             const psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    psMetadata *header = readHeader(fits); // Header
+    if (!header) {
+        return NULL;
+    }
+
+    // Explore the potential case that this is an empty PHU, and the first extension contains the sole image,
+    // which is compressed.
+    if (psFitsCheckSingleCompressedImagePHU(fits, header)) {
+        // This is really what we want, not the empty PHU
+        psTrace("psLib.fits", 1,
+                "This PHU should really be a compressed image --- getting that header instead.");
+        psFree(header);
+        header = readHeader(fits);
+        if (!header) {
+            return NULL;
+        }
+    }
+
+    if (!out) {
+        return header;
+    }
+
+    // Need to move header onto the nominated metadata
+    psMetadataIterator *iter = psMetadataIteratorAlloc(header, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item;           // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        // Need to look for MULTI, which won't be picked up using the iterator.
+        psMetadataItem *multiCheckItem = psMetadataLookup(header, item->name);
+        assert(multiCheckItem);
+        unsigned int flag = 0;      // Flag to indicate MULTI; otherwise default action
+        if (multiCheckItem->type == PS_DATA_METADATA_MULTI) {
+            flag = PS_META_DUPLICATE_OK;
+        }
+        if (!psMetadataAddItem(out, item, PS_LIST_TAIL, flag)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to add header item %s to extant metadata.",
+                    item->name);
+            psFree(iter);
+            psFree(header);
+            return NULL;
+        }
+    }
+    psFree(iter);
+    psFree(header);
     return out;
 }
@@ -235,11 +330,7 @@
 psMetadata* psFitsReadHeaderSet(psMetadata* out, const psFits* fits)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL."));
-        psFree(out);
-        return NULL;
-    }
-
-    if (out == NULL) {
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    if (!out) {
         out = psMetadataAlloc();
     }
@@ -378,5 +469,6 @@
                         }
                     } else {
-                        fits_update_key(fits->fd, TFLOAT, item->name, &item->data.F32, item->comment, &status);
+                        fits_update_key(fits->fd, TFLOAT, item->name, &item->data.F32, item->comment,
+                                        &status);
                     }
                     break;
@@ -393,5 +485,6 @@
                         }
                     } else {
-                        fits_update_key(fits->fd, TDOUBLE, item->name, &item->data.F64, item->comment, &status);
+                        fits_update_key(fits->fd, TDOUBLE, item->name, &item->data.F64, item->comment,
+                                        &status);
                     }
                     break;
@@ -424,13 +517,6 @@
                       )
 {
-    if (!fits) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL."));
-        return false;
-    }
-
-    if (!output) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psMetadata was NULL.  Need a non-NULL psMetadata for operation to be performed."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_METADATA_NON_NULL(output, false);
 
     return fitsWriteHeader(fits, output, true);
@@ -442,8 +528,5 @@
                      )
 {
-    if (!fits) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
 
     // We allow output == NULL in order to write a minimal header.
@@ -487,8 +570,5 @@
 bool psFitsHeaderValidate(psMetadata *header)
 {
-    if (header == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psMetadata was NULL.  Need a non-NULL psMetadata for operation to be performed."));
-        return false;
-    }
+    PS_ASSERT_METADATA_NON_NULL(header, false);
 
     // Traverse the metadata list and inspect at each key
Index: /branches/pap_branch_070920/psLib/src/fits/psFitsHeader.h
===================================================================
--- /branches/pap_branch_070920/psLib/src/fits/psFitsHeader.h	(revision 15167)
+++ /branches/pap_branch_070920/psLib/src/fits/psFitsHeader.h	(revision 15168)
@@ -4,6 +4,6 @@
  * @author Robert DeSonia, MHPCC
  *
- * @version $Revision: 1.10.14.1 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-09-22 03:08:05 $
+ * @version $Revision: 1.10.14.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-10-03 03:01:45 $
  *
  * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -19,9 +19,14 @@
 #include "psMetadata.h"
 
-/// Determines whether the current HDU is an empty PHU
-bool psFitsEmptyPHU(const psFits *fits, ///< FITS file pointer
-                    const psMetadata *header ///< Header
+
+/// Determine whether the current HDU is an empty PHU with a single compressed image following.
+///
+/// In that case, what should be treated as an image PHU is technically an empty PHU with a binary table
+/// extension.  We test the current position, number of extensions, the FITS headers and presence of a
+/// following compressed image to determine if this is the case.  If so, the FITS file pointer is left
+/// pointing at the compressed image.
+bool psFitsCheckSingleCompressedImagePHU(const psFits *fits, ///< FITS file pointer
+                                         const psMetadata *header ///< Header, or NULL
     );
-
 
 /** Reads the header of the current HDU.
Index: /branches/pap_branch_070920/psLib/src/fits/psFitsImage.c
===================================================================
--- /branches/pap_branch_070920/psLib/src/fits/psFitsImage.c	(revision 15167)
+++ /branches/pap_branch_070920/psLib/src/fits/psFitsImage.c	(revision 15168)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.17.14.1 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-09-29 21:55:05 $
+ *  @version $Revision: 1.17.14.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-10-03 03:01:45 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -54,5 +54,5 @@
                                               )
 {
-    PS_ASSERT_PTR_NON_NULL(fits, NULL);
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     PS_ASSERT_INT_NONNEGATIVE(z, NULL);
 
@@ -219,4 +219,13 @@
                         )
 {
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(z, NULL);
+
+    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
+        // This is really what we want, not the empty PHU
+        psTrace("psLib.fits", 1,
+                "This PHU should really be a compressed image --- reading that image instead.");
+    }
+
     p_psFitsReadInfo *info = p_psFitsReadInfoAlloc(fits, region, z);
 
@@ -241,7 +250,16 @@
                               )
 {
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(z, NULL);
+
     if (output && output->parent) {
         psError(PS_ERR_IO, true, "Unable to read into a buffer for a child image.\n");
         return NULL;
+    }
+
+    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
+        // This is really what we want, not the empty PHU
+        psTrace("psLib.fits", 1,
+                "This PHU should really be a compressed image --- reading that image instead.");
     }
 
@@ -268,4 +286,6 @@
                       const char* extname)
 {
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_IMAGE_NON_NULL(input, false);
     // this is equivalent to insert after the last HDU
 
@@ -281,14 +301,6 @@
                        bool after)
 {
-
-    if (!fits) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL."));
-        return false;
-    }
-
-    if (!input) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psImage was NULL.  Need a non-NULL psImage for operation to be performed."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_IMAGE_NON_NULL(input, false);
 
     int numCols = input->numCols;       // Number of columns for image
@@ -389,17 +401,8 @@
                        int z)
 {
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_IMAGE_NON_NULL(input, false);
+
     int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return false;
-    }
-
-    if (input == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psImage was NULL.  Need a non-NULL psImage for operation to be performed."));
-        return false;
-    }
 
     // check to see if we are positioned on an image HDU
@@ -497,4 +500,6 @@
 psArray *psFitsReadImageCube(const psFits *fits, psRegion region)
 {
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
     int nAxis = 0;                      // Number of axes
     long nAxes[3];                      // Number of pixels on each axis
@@ -502,12 +507,12 @@
     char fitsErr[80] = "";              // CFITSIO error message string
 
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return NULL;
-    }
-
     // Some of this replicates what is in psFitsReadImage, so it's a little inefficient.  But it saves
     // code replication, and should be sufficient for our needs.
+
+    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
+        // This is really what we want, not the empty PHU
+        psTrace("psLib.fits", 1,
+                "This PHU should really be a compressed image --- reading that image instead.");
+    }
 
     if (fits_get_img_dim(fits->fd, &nAxis, &status) != 0) {
@@ -542,5 +547,7 @@
 
     // Bad dimensionality
-    psError(PS_ERR_IO, true, _("Image number of dimensions, %d, is not valid.  Only two or three dimensions supported for FITS I/O."), nAxis);
+    psError(PS_ERR_IO, true,
+            _("Image number of dimensions, %d, is not valid."
+              " Only two or three dimensions supported for FITS I/O."), nAxis);
     return NULL;
 }
@@ -548,15 +555,6 @@
 bool psFitsWriteImageCube(psFits *fits, psMetadata *header, const psArray *input, const char *extname)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return false;
-    }
-
-    if (input == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psImage was NULL.  Need a non-NULL psImage for operation to be performed."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_ARRAY_NON_NULL(input, false);
 
     if (input->n == 0) {
@@ -590,8 +588,8 @@
     }
     bool update = psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS", PS_META_REPLACE, "Dimensionality", 3) &&
-                  psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS1", PS_META_REPLACE, "Number of columns", numCols) &&
-                  psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS2", PS_META_REPLACE, "Number of rows", numRows) &&
-                  psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS3", PS_META_REPLACE, "Number of image planes",
-                                   input->n);
+        psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS1", PS_META_REPLACE, "Number of columns", numCols) &&
+        psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS2", PS_META_REPLACE, "Number of rows", numRows) &&
+        psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS3", PS_META_REPLACE, "Number of image planes",
+                         input->n);
     if (! update) {
         psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s."),
@@ -623,15 +621,6 @@
 bool psFitsUpdateImageCube(psFits *fits, const psArray *input, int x0, int y0)
 {
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return false;
-    }
-
-    if (input == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psImage was NULL.  Need a non-NULL psImage for operation to be performed."));
-        return false;
-    }
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_ARRAY_NON_NULL(input, false);
 
     if (input->n == 0) {
Index: /branches/pap_branch_070920/psLib/src/fits/psFitsTable.c
===================================================================
--- /branches/pap_branch_070920/psLib/src/fits/psFitsTable.c	(revision 15167)
+++ /branches/pap_branch_070920/psLib/src/fits/psFitsTable.c	(revision 15168)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.27 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-03-22 21:40:47 $
+ *  @version $Revision: 1.27.10.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-10-03 03:01:45 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -38,13 +38,10 @@
                                int row)
 {
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(row, NULL);
+
     long numRows;
     int numCols;
     int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return NULL;
-    }
 
     // check to see if we even are positioned on a table HDU
@@ -185,12 +182,9 @@
                                const char* colname)
 {
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(colname, NULL);
+
     int colnum = 0;
     int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return NULL;
-    }
 
     // check to see if we even are positioned on a table HDU
@@ -266,12 +260,9 @@
                                    const char* colname)
 {
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(colname, NULL);
+
     int status = 0;
     int colnum = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return NULL;
-    }
 
     // check to see if we even are positioned on a table HDU
@@ -348,11 +339,7 @@
 psArray* psFitsReadTable(const psFits* fits)
 {
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
     int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return NULL;
-    }
 
     // check to see if we even are positioned on a table HDU
@@ -400,5 +387,9 @@
                       const char *extname)
 {
-    psFitsMoveLast(fits);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    if (!psFitsMoveLast(fits)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to move to last extension to write table");
+        return false;
+    }
     return psFitsInsertTable(fits, header, table, extname, true);
 }
@@ -460,11 +451,9 @@
 // Column specification
 // Included here, because there's no need for the user to have access to it
-typedef struct
-{
+typedef struct {
     psDataType type;                    // psLib type (e.g., PS_DATA_STRING or PS_TYPE_F32)
     size_t size;                        // Size (number of repeats)
     psElemType vectorType;              // psLib type of vectors
-}
-colSpec;
+} colSpec;
 
 
@@ -475,8 +464,8 @@
                        bool after)
 {
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_ARRAY_NON_NULL(table, false);
+
     int status = 0;
-
-    PS_ASSERT_PTR_NON_NULL(fits, false);
-    PS_ASSERT_ARRAY_NON_NULL(table, false);
 
     long numRows = table->n;
@@ -614,5 +603,6 @@
         char fitsErr[MAX_STRING_LENGTH];
         fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_LOCATION_INVALID, true, "Unable to create FITS table with %ld columns and %ld rows: %s",
+        psError(PS_ERR_LOCATION_INVALID, true,
+                "Unable to create FITS table with %ld columns and %ld rows: %s",
                 numColumns, table->n, fitsErr);
         psFree(colSpecsIter);
@@ -632,9 +622,9 @@
     if (extname && strlen(extname) > 0) {
         if (!psFitsSetExtName(fits, extname)) {
-	    psError(PS_ERR_IO, false, "Unable to write FITS header extension name.\n");
-	    psFree(colSpecsIter);
-	    psFree(colSpecs);
-	    return false;
-	}
+            psError(PS_ERR_IO, false, "Unable to write FITS header extension name.\n");
+            psFree(colSpecsIter);
+            psFree(colSpecs);
+            return false;
+        }
     }
 
@@ -728,17 +718,9 @@
                        int row)
 {
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_METADATA_NON_NULL(data, false);
+    PS_ASSERT_INT_NONNEGATIVE(row, false);
+
     int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psFits object can not NULL."));
-        return false;
-    }
-
-    if (data == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                _("The input psImage was NULL.  Need a non-NULL psImage for operation to be performed."));
-        return false;
-    }
 
     // check to see if we even are positioned on a table HDU
