Index: trunk/psModules/src/camera/pmFPAfileFitsIO.c
===================================================================
--- trunk/psModules/src/camera/pmFPAfileFitsIO.c	(revision 18554)
+++ trunk/psModules/src/camera/pmFPAfileFitsIO.c	(revision 18601)
@@ -22,9 +22,16 @@
 #include "pmFPAConstruct.h"
 #include "pmDark.h"
-
-pmFPA *pmFPAfileSuitableFPA(const pmFPAfile *file, const pmFPAview *view, const pmConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(file, NULL);
-    PS_ASSERT_PTR_NON_NULL(view, NULL);
+#include "pmConcepts.h"
+
+// Get a suitable FPA for the file; generate it if necessary
+static pmFPA *suitableFPA(const pmFPAfile *file, // File for which to get FPA
+                          const pmFPAview *view, // View at which to produce the FPA
+                          pmConfig *config, // Configuration (for concepts update)
+                          bool pixels   // Worry about copying pixels?
+    )
+{
+    psAssert(file, "It's supposed to be here");
+    psAssert(view, "It's supposed to be here");
+    psAssert(config, "It's supposed to be here");
 
     if (!file->format) {                // Working with the same output format as input format
@@ -86,5 +93,6 @@
     switch (level) {
       case PM_FPA_LEVEL_FPA:
-        if (!pmFPACopy(copy, file->fpa)) {
+        if ((pixels && !pmFPACopy(copy, file->fpa)) ||
+            (!pixels && !pmFPACopyStructure(copy, file->fpa, 1, 1))) {
             psError(PS_ERR_UNKNOWN, false, "Unable to copy FPA for format conversion.\n");
             return NULL;
@@ -94,5 +102,6 @@
           pmChip *chip = pmFPAviewThisChip(view, copy); // Chip of interest
           pmChip *srcChip = pmFPAviewThisChip(view, file->fpa); // Source chip
-          if (!pmChipCopy(chip, srcChip)) {
+          if ((pixels && !pmChipCopy(chip, srcChip)) ||
+              (!pixels && !pmChipCopyStructure(chip, srcChip, 1, 1))) {
               psError(PS_ERR_UNKNOWN, false, "Unable to copy chip for format conversion.\n");
               return false;
@@ -103,5 +112,6 @@
           pmCell *cell = pmFPAviewThisCell(view, copy); // Cell of interest
           pmCell *srcCell = pmFPAviewThisCell(view, file->fpa); // Source cell
-          if (!pmCellCopy(cell, srcCell)) {
+          if ((pixels && !pmCellCopy(cell, srcCell)) ||
+              (!pixels && !pmCellCopyStructure(cell, srcCell, 1, 1))) {
               psError(PS_ERR_UNKNOWN, false, "Unable to copy cell for format conversion.\n");
               return false;
@@ -115,6 +125,86 @@
     }
 
+    // Unreachable
     return NULL;
-
+}
+
+
+pmFPA *pmFPAfileSuitableFPA(const pmFPAfile *file, const pmFPAview *view, pmConfig *config, bool pixels)
+{
+    PS_ASSERT_PTR_NON_NULL(file, NULL);
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    pmFPA *fpa = suitableFPA(file, view, config, pixels); // A suitable FPA for writing
+    if (!fpa) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to produce suitable FPA.");
+        return NULL;
+    }
+
+    // Ensure headers and all are updated
+    // This is here so that the individual write functions (e.g., images, PSFs, sources, etc) don't have to
+    // take care of all this themselves (because they generally don't).
+    switch (file->type) {
+      case PM_FPA_FILE_IMAGE:
+      case PM_FPA_FILE_MASK:
+      case PM_FPA_FILE_WEIGHT:
+      case PM_FPA_FILE_HEADER:
+      case PM_FPA_FILE_FRINGE:
+      case PM_FPA_FILE_DARK:
+      case PM_FPA_FILE_CMP:
+      case PM_FPA_FILE_CMF:
+      case PM_FPA_FILE_PSF:
+      case PM_FPA_FILE_ASTROM_MODEL:
+      case PM_FPA_FILE_ASTROM_REFSTARS: {
+          pmHDU *hdu = pmFPAviewThisHDU(view, fpa);
+          if (hdu) {
+              if (!hdu->header) {
+                  hdu->header = psMetadataAlloc();
+              }
+              pmConfigConformHeader(hdu->header, file->format);
+
+              // whenever we write out a mask image, we should define the bits which represent mask concepts
+              if (file->type == PM_FPA_FILE_MASK) {
+                  assert (hdu->header);
+                  if (!pmConfigMaskWriteHeader(config, hdu->header)) {
+                      psError(PS_ERR_UNKNOWN, false,
+                              "failed to set the bitmask names in the PHU header for Image %s (%s)\n",
+                              file->filename, file->name);
+                      return false;
+                  }
+              }
+          }
+
+          pmChip *chip = pmFPAviewThisChip(view, fpa); // Chip of interest, or NULL
+          pmCell *cell = pmFPAviewThisCell(view, fpa); // Cell of interest, or NULL
+          if (!pmFPAUpdateNames(fpa, chip, cell)) {
+              psError(PS_ERR_UNKNOWN, false, "Unable to update names in header.");
+              return false;
+          }
+
+          pmConceptSource sources = PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CELLS |
+              PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_DATABASE; // Concept sources to write
+          if (cell) {
+              if (!pmConceptsWriteCell(cell, sources, true, config)) {
+                  psError(PS_ERR_IO, false, "Unable to write concepts for cell.\n");
+                  return false;
+              }
+          } else if (chip) {
+              if (!pmConceptsWriteChip(chip, sources, true, true, config)) {
+                  psError(PS_ERR_IO, false, "Unable to write concepts for chip.\n");
+                  return false;
+              }
+          } else if (!pmConceptsWriteFPA(fpa, sources, true, config)) {
+              psError(PS_ERR_IO, false, "Unable to write concepts for FPA.\n");
+              return false;
+          }
+          break;
+      }
+      default:
+        // No action
+        break;
+    }
+
+    return fpa;
 }
 
@@ -142,10 +232,10 @@
 
 // given an already-opened fits file, write the table corresponding to the specified view
-bool pmFPAviewWriteFitsTable(const pmFPAview *view, pmFPAfile *file, const char *name)
-{
-    PS_ASSERT_PTR_NON_NULL(view, false);
-    PS_ASSERT_PTR_NON_NULL(file, false);
-
-    pmFPA *fpa = file->fpa;             // FPA of interest
+bool pmFPAviewWriteFitsTable(const pmFPAview *view, pmFPAfile *file, const char *name, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // FPA of interest
     psFits *fits = file->fits;          // FITS file
 
@@ -280,5 +370,5 @@
     PS_ASSERT_PTR_NON_NULL(fits, false);
 
-    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config); // FPA to write
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, true); // FPA to write
 
     switch (pmFPAviewLevel(view)) {
@@ -489,5 +579,5 @@
 
     // select or generate the desired fpa in the correct output format
-    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config);
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false);
     pmHDU *phu = pmFPAviewThisHDU(view, fpa);
     if (!phu || !phu->blankPHU) {
@@ -499,9 +589,9 @@
     // whenever we write out a mask image, we should define the bits which represent mask concepts
     if (file->type == PM_FPA_FILE_MASK) {
-	assert (phu->header);
-	if (!pmConfigMaskWriteHeader (config, phu->header)) {
-	    psError(PS_ERR_UNKNOWN, false, "failed to set the bitmask names in the PHU header for Image %s (%s)\n", file->filename, file->name);
-	    return false;
-	}
+        assert (phu->header);
+        if (!pmConfigMaskWriteHeader (config, phu->header)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to set the bitmask names in the PHU header for Image %s (%s)\n", file->filename, file->name);
+            return false;
+        }
     }
 
