Index: trunk/archive/scripts/src/papFocalPlane.c
===================================================================
--- trunk/archive/scripts/src/papFocalPlane.c	(revision 4309)
+++ trunk/archive/scripts/src/papFocalPlane.c	(revision 4386)
@@ -44,15 +44,14 @@
     psMetadataItem *newItem = psMetadataItemAlloc(valueName, value->type, value->comment, value->data.V);
 
-    if (fpa) {
+    if (fpa && strncmp(valueName, "FPA", 3) == 0) {
 	psMetadataAddItem(fpa->values, newItem, PS_LIST_TAIL, PS_META_REPLACE);
     }
-    if (chip) {
+    if (chip && strncmp(valueName, "CHIP", 4) == 0) {
 	psMetadataAddItem(chip->values, newItem, PS_LIST_TAIL, PS_META_REPLACE);
     }
-    if (cell) {
+    if (cell && strncmp(valueName, "CELL", 4) == 0) {
 	psMetadataAddItem(cell->values, newItem, PS_LIST_TAIL, PS_META_REPLACE);
     }
 
-    psFree(newItem);
 }
 
@@ -65,8 +64,13 @@
 {
     bool mdStatus = true;		// Status of MD lookup
+    psMetadata *translation = psMetadataLookupMD(&mdStatus, fpa->camera, "TRANSLATION"); // FITS translation
+    if (! mdStatus) {
+	psError(PS_ERR_IO, false, "Unable to find TRANSLATION in camera configuration.\n");
+	return NULL;
+    }
 
     // Look for how to translate the concept into a FITS header name
-    const char *header = psMetadataLookupString(&mdStatus, fpa->fits, valueName);
-    if (strlen(header) > 0) {
+    const char *header = psMetadataLookupString(&mdStatus, translation, valueName);
+    if (mdStatus && strlen(header) > 0) {
 	// We have a FITS header to look up --- search each level
 	if (cell->header) {
@@ -110,8 +114,49 @@
     )
 {
-    psMetadataItem *defItem = psMetadataLookup((psMetadata*)fpa->defaults, valueName);
+    bool mdOK = true;			// Status of MD lookup
+    psMetadata *defaults = psMetadataLookupMD(&mdOK, fpa->camera, "DEFAULTS");
+    if (! mdOK) {
+	psError(PS_ERR_IO, false, "Unable to find DEFAULTS in camera configuration.\n");
+	return NULL;
+    }
+
+    psMetadataItem *defItem = psMetadataLookup(defaults, valueName);
     if (defItem) {
+	if (defItem->type == PS_META_META) {
+	    // A dependent default
+	    psTrace(__func__, 7, "Evaluating dependent default....\n");
+	    psMetadata *dependents = defItem->data.V; // The list of dependents
+	    // Find out what it depends on
+	    psString dependName = psStringCopy(valueName);
+	    psStringAppend(&dependName, "_DEPEND");
+	    psString dependsOn = psMetadataLookupString(&mdOK, defaults, dependName);
+	    if (! mdOK) {
+		psError(PS_ERR_IO, false, "Unable to find %s in camera configuration for dependent default"
+			" --- ignored\n", dependName);
+		// XXX: Need to clean up before returning
+		return NULL;
+	    }
+	    psFree(dependName);
+	    // Find the value of the dependent concept
+	    psMetadataItem *depItem = getValueFromCache(fpa, chip, cell, dependsOn);
+	    if (! depItem) {
+		depItem = getValueFromHeader(fpa, chip, cell, dependsOn);
+	    }
+	    if (! depItem) {
+		psError(PS_ERR_IO, true, "Unable to find value for %s (required for %s)\n", dependsOn,
+			valueName);
+		return NULL;
+	    }
+	    if (depItem->type != PS_META_STR) {
+		psError(PS_ERR_IO, true, "Value of %s is not of type string, as required for dependency"
+			" --- ignored.\n", dependsOn);
+	    }
+
+	    defItem = psMetadataLookup(dependents, depItem->data.V);	// This is now what we were after
+	}
 	setValueInCache(fpa, chip, cell, valueName, defItem);
     }
+
+    // XXX: Need to clean up before returning
     return defItem;			// defItem is either NULL or points to what was desired
 }
@@ -125,79 +170,85 @@
     )
 {
-    if (fpa->db) {
-	// The database has been initialised
-	bool mdStatus = true;		// Status of MD lookup
-	psMetadata *dbLookup = psMetadataLookupMD(&mdStatus, fpa->database, valueName);
-	if (dbLookup) {
-	    const char *tableName = psMetadataLookupString(&mdStatus, dbLookup, "TABLE"); // Name of the table
-	    const char *colName = psMetadataLookupString(&mdStatus, dbLookup, "COLUMN"); // Name of the column
-	    const char *givenCols = psMetadataLookupString(&mdStatus, dbLookup, "GIVENDBCOL");	// Name of "where" columns
-	    const char *givenPS = psMetadataLookupString(&mdStatus, dbLookup, "GIVENPS"); // Values for "where" columns
-	    
-	    // Now, need to get the "given"s
-	    if (strlen(givenCols) || strlen(givenPS)) {
-		psList *cols = papSplit(givenCols, ",;"); // List of column names
-		psList *values = papSplit(givenPS, ",;"); // List of value names for the columns
-		psMetadata *selection = psMetadataAlloc(); // The stuff to select in the DB
-		if (cols->size != values->size) {
-		    psLogMsg(__func__, PS_LOG_WARN, "The GIVENDBCOL and GIVENPS entries for %s do not have "
-			     "the same number of entries --- ignored.\n", valueName);
+    if (! fpa->db) {
+	// No database initialised
+	return NULL;
+    }
+
+    bool mdStatus = true;		// Status of MD lookup
+    psMetadata *database = psMetadataLookupMD(&mdStatus, fpa->camera, "DATABASE");
+    if (! mdStatus) {
+	// No error, because not everyone needs to use the DB
+	return NULL;
+    }
+
+    psMetadata *dbLookup = psMetadataLookupMD(&mdStatus, database, valueName);
+    if (dbLookup) {
+	const char *tableName = psMetadataLookupString(&mdStatus, dbLookup, "TABLE"); // Name of the table
+	const char *colName = psMetadataLookupString(&mdStatus, dbLookup, "COLUMN"); // Name of the column
+	const char *givenCols = psMetadataLookupString(&mdStatus, dbLookup, "GIVENDBCOL");	// Name of "where" columns
+	const char *givenPS = psMetadataLookupString(&mdStatus, dbLookup, "GIVENPS"); // Values for "where" columns
+	
+	// Now, need to get the "given"s
+	if (strlen(givenCols) || strlen(givenPS)) {
+	    psList *cols = papSplit(givenCols, ",;"); // List of column names
+	    psList *values = papSplit(givenPS, ",;"); // List of value names for the columns
+	    psMetadata *selection = psMetadataAlloc(); // The stuff to select in the DB
+	    if (cols->size != values->size) {
+		psLogMsg(__func__, PS_LOG_WARN, "The GIVENDBCOL and GIVENPS entries for %s do not have "
+			 "the same number of entries --- ignored.\n", valueName);
+	    } else {
+		// Iterators for the lists
+		psListIterator *colsIter = psListIteratorAlloc(cols, PS_LIST_HEAD, false);
+		psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false);
+		char *column = NULL;	// Name of the column
+		while (column = psListGetAndIncrement(colsIter)) {
+		    const char *name = psListGetAndIncrement(valuesIter); // Name for the value
+		    if (!strlen(column) || !strlen(name)) {
+			psLogMsg(__func__, PS_LOG_WARN, "One of the columns or value names for %s is "
+				 " empty --- ignored.\n", valueName);
+		    } else {
+			// Search for the value name
+			psMetadataItem *item = getValueFromCache(fpa, chip, cell, name);
+			if (! item) {
+			    item = getValueFromHeader(fpa, chip, cell, name);
+			}
+			if (! item) {
+			    item = getValueFromDefault(fpa, chip, cell, name);
+			}
+			if (! item) {
+			    psLogMsg(__func__, PS_LOG_ERROR, "Unable to find the value name %s for DB "
+				     " lookup on %s --- ignored.\n", name, valueName);
+			} else {
+			    // We need to create a new psMetadataItem.  I don't think we can't simply hack
+			    // the existing one, since that could conceivably cause memory leaks
+			    psMetadataItem *newItem = psMetadataItemAlloc(valueName, item->type,
+									  item->comment, item->data.V);
+			    psMetadataAddItem(selection, newItem, PS_LIST_TAIL, PS_META_REPLACE);
+			    psFree(newItem);
+			}
+		    }
+		} // Iterating through the columns
+		
+		psArray *dbResult = psDBSelectRows(fpa->db, tableName, selection, 2); // Lookup result
+		// Note that we use limit=2 in order to test if there are multiple rows returned
+		
+		psMetadataItem *result = NULL; // The final result of the DB lookup
+		if (dbResult->n == 0) {
+		    psLogMsg(__func__, PS_LOG_WARN, "Unable to find any rows in DB for %s --- ignored\n", 
+			     valueName);
 		} else {
-		    // Iterators for the lists
-		    psListIterator *colsIter = psListIteratorAlloc(cols, PS_LIST_HEAD, false);
-		    psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false);
-		    char *column = NULL;	// Name of the column
-		    while (column = psListGetAndIncrement(colsIter)) {
-			const char *name = psListGetAndIncrement(valuesIter); // Name for the value
-			if (!strlen(column) || !strlen(name)) {
-			    psLogMsg(__func__, PS_LOG_WARN, "One of the columns or value names for %s is "
-				     " empty --- ignored.\n", valueName);
-			} else {
-			    // Search for the value name
-			    psMetadataItem *item = getValueFromCache(fpa, chip, cell, name);
-			    if (! item) {
-				item = getValueFromHeader(fpa, chip, cell, name);
-			    }
-			    if (! item) {
-				item = getValueFromDefault(fpa, chip, cell, name);
-			    }
-			    if (! item) {
-				psLogMsg(__func__, PS_LOG_ERROR, "Unable to find the value name %s for DB "
-					 " lookup on %s --- ignored.\n", name, valueName);
-			    } else {
-				// We need to create a new psMetadataItem.  I don't think we can't simply hack
-				// the existing one, since that could conceivably cause memory leaks
-				psMetadataItem *newItem = psMetadataItemAlloc(valueName, item->type,
-									      item->comment, item->data.V);
-				psMetadataAddItem(selection, newItem, PS_LIST_TAIL, PS_META_REPLACE);
-				psFree(newItem);
-			    }
-			}
-		    } // Iterating through the columns
-		    
-		    psArray *dbResult = psDBSelectRows(fpa->db, tableName, selection, 2); // Result of lookup
-		    // Note that we use limit=2 in order to test if there are multiple rows returned
-
-		    psMetadataItem *result = NULL; // The final result of the DB lookup
-		    if (dbResult->n == 0) {
-			psLogMsg(__func__, PS_LOG_WARN, "Unable to find any rows in DB for %s --- ignored\n", 
-				 valueName);
-		    } else {
-			if (dbResult-> n > 1) {
-			    psLogMsg(__func__, PS_LOG_WARN, "Multiple rows returned in DB lookup for %s --- "
-				     " using the first one only.\n", valueName);
-			}
-			result = (psMetadataItem*)dbResult->data[0];
+		    if (dbResult-> n > 1) {
+			psLogMsg(__func__, PS_LOG_WARN, "Multiple rows returned in DB lookup for %s --- "
+				 " using the first one only.\n", valueName);
 		    }
-		    // XXX: Need to clean up before returning
-		    return result;
+		    result = (psMetadataItem*)dbResult->data[0];
 		}
-	    }
-	} // Doing the "given"s.
-    }
-
-    // XXX: Need to clean up before returning
-
-    // If we've fallen through somehow, we didn't get anything.
+		// XXX: Need to clean up before returning
+		return result;
+	    }
+	}
+    } // Doing the "given"s.
+
+    // Shouldn't get here
     return NULL;
 }
@@ -209,17 +260,31 @@
 			       )
 {
+    psTrace(__func__, 3, "Trying to retrieve %s for %s:%s...\n", valueName, chipName, cellName);
+
     bool mdStatus = true;		// Status of MD lookup
     papChip *chip = psMetadataLookupChip(&mdStatus, fpa->chips, chipName); // The chip
+    if (!mdStatus) {
+	psError(PS_ERR_IO, false, "Unable to find chip named %s\n", chipName);
+	return NULL;
+    }
     papCell *cell = psMetadataLookupCell(&mdStatus, chip->cells, cellName); // The cell
+    if (!mdStatus) {
+	psError(PS_ERR_IO, false, "Unable to find cell named %s in chip %s\n", cellName, chipName);
+	return NULL;
+    }
 
     // Try cache, headers, database, defaults in order
+    psTrace(__func__, 5, "Trying caches....\n");
     psMetadataItem *item = getValueFromCache(fpa, chip, cell, valueName);
     if (! item) {
+	psTrace(__func__, 5, "Trying headers....\n");
 	item = getValueFromHeader(fpa, chip, cell, valueName);
     }
     if (! item) {
+	psTrace(__func__, 5, "Trying database....\n");
 	item = getValueFromDB(fpa, chip, cell, valueName);
     }
     if (! item) {
+	psTrace(__func__, 5, "Trying defaults....\n");
 	item = getValueFromDefault(fpa, chip, cell, valueName);
     }
@@ -245,5 +310,4 @@
     }
 
-    psFree(item);
     return value;
 }
@@ -266,5 +330,4 @@
     }
 
-    psFree(item);
     return value;
 }
@@ -288,5 +351,4 @@
     }
 
-    psFree(item);
     return value;
 }
@@ -310,5 +372,4 @@
     }
 
-    psFree(item);
     return value;
 }
@@ -318,8 +379,6 @@
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-papFPA *papFPAAlloc(psMetadata *fits, // FITS translation info
-		    psMetadata *database, // Database lookup info
-		    psMetadata *defaults, // Defaults info
-		    psDB *db		// Database handle
+papFPA *papFPAAlloc(const psMetadata *camera, // Camera configuration
+		    psDB *db		// Database
     )
 {
@@ -327,15 +386,16 @@
     psMemSetDeallocator(fpa, (psFreeFcn)p_papFPAFree);
 
-    // Fill in the various components
-    fpa->fits = psMemIncrRefCounter(fits);
-    fpa->database = psMemIncrRefCounter(database);
-    fpa->defaults = psMemIncrRefCounter(defaults);
+    // Fill in the components
+    fpa->fromTangentPlane = NULL;
+    fpa->toTangentPlane = NULL;
+    fpa->projection = NULL;
 
     fpa->values = psMetadataAlloc();
+    fpa->camera = psMemIncrRefCounter((psPtr)camera);
+    fpa->db = db;
+    fpa->chips = psMetadataAlloc();
+
+    fpa->pixels = NULL;
     fpa->header = NULL;
-    fpa->db = psMemIncrRefCounter(db);
-
-    fpa->chips = psMetadataAlloc();
-    fpa->images = NULL;
 
     return fpa;
@@ -344,31 +404,42 @@
 void p_papFPAFree(papFPA *fpa)
 {
-    psFree((psPtr)fpa->fits);
-    psFree((psPtr)fpa->database);
-    psFree((psPtr)fpa->defaults);
+    psFree(fpa->fromTangentPlane);
+    psFree(fpa->toTangentPlane);
+    psFree(fpa->projection);
 
     psFree(fpa->values);
+    psFree((psPtr)fpa->camera);
+    psFree(fpa->db);
+    psFree(fpa->chips);
+
+    psFree(fpa->pixels);
     psFree(fpa->header);
-    if (fpa->db) {
-	psDBCleanup((psDB*)fpa->db);
-    }
-
-    psFree(fpa->chips);
-    psFree(fpa->images);
-}
-
-papChip *papChipAlloc(papFPA *fpa,		// FPA to which the chip belongs
-		    const char *name	// Name of the chip
+}
+
+papChip *papChipAlloc(papFPA *fpa,	// FPA to which the chip belongs
+		      const char *name	// Name of the chip
     )
 {
     papChip *chip = psAlloc(sizeof(papChip)); // The chip
     psMemSetDeallocator(chip, (psFreeFcn)p_papChipFree);
-    psMetadataAdd(fpa->chips, PS_LIST_TAIL, name, PS_META_CHIP, "Added on allocation of chip", chip);
+
+    // Push onto the FPA
+    psMetadataAdd(fpa->chips, PS_LIST_TAIL, name, PS_META_CHIP, "Chip added on allocation", chip);
+
+    // Fill in the components
+    *(int*)&chip->col0 = 0;		// Good enough for now
+    *(int*)&chip->row0 = 0;		// Good enough for now
+
+    chip->toFPA = NULL;
+    chip->fromFPA = NULL;
 
     chip->values = psMetadataAlloc();
+    chip->cells = psMetadataAlloc();
+
+    chip->pixels = NULL;
     chip->header = NULL;
 
-    chip->cells = psMetadataAlloc();
-    chip->images = NULL;
+    psMetadataAdd(chip->values, PS_LIST_TAIL, "CHIP.NAME", PS_META_STR, "Name of the chip",
+		  psStringCopy(name));
 
     return chip;
@@ -377,24 +448,43 @@
 void p_papChipFree(papChip *chip)
 {
+    psFree(chip->toFPA);
+    psFree(chip->fromFPA);
+
     psFree(chip->values);
+    psFree(chip->cells);
+
+    psFree(chip->pixels);
     psFree(chip->header);
-    psFree(chip->cells);
-    psFree(chip->images);
 }
 
 papCell *papCellAlloc(papChip *chip,	// Chip to which the cell belongs
-		    const char *name,	// Name of the cell
-		    int nReadouts	// Number of readouts contained
+		      const char *name,	// Name of the cell
+		      int nReadouts	// Number of readouts contained
     )
 {
     papCell *cell = psAlloc(sizeof(papCell)); // The cell
     psMemSetDeallocator(cell, (psFreeFcn)p_papCellFree);
-    psMetadataAdd(chip->cells, PS_LIST_TAIL, name, PS_META_CELL, "Added on allocation of cell", cell);
+
+    // Push onto the chip
+    psMetadataAdd(chip->cells, PS_LIST_TAIL, name, PS_META_CELL, "Cell added on allocation", cell);
+
+    // Fill in components
+    *(int*)&cell->col0 = 0;		// Good enough for now
+    *(int*)&cell->row0 = 0;		// Good enough for now
+
+    cell->toChip = NULL;
+    cell->fromChip = NULL;
+    cell->toFPA = NULL;
+    cell->toTP = NULL;
+    cell->toSky = NULL;
 
     cell->values = psMetadataAlloc();
+    cell->readouts = psArrayAlloc(nReadouts);
+
+    cell->pixels = NULL;
     cell->header = NULL;
 
-    cell->readouts = psArrayAlloc(nReadouts);
-    cell->images = NULL;
+    psMetadataAdd(cell->values, PS_LIST_TAIL, "CELL.NAME", PS_META_STR, "Name of the cell",
+		  psStringCopy(name));
 
     return cell;
@@ -403,8 +493,15 @@
 void p_papCellFree(papCell *cell)
 {
+    psFree(cell->toChip);
+    psFree(cell->fromChip);
+    psFree(cell->toFPA);
+    psFree(cell->toTP);
+    psFree(cell->toSky);
+
     psFree(cell->values);
+    psFree(cell->readouts);
+
+    psFree(cell->pixels);
     psFree(cell->header);
-    psFree(cell->readouts);
-    psFree(cell->images);
 }
 
