Index: /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.c	(revision 6833)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.c	(revision 6834)
@@ -324,4 +324,33 @@
 }
 
+static pmFPALevel hduLevel(psMetadata *format // The camera format configuration
+                          )
+{
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *file = psMetadataLookupMD(&mdok, format, "FILE"); // File information
+    if (!mdok || !file) {
+        psError(PS_ERR_IO, true, "Unable to find FILE information in camera format configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+    const char *extType = psMetadataLookupStr(&mdok, file, "EXTENSIONS");
+    if (!mdok || !extType || strlen(extType) == 0) {
+        psError(PS_ERR_IO, true, "Unable to find EXTENSIONS in the FILE information in the camera format"
+                " configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+
+    // Where do we stick in the HDUs?
+    pmFPALevel level = PM_FPA_LEVEL_NONE; // Level for HDU insertion
+    if (strcasecmp(extType, "CHIP") == 0) {
+        level = PM_FPA_LEVEL_CHIP;
+    } else if (strcasecmp(extType, "CELL") == 0) {
+        level = PM_FPA_LEVEL_CELL;
+    } else if (strcasecmp(extType, "NONE") != 0) {
+        psError(PS_ERR_IO, true, "EXTENSIONS is not CHIP or CELL or NONE.\n");
+    }
+
+    return level;
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // Public functions
@@ -362,10 +391,100 @@
 }
 
+bool pmFPAAddSourceFromView(pmFPA *fpa,   // The FPA
+                            pmFPAview *phuView, // The view, corresponding to the PHU
+                            psMetadata *format // Format of file
+                           )
+{
+    assert(fpa);
+    assert(phuView);
+    assert(format);
+
+    // Where does the PHU go?
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *fileInfo = psMetadataLookupMD(&mdok, format, "FILE"); // File information from the format
+    if (!mdok || !fileInfo) {
+        psError(PS_ERR_IO, false, "Unable to find FILE information in the camera format configuration.\n");
+        return false;
+    }
+    const char *phuType = psMetadataLookupStr(&mdok, fileInfo, "PHU"); // What is the PHU?
+    if (!mdok || strlen(phuType) == 0) {
+        psError(PS_ERR_IO, false, "Unable to find PHU in the FILE information of the camera format.\n");
+        return false;
+    }
+
+    // Generate the PHU
+    pmHDU *phdu = pmHDUAlloc("PHU");    // The primary header data unit
+    phdu->format = psMemIncrRefCounter(format);
+
+    // Put in the PHU
+    pmChip *chip = NULL;                // The chip that corresponds to the PHU
+    pmCell *cell = NULL;                // The cell that corresponds to the PHU
+    if (strcasecmp(phuType, "FPA") == 0) {
+        fpa->hdu = phdu;
+    } else {
+        psArray *chips = fpa->chips;    // Array of chips
+        if (phuView->chip < 0 || phuView->chip > chips->n) {
+            psError(PS_ERR_IO, true, "PHU specified by the camera format requires specification of a "
+                    "particular chip, which cannot be determined from the view (%d).\n", phuView->chip);
+            psFree(phdu);
+            return false;
+        }
+        chip = chips->data[phuView->chip];
+        if (strcasecmp(phuType, "CHIP") == 0) {
+            chip->hdu = phdu;
+        } else if (strcasecmp(phuType, "CELL") == 0) {
+            psArray *cells = chip->cells; // Array of cells
+            if (phuView->cell < 0 || phuView->cell > cells->n) {
+                psError(PS_ERR_IO, true, "PHU specified by the camera format requires specification of a "
+                        "particular cell, which cannot be determined from the view (%d).\n", phuView->cell);
+                psFree(phdu);
+                return false;
+            }
+            cell->hdu = phdu;
+        } else {
+            psError(PS_ERR_IO, true, "PHU in the camera configuration format is not FPA, CHIP or CELL.\n");
+            psFree(phdu);
+            return false;
+        }
+    }
+
+    // Put in the extensions
+    pmFPALevel level = hduLevel(format);// The level for the HDUs to go
+    if (level == PM_FPA_LEVEL_NONE) {
+        // No extensions --- we're done
+        return true;
+    }
+    psMetadata *contents = psMetadataLookupMD(&mdok, format, "CONTENTS"); // The contents of the FITS file
+    if (!mdok || !contents) {
+        psError(PS_ERR_IO, false, "Unable to find CONTENTS in the camera format configuration.\n");
+        return false;
+    }
+
+    psMetadataIterator *contentsIter = psMetadataIteratorAlloc(contents, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *contentsItem = NULL;// Item from the contents iteration
+    while ((contentsItem = psMetadataGetAndIncrement(contentsIter))) {
+        if (contentsItem->type != PS_DATA_STRING) {
+            psLogMsg(__func__, PS_LOG_WARN, "Content item %s is not of type STR --- ignored.\n",
+                     contentsItem->name);
+            continue;
+        }
+        pmHDU *hdu = pmHDUAlloc(contentsItem->name); // HDU to add
+        hdu->format = psMemIncrRefCounter(format);
+        const char *content = contentsItem->data.V; // The content data
+        processContents(fpa, chip, cell, hdu, level, content, format);
+        psFree(hdu);
+    }
+    psFree(contentsIter);
+
+    return true;
+}
+
+
 
 // Add an input file to the FPA
-pmFPAview *pmFPAAddSource(pmFPA *fpa, // The FPA
-                          psMetadata *phu, // Primary header of file
-                          psMetadata *format // Format of file
-                         )
+pmFPAview *pmFPAAddSourceFromHeader(pmFPA *fpa, // The FPA
+                                    psMetadata *phu, // Primary header of file
+                                    psMetadata *format // Format of file
+                                   )
 {
     assert(fpa);
@@ -531,15 +650,5 @@
     psFree(phdu);
 
-    // Where do we stick in the HDUs?
-    pmFPALevel hduLevel = PM_FPA_LEVEL_NONE; // Level for HDU insertion
-    if (strcasecmp(extType, "CHIP") == 0) {
-        hduLevel = PM_FPA_LEVEL_CHIP;
-    } else if (strcasecmp(extType, "CELL") == 0) {
-        hduLevel = PM_FPA_LEVEL_CELL;
-    } else {
-        psError(PS_ERR_IO, true, "EXTENSIONS is not CHIP or CELL or NONE.\n");
-        psFree(view);
-        return NULL;
-    }
+    pmFPALevel level = hduLevel(format);// The level at which to plug in HDU
 
     // Now go through the contents
@@ -556,5 +665,5 @@
         hdu->format = psMemIncrRefCounter(format);
 
-        processContents(fpa, chip, cell, hdu, hduLevel, contentsItem->data.V, format);
+        processContents(fpa, chip, cell, hdu, level, contentsItem->data.V, format);
         psFree(hdu);
     }
@@ -579,7 +688,11 @@
             psTrace(__func__, 2, "---> NO PIXELS read in for extension %s\n", fpa->hdu->extname);
         }
-        if (fpa->hdu->header && header) {
-            psTrace(__func__, 2, "---> Header:\n");
-            psMetadataPrint(fpa->hdu->header, 8);
+        if (header) {
+            if (fpa->hdu->header) {
+                psTrace(__func__, 2, "---> Header:\n");
+                psMetadataPrint(fpa->hdu->header, 8);
+            } else {
+                psTrace(__func__, 2, "---> NO HEADER read in for extension %s\n", fpa->hdu->extname);
+            }
         }
     }
@@ -595,7 +708,11 @@
         if (chip->hdu) {
             psTrace(__func__, 4, "---> Chip is extension %s.\n", chip->hdu->extname);
-            if (chip->hdu->header && header) {
-                psTrace(__func__, 4, "---> Header:\n");
-                psMetadataPrint(chip->hdu->header, 8);
+            if (header) {
+                if (chip->hdu->header) {
+                    psTrace(__func__, 4, "---> Header:\n");
+                    psMetadataPrint(chip->hdu->header, 8);
+                } else {
+                    psTrace(__func__, 4, "---> NO HEADER read in for extension %s\n", chip->hdu->extname);
+                }
             }
             if (! chip->hdu->images) {
@@ -614,7 +731,11 @@
             if (cell->hdu) {
                 psTrace(__func__, 6, "---> Cell is extension %s.\n", cell->hdu->extname);
-                if (cell->hdu->header && header) {
-                    psTrace(__func__, 4, "---> Header:\n");
-                    psMetadataPrint(cell->hdu->header, 8);
+                if (header) {
+                    if (cell->hdu->header) {
+                        psTrace(__func__, 6, "---> Header:\n");
+                        psMetadataPrint(cell->hdu->header, 8);
+                    } else {
+                        psTrace(__func__, 6, "---> NO HEADER read in for extension %s\n", cell->hdu->extname);
+                    }
                 }
                 if (! cell->hdu->images) {
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.h
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.h	(revision 6833)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.h	(revision 6834)
@@ -10,8 +10,13 @@
                      );
 
-pmFPAview *pmFPAAddSource(pmFPA *fpa, // The FPA
-                          psMetadata *phu, // Primary header of file
-                          psMetadata *format // Format of file
-                         );
+bool pmFPAAddSourceFromView(pmFPA *fpa,   // The FPA
+                            pmFPAview *phuView, // The view, corresponding to the PHU
+                            psMetadata *format // Format of file
+                           );
+
+pmFPAview *pmFPAAddSourceFromHeader(pmFPA *fpa, // The FPA
+                                    psMetadata *phu, // Primary header of file
+                                    psMetadata *format // Format of file
+                                   );
 
 // Print out the FPA
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPAfile.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPAfile.c	(revision 6833)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPAfile.c	(revision 6834)
@@ -698,5 +698,5 @@
 
         // set the view to the corresponding entry for this phu
-        pmFPAview *view = pmFPAAddSource (fpa, phu, format);
+        pmFPAview *view = pmFPAAddSourceFromHeader(fpa, phu, format);
 
         // XXX is this the correct psMD to save the filename?
@@ -786,5 +786,5 @@
 
         // set the view to the corresponding entry for this phu
-        pmFPAview *view = pmFPAAddSource (fpa, phu, format);
+        pmFPAview *view = pmFPAAddSourceFromHeader(fpa, phu, format);
 
         // XXX is this the correct psMD to save the filename?
@@ -879,5 +879,5 @@
 
         // set the view to the corresponding entry for this phu
-        pmFPAview *view = pmFPAAddSource (file->fpa, phu, format);
+        pmFPAview *view = pmFPAAddSourceFromHeader(file->fpa, phu, format);
 
         // XXX is this the correct psMD to save the filename?
Index: /branches/rel10_ifa/psModules/src/astrom/pmHDU.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmHDU.c	(revision 6833)
+++ /branches/rel10_ifa/psModules/src/astrom/pmHDU.c	(revision 6834)
@@ -135,10 +135,15 @@
     }
 
+    if (!hdu->images && !hdu->table && !hdu->header) {
+        psLogMsg(__func__, PS_LOG_WARN, "Nothing to write for HDU %s\n", hdu->extname);
+        return false;
+    }
+
     // Preserve the extension name, if it's the PHU
     char *extname = hdu->extname;       // The name of the extension
-    if (strcasecmp(extname, "PHU") == 0) {
+    if (strcasecmp(extname, "PHU") == 0 && hdu->header) {
         bool mdok = true;               // Status of MD lookup
         extname = psMetadataLookupStr(&mdok, hdu->header, "EXTNAME");
-        if (!mdok || strlen(extname) == 0) {
+        if (!mdok || !extname || strlen(extname) == 0) {
             extname = "";
         }
@@ -149,5 +154,7 @@
         // Tell CFITSIO there's nothing there
         psMetadataItem *naxis = psMetadataLookup(hdu->header, "NAXIS");
-        naxis->data.S32 = 0;
+        if (naxis) {
+            naxis->data.S32 = 0;
+        }
 
         if (!psFitsWriteHeader(hdu->header, fits)) {
