Index: trunk/psModules/src/camera/pmFPAWrite.c
===================================================================
--- trunk/psModules/src/camera/pmFPAWrite.c	(revision 7618)
+++ trunk/psModules/src/camera/pmFPAWrite.c	(revision 7717)
@@ -1,5 +1,5 @@
 #include <stdio.h>
 #include <strings.h>
-#include "pslib.h"
+#include <pslib.h>
 
 #include "pmFPA.h"
@@ -73,7 +73,6 @@
 
     // We can simply update an existing HDU
-    if (((hdu->phu || strcasecmp(hdu->extname, "PHU") == 0) && !psFitsMoveExtNum(fits, 0, false)) ||
-            !psFitsMoveExtName(fits, hdu->extname)) {
-        psError(PS_ERR_IO, false, "Unable to move to extension %s\n", hdu->extname);
+    if (hdu->blankPHU && !psFitsMoveExtNum(fits, 0, false)) {
+        psError(PS_ERR_IO, false, "Unable to move to PHU\n");
         return false;
     }
@@ -87,5 +86,5 @@
                  psFits *fits,          // FITS file to which to write
                  psDB *db,              // Database handle for "concepts" update
-                 bool pixels            // Write the pixels, or only the PHU header?
+                 bool blank             // Write a blank PHU?
                 )
 {
@@ -98,20 +97,31 @@
     }
 
-    bool success = true;                // Success of writing
-    if ((!pixels && hdu->phu && !hdu->images) || // Data-less PHU
-            (pixels && (hdu->images || (!hdu->images && pmHDUGenerateForCell(cell) && hdu->images)))) { // Data
-        success &= pmConceptsWriteCell(cell, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CAMERA |
-                                       PM_CONCEPT_SOURCE_DEFAULTS, false, NULL);
-        success &= pmHDUWrite(hdu, fits);
-    }
-
-    if (!success) {
-        psError(PS_ERR_IO, false, "Unable to write HDU for Chip.\n");
-        return false;
-    }
-
+    // Generate the HDU if needed --- this is required after a pmFPACopy, or similar, which does not
+    // generate the HDU, but only copies the structure.
+    if (!hdu->blankPHU && !hdu->images) {
+        if (!pmHDUGenerateForCell(cell) || !hdu->images) {
+            psAbort(__func__, "Unable to generate HDU for cell --- likely programming error.\n");
+        }
+    }
+
+    // We only write out a blank PHU if it's specifically requested.
+    bool writeBlank = blank && hdu->blankPHU && !hdu->images; // Write a blank PHU?
+    bool writeImage = !hdu->blankPHU && hdu->images; // Write an image?
+
+    if (writeBlank || writeImage) {
+        pmConceptSource source = PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CAMERA |
+                                 PM_CONCEPT_SOURCE_DEFAULTS;
+        if (!pmConceptsWriteCell(cell, source, false, NULL)) {
+            psError(PS_ERR_IO, false, "Unable to write concepts for cell.\n");
+            return false;
+        }
+        if (!pmHDUWrite(hdu, fits)) {
+            psError(PS_ERR_IO, false, "Unable to write HDU for cell.\n");
+            return false;
+        }
+    }
     // No lower levels to which to recurse
 
-    return success;
+    return true;
 }
 
@@ -120,5 +130,5 @@
                  psFits *fits,          // FITS file to which to write
                  psDB *db,              // Database handle for "concepts" update
-                 bool pixels,           // Write the pixels, or only the PHU header?
+                 bool blank,            // Write a blank PHU?
                  bool recurse           // Recurse to lower levels?
                 )
@@ -129,43 +139,38 @@
     pmHDU *hdu = chip->hdu;             // The HDU
 
-    // XXXX this makes no sense to me at all:
-    // an image made up of only cells would not have
-    // any entries at this level, and could not be written out!!!
-
-    // if we have data at this level, try to write it out
+    // If we have data at this level, try to write it out
     if (hdu) {
-        // generate the HDU if needed
-        if (pixels && !hdu->images) {
-            if (!pmHDUGenerateForChip(chip))
-                psAbort ("pmFPAWrite", "error generating HDU");
-            if (!hdu->images)
-                psAbort ("pmChipWrite", "programming error: failure generating HDU");
-        }
-
-        // chip->hdu represents a blank data segment
-        bool blankSegment = !pixels && hdu->phu && !hdu->images;
-
-        // chip->hdu represents an image data segment
-        bool imageSegment = pixels && hdu->images;
-
-        if (blankSegment || imageSegment) {
-            pmConceptSource source = PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CAMERA | PM_CONCEPT_SOURCE_DEFAULTS;
+        // Generate the HDU if needed --- this is required after a pmFPACopy, or similar, which does not
+        // generate the HDU, but only copies the structure.
+        if (!blank && !hdu->blankPHU && !hdu->images) {
+            if (!pmHDUGenerateForChip(chip) || !hdu->images) {
+                psAbort (__func__, "Unable to generate HDU for chip --- likely programming error.\n");
+            }
+        }
+
+        // We only write out a blank PHU if it's specifically requested.
+        bool writeBlank = blank && hdu->blankPHU && !hdu->images; // Write a blank HDU?
+        bool writeImage = !hdu->blankPHU && hdu->images; // Write an image?
+
+        if (writeBlank || writeImage) {
+            pmConceptSource source = PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CAMERA |
+                                     PM_CONCEPT_SOURCE_DEFAULTS;
             if (!pmConceptsWriteChip(chip, source, false, true, NULL)) {
-                psError(PS_ERR_IO, false, "Unable to write Concepts for Chip.\n");
+                psError(PS_ERR_IO, false, "Unable to write concepts for chip.\n");
                 return false;
             }
             if (!pmHDUWrite(hdu, fits)) {
-                psError(PS_ERR_IO, false, "Unable to write HDU for Chip.\n");
-                return false;
-            }
-        }
-    }
-
-    // XXX are we allowed to recurse if we have already written data at this level?
+                psError(PS_ERR_IO, false, "Unable to write HDU for chip.\n");
+                return false;
+            }
+        }
+    }
+
+    // Recurse to lower level if specifically requested.
     if (recurse) {
         psArray *cells = chip->cells;       // Array of cells
         for (int i = 0; i < cells->n; i++) {
             pmCell *cell = cells->data[i];  // The cell of interest
-            if (!pmCellWrite(cell, fits, db, pixels)) {
+            if (!pmCellWrite(cell, fits, db, blank)) {
                 psError(PS_ERR_IO, false, "Unable to write Chip.\n");
                 return false;
@@ -182,5 +187,5 @@
                 psFits *fits,           // FITS file to which to write
                 psDB *db,               // Database handle for "concepts" update
-                bool pixels,            // Write the pixels, or only the PHU header?
+                bool blank,             // Write a blank PHU?
                 bool recurse            // Recurse to lower levels?
                )
@@ -191,33 +196,26 @@
     pmHDU *hdu = fpa->hdu;              // The HDU
 
-    // XXXX this makes no sense to me at all:
-    // an image made up of only chips or cells would not have
-    // any entries at this level, and could not be written out!!!
-
-    // if we have data at this level, try to write it out
+    // If we have data at this level, try to write it out
     if (hdu) {
-
-        // XXXXXXXXX this was extremely unclear.  the conditions MUST be written more explicitly
-        // so someone else has a chance to understand it without massive reverse engineering!!!!
-
-        // generate the HDU if needed
-        if (pixels && !hdu->images) {
-            if (!pmHDUGenerateForFPA(fpa))
-                psAbort ("pmFPAWrite", "error generating HDU");
-            if (!hdu->images)
-                psAbort ("pmFPAWrite", "programming error: failure generating HDU");
-        }
-
-        // fpa->hdu represents a blank data segment
-        bool blankSegment = !pixels && hdu->phu && !hdu->images;
-
-        // fpa->hdu represents an image data segment
-        bool imageSegment = pixels && hdu->images;
-
-        // if neither of these conditions is true, we probably need to recurse down to the next level and try again
-        if (blankSegment || imageSegment) {
-            pmConceptSource source = PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CAMERA | PM_CONCEPT_SOURCE_DEFAULTS;
+        // Generate the HDU if needed --- this is required after a pmFPACopy, or similar, which does not
+        // generate the HDU, but only copies the structure.
+        if (!blank && !hdu->blankPHU && !hdu->images) {
+            if (!pmHDUGenerateForFPA(fpa)) {
+                psAbort("pmFPAWrite", "error generating HDU");
+            }
+            if (!hdu->images) {
+                psAbort("pmFPAWrite", "programming error: failure generating HDU");
+            }
+        }
+
+        // We only write out a blank PHU if it's specifically requested.
+        bool writeBlank = blank && hdu->blankPHU && !hdu->images; // Write a blank PHU?
+        bool writeImage = !hdu->blankPHU && hdu->images; // Write an image?
+
+        if (writeBlank || writeImage) {
+            pmConceptSource source = PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CAMERA |
+                                     PM_CONCEPT_SOURCE_DEFAULTS;
             if (!pmConceptsWriteFPA(fpa, source, true, NULL)) {
-                psError(PS_ERR_IO, false, "Unable to write Concepts for FPA.\n");
+                psError(PS_ERR_IO, false, "Unable to write concepts for FPA.\n");
                 return false;
             }
@@ -229,10 +227,10 @@
     }
 
-    // XXX what are the rules on when we allow recursion?
+    // Recurse to lower levels if requested
     if (recurse) {
         psArray *chips = fpa->chips;        // Array of chips
         for (int i = 0; i < chips->n; i++) {
             pmChip *chip = chips->data[i];  // The chip of interest
-            if (!pmChipWrite(chip, fits, db, pixels, true)) {
+            if (!pmChipWrite(chip, fits, db, blank, true)) {
                 psError(PS_ERR_IO, false, "Unable to write FPA.\n");
                 return false;
@@ -242,10 +240,3 @@
 
     return true;
-
-    // summary:
-    // pmHDUWrite writes out the PHU header or the header + pixels
-    // we need to generate the HDU (why?)
-    // we call pmHDUWrite if:
-    // - the fpa->hdu represents a blank data segment (header w/ no pixels)
-    // - the fpa->hdu represents an image data segment (header w/ pixels)
-}
+}
