Index: /branches/rel10_ifa/psModules/src/astrom/Makefile.am
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/Makefile.am	(revision 6662)
+++ /branches/rel10_ifa/psModules/src/astrom/Makefile.am	(revision 6663)
@@ -8,4 +8,5 @@
 	pmFPAMaskWeight.c \
 	pmFPARead.c \
+	pmFPAWrite.c \
 	pmHDU.c \
 	pmHDUGetLowest.c \
@@ -21,5 +22,4 @@
 #	pmAstrometryObjects.c
 #	pmChipMosaic.c
-#	pmFPAWrite.c
 
 psmoduleincludedir = $(includedir)
@@ -29,4 +29,5 @@
 	pmFPAMaskWeight.h \
 	pmFPARead.h \
+	pmFPAWrite.h \
 	pmHDU.h \
 	pmHDUGetLowest.h \
@@ -44,3 +45,2 @@
 #
 #	pmChipMosaic.h 
-#	pmFPAWrite.h 
Index: /branches/rel10_ifa/psModules/src/astrom/pmConceptsStandard.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmConceptsStandard.c	(revision 6662)
+++ /branches/rel10_ifa/psModules/src/astrom/pmConceptsStandard.c	(revision 6663)
@@ -413,5 +413,5 @@
         psString format = psMetadataLookupStr(&mdok, formats, name);
         if (mdok && strlen(format) > 0 && strcasecmp(format, "FORTRAN") == 0) {
-            return -1;
+            return 1;
         }
     }
@@ -429,5 +429,5 @@
     }
     int offset = concept->data.S32;
-    offset += fortranCorr(cameraFormat, pattern->name);
+    offset -= fortranCorr(cameraFormat, pattern->name);
     return psMetadataItemAllocS32(pattern->name, pattern->comment, offset);
 }
@@ -486,5 +486,5 @@
         psMetadataItem *yBinItem = psMetadataLookup(cell->concepts, "CELL.YBIN"); // Binning factor in y
         psString binString = psStringCopy("");
-        psStringAppend(&binString, "%d,%d", concept->data.S32, yBinItem->data.S32);
+        psStringAppend(&binString, "%d %d", concept->data.S32, yBinItem->data.S32);
         psMetadataItem *binItem = psMetadataItemAllocStr(concept->name, concept->comment, binString);
         psFree(binString);
@@ -611,5 +611,5 @@
     }
     int offset = concept->data.S32;
-    offset -= fortranCorr(cameraFormat, concept->name);
+    offset += fortranCorr(cameraFormat, concept->name);
     return psMetadataItemAllocS32(concept->name, concept->comment, offset);
 }
Index: /branches/rel10_ifa/psModules/src/astrom/pmConceptsWrite.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmConceptsWrite.c	(revision 6662)
+++ /branches/rel10_ifa/psModules/src/astrom/pmConceptsWrite.c	(revision 6663)
@@ -132,4 +132,7 @@
     if (cell) {
         pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
+        if (!hdu) {
+            return false;
+        }
         psMetadata *cameraFormat = hdu->format; // The camera format
         psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
@@ -145,4 +148,7 @@
                 // Formatted version
                 psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, NULL, NULL, cell);
+                if (!formatted) {
+                    continue;
+                }
                 psString nameSource = NULL; // String with the concept name and ".SOURCE" added
                 psStringAppend(&nameSource, "%s.SOURCE", name);
@@ -193,4 +199,7 @@
 {
     pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
+    if (!hdu) {
+        return false;
+    }
     psMetadata *cameraFormat = hdu->format; // The camera format
     bool mdok = true;                   // Status of MD lookup
@@ -208,4 +217,7 @@
                 psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
                 psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, fpa, chip, cell);
+                if (!formatted) {
+                    continue;
+                }
                 if (! compareConcepts(defaultItem, formatted)) {
                     psLogMsg(__func__, PS_LOG_WARN, "Concept %s is specified by the DEFAULTS in the camera "
@@ -229,4 +241,7 @@
 {
     pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
+    if (!hdu) {
+        return false;
+    }
     psMetadata *cameraFormat = hdu->format; // The camera format
     bool mdok = true;                   // Status of MD lookup
@@ -249,4 +264,7 @@
                 psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
                 psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, fpa, chip, cell);
+                if (!formatted) {
+                    continue;
+                }
                 psList *keywords = psStringSplit(headerItem->data.V, " ,;"); // List of header keywords
                 if (formatted->type == PS_DATA_LIST) {
@@ -289,4 +307,7 @@
 {
     pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
+    if (!hdu) {
+        return false;
+    }
     psMetadata *cameraFormat = hdu->format; // The camera format
     bool mdok = true;                   // Status of MD lookup
@@ -311,4 +332,7 @@
                 psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
                 psMetadataItem *formatted = conceptFormat(spec, conceptItem, cameraFormat, fpa, chip, cell);
+                if (!formatted) {
+                    continue;
+                }
 
                 psMetadata *dbLookup = dbItem->data.V; // How to look up the value of interest
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.c	(revision 6662)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.c	(revision 6663)
@@ -115,11 +115,10 @@
         return false;
     }
-    psString result = psMetadataLookupStr(&mdok, header, keyword);
-    if (!mdok || strlen(result) == 0) {
+    psMetadataItem *resultItem = psMetadataLookup(header, keyword);
+    if (! resultItem) {
         psError(PS_ERR_IO, false, "Unable to find %s in primary header to identify %s.\n", keyword, name);
         return NULL;
     }
-
-    return result;
+    return psMetadataItemParseString(resultItem);
 }
 
@@ -190,4 +189,8 @@
     }
     psMetadataItem *fpaNameItem = psMetadataLookup(phu, nameKeyword); // Name of the FPA
+    if (!fpaNameItem) {
+        psError(PS_ERR_IO, false, "Unable to find keyword %s with the name of the FPA.\n", nameKeyword);
+        return NULL;
+    }
     const char *newFPAname = psMetadataItemParseString(fpaNameItem); // FPA.NAME for new source
     fpaNameItem = psMetadataLookup(fpa->concepts, "FPA.NAME"); // Current name of FPA
@@ -421,5 +424,7 @@
             psString chipName = NULL;   // Name of chip under consideration
             pmChip *chip = NULL;        // The chip we're looking for
-            if (! fpa->hdu->phu) {
+            #if 1
+            // Think I'm doing this at the start now
+            if (!fpa->hdu || !fpa->hdu->phu) {
                 // Need to look up the name of the chip
                 chipName = phuNameFromHeader("CHIP.NAME", formatSpec, phu);
@@ -431,8 +436,9 @@
                 chip = fpa->chips->data[chipNum];
             }
+            #endif
             for (int i = 0; i < names->n; i++) {
                 psString cellType = values->data[i]; // The type of the cell
                 psString cellName = NULL; // The name of the cell
-                if (fpa->hdu->phu) {
+                if (fpa->hdu && fpa->hdu->phu) {
                     // We've got chipName:cellType with cellType == cellName
                     chipName = names->data[i];
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPARead.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPARead.c	(revision 6662)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPARead.c	(revision 6663)
@@ -59,5 +59,7 @@
 #if 0
 bool pmReadoutRead(pmReadout *readout,  // Readout to read into
-                   psFits *fits         // FITS file from which to read
+                   psFits *fits,        // FITS file from which to read
+                   int numSections      // Total number of sections
+                   int section          // The section of interest
                   )
 {
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPAWrite.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPAWrite.c	(revision 6662)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPAWrite.c	(revision 6663)
@@ -4,7 +4,78 @@
 
 #include "pmFPA.h"
-#include "pmFPARead.h"
+#include "pmHDU.h"
 #include "pmConcepts.h"
 
+
+bool pmCellWrite(pmCell *cell,          // Cell to write
+                 psFits *fits,          // FITS file to which to write
+                 psDB *db               // Database handle for "concepts" update
+                )
+{
+    pmConceptsWriteCell(cell, PM_CONCEPT_SOURCE_HEADER, false, NULL);
+
+    pmHDU *hdu = cell->hdu;             // The HDU
+    if (hdu && !pmHDUWrite(hdu, fits)) {
+        psError(PS_ERR_IO, false, "Unable to write HDU for Chip.\n");
+        return false;
+    }
+
+    return true;
+}
+
+
+bool pmChipWrite(pmChip *chip,          // Chip to write
+                 psFits *fits,          // FITS file to which to write
+                 psDB *db               // Database handle for "concepts" update
+                )
+{
+    pmConceptsWriteChip(chip, PM_CONCEPT_SOURCE_HEADER, false, NULL);
+
+    pmHDU *hdu = chip->hdu;             // The HDU
+    if (hdu && !pmHDUWrite(hdu, fits)) {
+        psError(PS_ERR_IO, false, "Unable to write HDU for Chip.\n");
+        return false;
+    }
+
+    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);
+    }
+
+    return success;
+}
+
+
+
+
+bool pmFPAWrite(pmFPA *fpa,             // FPA to write
+                psFits *fits,           // FITS file to which to write
+                psDB *db                // Database handle for "concepts" update
+               )
+{
+    pmConceptsWriteFPA(fpa, PM_CONCEPT_SOURCE_HEADER, NULL);
+
+    pmHDU *hdu = fpa->hdu;              // The HDU
+    if (hdu && !pmHDUWrite(hdu, fits)) {
+        psError(PS_ERR_IO, false, "Unable to write HDU for FPA.\n");
+        return false;
+    }
+
+    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);
+    }
+
+    return success;
+}
+
+
+
+
+#if 0
 static bool writeHDU(psFits *fits,      // FITS file to which to write
                      pmHDU *hdu         // Pixel data to write
@@ -258,2 +329,3 @@
     return true;
 }
+#endif
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPAWrite.h
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPAWrite.h	(revision 6662)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPAWrite.h	(revision 6663)
@@ -5,17 +5,17 @@
 #include "pmFPA.h"
 
-bool pmFPAWrite(psFits *fits,           // FITS file to which to write
-                pmFPA *fpa,             // FPA to write
-                psDB *db                // Database to update
+
+bool pmCellWrite(pmCell *cell,          // Cell to write
+                 psFits *fits,          // FITS file to which to write
+                 psDB *db               // Database handle for "concepts" update
+                );
+bool pmChipWrite(pmChip *chip,          // Chip to write
+                 psFits *fits,          // FITS file to which to write
+                 psDB *db               // Database handle for "concepts" update
+                );
+bool pmFPAWrite(pmFPA *fpa,             // FPA to write
+                psFits *fits,           // FITS file to which to write
+                psDB *db                // Database handle for "concepts" update
                );
 
-bool pmFPAWriteMask(pmFPA *fpa,         // FPA containing mask to write
-                    psFits *fits        // FITS file for image
-                   );
-
-bool pmFPAWriteWeight(pmFPA *fpa,       // FPA containing mask to write
-                      psFits *fits      // FITS file for image
-                     );
-
-
 #endif
Index: /branches/rel10_ifa/psModules/src/astrom/pmHDU.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmHDU.c	(revision 6662)
+++ /branches/rel10_ifa/psModules/src/astrom/pmHDU.c	(revision 6663)
@@ -114,4 +114,6 @@
     assert(fits);
 
+    psTrace(__func__, 7, "Writing HDU %s\n", hdu->extname);
+
     if (hdu->images && hdu->table && !hdu->header) {
         psError(PS_ERR_IO, true, "Both image and table data provided in HDU, but no header --- "
@@ -120,11 +122,22 @@
     }
 
+    // Preserve the extension name, if it's the PHU
+    char *extname = hdu->extname;       // The name of the extension
+    if (strcasecmp(extname, "PHU") == 0) {
+        bool mdok = true;               // Status of MD lookup
+        extname = psMetadataLookupStr(&mdok, hdu->header, "EXTNAME");
+        if (!mdok || strlen(extname) == 0) {
+            extname = "";
+        }
+    }
+
+    if (!hdu->images && !psFitsWriteHeader(hdu->header, fits)) {
+        psError(PS_ERR_IO, false, "Unable to write header for extension %s\n", extname);
+    }
+
     #ifdef FITS_TABLES
     if (hdu->images && (!hdu->table || psFitsIsImage(hdu->header))) {
-        #endif
-        psFitsWriteImageCube(fits, hdu->header, hdu->images, hdu->extname);
+        psFitsWriteImageCube(fits, hdu->header, hdu->images, extname);
         return true;
-        #ifdef FITS_TABLES
-
     }
 
@@ -136,100 +149,15 @@
     psError(PS_ERR_IO, true, "No idea what this HDU consists of!\n");
     return false;
+    #else
+
+    if (hdu->images) {
+        psTrace(__func__, 9, "Writing pixels for %s\n", hdu->extname);
+        if (!psFitsWriteImageCube(fits, hdu->header, hdu->images, extname)) {
+            psError(PS_ERR_IO, false, "Unable to write image to extension %s\n", hdu->extname);
+            return false;
+        }
+    }
+    return true;
     #endif
 }
 
-
-
-#if 0
-
-
-
-
-// Read the PHU of a file
-static bool readPHU(pmCameraFile *file  // File for which to read the PHU
-                   )
-{
-    if (! file->phu) {
-        if (! file->fits) {
-            file->fits = psFitsOpen(file->name, "r");
-        }
-        (void)psFitsMoveExtNum(file->fits, 0, false);
-        file->phu = psFitsReadHeader(NULL, file->fits);
-
-        return true;
-    }
-
-    return false;
-}
-
-bool pmCameraFileFormat(pmCameraFile *file, // File to inspect
-                        psMetadata *camera // Camera description
-                       )
-{
-    if (! camera) {
-        return false;
-    }
-
-    readPHU(file);
-
-    bool mdok = true;                   // Result of MD lookup
-    psMetadata *formats = psMetadataLookupMD(&mdok, camera, "FORMATS"); // List of known formats
-    if (! mdok || ! formats) {
-        psLogMsg(__func__, PS_LOG_WARN, "Unable to find list of FORMATS in camera configuration!\n");
-        return false;
-    }
-
-    bool result = false;                // Result of search
-    psMetadataIterator *formatsIter = psMetadataIteratorAlloc(formats, NULL); // Iterator for formats
-    psMetadataItem *formatsItem = NULL; // Item from formats
-    while ((formatsItem = psMetadataGetAndIncrement(formatsIter))) {
-        if (formatsItem->type != PS_DATA_STRING) {
-            psLogMsg(__func__, PS_LOG_WARN, "Entry not of type STR found in camera FORMATS list.\n");
-            continue;
-        }
-        psTrace(__func__, 7, "Trying format file: %s\n", formatsItem->name);
-        int numBadLines = 0;            // Number of bad lines in file
-        psMetadata *format = psMetadataConfigParse(NULL, &numBadLines, formatsItem->data.V, true);
-        if (numBadLines > 0) {
-            psLogMsg(__func__, PS_LOG_WARN, "%d bad lines found in %s.\n", formatsItem->name);
-        }
-        if (pmConfigValidateCamera(format, file->phu)) {
-            file->format = format;
-            result = true;
-            psLogMsg(__func__, PS_LOG_INFO + 2, "File %s matches camera format file %s\n", file->name,
-                     formatsItem->data.V);
-            break;
-        }
-        psFree(format);
-    }
-    psFree(formatsIter);
-
-    return result;
-}
-
-
-bool pmConfigValidateCamera(const psMetadata *camera, const psMetadata *header);
-
-pmFPA *pmFPASourceFile(pmFPA *fpa,      // FPA to which to add
-                       pmFile *file,    // File to add
-                       const char *name, // Symbolic name for file, e.g., "INPUT", "OUTPUT", "TESTFILE"
-                       pmConfig *config // Configuration set
-                      )
-{
-    assert(file);
-    assert(name);
-
-    if (! file->fits) {
-        file->fits = psFitsOpen(file->name, "r");
-    }
-    if (! file->phu) {
-        (void)psFitsMoveExtNum(file->fits, 0, false);
-        file->phu = psFitsReadHeader(NULL, file->fits);
-    }
-
-    psMetadata *fileConfig = NULL;      // The file configuration
-    if (fpa && fpa->camera) {
-        fpa
-
-        bool pmConfigValidateCamera(const psMetadata *camera, const psMetadata *header);
-        #endif
Index: /branches/rel10_ifa/psModules/src/astrom/pmHDU.h
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmHDU.h	(revision 6662)
+++ /branches/rel10_ifa/psModules/src/astrom/pmHDU.h	(revision 6663)
@@ -23,3 +23,8 @@
               );
 
+// Write the HDU
+bool pmHDUWrite(pmHDU *hdu,             // HDU to write
+                psFits *fits            // FITS file to write to
+               );
+
 #endif
Index: /branches/rel10_ifa/psModules/src/pslib/psMetadataItemParse.c
===================================================================
--- /branches/rel10_ifa/psModules/src/pslib/psMetadataItemParse.c	(revision 6662)
+++ /branches/rel10_ifa/psModules/src/pslib/psMetadataItemParse.c	(revision 6663)
@@ -48,9 +48,9 @@
     case PS_TYPE_F32:
         psLogMsg(__func__, PS_LOG_WARN, "Item %s (%s) should be S32, but is F32 --- converting.\n",
-                 item->name, comment);
+                 item->name, item->comment);
         return (int)item->data.F32;
     case PS_TYPE_F64:
         psLogMsg(__func__, PS_LOG_WARN, "Item %s (%s) should be S32, but is F64 --- converting.\n",
-                 item->name, comment);
+                 item->name, item->comment);
         return (int)item->data.F64;
     default:
Index: /branches/rel10_ifa/psModules/src/psmodules.h
===================================================================
--- /branches/rel10_ifa/psModules/src/psmodules.h	(revision 6662)
+++ /branches/rel10_ifa/psModules/src/psmodules.h	(revision 6663)
@@ -19,5 +19,5 @@
 #include "pmFPAConstruct.h"
 #include "pmFPARead.h"
-//#include "pmFPAWrite.h"
+#include "pmFPAWrite.h"
 #include "pmReadout.h"
 #include "pmFPAfile.h"
