Index: trunk/psLib/src/fileUtils/Makefile
===================================================================
--- trunk/psLib/src/fileUtils/Makefile	(revision 2369)
+++ trunk/psLib/src/fileUtils/Makefile	(revision 2375)
@@ -16,6 +16,6 @@
 all: $(TARGET_STATIC)
 
-#psAstronomyErrors.h: psAstronomyErrors.dat
-#	perl ../parseErrorCodes.pl --data=$? $@
+psFileUtilsErrors.h: psFileUtilsErrors.dat
+	perl ../parseErrorCodes.pl --data=$? $@
 
 
Index: trunk/psLib/src/fileUtils/psFileUtilsErrors.dat
===================================================================
--- trunk/psLib/src/fileUtils/psFileUtilsErrors.dat	(revision 2369)
+++ trunk/psLib/src/fileUtils/psFileUtilsErrors.dat	(revision 2375)
@@ -15,2 +15,22 @@
 psLookupTable_DIVIDE_BY_ZERO           Divide by zero error during interpolation.
 psLookupTable_INVALID_TYPE             Invalid psLookupType, %d;
+#
+psFits_NULL                            The input psFits object can not NULL.
+psFits_FILENAME_INVALID                Could not open file,'%s'.\nCFITSIO Error: %s
+psFits_FILENAME_NULL                   Specified filename can not be NULL.
+psFits_EXTNAME_INVALID                 Could not find HDU '%s' in file %s.\nCFITSIO Error: %s
+psFits_EXTNUM_INVALID                  Could not find HDU #%d in file %s.\nCFITSIO Error: %s
+psFits_GET_EXTNUM_FAILED               Failed to determine the current HDU number in file %s.\nCFITSIO Error: %s
+psFits_GETNUMHDUS_FAILED               Failed to determine the number of HDUs in file %s.\nCFITSIO Error: %s
+psFits_GETHDUTYPE_FAILED               Failed to determine an HDU type in file %s.\nCFITSIO Error: %s
+psFits_GETNUMKEYS_FAILED               Failed to determine the number of header keys in file %s.\nCFITSIO Error: %s
+psFits_FILENAME_CREATE_FAILED          Could not create file,'%s'.\nCFITSIO Error: %s
+psFits_TYPE_UNSUPPORTED                Specified type, %s, is not supported.
+psFits_CREATE_HDU_FAILED               Could not create new image HDU in file,'%s'.\nCFITSIO Error: %s
+psFits_NOT_IMAGE_TYPE                  Current FITS HDU type must be an IMAGE.
+psFits_TABLE_FIRSTROW_NULL             Can't create a table without the first row, where table column information is derived.
+psFits_CFITSIO_ERROR                   CFITSIO error: %s
+psFits_METATYPE_INVALID                Specified FITS metadata type, %c, is not supported.
+psFits_METADATA_ADD_FAILED             Failed to add metadata item, %s.
+psFits_WRITE_FAILED                    Could not write psImage data to file,'%s'.\nCFITSIO Error: %s
+psFits_IMAGE_NULL                      The input psImage was NULL.  Need a non-NULL psImage for operation.
Index: trunk/psLib/src/fileUtils/psFileUtilsErrors.h
===================================================================
--- trunk/psLib/src/fileUtils/psFileUtilsErrors.h	(revision 2369)
+++ trunk/psLib/src/fileUtils/psFileUtilsErrors.h	(revision 2375)
@@ -1,5 +1,5 @@
-/** @file  psAstronomyErrors.h
+/** @file  psFileUtilsErrors.h
  *
- *  @brief Contains the error text for the astronomy functions
+ *  @brief Contains the error text for the fileUtils functions
  *
  *  @ingroup ErrorHandling
@@ -7,12 +7,12 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-11-09 00:38:14 $
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-11-16 20:00:21 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
 
-#ifndef PS_SYSUTILS_ERRORS_H
-#define PS_SYSUTILS_ERRORS_H
+#ifndef PS_FILEUTIL_ERRORS_H
+#define PS_FILEUTIL_ERRORS_H
 
 /* N.B., lines between '//~Start' and '//~End' are automatic generated from
@@ -38,4 +38,23 @@
 #define PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO "Divide by zero error during interpolation."
 #define PS_ERRORTEXT_psLookupTable_INVALID_TYPE "Invalid psLookupType, %d;"
+#define PS_ERRORTEXT_psFits_NULL "The input psFits object can not NULL."
+#define PS_ERRORTEXT_psFits_FILENAME_INVALID "Could not open file,'%s'.\nCFITSIO Error: %s"
+#define PS_ERRORTEXT_psFits_FILENAME_NULL "Specified filename can not be NULL."
+#define PS_ERRORTEXT_psFits_EXTNAME_INVALID "Could not find HDU '%s' in file %s.\nCFITSIO Error: %s"
+#define PS_ERRORTEXT_psFits_EXTNUM_INVALID "Could not find HDU #%d in file %s.\nCFITSIO Error: %s"
+#define PS_ERRORTEXT_psFits_GET_EXTNUM_FAILED "Failed to determine the current HDU number in file %s.\nCFITSIO Error: %s"
+#define PS_ERRORTEXT_psFits_GETNUMHDUS_FAILED "Failed to determine the number of HDUs in file %s.\nCFITSIO Error: %s"
+#define PS_ERRORTEXT_psFits_GETHDUTYPE_FAILED "Failed to determine an HDU type in file %s.\nCFITSIO Error: %s"
+#define PS_ERRORTEXT_psFits_GETNUMKEYS_FAILED "Failed to determine the number of header keys in file %s.\nCFITSIO Error: %s"
+#define PS_ERRORTEXT_psFits_FILENAME_CREATE_FAILED "Could not create file,'%s'.\nCFITSIO Error: %s"
+#define PS_ERRORTEXT_psFits_TYPE_UNSUPPORTED "Specified type, %s, is not supported."
+#define PS_ERRORTEXT_psFits_CREATE_HDU_FAILED "Could not create new image HDU in file,'%s'.\nCFITSIO Error: %s"
+#define PS_ERRORTEXT_psFits_NOT_IMAGE_TYPE "Current FITS HDU type must be an IMAGE."
+#define PS_ERRORTEXT_psFits_TABLE_FIRSTROW_NULL "Can't create a table without the first row, where table column information is derived."
+#define PS_ERRORTEXT_psFits_CFITSIO_ERROR "CFITSIO error: %s"
+#define PS_ERRORTEXT_psFits_METATYPE_INVALID "Specified FITS metadata type, %c, is not supported."
+#define PS_ERRORTEXT_psFits_METADATA_ADD_FAILED "Failed to add metadata item, %s."
+#define PS_ERRORTEXT_psFits_WRITE_FAILED "Could not write psImage data to file,'%s'.\nCFITSIO Error: %s"
+#define PS_ERRORTEXT_psFits_IMAGE_NULL "The input psImage was NULL.  Need a non-NULL psImage for operation."
 //~End
 
Index: trunk/psLib/src/fileUtils/psFits.c
===================================================================
--- trunk/psLib/src/fileUtils/psFits.c	(revision 2375)
+++ trunk/psLib/src/fileUtils/psFits.c	(revision 2375)
@@ -0,0 +1,614 @@
+/** @file  psFits.c
+ *
+ *  @brief Contains Fits I/O routines
+ *
+ *  @ingroup FileIO
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-11-16 20:00:21 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <unistd.h>
+
+#include "psFits.h"
+#include "string.h"
+#include "psError.h"
+#include "psFileUtilsErrors.h"
+#include "psMemory.h"
+#include "psString.h"
+#include "psLogMsg.h"
+
+#define MAX_STRING_LENGTH 256  // maximum length string for FITS routines
+
+static bool convertPsTypeToFits(psElemType type, int* bitPix, double* bZero, int* dataType)
+{
+
+    int bitpix;
+    int datatype;
+    double bzero = 0.0;
+
+    switch (type) {
+
+    case PS_TYPE_U8:
+        bitpix = BYTE_IMG;
+        datatype = TBYTE;
+        break;
+
+    case PS_TYPE_S8:
+        bitpix = BYTE_IMG;
+        bzero = INT8_MIN;
+        datatype = TSBYTE;
+        break;
+
+    case PS_TYPE_U16:
+        bitpix = SHORT_IMG;
+        bzero = -1.0 * INT16_MIN;
+        datatype = TUSHORT;
+        break;
+
+    case PS_TYPE_S16:
+        bitpix = SHORT_IMG;
+        datatype = TSHORT;
+        break;
+
+    case PS_TYPE_U32:
+        bitpix = LONG_IMG;
+        bzero = -1.0 * INT32_MIN;
+        datatype = TUINT;
+        break;
+
+    case PS_TYPE_S32:
+        bitpix = LONG_IMG;
+        datatype = TINT;
+        break;
+
+    case PS_TYPE_F32:
+        bitpix = FLOAT_IMG;
+        datatype = TFLOAT;
+        break;
+
+    case PS_TYPE_F64:
+        bitpix = DOUBLE_IMG;
+        datatype = TDOUBLE;
+        break;
+
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    PS_ERRORTEXT_psFits_TYPE_UNSUPPORTED,
+                    typeStr);
+            return false;
+        }
+    }
+
+    // pass the requested parameters  (NULL parameters are not set, of course).
+    if (bitPix != NULL) {
+        *bitPix = bitpix;
+    }
+
+    if (dataType != NULL) {
+        *dataType = datatype;
+    }
+
+    if (bZero != NULL) {
+        *bZero = bzero;
+    }
+
+    return true;
+}
+
+static bool convertPsMetadataTypeToBinaryTForm(psMetadataType type, char** fitsType)
+{
+    switch (type) {
+    case PS_META_BOOL:
+        *fitsType = "1L";
+        break;
+    case PS_META_S32:
+        *fitsType = "1J";
+        break;
+    case PS_META_F32:
+        *fitsType = "1E";
+        break;
+    case PS_META_F64:
+        *fitsType = "1D";
+        break;
+        // XXX: Handle other types, e.g., Vectors, etc.
+    default:
+        return false;
+    }
+
+    return true;
+}
+
+static bool isHDUEmpty(psFits* fits)
+{
+    /* check for keys - no keys means this is really an empty HDU */
+    int keysexist = -1;
+    int morekeys;
+    int status = 0;
+
+    fits_get_hdrspace(fits->p_fd, &keysexist, &morekeys, &status);
+
+    // if no keys exist and not primary HDU, this really is an empty HDU
+    if (keysexist == 0) {
+        return true;
+    }
+
+    return false;
+
+}
+
+static void fitsFree(psFits* fits)
+{
+    int status = 0;
+
+    if (fits != NULL) {
+        (void)fits_close_file(fits->p_fd, &status);
+        psFree((void*)fits->filename);
+    }
+}
+
+psFits* psFitsAlloc(const char* name,                  ///< the FITS file name
+                    bool readwrite)                    ///< if TRUE, the file is open for read/write.
+{
+    int status = 0;
+    fitsfile *fptr = NULL;      /* Pointer to the FITS file */
+
+    if (name == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_FILENAME_NULL);
+        return NULL;
+    }
+
+    int iomode = (readwrite) ? READWRITE : READONLY;
+
+    /* Open/Create the FITS file */
+    if (access(name, F_OK) == 0) {     // file exists
+        (void)fits_open_file(&fptr, name, iomode, &status);
+        if (fptr == NULL || status != 0) {
+            char fitsErr[MAX_STRING_LENGTH];
+            fits_get_errstatus(status, fitsErr);
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    PS_ERRORTEXT_psFits_FILENAME_INVALID,
+                    name, fitsErr);
+            return NULL;
+        }
+    } else {  // file does not exist
+        (void)fits_create_file(&fptr, name, &status);
+        if (fptr == NULL || status != 0) {
+            char fitsErr[MAX_STRING_LENGTH];
+            fits_get_errstatus(status, fitsErr);
+            psError(PS_ERR_IO, true,
+                    PS_ERRORTEXT_psFits_FILENAME_CREATE_FAILED,
+                    name, fitsErr);
+            return NULL;
+        }
+    }
+
+    psFits* fits = psAlloc(sizeof(psFits));
+    fits->filename = psAlloc(strlen(name)+1);
+    fits->p_fd = fptr;
+    strcpy((char*)fits->filename,name);
+    p_psMemSetDeallocator(fits,(psFreeFcn)fitsFree);
+
+    return fits;
+}
+
+psFitsType psFitsMoveExtName(psFits* fits,
+                             const char* extname)
+{
+    int status = 0;
+
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return PS_FITS_TYPE_NONE;
+    }
+
+
+    if (fits_movnam_hdu(fits->p_fd, ANY_HDU, (char*)extname, 0, &status) != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_LOCATION_INVALID, true,
+                PS_ERRORTEXT_psFits_EXTNAME_INVALID,
+                extname, fits->filename, fitsErr);
+        return PS_FITS_TYPE_NONE;
+    }
+
+    return psFitsGetExtType(fits);
+}
+
+psFitsType psFitsMoveExtNum(psFits* fits,
+                            int extnum,
+                            bool relative)
+{
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return PS_FITS_TYPE_NONE;
+    }
+
+    int status = 0;
+    int hdutype = 0;
+
+    if (relative) {
+        fits_movrel_hdu(fits->p_fd, extnum+1, &hdutype, &status);
+    } else {
+        fits_movabs_hdu(fits->p_fd, extnum+1, &hdutype, &status);
+    }
+
+    if (status != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_LOCATION_INVALID, true,
+                PS_ERRORTEXT_psFits_EXTNUM_INVALID,
+                extnum, fits->filename, fitsErr);
+        return PS_FITS_TYPE_NONE;
+    }
+
+    return hdutype;
+}
+
+int psFitsGetExtNum(psFits* fits)
+{
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return PS_FITS_TYPE_NONE;
+    }
+
+    int hdutype = ANY_HDU;
+    int status = 0;
+
+    if (fits_get_hdu_type(fits->p_fd, &hdutype, &status) != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_LOCATION_INVALID, true,
+                PS_ERRORTEXT_psFits_GET_EXTNUM_FAILED,
+                fits->filename, fitsErr);
+        return -1;
+    }
+
+    return hdutype-1;
+}
+
+char* psFitsGetExtName(psFits* fits)
+{
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return NULL;
+    }
+
+    int status = 0;
+    char name[MAX_STRING_LENGTH];
+
+    if (fits_read_key_str(fits->p_fd, "EXTNAME", name, NULL, &status) != 0) {
+        status = 0;
+        if (fits_read_key_str(fits->p_fd, "HDUNAME", name, NULL, &status) != 0) {
+            int num = psFitsGetExtNum(fits);
+            snprintf(name, MAX_STRING_LENGTH, "EXT-%3d",num);
+        }
+    }
+    return psStringCopy(name);
+}
+
+int psFitsGetSize(psFits* fits)
+{
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return PS_FITS_TYPE_NONE;
+    }
+
+    int num = 0;
+    int status = 0;
+
+    if (fits_get_num_hdus(fits->p_fd, &num, &status) != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_LOCATION_INVALID, true,
+                PS_ERRORTEXT_psFits_GETNUMHDUS_FAILED,
+                fits->filename, fitsErr);
+        return -1;
+    }
+
+    return num;
+}
+
+bool psFitsCreateExt(psFits* fits)
+{
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return false;
+    }
+
+    int status = 0;
+
+    fits_create_hdu(fits->p_fd,&status);
+
+    if ( status != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_CREATE_HDU_FAILED,
+                fits->filename, fitsErr);
+        return false;
+    }
+
+    return true;
+}
+
+psFitsType psFitsGetExtType(psFits* fits)
+{
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return PS_FITS_TYPE_NONE;
+    }
+
+    int status = 0;
+    int hdutype = PS_FITS_TYPE_NONE;
+
+    if (fits_get_hdu_type(fits->p_fd, &hdutype, &status) != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_LOCATION_INVALID, true,
+                PS_ERRORTEXT_psFits_GETHDUTYPE_FAILED,
+                fits->filename, fitsErr);
+        return PS_FITS_TYPE_NONE;
+    }
+
+    if (hdutype == PS_FITS_TYPE_IMAGE &&
+            psFitsGetExtNum(fits) > 0 &&
+            isHDUEmpty(fits)) {
+        return PS_FITS_TYPE_ANY;
+    }
+
+    return hdutype;
+}
+
+psMetadata* psFitsReadHeader(psMetadata* out,
+                             const psFits* fits)
+{
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return NULL;
+    }
+
+    if (out == NULL) {
+        out = psMetadataAlloc();
+        if (out == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to allocate a new psMetadata container.");
+            return NULL;
+        }
+    }
+
+    // Get number of key names
+    int numKeys = 0;
+    int keyNum = 0;
+    int status = 0;
+    fits_get_hdrpos(fits->p_fd, &numKeys, &keyNum, &status);
+
+    // Get each key name. Keywords start at one.
+    char keyType;
+    char keyName[MAX_STRING_LENGTH];
+    char keyValue[MAX_STRING_LENGTH];
+    char keyComment[MAX_STRING_LENGTH];
+    psMetadataType metadataItemType;
+    psBool tempBool;
+    psBool success;
+    for (int i = 1; i <= numKeys; i++) {
+
+        fits_read_keyn(fits->p_fd, i, keyName, keyValue, keyComment, &status);
+        fits_get_keytype(keyValue, &keyType, &status);
+        if (status != 0) {
+            break;
+        }
+
+        switch (keyType) {
+        case 'I':
+            metadataItemType = PS_META_S32;
+            success = psMetadataAdd(out, PS_LIST_TAIL, keyName, metadataItemType, keyComment, atoi(keyValue));
+            break;
+        case 'F':
+            metadataItemType = PS_META_F64;
+            success = psMetadataAdd(out, PS_LIST_TAIL, keyName, metadataItemType, keyComment, atof(keyValue));
+            break;
+        case 'C':
+            metadataItemType = PS_META_STR;
+            success = psMetadataAdd(out, PS_LIST_TAIL, keyName, metadataItemType, keyComment, keyValue);
+            break;
+        case 'L':
+            metadataItemType = PS_META_BOOL;
+            tempBool = (keyValue[0] == 'T') ? 1 : 0;
+            success = psMetadataAdd(out, PS_LIST_TAIL, keyName, metadataItemType, keyComment, tempBool);
+            break;
+        case 'U':
+        case 'X':
+        default:
+            psError(PS_ERR_IO, true,
+                    PS_ERRORTEXT_psFits_METATYPE_INVALID,
+                    keyType);
+            return out;
+        }
+
+        if (!success) {
+            psError(PS_ERR_UNKNOWN, false,
+                    PS_ERRORTEXT_psFits_METADATA_ADD_FAILED,
+                    keyName);
+            return out;
+        }
+    }
+
+    if ( status != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_METADATA_ADD_FAILED,
+                fitsErr);
+        return false;
+    }
+
+    return out;
+}
+
+psHash* psFitsReadHeaderSet(psHash* out,
+                            psFits* fits)
+{
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return out;
+    }
+
+    if (out == NULL) {
+        out = psHashAlloc(10);
+        // XXX: what is the appropriate number of buckets? Got 10 from psMetadataAlloc.
+        if (out == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to allocate a new psHash container.");
+            return NULL;
+        }
+    }
+
+    int status = 0;
+
+    int size = psFitsGetSize(fits);
+    int position = psFitsGetExtNum(fits);
+
+    for (int lcv=0; lcv < size; lcv++) {
+        if (psFitsMoveExtNum(fits, lcv, false)) {
+            char* name = psFitsGetExtName(fits);
+            psMetadata* header = psFitsReadHeader(NULL, fits);
+            if (name != NULL || header != NULL) {
+                psHashAdd(out, name, header);
+            } else { // XXX: is this a warning or error?
+                psLogMsg(__func__, PS_LOG_WARN,
+                         "Failed to read HDU#%d header data.",
+                         lcv);
+            }
+
+            psFree(name);
+            psFree(header);
+        }
+    }
+}
+
+bool psFitsWriteImage(psFits* fits,
+                      const psImage* input,
+                      int x,
+                      int y,
+                      int z)
+{
+
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return false;
+    }
+
+    if (input == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_IMAGE_NULL);
+        return false;
+    }
+    int numCols = input->numCols;
+    int numRows = input->numRows;
+
+    int status = 0;
+
+    psFitsType fitsType = psFitsGetExtType(fits);
+
+    if (fitsType != PS_FITS_TYPE_IMAGE && fitsType != PS_FITS_TYPE_ANY) {
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_NOT_IMAGE_TYPE);
+        return false;
+    }
+
+    // determine the FITS-equivalent parameters
+    int bitPix;
+    double bZero;
+    int dataType;
+    if (! convertPsTypeToFits(input->type.type, &bitPix, &bZero, &dataType) ) {
+        return false;
+    }
+
+    if (fitsType == PS_FITS_TYPE_ANY) {
+        int naxis = 3;
+        long naxes[3];
+
+        naxes[0] = numCols;
+        naxes[1] = numRows;
+        naxes[2] = z;
+
+        if (z < 2) {
+            naxis = 2;
+        }
+
+        /* write the required keys to make an empty HDU be an IMAGE HDU */
+        fits_write_imghdr(fits->p_fd, bitPix, naxis, naxes, &status);
+        if (bZero != 0) {        // set the bscale/bzero
+            fits_write_key_dbl(fits->p_fd, "BZERO", bZero, 12, "Pixel Value Offset", &status);
+            fits_write_key_dbl(fits->p_fd, "BSCALE", 1.0, 12, "Pixel Value Scale", &status);
+            // don't think this is needed: fits_set_bscale(fits->p_fd, bScale, bZero, &status);
+        }
+    }
+
+    long firstPixel[3];         /* First Pixel to read */
+    long lastPixel[3];          /* Last Pixel to read */
+    firstPixel[0] = x + 1;
+    firstPixel[1] = y + 1;
+    firstPixel[2] = z + 1;
+
+    lastPixel[0] = firstPixel[0] + numCols - 1;
+    lastPixel[1] = firstPixel[1] + numRows - 1;
+    lastPixel[2] = z + 1;
+
+    fits_write_subset(fits->p_fd, dataType, firstPixel, lastPixel, input->data.V[0], &status);
+
+    if ( status != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_WRITE_FAILED,
+                fits->filename, fitsErr);
+        return false;
+    }
+
+    return true;
+
+}
+
+psMetadata* psFitsReadTableRow(psFits* fits,
+                               int row)
+{
+}
+
+psArray* psFitsReadTableColumn(psFits* fits,
+                               const char* colname)
+{
+}
+
+psVector* psFitsReadTableColumnNum(psFits* fits,
+                                   const char* colname)
+{
+}
+
+
+psArray* psFitsReadTable(psFits* fits)
+{
+}
+
+bool psFitsWriteTable(psFits* fits,
+                      psArray* table)
+{
+}
Index: trunk/psLib/src/fileUtils/psFits.h
===================================================================
--- trunk/psLib/src/fileUtils/psFits.h	(revision 2375)
+++ trunk/psLib/src/fileUtils/psFits.h	(revision 2375)
@@ -0,0 +1,240 @@
+/** @file  psFits.h
+ *
+ *  @brief Contains Fits I/O routines
+ *
+ *  @ingroup FileIO
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-11-16 20:00:21 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_FITS_H
+#define PS_FITS_H
+
+#include<fitsio.h>
+
+#include "psType.h"
+#include "psArray.h"
+#include "psVector.h"
+#include "psMetadata.h"
+#include "psHash.h"
+#include "psImage.h"
+
+/// @addtogroup FileIO
+/// @{
+
+typedef enum {
+    PS_FITS_TYPE_NONE = -1,
+    PS_FITS_TYPE_IMAGE = IMAGE_HDU,
+    PS_FITS_TYPE_BINARY_TABLE = BINARY_TBL,
+    PS_FITS_TYPE_ASCII_TABLE = ASCII_TBL,
+    PS_FITS_TYPE_ANY = ANY_HDU
+} psFitsType;
+
+/** FITS file object.
+ * 
+ *  This object should be considered opaque to the user; no item in this
+ *  struct should be accessed directly.
+ *
+ */
+typedef struct
+{
+    fitsfile* p_fd;                    ///< the CFITSIO fits files handle.
+    const char* filename;              ///< the filename of the fits file
+}
+psFits;
+
+/** Opens a FITS file and allocates the associated psFits object.
+ *
+ *  @return psFits*    new psFits object for the FITS files specified or 
+ *                     NULL if the open of the FITS file failed
+ */
+psFits* psFitsAlloc(
+    const char* name,                  ///< the FITS file name
+    bool readwrite                     ///< if TRUE, the file is open for read/write.
+);
+
+/** Moves the FITS HDU to the specified extension name.
+ *
+ *  @return psFitsType    The HDU type, or PS_FITS_TYPE_NONE if move failed.
+ */
+psFitsType psFitsMoveExtName(
+    psFits* fits,                      ///< the psFits object to move
+    const char* extname                ///< the extension name
+);
+
+/** Moves the FITS HDU to the specified extension number
+ *
+ *  @return psFitsType    The HDU type, or PS_FITS_TYPE_NONE if move failed.
+ */
+psFitsType psFitsMoveExtNum(
+    psFits* fits,                      ///< the psFits object to move
+    int extnum,                        ///< the extension number to move to (zero is primary HDU)
+    bool relative                      ///< if true, extnum is a relative number to the current position
+);
+
+/** Get the current extension number, where 0 is the primary HDU.
+ *
+ *  @return int        Current HDU number of the psFits file or < 0 if an error
+ *                     occurred.
+ */
+int psFitsGetExtNum(
+    psFits* fits                       ///< the psFits object
+);
+
+/** Get the current extension name.
+ *
+ *  @return int        Current HDU name of the psFits file or NULL if an 
+ *                     error occurred.
+ */
+char* psFitsGetExtName(
+    psFits* fits                       ///< the psFits object
+);
+
+/** Get the total number of HDUs in the FITS file.
+ *
+ *  @return int        The total number of HDUs in the FITS file or < 0 if an 
+ *                     error occurred.
+ */
+int psFitsGetSize(
+    psFits* fits                       ///< the psFits object
+);
+
+/** Create a new extension on the end of the file of the given type.  The
+ *  FITS file is 
+ *
+ *  @return bool       true if successful, otherwise false
+ */
+bool psFitsCreateExt(
+    psFits* fits                       ///< the psFits object
+);
+
+/** Get the extension type of the current HDU.
+ *
+ *  @return psFitsType The type of the current HDU.  If PS_FITS_TYPE_UNKNOWN, 
+ *                     the type could not be determined.
+ */
+psFitsType psFitsGetExtType(
+    psFits* fits                       ///< the psFits object
+);
+
+/** Reads the header of the current HDU.
+ *
+ *  @return psMetadata*   the header data
+ */
+psMetadata* psFitsReadHeader(
+    psMetadata* out,
+    ///< The psMetadata to add the header data.  If null, a new psMetadata is created.
+
+    const psFits* fits                 ///< the psFits object
+);
+
+/** Reads the header of all HDUs.  The current HDU is not changed.
+ *
+ *  @return psHash*      the header data
+ */
+psHash* psFitsReadHeaderSet(
+    psHash* out,
+    ///< The psHash to add the header data via psMetadata items.  If null, a
+    ///< new psHash is created.  The keys of the psHash are the extension names
+    ///< of the cooresponding HDUs.
+
+    psFits* fits                       ///< the psFits object
+);
+
+/** Writes the values of the metadata to the current HDU header.
+ *
+ *  @return bool        if TRUE, the write was successful, otherwise FALSE.
+ */
+bool psFitsWriteHeader(
+    psFits* fits,                      ///< the psFits object
+    psMetadata* out                    ///< the psMetadata data in which to write
+);
+
+/** Reads an image, given the desired region and z-plane.
+ *
+ *  @return psImage*     the read image or NULL if there was an error.
+ */
+psImage* psfitsReadImageSection(
+    psImage* out,                      ///< a psImage to recycle.
+    psFits* fits,                      ///< the psFits object
+    psRegion region,                   ///< the region in the FITS image to read
+    int z                              ///< the z-plane in the FITS image cube to read
+);
+
+/** Writes an image, given the desired region and z-plane.
+ *
+ *  @return bool        TRUE is the write was successful, otherwise FALSE.
+ */
+bool psFitsWriteImageSection(
+    psFits* fits,                      ///< the psFits object
+    const psImage* input,              ///< the image to output
+    psRegion region,                   ///< the part of the FITS image to overwrite
+    int z                              ///< the z-plane of the FITS image data cube to use
+);
+
+/** Reads a table row.  The current HDU type must be either
+ *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+ *
+ *  @return psMetadata*    The table row's data.  The keys are the column names.
+ */
+psMetadata* psFitsReadTableRow(
+    psFits* fits,                      ///< the psFits object
+    int row                            ///< row number to read
+);
+
+/** Reads a table column.  The current HDU type must be either
+ *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+ *
+ *  @return psArray*    Array of data items for the specified column or NULL 
+ *                      if an error occurred.
+ */
+psArray* psFitsReadTableColumn(
+    psFits* fits,
+    const char* colname
+);
+
+/** Reads a table column of numbers.  The current HDU type must be either
+ *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+ *
+ *  @return psVector*    Vector of data for the specified column or NULL
+ *                       if an error occurred.
+ */
+psVector* psFitsReadTableColumnNum(
+    psFits* fits,                      ///< the psFits object
+    const char* colname                ///< the column name
+);
+
+
+/** Reads a whole FITS table.  The current HDU type must be either
+ *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+ *
+ *  @return psArray*     Array of psMetadata items, which contains the output
+ *                       data items of each row.
+ *  
+ *  @see psFitsReadTableRow
+ */
+psArray* psFitsReadTable(
+    psFits* fits                       ///< the psFits object
+);
+
+/** Writes a whole FITS table.  The current HDU type must be either
+ *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+ *
+ *  @return bool        TRUE if the write was successful, otherwise FALSE
+ *  
+ *  @see psFitsReadTableRow
+ */
+bool psFitsWriteTable(
+    psFits* fits,                      ///< the psFits object
+    psArray* table
+    ///< Array of psMetadata items, which contains the output data items of each row.
+);
+
+/// @}
+
+#endif
