Index: /trunk/psModules/src/camera/pmFPAConstruct.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAConstruct.c	(revision 11254)
+++ /trunk/psModules/src/camera/pmFPAConstruct.c	(revision 11255)
@@ -766,5 +766,5 @@
 
     pmFPAview *view = addSource(fpa, phuView, NULL, format, true);
-    bool status = (view == NULL);
+    bool status = (view != NULL);
     psFree(view);
     return status;
@@ -895,2 +895,43 @@
 
 }
+
+
+pmFPALevel pmFPAPHULevel(const psMetadata *format)
+{
+    PS_ASSERT_METADATA_NON_NULL(format, PM_FPA_LEVEL_NONE);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *fileInfo = psMetadataLookupMetadata(&mdok, format, "FILE"); // Contents of FILE metadata
+    if (!mdok || !fileInfo) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find FILE in camera format configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+    const char *phu = psMetadataLookupStr(&mdok, fileInfo, "PHU"); // PHU level
+    if (!mdok || !phu || strlen(phu) == 0) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find PHU in FILE in camera format configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+
+    return pmFPALevelFromName(phu);
+}
+
+pmFPALevel pmFPAExtensionsLevel(const psMetadata *format)
+{
+    PS_ASSERT_METADATA_NON_NULL(format, PM_FPA_LEVEL_NONE);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *fileInfo = psMetadataLookupMetadata(&mdok, format, "FILE"); // Contents of FILE metadata
+    if (!mdok || !fileInfo) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find FILE in camera format configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+
+    const char *extensions = psMetadataLookupStr(&mdok, fileInfo, "EXTENSIONS"); // EXTENSIONS level
+    if (!mdok || !extensions || strlen(extensions) == 0) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find EXTENSIONS in FILE in camera format configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+
+    return pmFPALevelFromName(extensions);
+}
+
Index: /trunk/psModules/src/camera/pmFPAConstruct.h
===================================================================
--- /trunk/psModules/src/camera/pmFPAConstruct.h	(revision 11254)
+++ /trunk/psModules/src/camera/pmFPAConstruct.h	(revision 11255)
@@ -4,6 +4,6 @@
  * @author Paul Price, IfA
  *
- * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-01-24 02:54:14 $
+ * @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-24 03:11:19 $
  * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
  */
@@ -61,4 +61,12 @@
                 bool concepts           ///< Print concepts?
                );
+
+/// Return the PHU level for an FPA, given the format
+pmFPALevel pmFPAPHULevel(const psMetadata *format);
+
+/// Return the Extensions level for an FPA, given the format
+pmFPALevel pmFPAExtensionsLevel(const psMetadata *format);
+
 /// @}
+
 #endif
Index: /trunk/psModules/src/camera/pmFPACopy.c
===================================================================
--- /trunk/psModules/src/camera/pmFPACopy.c	(revision 11254)
+++ /trunk/psModules/src/camera/pmFPACopy.c	(revision 11255)
@@ -37,4 +37,5 @@
 }
 
+#if 0
 // Find the blank (image-less) PHU, given a cell.
 static pmHDU *findBlankPHU(const pmCell *cell // The cell for which to find the PHU
@@ -57,4 +58,5 @@
     return NULL;
 }
+#endif
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -277,4 +279,5 @@
     binItem->data.S32 *= yBin;
 
+    #if 0
     // Copy any headers
     pmHDU *targetHDU = pmHDUFromCell(target); // The target HDU
@@ -285,12 +288,15 @@
         }
     }
+
     // Copy the PHU over as well, if required
     pmHDU *targetPHU = findBlankPHU(target); // The target PHU
     if (targetPHU && targetPHU != targetHDU && !targetPHU->header) {
-        pmHDU *sourcePHU = findBlankPHU(source); // The source PHU
-        if (sourcePHU->header) {
+        //        pmHDU *sourcePHU = pmHDUGetHighest(source->parent->parent, source->parent, source); // A source HDU
+        pmHDU *sourcePHU = findBlankPHU(source); // The target PHU
+        if (sourcePHU && sourcePHU->header) {
             targetPHU->header = psMetadataCopy(targetPHU->header, sourcePHU->header);
         }
     }
+    #endif
 
     target->data_exists = true;
Index: /trunk/psModules/src/camera/pmFPAMosaic.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAMosaic.c	(revision 11254)
+++ /trunk/psModules/src/camera/pmFPAMosaic.c	(revision 11255)
@@ -1200,5 +1200,10 @@
         return false;
     }
-    targetHDU->header = psMetadataCopy(targetHDU->header, sourceHDU->header);
+
+    if (sourceHDU->header) {
+        targetHDU->header = psMetadataCopy(targetHDU->header, sourceHDU->header);
+    } else if (!targetHDU->header) {
+        targetHDU->header = psMetadataAlloc();
+    }
 
     if (!pmConfigConformHeader(targetHDU->header, targetHDU->format)) {
Index: /trunk/psModules/src/camera/pmFPAWrite.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAWrite.c	(revision 11254)
+++ /trunk/psModules/src/camera/pmFPAWrite.c	(revision 11255)
@@ -38,4 +38,7 @@
         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find HDU.\n");
         return false;
+    }
+    if (!hdu->header) {
+        hdu->header = psMetadataAlloc();
     }
     bool mdok;                          // Status of MD lookup
Index: /trunk/psModules/src/camera/pmFPAfile.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfile.c	(revision 11254)
+++ /trunk/psModules/src/camera/pmFPAfile.c	(revision 11255)
@@ -382,3 +382,2 @@
     return PM_FPA_FILE_NONE;
 }
-
Index: /trunk/psModules/src/camera/pmFPAfileDefine.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 11254)
+++ /trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 11255)
@@ -106,4 +106,16 @@
 }
 
+// Check the various levels for file operations to make sure that they are suitable based on the format
+static void adjustLevels(pmFPAfile *file, // File for which to adjust levels
+                         const psMetadata *format // Format to use to adjust levels
+                        )
+{
+    assert(file);
+    assert(format);
+
+
+    return;
+}
+
 // define a pmFPAfile, bind to the optional fpa if supplied
 pmFPAfile *pmFPAfileDefineOutput(pmConfig *config, pmFPA *fpa, const char *name)
@@ -167,11 +179,45 @@
     }
 
-    file->fileLevel = pmFPALevelFromName(psMetadataLookupStr(&status, data, "FILE.LEVEL"));
+    file->camera = psMemIncrRefCounter(config->camera);
+    const char *formatName = psMetadataLookupStr (&status, data, "FILE.FORMAT");
+    psMetadata *format = NULL;          // Camera format to use
+    if (formatName && strcasecmp(formatName, "NONE") != 0) {
+        // select the format list from the selected camera
+        psMetadata *formats = psMetadataLookupMetadata(&status, file->camera, "FORMATS"); // List of formats
+
+        // select the desired format
+        format = psMetadataLookupMetadata(&status, formats, formatName);
+        if (!format) {
+            psError(PS_ERR_IO, false, "format %s for %s not defined", formatName, name);
+            psFree(file);
+            return NULL;
+        }
+        file->format = psMemIncrRefCounter(format);
+        #if 0
+
+        file->src = psMemIncrRefCounter(fpa);
+        file->fpa = pmFPAConstruct(file->camera);
+        #endif
+
+    } else {
+        format = config->format;
+        #if 0
+
+        file->fpa = psMemIncrRefCounter(fpa);
+        #endif
+
+    }
+    #if 1
+    file->fpa = psMemIncrRefCounter(fpa);
+    #endif
+
+
+    file->fileLevel = pmFPAPHULevel(format);
     if (file->fileLevel == PM_FPA_LEVEL_NONE) {
-        psError(PS_ERR_IO, true, "FILE.LEVEL is not set for %s\n", name);
-        return NULL;
-    }
-
-    file->dataLevel = pmFPALevelFromName(psMetadataLookupStr (&status, data, "DATA.LEVEL"));
+        psError(PS_ERR_IO, true, "Unable to determine file level for %s\n", name);
+        return NULL;
+    }
+
+    file->dataLevel = pmFPALevelFromName(psMetadataLookupStr(&status, data, "DATA.LEVEL"));
     if (file->dataLevel == PM_FPA_LEVEL_NONE) {
         psError(PS_ERR_IO, true, "DATA.LEVEL is not set for %s\n", name);
@@ -182,57 +228,21 @@
     file->freeLevel = file->dataLevel;
 
-    if (fpa != NULL) {
-        file->fpa = psMemIncrRefCounter(fpa);
-    }
-
-    #if 0
-    // for WRITE type of data, the output format needs to be determined
-    // this is only needed if the output file is not identical in structure to the input?
-    // for
-    char *formatLine = psMetadataLookupStr (&status, data, "FILE.FORMAT");
-    if (formatLine && strcasecmp (formatLine, "NONE")) {
-
-        char *formatName = NULL;
-
-        psArray *words = psStringSplitArray (formatLine, ":", false);
-        if (!words || !words->n) {
-            psAbort("pmFPAfileDefine", "programming error: cannot be NULL or empty!");
-        }
-        if (words->n == 1) {
-            // format selected in this camera
-            formatName = formatLine;
-            file->camera = psMemIncrRefCounter (config->camera);
-        }
-        if (words->n == 2) {
-            // select the requested camera
-            formatName = words->data[1];
-            file->camera = pmConfigCameraByName(config, words->data[0]);
-            // XXX do we need to save the camera name?
-            if (!file->camera) {
-                psError(PS_ERR_IO, false, "camera %s not found\n", (char *)words->data[0]);
-                psFree(words);
-                return NULL;
-            }
-        }
-
-        // select the format list from the selected camera
-        psMetadata *formats = psMetadataLookupMetadata(&status, file->camera, "FORMATS"); // List of formats
-
-        // select the desired format
-        char *formatFile = psMetadataLookupStr (&status, formats, formatName);
-        if (!formatFile) {
-            psError(PS_ERR_IO, false, "format %s for %s not defined", formatName, name);
-            psFree (file);
-            psFree (words);
-            return NULL;
-        }
-        pmConfigFileRead(&file->format, formatFile, formatName);
-        psFree (words);
-    }
-    #endif
+    pmFPALevel extLevel = pmFPAExtensionsLevel(format); // Level for extensions
+    if (extLevel != PM_FPA_LEVEL_NONE) {
+        if (extLevel < file->dataLevel) {
+            psWarning("Level for extensions is higher than desired data level --- adjusting.\n");
+            file->dataLevel = extLevel;
+        }
+        if (extLevel < file->freeLevel) {
+            psWarning("Level for extensions is higher than desired free level --- adjusting.\n");
+            file->freeLevel = extLevel;
+        }
+    }
+    adjustLevels(file, format);
+
 
     // add argument-supplied OUTPUT name to this file
     char *outname = psMetadataLookupStr(&status, config->arguments, "OUTPUT");
-    psMetadataAddStr (file->names, PS_LIST_TAIL, "OUTPUT", PS_META_NO_REPLACE, "", outname);
+    psMetadataAddStr(file->names, PS_LIST_TAIL, "OUTPUT", PS_META_NO_REPLACE, "", outname);
 
     // place the resulting file in the config system
@@ -241,4 +251,5 @@
     return (file); // the returned value is a view into the version on 'files'
 }
+
 
 // search for argname on the config->argument list
Index: /trunk/psModules/src/camera/pmFPAfileFitsIO.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfileFitsIO.c	(revision 11254)
+++ /trunk/psModules/src/camera/pmFPAfileFitsIO.c	(revision 11255)
@@ -16,4 +16,78 @@
 #include "pmFPAfile.h"
 #include "pmFPAfileFitsIO.h"
+#include "pmFPACopy.h"
+
+pmFPA *pmFPAfileSuitableFPA(const pmFPAfile *file, const pmFPAview *view)
+{
+    PS_ASSERT_PTR_NON_NULL(file, NULL);
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+
+    if (!file->format) {
+        return psMemIncrRefCounter(file->fpa);
+    }
+
+    // Need to change format
+    pmFPA *fpa = pmFPAConstruct(file->camera);
+
+    pmFPAview *phuView = pmFPAviewAlloc(0); // View corresponding to the PHU
+    *phuView = *view;               // Copy contents
+    pmFPALevel phuLevel = pmFPAPHULevel(file->format); // Level for the PHU
+    switch (phuLevel) {
+    case PM_FPA_LEVEL_FPA:
+        phuView->chip = -1;
+        // Flow through
+    case PM_FPA_LEVEL_CHIP:
+        phuView->cell = -1;
+        // Flow through
+    case PM_FPA_LEVEL_CELL:
+        phuView->readout = -1;
+        break;
+    case PM_FPA_LEVEL_READOUT:
+    case PM_FPA_LEVEL_NONE:
+    default:
+        psAbort(PS_FILE_LINE, "Should never get here: bad phu level.\n");
+    }
+
+    if (!pmFPAAddSourceFromView(fpa, phuView, file->format)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to insert HDU into FPA for writing.\n");
+        psFree(fpa);
+        psFree(phuView);
+        return false;
+    }
+    psFree(phuView);
+
+
+    switch (phuLevel) {
+    case PM_FPA_LEVEL_FPA:
+        if (!pmFPACopy(fpa, file->fpa)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to copy FPA for format conversion.\n");
+            return NULL;
+        }
+        return fpa;
+    case PM_FPA_LEVEL_CHIP: {
+            pmChip *chip = pmFPAviewThisChip(view, fpa); // Chip of interest
+            pmChip *srcChip = pmFPAviewThisChip(view, file->fpa); // Source chip
+            if (!pmChipCopy(chip, srcChip)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to copy chip for format conversion.\n");
+                return false;
+            }
+            return fpa;
+        }
+    case PM_FPA_LEVEL_CELL: {
+            pmCell *cell = pmFPAviewThisCell(view, fpa); // Cell of interest
+            pmCell *srcCell = pmFPAviewThisCell(view, file->fpa); // Source cell
+            if (!pmCellCopy(cell, srcCell)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to copy cell for format conversion.\n");
+                return false;
+            }
+            return fpa;
+        }
+    case PM_FPA_LEVEL_READOUT:
+    case PM_FPA_LEVEL_NONE:
+    default:
+        psAbort(PS_FILE_LINE, "Should never get here: bad phu level.\n");
+    }
+    return NULL;
+}
 
 // given an already-opened fits file, read the table corresponding to the specified view
@@ -159,51 +233,53 @@
     assert(file);
 
-    pmFPA *fpa = file->fpa;             // FPA of interest
     psFits *fits = file->fits;          // FITS file
-
-    // pmFPAWrite takes care of all PHUs as needed
-    if (view->chip == -1) {
-        return fpaWriteFunc(fpa, fits, NULL, false, true);
-    }
-
-    if (view->chip >= fpa->chips->n) {
-        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %ld", view->chip, fpa->chips->n);
-        return false;
-    }
-    pmChip *chip = fpa->chips->data[view->chip]; // Chip of interest
-
-    if (view->cell == -1) {
-        return chipWriteFunc(chip, fits, NULL, false, true);
-    }
-
-    if (view->cell >= chip->cells->n) {
-        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %ld", view->cell, chip->cells->n);
-        return false;
-    }
-    pmCell *cell = chip->cells->data[view->cell]; // Cell of interest
-
-    if (view->readout == -1) {
-        return cellWriteFunc(cell, fits, NULL, false);
-    }
-    psError(PS_ERR_UNKNOWN, true, "Bad view: %d,%d", view->chip, view->cell);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view); // FPA to write
+
+    switch (pmFPAviewLevel(view)) {
+    case PM_FPA_LEVEL_FPA: {
+            bool success = fpaWriteFunc(fpa, fits, NULL, false, true);
+            psFree(fpa);
+            return success;
+        }
+    case PM_FPA_LEVEL_CHIP: {
+            pmChip *chip = pmFPAviewThisChip(view, fpa); // Chip of interest
+            bool success = chipWriteFunc(chip, fits, NULL, false, true);
+            psFree(fpa);
+            return success;
+        }
+    case PM_FPA_LEVEL_CELL: {
+            pmCell *cell = pmFPAviewThisCell(view, fpa); // Cell of interest
+            bool success = cellWriteFunc(cell, fits, NULL, false);
+            psFree(fpa);
+            return success;
+        }
+    case PM_FPA_LEVEL_READOUT:
+        #if 0 // XXX disable readout write for now
+
+        {
+            pmReadout *readout = pmFPAviewThisReadout(view, file->fpa); // Readout of interest
+            if (changeFormat)
+        {
+            // No copy function defined for readouts!
+            psError(PS_ERR_UNKNOWN, false, "Unable to copy readout for format conversion on write.\n");
+                return false;
+            }
+            if (view->nRows == 0)
+        {
+            return pmReadoutWrite(readout, fits, NULL, NULL);
+            } else
+            {
+                return pmReadoutWriteSegment(readout, fits, view->nRows, view->iRows, NULL, NULL);
+            }
+        }
+        #endif
+    case PM_FPA_LEVEL_NONE:
+    default:
+        psAbort(PS_FILE_LINE, "Should never reach here: invalid file level.");
+    }
+
     return false;
-
-    // XXX disable readout write for now
-    #if 0
-
-    if (view->readout >= cell->readouts->n) {
-        psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouts->n == %d",
-                view->readout, cell->readouts->n);
-        return false;
-    }
-    pmReadout *readout = cell->readouts->data[view->readout];
-
-    if (view->nRows == 0) {
-        pmReadoutWrite (readout, fits, NULL, NULL);
-    } else {
-        pmReadoutWriteSegment (readout, fits, view->nRows, view->iRows, NULL, NULL);
-    }
-    return true;
-    #endif
 }
 
Index: /trunk/psModules/src/camera/pmFPAfileFitsIO.h
===================================================================
--- /trunk/psModules/src/camera/pmFPAfileFitsIO.h	(revision 11254)
+++ /trunk/psModules/src/camera/pmFPAfileFitsIO.h	(revision 11255)
@@ -5,6 +5,6 @@
  * @author PAP, IfA
  *
- * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-01-24 02:54:14 $
+ * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-24 03:11:19 $
  * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
  */
@@ -61,4 +61,13 @@
                              const char *name ///< Name of table
                             );
+
+/// Produce a suitable FPA for writing, on the basis of the input FPAfile
+///
+/// A format change is done is required.  Otherwise the file->fpa is returned (incremented).
+pmFPA *pmFPAfileSuitableFPA(const pmFPAfile *file,///< File containing the fpa
+                            const pmFPAview *view ///< View at which to produce the fpa
+                           );
+
 /// @}
+
 # endif
Index: /trunk/psModules/src/camera/pmFPAfileIO.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfileIO.c	(revision 11254)
+++ /trunk/psModules/src/camera/pmFPAfileIO.c	(revision 11255)
@@ -108,15 +108,18 @@
     }
     if (file->mode == PM_FPA_MODE_WRITE) {
+        // Want to write out any potential blank
+        pmFPA *fpa = pmFPAfileSuitableFPA(file, view);
+
         switch (file->fileLevel) {
         case PM_FPA_LEVEL_FPA:
-            pmFPAWrite (file->fpa, file->fits, NULL, true, false);
+            pmFPAWrite(fpa, file->fits, NULL, true, false);
             break;
         case PM_FPA_LEVEL_CHIP: {
-                pmChip *chip = pmFPAviewThisChip(view, file->fpa);
-                pmChipWrite (chip, file->fits, NULL, true, false);
+                pmChip *chip = pmFPAviewThisChip(view, fpa);
+                pmChipWrite(chip, file->fits, NULL, true, false);
                 break;
             }
         case PM_FPA_LEVEL_CELL: {
-                pmCell *cell = pmFPAviewThisCell(view, file->fpa);
+                pmCell *cell = pmFPAviewThisCell(view, fpa);
                 pmCellWrite(cell, file->fits, NULL, true);
                 break;
@@ -126,4 +129,6 @@
             break;
         }
+
+        psFree(fpa);
     }
 
@@ -152,4 +157,13 @@
         return true;
     }
+
+    #if 0
+    // do we need to open this file?
+    if (level != file->fileLevel) {
+        psTrace("psModules.camera", 6, "skip open of %s at this level %s: fileLevel is %s",
+                file->name, pmFPALevelToName(level), pmFPALevelToName(file->fileLevel));
+        return true;
+    }
+    #endif
 
     if (file->mode == PM_FPA_MODE_NONE) {
@@ -755,4 +769,11 @@
         switch (place) {
         case PM_FPA_BEFORE:
+            #if 0
+
+            if (!pmFPAfileOpen(file, view, config)) {
+                psError(PS_ERR_IO, false, "failed OPEN in FPA_BEFORE block for %s", file->name);
+                goto failure;
+            }
+            #endif
             if (!pmFPAfileRead (file, view, config)) {
                 psError(PS_ERR_IO, false, "failed READ in FPA_BEFORE block for %s", file->name);
