Index: /trunk/psModules/src/config/pmConfigCamera.c
===================================================================
--- /trunk/psModules/src/config/pmConfigCamera.c	(revision 12590)
+++ /trunk/psModules/src/config/pmConfigCamera.c	(revision 12591)
@@ -70,4 +70,5 @@
 
 // Generate a mosaicked version of a camera configuration
+// XXX EAM : the error states of this function need to be more carefully considered
 static bool mosaickedVersion(psMetadata *oldCameras, // Old list of camera configurations
                              psMetadata *newCameras, // New list of camera configurations
@@ -84,4 +85,6 @@
     psMetadata *camera = psMetadataLookupMetadata(NULL, oldCameras, name); // The camera configuration
     if (!camera) {
+	// XXX is this an error?
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find camera to be mosaicked in camera list.");
         return false;
     }
@@ -94,24 +97,26 @@
     }
 
-    psMetadata *new = psMetadataCopy(NULL, camera); // Copy of the camera
+    psMetadata *new = psMetadataCopy(NULL, camera); // Copy of the camera description
     bool mdok;                          // Status of MD lookups
 
-    // Fix up the contents of the FPA
-    psMetadata *fpa = psMetadataLookupMetadata(&mdok, new, "FPA"); // FPA in the camera configuration
-    if (!mdok || !fpa) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "Can't find FPA within camera configuration.");
+    // ** Fix up the contents of the FPA description to match the mosaicked camera **
+    // select the FPA description
+    psMetadata *fpa = psMetadataLookupMetadata(NULL, new, "FPA"); // FPA in the camera configuration
+    if (!fpa) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find FPA within camera configuration.");
         psFree(new);
-        return NULL;
+        return false;
     }
     switch (mosaicLevel) {
+	// For CHIP mosaic, replace the contents of each chip with a single cell
       case PM_FPA_LEVEL_CHIP: {
-          // Replace the contents of each chip with a single cell
           psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iterator
           psMetadataItem *fpaItem = NULL;     // Item from iteration
           while ((fpaItem = psMetadataGetAndIncrement(fpaIter))) {
               if (fpaItem->type != PS_DATA_STRING) {
-                  psWarning("Element %s within FPA in camera configuration is not of type STR.",
+                  psError(PS_ERR_UNKNOWN, true, "Element %s within FPA in camera configuration is not of type STR.",
                             fpaItem->name);
-                  continue;
+		  psFree(new);
+		  return false;
               }
 
@@ -124,6 +129,6 @@
           break;
       }
+	// For FPA mosaic, replace the contents of the FPA with a single chip containing a single cell
       case PM_FPA_LEVEL_FPA: {
-          // Replace the contents of the FPA with a single chip containing a single cell
           while (psListLength(fpa->list) > 0) {
               psMetadataRemoveIndex(fpa, PS_LIST_TAIL);
@@ -139,7 +144,9 @@
     }
 
-    // Update the camera formats appropriately
-    psMetadata *formats = psMetadataLookupMetadata(&mdok, new, "FORMATS"); // FORMATS in the configuration
-    assert(mdok && formats);            // It had better be there --- we've already read them in
+    // ** Update the camera formats : add a new (mosaicked) format for each existing camera format **
+    // select the list of all camera formats
+    psMetadata *formats = psMetadataLookupMetadata(NULL, new, "FORMATS"); // FORMATS in the configuration
+    assert(formats);            // It had better be there --- we've already read them in
+    // loop over each of the formats
     psMetadataIterator *formatsIter = psMetadataIteratorAlloc(formats, PS_LIST_HEAD, NULL); // Iterator
     psMetadataItem *formatsItem = NULL; // Item from iteration
@@ -148,10 +155,14 @@
         psMetadata *format = formatsItem->data.V; // The camera format
 
-        // Add a RULE, so that when a mosaic is written to a FITS file, it can be recognised again when read.
-        psMetadata *rule = psMetadataLookupMetadata(&mdok, format, "RULE"); // Way to identify format from PHU
-        if (!mdok || !rule) {
-            psWarning("Couldn't find RULE in the camera format %s.\n", formatsItem->name);
-            continue;
-        }
+        // Add a new RULE which uniquely describes the mosaicked format.  this is needed so
+	// that when a mosaic is written to a FITS file, it can be recognised again when read.
+        psMetadata *rule = psMetadataLookupMetadata(NULL, format, "RULE"); // Way to identify format from PHU
+        if (!rule) {
+	    // a camera format without a rule is not allowed.
+	    psError(PS_ERR_UNKNOWN, false, "Camera format %s has no RULE", formatsItem->name);
+	    return false;
+	}
+
+	// the new rule is supplemented by the mosaicLevel
         switch (mosaicLevel) {
         case PM_FPA_LEVEL_CHIP:
@@ -166,75 +177,136 @@
 
         // Fix the FILE information: need to fix the levels for the PHU and EXTENSIONS.
+	// both of these elements are required in the format; we raise an error if they are not found
         // If EXTENSIONS is NONE, then we need to change the CONTENT specifier to point to the chip name.
-        psMetadata *file = psMetadataLookupMetadata(&mdok, format, "FILE"); // File information
-        if (!mdok || !file) {
-            psWarning("Couldn't find FILE in the camera format %s.\n", formatsItem->name);
-            continue;
+        psMetadata *file = psMetadataLookupMetadata(NULL, format, "FILE"); // File information
+        if (!file) {
+            psError(PS_ERR_UNKNOWN, false, "Camera format %s has no FILE", formatsItem->name);
+	    return false;
         }
         psMetadataItem *phuItem = psMetadataLookup(file, "PHU"); // PHU level
         if (!phuItem || phuItem->type != PS_DATA_STRING) {
-            psWarning("Couldn't find PHU of type STR in the FILE information in the camera format %s.\n",
-                      formatsItem->name);
-            continue;
-        }
-        if (strcasecmp(phuItem->data.str, "CELL") == 0 ||
-                (mosaicLevel == PM_FPA_LEVEL_FPA && (strcasecmp(phuItem->data.str, "CHIP") == 0))) {
-            psFree(phuItem->data.str);
-            if (mosaicLevel == PM_FPA_LEVEL_CHIP) {
-                phuItem->data.str = psStringCopy("CHIP");
-            } else {
-                phuItem->data.str = psStringCopy("FPA");
-            }
+            psError(PS_ERR_UNKNOWN, false, "Camera format %s is missing PHU in the FILE information", formatsItem->name);
+	    return false;
         }
         psMetadataItem *extensionsItem = psMetadataLookup(file, "EXTENSIONS"); // Extensions level
         if (!extensionsItem || extensionsItem->type != PS_DATA_STRING) {
-            psWarning("Couldn't find EXTENSIONS of type STR in the FILE information "
-                      "in the camera format %s.\n", formatsItem->name);
-            continue;
-        }
+            psError(PS_ERR_UNKNOWN, false, "Camera format %s is missing EXTENSIONS in the FILE information", formatsItem->name);
+            return false;
+        }
+
+	// mosaicLevel == CHIP:
+	// Case    PHU     EXTENSIONS     Modifications
+	// ====    ===     ==========     ===========
+	// 1.      FPA     CHIP           NONE
+	// 2.      FPA     CELL           EXT->CHIP
+	// 3.      FPA     NONE           NONE
+	// 4.      CHIP    CELL           EXT->NONE
+	// 5.      CHIP    NONE           NONE
+	// 6.      CELL    NONE           PHU->CHIP
+	// possible outcomes:
+	//         FPA     CHIP
+	//         FPA     NONE
+	//         CHIP    NONE
+
+	// mosaicLevel == FPA:
+	// Case    PHU     EXTENSIONS     Modifications
+	// ====    ===     ==========     ===========
+	// 1.      FPA     CHIP           EXT->NONE
+	// 2.      FPA     CELL           EXT->NONE
+	// 3.      FPA     NONE           NONE
+	// 4.      CHIP    CELL           PHU->FPA, EXT->NONE
+	// 5.      CHIP    NONE           PHU->FPA
+	// 6.      CELL    NONE           PHU->FPA
+	// possible outcomes:
+	//         FPA     NONE
+
+	// modify the values of phuItem and extensionsItem
         switch (mosaicLevel) {
           case PM_FPA_LEVEL_CHIP:
-            if (strcasecmp(phuItem->data.str, "FPA") == 0 &&
-                strcasecmp(extensionsItem->data.str, "CELL") == 0) {
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "CHIP")) {
+		break;
+            } 
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "CELL")) {
                 psFree(extensionsItem->data.str);
                 extensionsItem->data.str = psStringCopy("CHIP");
-            } else {
+		break;
+            } 
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "NON")) {
+		break;
+            } 
+            if (!strcasecmp(phuItem->data.str, "CHIP") && !strcasecmp(extensionsItem->data.str, "CELL")) {
                 psFree(extensionsItem->data.str);
                 extensionsItem->data.str = psStringCopy("NONE");
-
-                if (strcasecmp(phuItem->data.str, "FPA") == 0) {
-                    // Don't need a "CONTENT" to identify the content!
-                    if (psMetadataLookup(file, "CONTENT")) {
-                        psMetadataRemoveKey(file, "CONTENT");
-                    }
-                    break;
-                }
-                psMetadataAddStr(file, PS_LIST_TAIL, "CONTENT", PS_META_REPLACE, "Key to CONTENTS menu",
-                                 "{CHIP.NAME}");
-            }
+		break;
+            } 
+            if (!strcasecmp(phuItem->data.str, "CHIP") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+		break;
+            } 
+            if (!strcasecmp(phuItem->data.str, "CELL") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+		psFree(phuItem->data.str);
+                phuItem->data.str = psStringCopy("CHIP");
+		break;
+            } 
+	    psAbort ("should not reach here");
+
+          case PM_FPA_LEVEL_FPA:
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "CHIP")) {
+                psFree(extensionsItem->data.str);
+                extensionsItem->data.str = psStringCopy("NONE");
+		break;
+            } 
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "CELL")) {
+                psFree(extensionsItem->data.str);
+                extensionsItem->data.str = psStringCopy("NONE");
+		break;
+            } 
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "NON")) {
+		break;
+            } 
+            if (!strcasecmp(phuItem->data.str, "CHIP") && !strcasecmp(extensionsItem->data.str, "CELL")) {
+		psFree(phuItem->data.str);
+                phuItem->data.str = psStringCopy("FPA");
+		break;
+                psFree(extensionsItem->data.str);
+                extensionsItem->data.str = psStringCopy("NONE");
+		break;
+            } 
+            if (!strcasecmp(phuItem->data.str, "CHIP") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+		psFree(phuItem->data.str);
+                phuItem->data.str = psStringCopy("FPA");
+		break;
+            } 
+            if (!strcasecmp(phuItem->data.str, "CELL") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+		psFree(phuItem->data.str);
+                phuItem->data.str = psStringCopy("FPA");
+		break;
+            } 
+	    psAbort ("should not reach here");
+
+	  default:
+            psAbort("Should never get here.\n");
+        }
 
 #if 0
-            // Don't need CELL.NAME for chip-mosaicked camera
-            if (psMetadataLookup(file, "CELL.NAME")) {
-                psMetadataRemoveKey(file, "CELL.NAME");
-            }
+	// XXXX when do I need to adjust the value of CONTENT, CELL.NAME, CHIP.NAME?
+
+	// Don't need a "CONTENT" to identify the content!
+	if (psMetadataLookup(file, "CONTENT")) {
+	    psMetadataRemoveKey(file, "CONTENT");
+	}
+	psMetadataAddStr(file, PS_LIST_TAIL, "CONTENT", PS_META_REPLACE, "Key to CONTENTS menu",
+			 "{CHIP.NAME}");
+	// Don't need CELL.NAME for chip-mosaicked camera
+	if (psMetadataLookup(file, "CELL.NAME")) {
+	    psMetadataRemoveKey(file, "CELL.NAME");
+	}
+	// Don't need CHIP.NAME or CELL.NAME for fpa-mosaicked camera
+	if (psMetadataLookup(file, "CHIP.NAME")) {
+	    psMetadataRemoveKey(file, "CHIP.NAME");
+	}
+	if (psMetadataLookup(file, "CELL.NAME")) {
+	    psMetadataRemoveKey(file, "CELL.NAME");
+	}
 #endif
-            break;
-          case PM_FPA_LEVEL_FPA:
-            psFree(extensionsItem->data.str);
-            extensionsItem->data.str = psStringCopy("NONE");
-#if 0
-            // Don't need CHIP.NAME or CELL.NAME for fpa-mosaicked camera
-            if (psMetadataLookup(file, "CHIP.NAME")) {
-                psMetadataRemoveKey(file, "CHIP.NAME");
-            }
-            if (psMetadataLookup(file, "CELL.NAME")) {
-                psMetadataRemoveKey(file, "CELL.NAME");
-            }
-#endif
-            break;
-        default:
-            psAbort("Should never get here.\n");
-        }
 
         // Fix up the CONTENTS to contain only the mosaicked cell for each chip
@@ -245,85 +317,78 @@
             break;
           case PM_FPA_LEVEL_CHIP:
-            if (strcasecmp(phuItem->data.str, "FPA") == 0) {
-                if (strcasecmp(extensionsItem->data.str, "CHIP") == 0) {
-                    // List the chipName:chipType for each chip.
-
-                    psMetadata *contents = psMetadataAlloc(); // List of contents, with chipName:chipType
-
-                    psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iteratr
-                    psMetadataItem *fpaItem;    // Item from iteration
-                    while ((fpaItem = psMetadataGetAndIncrement(fpaIter))) {
-                        if (fpaItem->type != PS_DATA_STRING) {
-                            // We've already thrown a warning on this, above.
-                            continue;
-                        }
-                        psString content = NULL; // Content to add
-                        psStringAppend(&content, "%s:_mosaicChip ", fpaItem->name);
-                        psMetadataAddStr(contents, PS_LIST_TAIL, fpaItem->name, 0, NULL, content);
-                        psFree(content);
-                    }
-                    psFree(fpaIter);
-                    psMetadataAddMetadata(format, PS_LIST_TAIL, TABLE_OF_CONTENTS, PS_META_REPLACE,
-                                          "List of contents", contents);
-                    psFree(contents);
-
-                    psMetadata *chips = psMetadataAlloc(); // List of chip types, with cellName:cellType
-                    psMetadataAddStr(chips, PS_LIST_TAIL, "_mosaicChip", 0, NULL,
-                                     "MosaickedCell:_mosaic");
-                    psMetadataAddMetadata(format, PS_LIST_TAIL, CHIP_TYPES, PS_META_REPLACE,
-                                          "List of chip types", chips);
-                    psFree(chips);
-                    break;
-                } else if (strcasecmp(extensionsItem->data.str, "NONE") == 0) {
-                    // List the contents on a single line
-                    psString contentsLine = NULL; // Contents of the PHU
-                    psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iteratr
-                    psMetadataItem *fpaItem;    // Item from iteration
-                    while ((fpaItem = psMetadataGetAndIncrement(fpaIter))) {
-                        if (fpaItem->type != PS_DATA_STRING) {
-                            // We've already thrown a warning on this, above.
-                            continue;
-                        }
-                        psStringAppend(&contentsLine, "%s:MosaickedCell:_mosaic ", fpaItem->name);
-                    }
-                    psFree(fpaIter);
-                    psMetadataAddStr(format, PS_LIST_TAIL, TABLE_OF_CONTENTS, PS_META_REPLACE,
-                                     NULL, contentsLine);
-                    psFree(contentsLine);
-                    break;
-                }
-            }
-            // PHU level is CHIP, EXTENSIONS is NONE.
-
-            psMetadata *contents = psMetadataLookupMetadata(&mdok, format,
-                                                            TABLE_OF_CONTENTS); // File contents
-            if (!mdok || !contents) {
-                psWarning("Couldn't find %s in the camera format %s.\n", TABLE_OF_CONTENTS,
-                          formatsItem->name);
-                continue;
-            }
-            while (psListLength(contents->list) > 0) {
-                psMetadataRemoveIndex(contents, PS_LIST_TAIL);
-            }
-
-            psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iterator
-            psMetadataItem *fpaItem;    // Item from iteration
-            while ((fpaItem = psMetadataGetAndIncrement(fpaIter))) {
-                if (fpaItem->type != PS_DATA_STRING) {
-                    // We've already thrown a warning on this, above.
-                    continue;
-                }
-
-                psMetadataAddStr(contents, PS_LIST_TAIL, fpaItem->name, 0, NULL, "_mosaicChip");
-            }
-            psFree(fpaIter);
-
-            psMetadata *chips = psMetadataAlloc(); // List of chip types, with cellName:cellType
-            psMetadataAddStr(chips, PS_LIST_TAIL, "_mosaicChip", 0, NULL,
-                             "MosaickedCell:_mosaic");
-            psMetadataAddMetadata(format, PS_LIST_TAIL, CHIP_TYPES, PS_META_REPLACE,
-                                  "List of chip types", chips);
-            psFree(chips);
-            break;
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "CHIP")) {
+		// ensure the value of CONTENT in the FILE section has the right value
+		psMetadataAddStr(file, PS_LIST_TAIL, "CONTENT", PS_META_REPLACE, "Key to CONTENTS menu", "{CHIP.NAME}");
+
+		// List the chipName:chipType for each chip.
+		psMetadata *contents = psMetadataAlloc(); // List of contents, with chipName:chipType
+
+		psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iteratr
+		psMetadataItem *fpaItem;    // Item from iteration
+		while ((fpaItem = psMetadataGetAndIncrement(fpaIter))) {
+		    assert (fpaItem->type == PS_DATA_STRING); 
+		    psString content = NULL; // Content to add
+		    psStringAppend(&content, "%s:_mosaicChip ", fpaItem->name);
+		    psMetadataAddStr(contents, PS_LIST_TAIL, fpaItem->name, 0, NULL, content);
+		    psFree(content);
+		}
+		psFree(fpaIter);
+		psMetadataAddMetadata(format, PS_LIST_TAIL, TABLE_OF_CONTENTS, PS_META_REPLACE,
+				      "List of contents", contents);
+		psFree(contents);
+
+		psMetadata *chips = psMetadataAlloc(); // List of chip types, with cellName:cellType
+		psMetadataAddStr(chips, PS_LIST_TAIL, "_mosaicChip", 0, NULL,
+				 "MosaickedCell:_mosaic");
+		psMetadataAddMetadata(format, PS_LIST_TAIL, CHIP_TYPES, PS_META_REPLACE,
+				      "List of chip types", chips);
+		psFree(chips);
+		break;
+	    } 
+	    if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+		// List the contents on a single line
+		psString contentsLine = NULL; // Contents of the PHU
+		psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iteratr
+		psMetadataItem *fpaItem;    // Item from iteration
+		while ((fpaItem = psMetadataGetAndIncrement(fpaIter))) {
+		    assert (fpaItem->type == PS_DATA_STRING);
+		    psStringAppend(&contentsLine, "%s:MosaickedCell:_mosaic ", fpaItem->name);
+		}
+		psFree(fpaIter);
+		psMetadataAddStr(format, PS_LIST_TAIL, TABLE_OF_CONTENTS, PS_META_REPLACE,
+				 NULL, contentsLine);
+		psFree(contentsLine);
+		break;
+	    }
+	    if (!strcasecmp(phuItem->data.str, "CHIP") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+		// XXX recode this to match the structure above (FPA/CHIP)?
+		// select and remove the old contents
+		psMetadata *contents = psMetadataLookupMetadata(NULL, format, TABLE_OF_CONTENTS); // File contents
+		if (!contents) {
+		    psError(PS_ERR_UNKNOWN, false, "Couldn't find %s in the camera format %s.\n", 
+			    TABLE_OF_CONTENTS, formatsItem->name);
+		    return false;
+		}
+		while (psListLength(contents->list) > 0) {
+		    psMetadataRemoveIndex(contents, PS_LIST_TAIL);
+		}
+
+		// update with the new contents
+		psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iterator
+		psMetadataItem *fpaItem;    // Item from iteration
+		while ((fpaItem = psMetadataGetAndIncrement(fpaIter))) {
+		    assert (fpaItem->type == PS_DATA_STRING);
+		    psMetadataAddStr(contents, PS_LIST_TAIL, fpaItem->name, 0, NULL, "_mosaicChip");
+		}
+		psFree(fpaIter);
+
+		psMetadata *chips = psMetadataAlloc(); // List of chip types, with cellName:cellType
+		psMetadataAddStr(chips, PS_LIST_TAIL, "_mosaicChip", 0, NULL,
+				 "MosaickedCell:_mosaic");
+		psMetadataAddMetadata(format, PS_LIST_TAIL, CHIP_TYPES, PS_META_REPLACE,
+				      "List of chip types", chips);
+		psFree(chips);
+		break;
+	    }
         default:
             psAbort("Should never get here.\n");
@@ -331,8 +396,8 @@
 
         // Fix the cell type
-        psMetadata *cells = psMetadataLookupMetadata(&mdok, format, CELL_TYPES); // CELLS information
-        if (!mdok || !cells) {
-            psWarning("Couldn't find CELLS of type METADATA in the camera format %s.\n", formatsItem->name);
-            continue;
+        psMetadata *cells = psMetadataLookupMetadata(NULL, format, CELL_TYPES); // CELLS information
+        if (!cells) {
+            psError(PS_ERR_UNKNOWN, false, "Couldn't find CELLS of type METADATA in the camera format %s.\n", formatsItem->name);
+	    return false;
         }
         psMetadata *cell = psMetadataAlloc(); // Cell information
@@ -341,6 +406,5 @@
         psMetadataAddStr(cell, PS_LIST_TAIL, "CELL.TRIMSEC.SOURCE", 0, "Trim section source", "HEADER");
         psMetadataAddStr(cell, PS_LIST_TAIL, "CELL.BIASSEC.SOURCE", 0, "Bias section source", "HEADER");
-        psMetadataAddMetadata(cells, PS_LIST_HEAD, "_mosaic", PS_META_REPLACE,
-                              "Mosaic cell information", cell);
+        psMetadataAddMetadata(cells, PS_LIST_HEAD, "_mosaic", PS_META_REPLACE, "Mosaic cell information", cell);
         psFree(cell);                   // Drop reference
 
@@ -428,5 +492,6 @@
 }
 
-
+// XXX EAM : shouldn't this loop over the unmosaicked camera names, calling the above function?
+// the operation putting the new entries first is now implemented in mosaickedVersion
 bool pmConfigCameraMosaickedVersionsAll(psMetadata *site)
 {
