Index: trunk/psModules/src/astrom/pmAstrometryTable.c
===================================================================
--- trunk/psModules/src/astrom/pmAstrometryTable.c	(revision 15562)
+++ trunk/psModules/src/astrom/pmAstrometryTable.c	(revision 15665)
@@ -8,6 +8,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-11-10 01:09:20 $
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-21 07:02:55 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -36,6 +36,8 @@
 #include "pmFPAview.h"
 #include "pmFPAfile.h"
+#include "pmFPAExtent.h"
+#include "pmAstrometryWCS.h"
+#include "pmAstrometryRegions.h"
 #include "pmAstrometryTable.h"
-
 
 /********************* CheckDataStatus functions *****************************/
@@ -181,36 +183,172 @@
 
 // write out chip-level Astrometry data for this chip
+// XXX this function writes out astrometry elements for a chip->fpa->tp->sky layer set
 // XXX we need to ensure the chip and fpa level data are written
 // XXX can we write the rows one at a time (or groups at a time?)
+// XXX allow this to be chip level, or just force to be fpa?  is it valid at the chip level??
 bool pmAstromWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
 {
-    bool status;
-    // *** define the EXTNAME values used for the table data, and residual image segments ***
-
-    // lookup the EXTNAME values used for table data and image header segments
-    char *rule = NULL;
-
-    // Menu of EXTNAME rules
-    psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
-    if (!menu) {
-	psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
-	return false;
-    }
-
-    // EXTNAME for image header
-    rule = psMetadataLookupStr(&status, menu, "ASTROMETRY");
-    if (!rule) {
-	psError(PS_ERR_UNKNOWN, false, "missing entry for ASTROMETRY in EXTNAME.RULES in camera.config");
-	return false;
-    }
-
-    // XXX need to finish this: uncomment when used
-    # if (0)
-    char *extname = pmFPAfileNameFromRule (rule, file, view);
-    # endif
-
-    // write the chip elements in the following form:
-    // chipID, ...?  I forget the form: look at ICD
-
+    psArray *table;
+    psMetadata *row;
+    psMetadata *header;
+
+    // write out the blank PHU to start the file
+    psFitsWriteBlank (file->fits, NULL, NULL);
+
+    // first layer is the sky
+    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");
+
+    table = psArrayAllocEmpty (1);
+    row = psMetadataAlloc ();
+    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 (table, 100, row);
+    psFree (row);
+
+    if (!psFitsWriteTable (file->fits, header, table, "SKY")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree(table);
+        return false;
+    }
+
+    psFree (table);
+    psFree (header);
+
+    // second layer is the tangent plane
+    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");
+
+    table = psArrayAllocEmpty (1);
+    row = psMetadataAlloc ();
+    psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", "TANGENT_PLANE");
+    psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "SKY");
+
+    psRegion *region = pmAstromFPAExtent (file->fpa);
+    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);
+    
+    psMetadataAddF32(row,    PS_LIST_TAIL, "XSCALE",   PS_META_REPLACE, "", file->fpa->toSky->Xs * PM_DEG_RAD);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "YSCALE",   PS_META_REPLACE, "", file->fpa->toSky->Ys * PM_DEG_RAD);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "XREF",     PS_META_REPLACE, "", file->fpa->toSky->R * PM_DEG_RAD);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "YREF",     PS_META_REPLACE, "", file->fpa->toSky->D * PM_DEG_RAD);
+
+    psArrayAdd (table, 100, row);
+    psFree (row);
+
+    if (!psFitsWriteTable (file->fits, header, table, "TP")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree(table);
+        return false;
+    }
+
+    psFree (table);
+    psFree (header);
+
+    // third layer is the focal plane
+    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");
+
+    table = psArrayAllocEmpty (1);
+
+    // XXX is this or the tpa region correct?
+    region = pmAstromFPAExtent (file->fpa);
+
+    for (int i = 0; i <= file->fpa->toTPA->x->nX; i++) {
+	for (int j = 0; j <= file->fpa->toTPA->x->nY; j++) {
+	    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, "NX",       PS_META_REPLACE, "", file->fpa->toTPA->x->nX);
+	    psMetadataAddS32(row,    PS_LIST_TAIL, "NY",       PS_META_REPLACE, "", file->fpa->toTPA->x->nY);
+	    psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_X",   PS_META_REPLACE, "", file->fpa->toTPA->x->coeff[i][j]);
+	    psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_Y",   PS_META_REPLACE, "", file->fpa->toTPA->y->coeff[i][j]);
+	    psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_X",  PS_META_REPLACE, "", file->fpa->toTPA->x->coeffErr[i][j]);
+	    psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_Y",  PS_META_REPLACE, "", file->fpa->toTPA->y->coeffErr[i][j]);
+
+	    psArrayAdd (table, 100, row);
+	    psFree (row);
+	}
+    }
+
+    if (!psFitsWriteTable (file->fits, header, table, "FP")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree(table);
+        return false;
+    }
+
+    psFree (table);
+    psFree (header);
+
+    // fourth layer holds the chips
+    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");
+
+    table = psArrayAllocEmpty (1);
+
+    pmFPAview *view = pmFPAviewAlloc (0);
+
+    pmChip *chip = NULL;
+    while ((chip = pmFPAviewNextChip (view, file->fpa, 1)) != NULL) {
+
+	psRegion *region = pmChipPixels (chip);
+
+	char *chiprule = psStringCopy ("CHIP.{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++) {
+		row = psMetadataAlloc ();
+		// xXXX set chip name based on metadata
+		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",        "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, "NX",       PS_META_REPLACE, "", chip->toFPA->x->nX);
+		psMetadataAddS32(row,    PS_LIST_TAIL, "NY",       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]);
+		psArrayAdd (table, 100, row);
+		psFree (row);
+	    }
+	}
+	psFree (chiprule);
+	psFree (chipname);
+    }
+    psFree (view);
+
+    if (!psFitsWriteTable (file->fits, header, table, "CHIPS")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree(table);
+        return false;
+    }
+
+    psFree (table);
+    psFree (header);
     return true;
 }
@@ -267,7 +405,7 @@
 
     // EXTNAME for image header
-    rule = psMetadataLookupStr(&status, menu, "ASTROMETRY");
+    rule = psMetadataLookupStr(&status, menu, "REF.ASTROM");
     if (!rule) {
-	psError(PS_ERR_UNKNOWN, false, "missing entry for ASTROMETRY in EXTNAME.RULES in camera.config");
+	psError(PS_ERR_UNKNOWN, false, "missing entry for REF.ASTROM in EXTNAME.RULES in camera.config");
 	return false;
     }
