Index: /trunk/psModules/src/astrom/pmAstrometryModel.c
===================================================================
--- /trunk/psModules/src/astrom/pmAstrometryModel.c	(revision 18600)
+++ /trunk/psModules/src/astrom/pmAstrometryModel.c	(revision 18601)
@@ -2,5 +2,5 @@
  *
  *  @brief Functions to read and write astrometric model
- * 
+ *
  *  The generic model does not specify the location of the boresite on the sky, and it includes
  *  a model for the rotator and motion of the boresite.
@@ -9,6 +9,6 @@
  *
  *  @author EAM, IfA
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-06-09 01:53:31 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-17 22:38:15 $
  *
  *  Copyright 2007 Institute for Astronomy, University of Hawaii
@@ -38,4 +38,5 @@
 #include "pmFPAfile.h"
 #include "pmFPAExtent.h"
+#include "pmFPAfileFitsIO.h"
 #include "pmAstrometryWCS.h"
 #include "pmAstrometryUtils.h"
@@ -96,57 +97,66 @@
 /********************* Write Data functions *****************************/
 
-bool pmAstromModelWriteForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config) {
-
+bool pmAstromModelWriteForView (const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
     // write the full model in one pass: require the level to be FPA
     if (view->chip != -1) {
-	psError(PS_ERR_IO, false, "Astrometry must be written at the FPA level");
-	return false;
-    }
-
-    if (!pmAstromModelWriteFPA (file)) {
-	psError(PS_ERR_IO, false, "Failed to write Astrometry for fpa");
-	return false;
-    }
+        psError(PS_ERR_IO, false, "Astrometry must be written at the FPA level");
+        return false;
+    }
+
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+
+    if (!pmAstromModelWriteFPA(file, fpa)) {
+        psError(PS_ERR_IO, false, "Failed to write Astrometry for fpa");
+        psFree(fpa);
+        return false;
+    }
+
+    psFree(fpa);
+
     return true;
 }
 
 // write out all chip-level Astrometry data for this FPA
-bool pmAstromModelWriteFPA (pmFPAfile *file) {
-
-    if (!pmAstromModelWritePHU (file)) {
-	psError(PS_ERR_IO, false, "Failed to write PHU for Astrometry model");
-	return false;
+bool pmAstromModelWriteFPA (pmFPAfile *file, const pmFPA *fpa)
+{
+
+
+    if (!pmAstromModelWritePHU (file, fpa)) {
+        psError(PS_ERR_IO, false, "Failed to write PHU for Astrometry model");
+        return false;
     }
 
     if (!pmAstromModelWriteChips (file)) {
-	psError(PS_ERR_IO, false, "Failed to write Astrometry for chips");
-	return false;
+        psError(PS_ERR_IO, false, "Failed to write Astrometry for chips");
+        return false;
     }
 
     if (!pmAstromModelWriteFP (file)) {
-	psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry model");
-	return false;
+        psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry model");
+        return false;
     }
 
     if (!pmAstromModelWriteTP (file)) {
-	psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry model");
-	return false;
+        psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry model");
+        return false;
     }
 
     if (!pmAstromModelWriteSky (file)) {
-	psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry model");
-	return false;
-    }
-
-    return true;
-}
-
-bool pmAstromModelWritePHU (pmFPAfile *file) { 
-
-    // output header data 
+        psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry model");
+        return false;
+    }
+
+    return true;
+}
+
+bool pmAstromModelWritePHU (pmFPAfile *file, const pmFPA *fpa) {
+    // Need to have an FPA suitable for writing, so that the headers are all kosher
+
+    // output header data
     psMetadata *outhead = psMetadataAlloc();
 
     // use the FPA phu to generate the PHU header
-    pmHDU *phu = file->fpa->hdu;
+    pmHDU *phu = fpa->hdu;
 
     // if there is no FPA PHU, this is a single header+image (extension-less) file. This could be
@@ -154,18 +164,7 @@
     // write it out as a 'blank'
     if (phu) {
-	psMetadataCopy (outhead, phu->header);
+        psMetadataCopy (outhead, phu->header);
     } else {
-	pmConfigConformHeader (outhead, file->format);
-
-# if (0)
-	// XXX this is no longer needed : FPA.OBS is now correctly copied in pmConfigConformHeader
-	// XXX probably need other info to conform the header
-	psMetadata *fileData = psMetadataLookupMetadata(NULL, file->format, "FILE"); // File information
-	const char *fpaNameHdr = psMetadataLookupStr(NULL, fileData, "FPA.NAME");
-	if (fpaNameHdr && strlen(fpaNameHdr) > 0) {
-	    const char *fpaName = psMetadataLookupStr(NULL, file->fpa->concepts, "FPA.NAME");
-	    psMetadataAddStr(outhead, PS_LIST_TAIL, fpaNameHdr, PS_META_REPLACE, "FPA name", fpaName);
-	}
-# endif
+        pmConfigConformHeader (outhead, file->format);
     }
 
@@ -184,8 +183,8 @@
 
     psMetadata *header = psMetadataAlloc();
-    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",	"CHIPS");
-    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",     	"FOCAL_PLANE");
-    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",   	"RECTANGLE");
-    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent", 	"POLYNOMIAL");
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "CHIPS");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "FOCAL_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "RECTANGLE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "POLYNOMIAL");
 
     psArray *model = psArrayAllocEmpty (1);
@@ -196,42 +195,42 @@
     while ((chip = pmFPAviewNextChip (view, file->fpa, 1)) != NULL) {
 
-	if (!chip->toFPA) continue;
-	assert (chip->toFPA->x);
-	assert (chip->toFPA->y);
-      
-	psRegion *region = pmChipPixels (chip);
-
-	// set the chip name
-	char *chiprule = psStringCopy ("{CHIP.NAME}"); 
+        if (!chip->toFPA) continue;
+        assert (chip->toFPA->x);
+        assert (chip->toFPA->y);
+
+        psRegion *region = pmChipPixels (chip);
+
+        // set the chip name
+        char *chiprule = psStringCopy ("{CHIP.NAME}");
         char *chipname = pmFPAfileNameFromRule (chiprule, file, view);
 
-	for (int i = 0; i <= chip->toFPA->x->nX; i++) {
-	    for (int j = 0; j <= chip->toFPA->x->nY; j++) {
-		psMetadata *row = psMetadataAlloc ();
-		
-		psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", chipname);
-		psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "FOCAL_PLANE");
-		psMetadataAddF32(row,    PS_LIST_TAIL, "MINX",     PS_META_REPLACE, "range", region->x0);
-		psMetadataAddF32(row,    PS_LIST_TAIL, "MAXX",     PS_META_REPLACE, "range", region->x1);
-		psMetadataAddF32(row,    PS_LIST_TAIL, "MINY",     PS_META_REPLACE, "range", region->y0);
-		psMetadataAddF32(row,    PS_LIST_TAIL, "MAXY",     PS_META_REPLACE, "range", region->y1);
-    
-		psMetadataAddS32(row,    PS_LIST_TAIL, "XORDER",   PS_META_REPLACE, "", i);
-		psMetadataAddS32(row,    PS_LIST_TAIL, "YORDER",   PS_META_REPLACE, "", j);
-		psMetadataAddS32(row,    PS_LIST_TAIL, "NXORDER",  PS_META_REPLACE, "", chip->toFPA->x->nX);
-		psMetadataAddS32(row,    PS_LIST_TAIL, "NYORDER",  PS_META_REPLACE, "", chip->toFPA->x->nY);
-		psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_X",   PS_META_REPLACE, "", chip->toFPA->x->coeff[i][j]);
-		psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_Y",   PS_META_REPLACE, "", chip->toFPA->y->coeff[i][j]);
-		psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_X",  PS_META_REPLACE, "", chip->toFPA->x->coeffErr[i][j]);
-		psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_Y",  PS_META_REPLACE, "", chip->toFPA->y->coeffErr[i][j]);
-		psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_X",   PS_META_REPLACE, "", chip->toFPA->x->coeffMask[i][j]);
-		psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_Y",   PS_META_REPLACE, "", chip->toFPA->y->coeffMask[i][j]);
-		psArrayAdd (model, 100, row);
-		psFree (row);
-	    }
-	}
-	psFree (chiprule);
-	psFree (chipname);
-	psFree (region);
+        for (int i = 0; i <= chip->toFPA->x->nX; i++) {
+            for (int j = 0; j <= chip->toFPA->x->nY; j++) {
+                psMetadata *row = psMetadataAlloc ();
+
+                psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", chipname);
+                psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "FOCAL_PLANE");
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MINX",     PS_META_REPLACE, "range", region->x0);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MAXX",     PS_META_REPLACE, "range", region->x1);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MINY",     PS_META_REPLACE, "range", region->y0);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MAXY",     PS_META_REPLACE, "range", region->y1);
+
+                psMetadataAddS32(row,    PS_LIST_TAIL, "XORDER",   PS_META_REPLACE, "", i);
+                psMetadataAddS32(row,    PS_LIST_TAIL, "YORDER",   PS_META_REPLACE, "", j);
+                psMetadataAddS32(row,    PS_LIST_TAIL, "NXORDER",  PS_META_REPLACE, "", chip->toFPA->x->nX);
+                psMetadataAddS32(row,    PS_LIST_TAIL, "NYORDER",  PS_META_REPLACE, "", chip->toFPA->x->nY);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_X",   PS_META_REPLACE, "", chip->toFPA->x->coeff[i][j]);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_Y",   PS_META_REPLACE, "", chip->toFPA->y->coeff[i][j]);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_X",  PS_META_REPLACE, "", chip->toFPA->x->coeffErr[i][j]);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_Y",  PS_META_REPLACE, "", chip->toFPA->y->coeffErr[i][j]);
+                psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_X",   PS_META_REPLACE, "", chip->toFPA->x->coeffMask[i][j]);
+                psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_Y",   PS_META_REPLACE, "", chip->toFPA->y->coeffMask[i][j]);
+                psArrayAdd (model, 100, row);
+                psFree (row);
+            }
+        }
+        psFree (chiprule);
+        psFree (chipname);
+        psFree (region);
     }
 
@@ -254,8 +253,8 @@
 
     psMetadata *header = psMetadataAlloc();
-    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",	"FOCAL_PLANE");
-    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",     	"TANGENT_PLANE");
-    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",   	"RECTANGLE");
-    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent", 	"POLYNOMIAL");
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "FOCAL_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "TANGENT_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "RECTANGLE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "POLYNOMIAL");
 
     psArray *model = psArrayAllocEmpty (1);
@@ -265,5 +264,5 @@
 
     // rotate the toTPA to have 0.0 posangle
-    float posangle = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.POSANGLE"); 
+    float posangle = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.POSANGLE");
 
     // the to/from TPA transform currently has rotation of posangle; remove it & create the toTPA version
@@ -272,27 +271,27 @@
 
     for (int i = 0; i <= toTPA->x->nX; i++) {
-	for (int j = 0; j <= toTPA->x->nY; j++) {
-	    psMetadata *row = psMetadataAlloc ();
-	    psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", "FOCAL_PLANE");
-	    psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "TANGENT_PLANE");
-	    psMetadataAddF32(row,    PS_LIST_TAIL, "MINX",     PS_META_REPLACE, "range", region->x0);
-	    psMetadataAddF32(row,    PS_LIST_TAIL, "MAXX",     PS_META_REPLACE, "range", region->x1);
-	    psMetadataAddF32(row,    PS_LIST_TAIL, "MINY",     PS_META_REPLACE, "range", region->y0);
-	    psMetadataAddF32(row,    PS_LIST_TAIL, "MAXY",     PS_META_REPLACE, "range", region->y1);
-    
-	    psMetadataAddS32(row,    PS_LIST_TAIL, "XORDER",   PS_META_REPLACE, "", i);
-	    psMetadataAddS32(row,    PS_LIST_TAIL, "YORDER",   PS_META_REPLACE, "", j);
-	    psMetadataAddS32(row,    PS_LIST_TAIL, "NXORDER",  PS_META_REPLACE, "", toTPA->x->nX);
-	    psMetadataAddS32(row,    PS_LIST_TAIL, "NYORDER",  PS_META_REPLACE, "", toTPA->x->nY);
-	    psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_X",   PS_META_REPLACE, "", toTPA->x->coeff[i][j]);
-	    psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_Y",   PS_META_REPLACE, "", toTPA->y->coeff[i][j]);
-	    psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_X",  PS_META_REPLACE, "", toTPA->x->coeffErr[i][j]);
-	    psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_Y",  PS_META_REPLACE, "", toTPA->y->coeffErr[i][j]);
-	    psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_X",   PS_META_REPLACE, "", toTPA->x->coeffMask[i][j]);
-	    psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_Y",   PS_META_REPLACE, "", toTPA->y->coeffMask[i][j]);
-
-	    psArrayAdd (model, 100, row);
-	    psFree (row);
-	}
+        for (int j = 0; j <= toTPA->x->nY; j++) {
+            psMetadata *row = psMetadataAlloc ();
+            psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", "FOCAL_PLANE");
+            psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "TANGENT_PLANE");
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MINX",     PS_META_REPLACE, "range", region->x0);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MAXX",     PS_META_REPLACE, "range", region->x1);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MINY",     PS_META_REPLACE, "range", region->y0);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MAXY",     PS_META_REPLACE, "range", region->y1);
+
+            psMetadataAddS32(row,    PS_LIST_TAIL, "XORDER",   PS_META_REPLACE, "", i);
+            psMetadataAddS32(row,    PS_LIST_TAIL, "YORDER",   PS_META_REPLACE, "", j);
+            psMetadataAddS32(row,    PS_LIST_TAIL, "NXORDER",  PS_META_REPLACE, "", toTPA->x->nX);
+            psMetadataAddS32(row,    PS_LIST_TAIL, "NYORDER",  PS_META_REPLACE, "", toTPA->x->nY);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_X",   PS_META_REPLACE, "", toTPA->x->coeff[i][j]);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_Y",   PS_META_REPLACE, "", toTPA->y->coeff[i][j]);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_X",  PS_META_REPLACE, "", toTPA->x->coeffErr[i][j]);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_Y",  PS_META_REPLACE, "", toTPA->y->coeffErr[i][j]);
+            psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_X",   PS_META_REPLACE, "", toTPA->x->coeffMask[i][j]);
+            psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_Y",   PS_META_REPLACE, "", toTPA->y->coeffMask[i][j]);
+
+            psArrayAdd (model, 100, row);
+            psFree (row);
+        }
     }
 
@@ -300,6 +299,6 @@
         psError(PS_ERR_IO, false, "writing sky data\n");
         psFree(model);
-	psFree (header);
-	psFree (region);
+        psFree (header);
+        psFree (region);
         return false;
     }
@@ -317,18 +316,18 @@
 
     // get the boresite model parameters
-    float Xo = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.X0"); 
-    float Yo = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.Y0"); 
-    float RX = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.RX"); 
-    float RY = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.RY"); 
-    float To = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.T0"); 
-    float Po = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.P0"); 
+    float Xo = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.X0");
+    float Yo = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.Y0");
+    float RX = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.RX");
+    float RY = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.RY");
+    float To = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.T0");
+    float Po = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.P0");
     float PosZero = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.POS_ZERO");  /// XXX be consistent with degrees v radians
     char *refChip = psMetadataLookupStr (&status, file->fpa->concepts, "FPA.REF.CHIP");
 
     psMetadata *header = psMetadataAlloc();
-    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",	"TANGENT_PLANE");
-    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",     	"SKY");
-    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",   	"RECTANGLE");
-    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent", 	"PROJECTION");
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "TANGENT_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "SKY");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "RECTANGLE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "PROJECTION");
 
     psArray *model = psArrayAllocEmpty (1);
@@ -342,5 +341,5 @@
     psMetadataAddF32(row,    PS_LIST_TAIL, "MINY",     PS_META_REPLACE, "range", region->y0);
     psMetadataAddF32(row,    PS_LIST_TAIL, "MAXY",     PS_META_REPLACE, "range", region->y1);
-    
+
     // psMetadataAddF32(row,    PS_LIST_TAIL, "XREF",     PS_META_REPLACE, "", file->fpa->toSky->R  * PS_DEG_RAD);
     // psMetadataAddF32(row,    PS_LIST_TAIL, "YREF",     PS_META_REPLACE, "", file->fpa->toSky->D  * PS_DEG_RAD);
@@ -362,7 +361,7 @@
     if (!psFitsWriteTable (file->fits, header, model, "TP")) {
         psError(PS_ERR_IO, false, "writing sky data\n");
-	psFree (region);
+        psFree (region);
         psFree (model);
-	psFree (header);
+        psFree (header);
         return false;
     }
@@ -378,8 +377,8 @@
 
     psMetadata *header = psMetadataAlloc();
-    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer", 	"SKY");
-    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",      	"NONE");
-    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",    	"NONE");
-    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",  	"NONE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "SKY");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "NONE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "NONE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "NONE");
 
     psArray *model = psArrayAllocEmpty (1);
@@ -387,5 +386,5 @@
     psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", "SKY");
     psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "NONE");
-    
+
     psArrayAdd (model, 100, row);
     psFree (row);
@@ -407,15 +406,15 @@
     {
 
-	// write the full model in one pass: require the level to be FPA
-	if (view->chip != -1) {
-	    psError(PS_ERR_IO, false, "Astrometry must be read at the FPA level");
-	    return false;
-	}
-
-	if (!pmAstromModelReadFPA (file)) {
-	    psError(PS_ERR_IO, false, "Failed to read Astrometry for fpa");
-	    return false;
-	}
-	return true;
+        // write the full model in one pass: require the level to be FPA
+        if (view->chip != -1) {
+            psError(PS_ERR_IO, false, "Astrometry must be read at the FPA level");
+            return false;
+        }
+
+        if (!pmAstromModelReadFPA (file)) {
+            psError(PS_ERR_IO, false, "Failed to read Astrometry for fpa");
+            return false;
+        }
+        return true;
     }
 
@@ -424,16 +423,16 @@
 
     if (!pmAstromModelReadPHU (file)) {
-	psError(PS_ERR_IO, false, "Failed to read PHU for Astrometry model");
-	return false;
+        psError(PS_ERR_IO, false, "Failed to read PHU for Astrometry model");
+        return false;
     }
 
     if (!pmAstromModelReadChips (file)) {
-	psError(PS_ERR_IO, false, "Failed to read Astrometry for chips");
-	return false;
+        psError(PS_ERR_IO, false, "Failed to read Astrometry for chips");
+        return false;
     }
 
     if (!pmAstromModelReadFP (file)) {
-	psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry model");
-	return false;
+        psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry model");
+        return false;
     }
 
@@ -441,17 +440,17 @@
     // transformation determined in FP
     if (!pmAstromModelReadTP (file)) {
-	psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry model");
-	return false;
+        psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry model");
+        return false;
     }
 
     if (!pmAstromModelReadSky (file)) {
-	psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry model");
-	return false;
-    }
-
-    return true;
-}
-
-bool pmAstromModelReadPHU (pmFPAfile *file) { 
+        psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry model");
+        return false;
+    }
+
+    return true;
+}
+
+bool pmAstromModelReadPHU (pmFPAfile *file) {
 
     fprintf (stderr, "not sure we need to read PHU\n");
@@ -462,9 +461,9 @@
 
     for (int i = 0; i < fpa->chips->n; i++) {
-	pmChip *chip = fpa->chips->data[i];
-	if (!chip) continue;
-	char *thisone = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME");
-	if (!thisone) continue;
-	if (!strcmp (name, thisone)) return (i);
+        pmChip *chip = fpa->chips->data[i];
+        if (!chip) continue;
+        char *thisone = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME");
+        if (!thisone) continue;
+        if (!strcmp (name, thisone)) return (i);
     }
     return -1;
@@ -474,9 +473,9 @@
 
     for (int i = 0; i < fpa->chips->n; i++) {
-	pmChip *chip = fpa->chips->data[i];
-	if (!chip) continue;
-	char *thisone = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME");
-	if (!thisone) continue;
-	if (!strcmp (name, thisone)) return (chip);
+        pmChip *chip = fpa->chips->data[i];
+        if (!chip) continue;
+        char *thisone = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME");
+        if (!thisone) continue;
+        if (!strcmp (name, thisone)) return (chip);
     }
     return NULL;
@@ -496,7 +495,7 @@
     // free exising tranformations in prep for new alloc below
     for (int i = 0; i < file->fpa->chips->n; i++) {
-	pmChip *chip = file->fpa->chips->data[i];
-	psFree (chip->toFPA);
-	chip->toFPA = NULL;
+        pmChip *chip = file->fpa->chips->data[i];
+        psFree (chip->toFPA);
+        chip->toFPA = NULL;
     }
 
@@ -512,51 +511,51 @@
     // parse the model entries
     for (int i = 0; i < model->n; i++) {
-	psMetadata *row = model->data[i];
-
-	// name of the chip for this row. 
-	char *chipname = psMetadataLookupStr (&status, row, "SEGMENT");
-
-	// get chip from name
-	pmChip *chip = pmConceptsChipFromName (file->fpa, chipname);
-	REQUIRE (chip, "invalid chip name");
-
-	// define the toFPA transform if not already defined
-	int nX = psMetadataLookupS32(&status, row, "NXORDER"); REQUIRE (status, "missing NXORDER");
-	int nY = psMetadataLookupS32(&status, row, "NYORDER"); REQUIRE (status, "missing NYORDER");
-	if (chip->toFPA == NULL) {
-	    chip->toFPA = psPlaneTransformAlloc(nX, nY);
-	} else {
-	    REQUIRE (chip->toFPA->x->nX == nX, "mismatch in chip order");
-	    REQUIRE (chip->toFPA->x->nY == nY, "mismatch in chip order");
-	    REQUIRE (chip->toFPA->y->nX == nX, "mismatch in chip order");
-	    REQUIRE (chip->toFPA->y->nY == nY, "mismatch in chip order");
-	}
-
-	int ix = psMetadataLookupS32(&status, row, "XORDER");  REQUIRE (status, "missing XORDER");
-	int iy = psMetadataLookupS32(&status, row, "YORDER");  REQUIRE (status, "missing YORDER");
-
-	// XXX do I need to use this or can i rely on the camera concepts?
-	// minX = psMetadataLookupF32(&status, row, "MINX");
-	// maxX = psMetadataLookupF32(&status, row, "MAXX");
-	// minY = psMetadataLookupF32(&status, row, "MINY");
-	// maxY = psMetadataLookupF32(&status, row, "MAXY");
-
-	// XXX need to include mask values
-	chip->toFPA->x->coeff[ix][iy]    = psMetadataLookupF32(&status, row, "POLY_X");
-	chip->toFPA->y->coeff[ix][iy]    = psMetadataLookupF32(&status, row, "POLY_Y");
-	chip->toFPA->x->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_X");
-	chip->toFPA->y->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_Y");
-	chip->toFPA->x->coeffMask[ix][iy] = psMetadataLookupU8(&status, row, "MASK_X");
-	chip->toFPA->y->coeffMask[ix][iy] = psMetadataLookupU8(&status, row, "MASK_Y");
+        psMetadata *row = model->data[i];
+
+        // name of the chip for this row.
+        char *chipname = psMetadataLookupStr (&status, row, "SEGMENT");
+
+        // get chip from name
+        pmChip *chip = pmConceptsChipFromName (file->fpa, chipname);
+        REQUIRE (chip, "invalid chip name");
+
+        // define the toFPA transform if not already defined
+        int nX = psMetadataLookupS32(&status, row, "NXORDER"); REQUIRE (status, "missing NXORDER");
+        int nY = psMetadataLookupS32(&status, row, "NYORDER"); REQUIRE (status, "missing NYORDER");
+        if (chip->toFPA == NULL) {
+            chip->toFPA = psPlaneTransformAlloc(nX, nY);
+        } else {
+            REQUIRE (chip->toFPA->x->nX == nX, "mismatch in chip order");
+            REQUIRE (chip->toFPA->x->nY == nY, "mismatch in chip order");
+            REQUIRE (chip->toFPA->y->nX == nX, "mismatch in chip order");
+            REQUIRE (chip->toFPA->y->nY == nY, "mismatch in chip order");
+        }
+
+        int ix = psMetadataLookupS32(&status, row, "XORDER");  REQUIRE (status, "missing XORDER");
+        int iy = psMetadataLookupS32(&status, row, "YORDER");  REQUIRE (status, "missing YORDER");
+
+        // XXX do I need to use this or can i rely on the camera concepts?
+        // minX = psMetadataLookupF32(&status, row, "MINX");
+        // maxX = psMetadataLookupF32(&status, row, "MAXX");
+        // minY = psMetadataLookupF32(&status, row, "MINY");
+        // maxY = psMetadataLookupF32(&status, row, "MAXY");
+
+        // XXX need to include mask values
+        chip->toFPA->x->coeff[ix][iy]    = psMetadataLookupF32(&status, row, "POLY_X");
+        chip->toFPA->y->coeff[ix][iy]    = psMetadataLookupF32(&status, row, "POLY_Y");
+        chip->toFPA->x->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_X");
+        chip->toFPA->y->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_Y");
+        chip->toFPA->x->coeffMask[ix][iy] = psMetadataLookupU8(&status, row, "MASK_X");
+        chip->toFPA->y->coeffMask[ix][iy] = psMetadataLookupU8(&status, row, "MASK_Y");
     }
 
     // convert the toFPA transfomations to fromFPA transformations
     for (int i = 0; i < file->fpa->chips->n; i++) {
-	pmChip *chip = file->fpa->chips->data[i];
-	if (!chip->toFPA) continue;
-	psRegion *region = pmChipPixels (chip);
-	psFree (chip->fromFPA);
-	chip->fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50);
-	psFree (region);
+        pmChip *chip = file->fpa->chips->data[i];
+        if (!chip->toFPA) continue;
+        psRegion *region = pmChipPixels (chip);
+        psFree (chip->fromFPA);
+        chip->fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50);
+        psFree (region);
     }
 
@@ -589,27 +588,27 @@
     // parse the model
     for (int i = 0; i < model->n; i++) {
-	psMetadata *row = model->data[i];
-
-	// there is only one transformation in this model; the order is defined in the header
-	int nX = psMetadataLookupS32(&status, row, "NXORDER"); REQUIRE (status, "missing NXORDER");
-	int nY = psMetadataLookupS32(&status, row, "NYORDER"); REQUIRE (status, "missing NYORDER");
-	if (file->fpa->toTPA == NULL) {
-	    // allocate the new transformation
-	    file->fpa->toTPA = psPlaneTransformAlloc(nX, nY);
-	} else {
-	    REQUIRE (file->fpa->toTPA->x->nX == nX, "mismatch in chip order");
-	    REQUIRE (file->fpa->toTPA->x->nY == nY, "mismatch in chip order");
-	    REQUIRE (file->fpa->toTPA->y->nX == nX, "mismatch in chip order");
-	    REQUIRE (file->fpa->toTPA->y->nY == nY, "mismatch in chip order");
-	}
-
-	int ix = psMetadataLookupS32(&status, row, "XORDER"); REQUIRE (status, "missing XORDER");
-	int iy = psMetadataLookupS32(&status, row, "YORDER"); REQUIRE (status, "missing YORDER");
-	file->fpa->toTPA->x->coeff[ix][iy]     = psMetadataLookupF32(&status, row, "POLY_X");  REQUIRE (status, "missing POLY_X");
-	file->fpa->toTPA->y->coeff[ix][iy]     = psMetadataLookupF32(&status, row, "POLY_Y");  REQUIRE (status, "missing POLY_Y");
-	file->fpa->toTPA->x->coeffErr[ix][iy]  = psMetadataLookupF32(&status, row, "ERROR_X"); REQUIRE (status, "missing ERROR_X");
-	file->fpa->toTPA->y->coeffErr[ix][iy]  = psMetadataLookupF32(&status, row, "ERROR_Y"); REQUIRE (status, "missing ERROR_Y");
-	file->fpa->toTPA->x->coeffMask[ix][iy] = psMetadataLookupU8 (&status, row, "MASK_X");  REQUIRE (status, "missing MASK_X");
-	file->fpa->toTPA->y->coeffMask[ix][iy] = psMetadataLookupU8 (&status, row, "MASK_Y");  REQUIRE (status, "missing MASK_Y");
+        psMetadata *row = model->data[i];
+
+        // there is only one transformation in this model; the order is defined in the header
+        int nX = psMetadataLookupS32(&status, row, "NXORDER"); REQUIRE (status, "missing NXORDER");
+        int nY = psMetadataLookupS32(&status, row, "NYORDER"); REQUIRE (status, "missing NYORDER");
+        if (file->fpa->toTPA == NULL) {
+            // allocate the new transformation
+            file->fpa->toTPA = psPlaneTransformAlloc(nX, nY);
+        } else {
+            REQUIRE (file->fpa->toTPA->x->nX == nX, "mismatch in chip order");
+            REQUIRE (file->fpa->toTPA->x->nY == nY, "mismatch in chip order");
+            REQUIRE (file->fpa->toTPA->y->nX == nX, "mismatch in chip order");
+            REQUIRE (file->fpa->toTPA->y->nY == nY, "mismatch in chip order");
+        }
+
+        int ix = psMetadataLookupS32(&status, row, "XORDER"); REQUIRE (status, "missing XORDER");
+        int iy = psMetadataLookupS32(&status, row, "YORDER"); REQUIRE (status, "missing YORDER");
+        file->fpa->toTPA->x->coeff[ix][iy]     = psMetadataLookupF32(&status, row, "POLY_X");  REQUIRE (status, "missing POLY_X");
+        file->fpa->toTPA->y->coeff[ix][iy]     = psMetadataLookupF32(&status, row, "POLY_Y");  REQUIRE (status, "missing POLY_Y");
+        file->fpa->toTPA->x->coeffErr[ix][iy]  = psMetadataLookupF32(&status, row, "ERROR_X"); REQUIRE (status, "missing ERROR_X");
+        file->fpa->toTPA->y->coeffErr[ix][iy]  = psMetadataLookupF32(&status, row, "ERROR_Y"); REQUIRE (status, "missing ERROR_Y");
+        file->fpa->toTPA->x->coeffMask[ix][iy] = psMetadataLookupU8 (&status, row, "MASK_X");  REQUIRE (status, "missing MASK_X");
+        file->fpa->toTPA->y->coeffMask[ix][iy] = psMetadataLookupU8 (&status, row, "MASK_Y");  REQUIRE (status, "missing MASK_Y");
     }
 
@@ -629,5 +628,5 @@
     psMetadataItem *newItem = psMetadataItemCopy(item); \
     if (!psMetadataAddItem(TO, newItem, PS_LIST_TAIL, PS_META_REPLACE)) { \
-	psAbort ("cannot copy %s", NAME); \
+        psAbort ("cannot copy %s", NAME); \
     } \
     psFree (newItem); }
@@ -635,5 +634,5 @@
 // third layer applies boresite corrections and converts tangent plane to sky
 bool pmAstromModelReadTP (pmFPAfile *file) {
-    
+
     if (!psFitsMoveExtName (file->fits, "TP")) {
         psError(PS_ERR_IO, false, "missing TP extension in astrometry model\n");
@@ -692,5 +691,5 @@
 // third layer applies boresite corrections and converts tangent plane to sky
 bool pmAstromModelSetTP (pmFPAfile *file, psMetadata *concepts) {
-    
+
     bool status;
 
@@ -748,5 +747,5 @@
     psPlaneTransformApply (boreFP, chip->toFPA, boreCH);
     psPlaneTransformApply (boreTP, file->fpa->toTPA, boreFP);
-    psDeproject (boreSky, boreTP, file->fpa->toSky); 
+    psDeproject (boreSky, boreTP, file->fpa->toSky);
 
     // modify the projection to account for offset between true and reported boresite
Index: /trunk/psModules/src/astrom/pmAstrometryModel.h
===================================================================
--- /trunk/psModules/src/astrom/pmAstrometryModel.h	(revision 18600)
+++ /trunk/psModules/src/astrom/pmAstrometryModel.h	(revision 18601)
@@ -4,6 +4,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
- * @date $Date: 2008-03-18 18:24:29 $
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
  * Copyright 2006 Institute for Astronomy, University of Hawaii
  */
@@ -19,7 +19,7 @@
 bool pmAstromModelCheckDataStatusForChip (const pmChip *chip);
 
-bool pmAstromModelWriteForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
-bool pmAstromModelWriteFPA (pmFPAfile *file);
-bool pmAstromModelWritePHU (pmFPAfile *file);
+bool pmAstromModelWriteForView (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmAstromModelWriteFPA (pmFPAfile *file, const pmFPA *fpa);
+bool pmAstromModelWritePHU (pmFPAfile *file, const pmFPA *fpa);
 bool pmAstromModelWriteSky (pmFPAfile *file);
 bool pmAstromModelWriteTP (pmFPAfile *file);
Index: /trunk/psModules/src/astrom/pmAstrometryRefstars.c
===================================================================
--- /trunk/psModules/src/astrom/pmAstrometryRefstars.c	(revision 18600)
+++ /trunk/psModules/src/astrom/pmAstrometryRefstars.c	(revision 18601)
@@ -1,10 +1,10 @@
 /* @file  pmAstrometryRefstars.c
  * @brief Functions to write (and read?) astrometric reference stars
- * 
+ *
  * @ingroup AstroImage
  *
  * @author EAM, IfA
- * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- * @date $Date: 2008-03-20 00:27:00 $
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
  * Copyright 2008 Institute for Astronomy, University of Hawaii
  */
@@ -32,4 +32,5 @@
 #include "pmFPAview.h"
 #include "pmFPAfile.h"
+#include "pmFPAfileFitsIO.h"
 #include "pmAstrometryObjects.h"
 #include "pmAstrometryRefstars.h"
@@ -144,11 +145,13 @@
 }
 
-bool pmAstromRefstarsWritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config) { 
-
-    // output header data 
+bool pmAstromRefstarsWritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config) {
+
+    // output header data
     psMetadata *outhead = psMetadataAlloc();
 
     // use the FPA phu to generate the PHU header
-    pmHDU *phu = file->fpa->hdu;
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+    pmHDU *phu = psMemIncrRefCounter(fpa->hdu);
+    psFree(fpa);
 
     // if there is no FPA PHU, this is a single header+image (extension-less) file. This could be
@@ -156,8 +159,9 @@
     // write it out as a 'blank'
     if (phu) {
-	psMetadataCopy (outhead, phu->header);
+        psMetadataCopy (outhead, phu->header);
     } else {
-	pmConfigConformHeader (outhead, file->format);
-    }
+        pmConfigConformHeader (outhead, file->format);
+    }
+    psFree(phu);
 
     psMetadataAddBool (outhead, PS_LIST_TAIL, "EXTEND", PS_META_REPLACE, "this file has extensions", true);
@@ -256,21 +260,21 @@
 
     // set the extname : we are really only allowed one entry per chip; check this here?
-    char *chiprule = psStringCopy ("{CHIP.NAME}"); 
+    char *chiprule = psStringCopy ("{CHIP.NAME}");
     char *chipname = pmFPAfileNameFromRule (chiprule, file, view);
 
     for (int i = 0; i < refstars->n; i++) {
       psMetadata *row = psMetadataAlloc ();
-		
+
       pmAstromObj *ref = refstars->data[i];
 
-      psMetadataAddF64(row,    PS_LIST_TAIL, "RA",     	PS_META_REPLACE, "degrees", PS_DEG_RAD*ref->sky->r);
-      psMetadataAddF64(row,    PS_LIST_TAIL, "DEC",    	PS_META_REPLACE, "degrees", PS_DEG_RAD*ref->sky->d);
-      psMetadataAddF32(row,    PS_LIST_TAIL, "TP_X",   	PS_META_REPLACE, "microns", ref->TP->x);
-      psMetadataAddF32(row,    PS_LIST_TAIL, "TP_Y",   	PS_META_REPLACE, "microns", ref->TP->y);
-      psMetadataAddF32(row,    PS_LIST_TAIL, "FP_X",   	PS_META_REPLACE, "microns", ref->FP->x);
-      psMetadataAddF32(row,    PS_LIST_TAIL, "FP_Y",   	PS_META_REPLACE, "microns", ref->FP->y);
-      psMetadataAddF32(row,    PS_LIST_TAIL, "CHIP_X", 	PS_META_REPLACE, "microns", ref->chip->x);
-      psMetadataAddF32(row,    PS_LIST_TAIL, "CHIP_Y", 	PS_META_REPLACE, "microns", ref->chip->y);
-      psMetadataAddF32(row,    PS_LIST_TAIL, "MAG",    	PS_META_REPLACE, "microns", ref->Mag);
+      psMetadataAddF64(row,    PS_LIST_TAIL, "RA",      PS_META_REPLACE, "degrees", PS_DEG_RAD*ref->sky->r);
+      psMetadataAddF64(row,    PS_LIST_TAIL, "DEC",     PS_META_REPLACE, "degrees", PS_DEG_RAD*ref->sky->d);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "TP_X",    PS_META_REPLACE, "microns", ref->TP->x);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "TP_Y",    PS_META_REPLACE, "microns", ref->TP->y);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "FP_X",    PS_META_REPLACE, "microns", ref->FP->x);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "FP_Y",    PS_META_REPLACE, "microns", ref->FP->y);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "CHIP_X",  PS_META_REPLACE, "microns", ref->chip->x);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "CHIP_Y",  PS_META_REPLACE, "microns", ref->chip->y);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "MAG",     PS_META_REPLACE, "microns", ref->Mag);
       psMetadataAddF32(row,    PS_LIST_TAIL, "MAG_ERR", PS_META_REPLACE, "microns", ref->dMag);
 
@@ -281,7 +285,7 @@
         psError(PS_ERR_IO, false, "writing refstars\n");
         psFree (table);
-	psFree (header);
-	psFree (chiprule);
-	psFree (chipname);
+        psFree (header);
+        psFree (chiprule);
+        psFree (chipname);
         return false;
     }
Index: /trunk/psModules/src/astrom/pmAstrometryRefstars.h
===================================================================
--- /trunk/psModules/src/astrom/pmAstrometryRefstars.h	(revision 18600)
+++ /trunk/psModules/src/astrom/pmAstrometryRefstars.h	(revision 18601)
@@ -5,6 +5,6 @@
  *
  * @author EAM, IfA
- * @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
- * @date $Date: 2008-03-18 18:24:29 $
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
  * Copyright 2008 Institute for Astronomy, University of Hawaii
  */
@@ -23,5 +23,5 @@
 
 bool pmAstromRefstarsWriteForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
-bool pmAstromRefstarsWritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromRefstarsWritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
 
 bool pmAstromRefstarsWriteFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
Index: /trunk/psModules/src/camera/pmFPAfileFitsIO.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfileFitsIO.c	(revision 18600)
+++ /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;
+        }
     }
 
Index: /trunk/psModules/src/camera/pmFPAfileFitsIO.h
===================================================================
--- /trunk/psModules/src/camera/pmFPAfileFitsIO.h	(revision 18600)
+++ /trunk/psModules/src/camera/pmFPAfileFitsIO.h	(revision 18601)
@@ -5,6 +5,6 @@
  * @author PAP, IfA
  *
- * @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
- * @date $Date: 2008-06-30 00:53:45 $
+ * @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
  * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
  */
@@ -86,5 +86,6 @@
 bool pmFPAviewWriteFitsTable(const pmFPAview *view, ///<  View specifying level of interest
                              pmFPAfile *file, ///< FPA file to write
-                             const char *name ///< Name of table
+                             const char *name, ///< Name of table
+                             pmConfig *config ///< Configuration
                             );
 
@@ -97,5 +98,6 @@
 pmFPA *pmFPAfileSuitableFPA(const pmFPAfile *file,///< File containing the fpa
                             const pmFPAview *view, ///< View at which to produce the fpa
-                            const pmConfig *config ///< Configuration
+                            pmConfig *config, ///< Configuration
+                            bool pixels ///< Worry about copying the pixels?
                            );
 
Index: /trunk/psModules/src/camera/pmFPAfileIO.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfileIO.c	(revision 18600)
+++ /trunk/psModules/src/camera/pmFPAfileIO.c	(revision 18601)
@@ -405,64 +405,7 @@
     }
 
-    // check if the file is a FITS file (or uses the fits header)
-    bool fitsType = false;
-    fitsType |= (file->type == PM_FPA_FILE_IMAGE);
-    fitsType |= (file->type == PM_FPA_FILE_MASK);
-    fitsType |= (file->type == PM_FPA_FILE_WEIGHT);
-    fitsType |= (file->type == PM_FPA_FILE_HEADER);
-    fitsType |= (file->type == PM_FPA_FILE_FRINGE);
-    fitsType |= (file->type == PM_FPA_FILE_DARK);
-    fitsType |= (file->type == PM_FPA_FILE_CMP);
-    fitsType |= (file->type == PM_FPA_FILE_CMF);
-    fitsType |= (file->type == PM_FPA_FILE_PSF);
-    fitsType |= (file->type == PM_FPA_FILE_ASTROM_MODEL);
-    fitsType |= (file->type == PM_FPA_FILE_ASTROM_REFSTARS);
-
-    // 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).
-    if (fitsType) {
-        pmHDU *hdu = pmFPAviewThisHDU(view, file->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;
-		}
-	    }
-        }
-
-        pmFPA *fpa = file->fpa;         // FPA of interest
-        pmChip *chip = pmFPAviewThisChip(view, file->fpa); // Chip of interest, or NULL
-        pmCell *cell = pmFPAviewThisCell(view, file->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;
-        }
-    }
+    // IMPORTANT: If adding a FITS-based file, make sure your write function uses an FPA produced by
+    // pmFPAfileSuitableFPA.  This ensures the HDUs are at the correct level for your output format, and sets
+    // the headers correctly.
 
     // select a writing method
@@ -487,5 +430,5 @@
         status = pmFPAviewWriteFitsImage (view, file, config);
         if (status) {
-            if (!pmFPAviewWriteFitsTable(view, file, "FRINGE")) {
+            if (!pmFPAviewWriteFitsTable(view, file, "FRINGE", config)) {
                 psError(PS_ERR_UNKNOWN, false, "Unable to write fringe data from %s.\n", file->filename);
                 return false;
@@ -802,12 +745,12 @@
           }
 
-	  // XXX if we have a mask file, then we need to read the mask bit names
-	  // defined for this file
-	  if (file->type == PM_FPA_FILE_MASK) {
-	    if (!pmConfigMaskReadHeader (config, phu)) {
-		psError(PS_ERR_IO, false, "error in mask bits");
-		return false;
-	    }
-	  }
+          // XXX if we have a mask file, then we need to read the mask bit names
+          // defined for this file
+          if (file->type == PM_FPA_FILE_MASK) {
+            if (!pmConfigMaskReadHeader (config, phu)) {
+                psError(PS_ERR_IO, false, "error in mask bits");
+                return false;
+            }
+          }
 
           // determine the current format from the header
Index: /trunk/psModules/src/objects/pmPSF_IO.c
===================================================================
--- /trunk/psModules/src/objects/pmPSF_IO.c	(revision 18600)
+++ /trunk/psModules/src/objects/pmPSF_IO.c	(revision 18601)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.33 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-07-17 20:43:38 $
+ *  @version $Revision: 1.34 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-17 22:38:15 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -35,4 +35,5 @@
 #include "pmFPAview.h"
 #include "pmFPAfile.h"
+#include "pmFPAfileFitsIO.h"
 
 #include "pmPeaks.h"
@@ -107,5 +108,5 @@
 }
 
-bool pmPSFmodelWriteForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+bool pmPSFmodelWriteForView (const pmFPAview *view, pmFPAfile *file, pmConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(view, false);
@@ -142,5 +143,5 @@
 
 // read in all chip-level PSFmodel files for this FPA
-bool pmPSFmodelWriteFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+bool pmPSFmodelWriteFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, pmConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(view, false);
@@ -164,5 +165,5 @@
 
 // read in all cell-level PSFmodel files for this chip
-bool pmPSFmodelWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+bool pmPSFmodelWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, pmConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(view, false);
@@ -185,5 +186,5 @@
 //   - psf table (+header) : FITS Table
 bool pmPSFmodelWrite (psMetadata *analysis, const pmFPAview *view,
-                      pmFPAfile *file, const pmConfig *config)
+                      pmFPAfile *file, pmConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(view, false);
@@ -208,5 +209,7 @@
 
     // get the current header
-    pmHDU *hdu = pmFPAviewThisHDU (view, file->fpa);
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+    pmHDU *hdu = psMemIncrRefCounter(pmFPAviewThisHDU(view, fpa));
+    psFree(fpa);
     if (!hdu) {
         psError(PS_ERR_UNKNOWN, false, "Unable to find HDU");
@@ -229,4 +232,5 @@
         if (!menu) {
             psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
+            psFree(hdu);
             return false;
         }
@@ -236,4 +240,5 @@
         if (!rule) {
             psError(PS_ERR_UNKNOWN, false, "missing entry for PSF.HEAD in EXTNAME.RULES in camera.config");
+            psFree(hdu);
             return false;
         }
@@ -245,4 +250,5 @@
             psError(PS_ERR_UNKNOWN, false, "missing entry for PSF.TABLE in EXTNAME.RULES in camera.config");
             psFree (headName);
+            psFree(hdu);
             return false;
         }
@@ -255,4 +261,5 @@
             psFree (headName);
             psFree (tableName);
+            psFree(hdu);
             return false;
         }
@@ -278,4 +285,5 @@
         psFree (headName);
     }
+    psFree(hdu);
 
     // select the psf of interest
@@ -481,5 +489,5 @@
 
 // if this file needs to have a PHU written out, write one
-bool pmPSFmodelWritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+bool pmPSFmodelWritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(view, false);
@@ -496,6 +504,9 @@
     if (file->fpa->chips->n == 1) return true;
 
+
     // find the FPA phu
-    pmHDU *phu = pmFPAviewThisPHU (view, file->fpa);
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+    pmHDU *phu = psMemIncrRefCounter(pmFPAviewThisPHU(view, fpa));
+    psFree(fpa);
 
     // if there is no PHU, this is a single header+image (extension-less) file. This could be
@@ -508,4 +519,5 @@
         pmConfigConformHeader (outhead, file->format);
     }
+    psFree(phu);
 
     psMetadataAddBool (outhead, PS_LIST_TAIL, "EXTEND", PS_META_REPLACE, "this file has extensions", true);
Index: /trunk/psModules/src/objects/pmPSF_IO.h
===================================================================
--- /trunk/psModules/src/objects/pmPSF_IO.h	(revision 18600)
+++ /trunk/psModules/src/objects/pmPSF_IO.h	(revision 18601)
@@ -6,6 +6,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-09-24 21:27:58 $
+ * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -17,10 +17,10 @@
 /// @{
 
-bool pmPSFmodelWriteForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
-bool pmPSFmodelWriteFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
-bool pmPSFmodelWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
-bool pmPSFmodelWrite (psMetadata *analysis, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmPSFmodelWriteForView (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmPSFmodelWriteFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmPSFmodelWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmPSFmodelWrite (psMetadata *analysis, const pmFPAview *view, pmFPAfile *file, pmConfig *config);
 
-bool pmPSFmodelWritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmPSFmodelWritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
 
 bool pmPSFmodelReadForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
Index: /trunk/psModules/src/objects/pmSourceIO.c
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO.c	(revision 18600)
+++ /trunk/psModules/src/objects/pmSourceIO.c	(revision 18601)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.62 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-07-17 20:43:23 $
+ *  @version $Revision: 1.63 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-17 22:38:15 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -28,4 +28,5 @@
 #include "pmFPAview.h"
 #include "pmFPAfile.h"
+#include "pmFPAfileFitsIO.h"
 #include "pmConcepts.h"
 
@@ -108,5 +109,5 @@
 
 // Given a FITS file pointer, write the table of object data
-bool pmFPAviewWriteObjects (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+bool pmFPAviewWriteObjects (const pmFPAview *view, pmFPAfile *file, pmConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(view, false);
@@ -114,11 +115,13 @@
     PS_ASSERT_PTR_NON_NULL(file->fpa, false);
 
-    pmFPA *fpa = file->fpa;
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
 
     if (view->chip == -1) {
         if (!pmFPAWriteObjects (fpa, view, file, config)) {
             psError(PS_ERR_IO, false, "Failed to write objects from fpa");
-            return false;
-        }
+            psFree(fpa);
+            return false;
+        }
+        psFree(fpa);
         return true;
     }
@@ -126,4 +129,5 @@
     if (view->chip >= fpa->chips->n) {
         psError(PS_ERR_UNKNOWN, false, "Writing chip == %d (>= chips->n == %ld)", view->chip, fpa->chips->n);
+        psFree(fpa);
         return false;
     }
@@ -133,6 +137,8 @@
         if (!pmChipWriteObjects (chip, view, file, config)) {
             psError(PS_ERR_IO, false, "Failed to write objects from chip");
-            return false;
-        }
+            psFree(fpa);
+            return false;
+        }
+        psFree(fpa);
         return true;
     }
@@ -141,4 +147,5 @@
         psError(PS_ERR_UNKNOWN, false, "Writing cell == %d (>= cells->n == %ld)",
                 view->cell, chip->cells->n);
+        psFree(fpa);
         return false;
     }
@@ -148,7 +155,8 @@
         if (!pmCellWriteObjects (cell, view, file, config)) {
             psError(PS_ERR_IO, false, "Failed to write objects from cell");
-            return false;
-        }
-
+            psFree(fpa);
+            return false;
+        }
+        psFree(fpa);
         return true;
     }
@@ -157,4 +165,5 @@
         psError(PS_ERR_UNKNOWN, false, "Writing readout == %d (>= readouts->n == %ld)",
                 view->readout, cell->readouts->n);
+        psFree(fpa);
         return false;
     }
@@ -163,7 +172,9 @@
     if (!pmReadoutWriteObjects (readout, view, file, config)) {
         psError(PS_ERR_IO, false, "Failed to write objects from readout %d", view->readout);
-        return false;
-    }
-
+        psFree(fpa);
+        return false;
+    }
+
+    psFree(fpa);
     return true;
 }
@@ -244,5 +255,11 @@
     PS_ASSERT_PTR_NON_NULL(view, false);
     PS_ASSERT_PTR_NON_NULL(file, false);
-    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
+    pmCell *cell = readout->parent;
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    pmChip *chip = cell->parent;
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    pmFPA *fpa = chip->parent;
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
 
     bool status;
@@ -281,5 +298,5 @@
       case PM_FPA_FILE_CMP:
         // a SPLIT format : only one header and object table per file
-        hdu = pmFPAviewThisHDU (view, file->fpa);
+        hdu = pmFPAviewThisHDU (view, fpa);
         if (!hdu) {
             psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find HDU to write sources.");
@@ -317,5 +334,5 @@
 
         // get the current header
-        hdu = pmFPAviewThisHDU (view, file->fpa);
+        hdu = pmFPAviewThisHDU (view, fpa);
         if (!hdu) {
             psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find HDU to write sources.");
@@ -486,5 +503,5 @@
 
 // if this file needs to have a PHU written out, write one
-bool pmSource_CMF_WritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+bool pmSource_CMF_WritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(view, false);
@@ -503,6 +520,8 @@
     if (file->fpa->chips->n == 1) return true;
 
+
     // find the FPA phu
-    pmHDU *phu = pmFPAviewThisPHU (view, file->fpa);
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+    pmHDU *phu = psMemIncrRefCounter(pmFPAviewThisPHU(view, fpa));
 
     // if there is no PHU, this is a single header+image (extension-less) file. This could be
@@ -513,4 +532,5 @@
         psMetadataCopy (outhead, phu->header);
     }
+    psFree(phu);
 
     pmConfigConformHeader (outhead, file->format);
@@ -521,9 +541,16 @@
     // XXX why are these not correctly inserted by pmConfigConformHeader??
 
-    psMetadata *headers = psMetadataLookupMetadata(NULL, file->fpa->camera, BLANK_HEADERS); // Header names
+    // Because these concepts are not part of the "RULE" in the camera format, pmConfigConformHeader only adds
+    // what is required by the "RULE".
+    // Though we can configure Ohana to look at particular header keywords, it doesn't like having the
+    // important values in "HIERARCH FPA.TIME", etc, as is done for skycells, so we stoop to its level,
+    // putting in additional header keywords that it can understand.
+
+    psMetadata *headers = psMetadataLookupMetadata(NULL, fpa->camera, BLANK_HEADERS); // Header names
     if (!headers) {
         psError(PS_ERR_UNEXPECTED_NULL, false,
                 "Unable to find %s metadata within camera configuration", BLANK_HEADERS);
         psFree(outhead);
+        psFree(fpa);
         return false;
     }
@@ -535,7 +562,8 @@
                     "Unable to find FPA.TIME in %s within camera configuration.", BLANK_HEADERS);
             psFree(outhead);
-            return false;
-        }
-        psTime *time = psMetadataLookupTime(NULL, file->fpa->concepts, "FPA.TIME"); // Time of observation
+            psFree(fpa);
+            return false;
+        }
+        psTime *time = psMetadataLookupTime(NULL, fpa->concepts, "FPA.TIME"); // Time of observation
         double mjd = psTimeToMJD(time); // The MJD of observation
         psMetadataAddF64(outhead, PS_LIST_TAIL, mjdName, PS_META_REPLACE,
@@ -550,8 +578,8 @@
                     BLANK_HEADERS);
             psFree(outhead);
-            return false;
-        }
-        float exptime = psMetadataLookupF32(NULL, file->fpa->concepts,
-                                            "FPA.EXPOSURE"); // Exposure time
+            psFree(fpa);
+            return false;
+        }
+        float exptime = psMetadataLookupF32(NULL, fpa->concepts, "FPA.EXPOSURE"); // Exposure time
         psMetadataAddF32(outhead, PS_LIST_TAIL, expName, PS_META_REPLACE,
                          "Exposure time (sec)", exptime);
@@ -565,7 +593,8 @@
                     BLANK_HEADERS);
             psFree(outhead);
-            return false;
-        }
-        float airmass = psMetadataLookupF32(NULL, file->fpa->concepts, "FPA.AIRMASS"); // Airmass
+            psFree(fpa);
+            return false;
+        }
+        float airmass = psMetadataLookupF32(NULL, fpa->concepts, "FPA.AIRMASS"); // Airmass
         psMetadataAddF32(outhead, PS_LIST_TAIL, amName, PS_META_REPLACE,
                          "Observation airmass", airmass);
@@ -575,5 +604,5 @@
     const char *fpaNameHdr = psMetadataLookupStr(NULL, fileData, "FPA.OBS");
     if (fpaNameHdr && strlen(fpaNameHdr) > 0) {
-        const char *fpaName = psMetadataLookupStr(NULL, file->fpa->concepts, "FPA.OBS");
+        const char *fpaName = psMetadataLookupStr(NULL, fpa->concepts, "FPA.OBS");
         psMetadataAddStr(outhead, PS_LIST_TAIL, fpaNameHdr, PS_META_REPLACE,
                          "FPA observation identifier", fpaName);
@@ -581,8 +610,9 @@
 
     // if we have mosaic-level astrometry information, add it here:
-    psMetadata *updates = psMetadataLookupPtr (&status, file->fpa->analysis, "PSASTRO.HEADER");
+    psMetadata *updates = psMetadataLookupPtr (&status, fpa->analysis, "PSASTRO.HEADER");
     if (updates) {
         psMetadataCopy (outhead, updates);
     }
+    psFree(fpa);
 
     psMetadataAddBool (outhead, PS_LIST_TAIL, "EXTEND", PS_META_REPLACE, "this file has extensions", true);
Index: /trunk/psModules/src/objects/pmSourceIO.h
===================================================================
--- /trunk/psModules/src/objects/pmSourceIO.h	(revision 18600)
+++ /trunk/psModules/src/objects/pmSourceIO.h	(revision 18601)
@@ -4,6 +4,6 @@
  * @author EAM, IfA; GLG, MHPCC
  *
- * @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
- * @date $Date: 2008-05-29 13:25:38 $
+ * @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  *
@@ -30,5 +30,5 @@
 bool pmSourcesWrite_PS1_DEV_1_XFIT (psFits *fits, psArray *sources, char *extname);
 
-bool pmSource_CMF_WritePHU (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmSource_CMF_WritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
 
 psArray *pmSourcesReadCMP (char *filename, psMetadata *header);
@@ -50,5 +50,5 @@
 bool pmReadoutReadObjects (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
 
-bool pmFPAviewWriteObjects (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmFPAviewWriteObjects (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
 bool pmFPAWriteObjects (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
 bool pmChipWriteObjects (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
