Index: trunk/psModules/src/config/pmConfigCamera.c
===================================================================
--- trunk/psModules/src/config/pmConfigCamera.c	(revision 11754)
+++ trunk/psModules/src/config/pmConfigCamera.c	(revision 12564)
@@ -11,4 +11,9 @@
 
 #include "pmConfigCamera.h"
+
+
+#define TABLE_OF_CONTENTS "CONTENTS"    // Name for camera format metadata containing the contents
+#define CHIP_TYPES "CHIPS"              // Name for camera format metadata containing the chip types
+#define CELL_TYPES "CELLS"              // Name for camera format metadata containing the cell types
 
 
@@ -68,5 +73,5 @@
                              psMetadata *newCameras, // New list of camera configurations
                              const char *name, // Name of original camera configuration
-                             pmFPALevel level // Level
+                             pmFPALevel mosaicLevel // Level to which we are mosaicking
                             )
 {
@@ -74,5 +79,5 @@
     assert(newCameras);
     assert(name);
-    assert(level == PM_FPA_LEVEL_CHIP || level == PM_FPA_LEVEL_FPA);
+    assert(mosaicLevel == PM_FPA_LEVEL_CHIP || mosaicLevel == PM_FPA_LEVEL_FPA);
 
     // See if the old one is there
@@ -84,5 +89,5 @@
     // See if the new one is already there
     psString newName = NULL;       // Name of mosaicked camera
-    psStringAppend(&newName, "_%s-%s", name, level == PM_FPA_LEVEL_CHIP ? "CHIP" : "FPA");
+    psStringAppend(&newName, "_%s-%s", name, mosaicLevel == PM_FPA_LEVEL_CHIP ? "CHIP" : "FPA");
     if (psMetadataLookup(oldCameras, newName)) {
         return true;
@@ -99,34 +104,35 @@
         return NULL;
     }
-    switch (level) {
-    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.",
-                              fpaItem->name);
-                    continue;
-                }
-
-                psFree(fpaItem->data.str);
-                fpaItem->data.str = psStringCopy("MosaickedCell");
-                psFree(fpaItem->comment);
-                fpaItem->comment = psStringCopy("Mosaicked cell; automatically generated");
-            }
-            psFree(fpaIter);
-        }
-        break;
-    case PM_FPA_LEVEL_FPA: {
-            while (psListLength(fpa->list) > 0) {
-                psMetadataRemoveIndex(fpa, PS_LIST_TAIL);
-            }
-
-            psMetadataAddStr(fpa, PS_LIST_HEAD, "MosaickedChip", 0,
-                             "Mosaicked chip with mosaicked cell; automatically generated",
-                             "MosaickedCell");
-        }
-        break;
+    switch (mosaicLevel) {
+      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.",
+                            fpaItem->name);
+                  continue;
+              }
+
+              psFree(fpaItem->data.str);
+              fpaItem->data.str = psStringCopy("MosaickedCell");
+              psFree(fpaItem->comment);
+              fpaItem->comment = psStringCopy("Mosaicked cell; automatically generated");
+          }
+          psFree(fpaIter);
+          break;
+      }
+      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);
+          }
+
+          psMetadataAddStr(fpa, PS_LIST_HEAD, "MosaickedChip", 0,
+                           "Mosaicked chip with mosaicked cell; automatically generated",
+                           "MosaickedCell");
+          break;
+      }
     default:
         psAbort("Should never get here.\n");
@@ -142,5 +148,5 @@
         psMetadata *format = formatsItem->data.V; // The camera format
 
-        // Add a RULE
+        // 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) {
@@ -148,5 +154,5 @@
             continue;
         }
-        switch (level) {
+        switch (mosaicLevel) {
         case PM_FPA_LEVEL_CHIP:
             psMetadataAddStr(rule, PS_LIST_TAIL, "PSMOSAIC", 0, "Mosaicked level", "CHIP");
@@ -173,7 +179,7 @@
         }
         if (strcasecmp(phuItem->data.str, "CELL") == 0 ||
-                (level == PM_FPA_LEVEL_FPA && (strcasecmp(phuItem->data.str, "CHIP") == 0))) {
+                (mosaicLevel == PM_FPA_LEVEL_FPA && (strcasecmp(phuItem->data.str, "CHIP") == 0))) {
             psFree(phuItem->data.str);
-            if (level == PM_FPA_LEVEL_CHIP) {
+            if (mosaicLevel == PM_FPA_LEVEL_CHIP) {
                 phuItem->data.str = psStringCopy("CHIP");
             } else {
@@ -187,26 +193,44 @@
             continue;
         }
-        switch (level) {
-        case PM_FPA_LEVEL_CHIP:
-            if (strcasecmp(extensionsItem->data.str, "NONE") == 0) {
-                if (strcasecmp(phuItem->data.str, "FPA") == 0) {
-                    break;              // Don't need a "CONTENT" to identify the content!
-                }
-                psMetadataItem *contentItem = psMetadataLookup(file, "CONTENT"); // Key to CONTENTS menu
-                if (!contentItem || contentItem->type != PS_DATA_STRING) {
-                    psWarning("Couldn't find CONTENT of type STR in the FILE information "
-                              "in the camera format %s.\n", formatsItem->name);
-                    continue;
-                }
-                psFree(contentItem->data.str);
-                contentItem->data.str = psStringCopy("{CHIP.NAME}");
-            } else if (strcasecmp(extensionsItem->data.str, "CELL") == 0) {
+        switch (mosaicLevel) {
+          case PM_FPA_LEVEL_CHIP:
+            if (strcasecmp(phuItem->data.str, "FPA") == 0 &&
+                strcasecmp(extensionsItem->data.str, "CELL") == 0) {
                 psFree(extensionsItem->data.str);
                 extensionsItem->data.str = psStringCopy("CHIP");
-            }
-            break;
-        case PM_FPA_LEVEL_FPA:
+            } else {
+                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}");
+            }
+
+#if 0
+            // Don't need CELL.NAME for chip-mosaicked camera
+            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:
@@ -215,28 +239,66 @@
 
         // Fix up the CONTENTS to contain only the mosaicked cell for each chip
-        switch (level) {
-        case PM_FPA_LEVEL_CHIP:
-            if (strcasecmp(phuItem->data.str, "FPA") == 0 &&
-                    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); // 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;
+        switch (mosaicLevel) {
+          case PM_FPA_LEVEL_FPA:
+            psMetadataAddStr(format, PS_LIST_TAIL, TABLE_OF_CONTENTS, PS_META_REPLACE, NULL,
+                             "MosaickedChip:MosaickedCell:_mosaic");
+            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);
                     }
-                    psStringAppend(&contentsLine, "%s:MosaickedCell:_mosaic ", fpaItem->name);
+                    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;
                 }
-                psFree(fpaIter);
-                psMetadataAddStr(format, PS_LIST_TAIL, "CONTENTS", PS_META_REPLACE, NULL, contentsLine);
-                psFree(contentsLine);
-                break;
-            }
-
-            psMetadata *contents = psMetadataLookupMetadata(&mdok, format, "CONTENTS"); // Contents of file
+            }
+            // PHU level is CHIP, EXTENSIONS is NONE.
+
+            psMetadata *contents = psMetadataLookupMetadata(&mdok, format,
+                                                            TABLE_OF_CONTENTS); // File contents
             if (!mdok || !contents) {
-                psWarning("Couldn't find CONTENTS in the camera format %s.\n", formatsItem->name);
+                psWarning("Couldn't find %s in the camera format %s.\n", TABLE_OF_CONTENTS,
+                          formatsItem->name);
                 continue;
             }
@@ -244,4 +306,5 @@
                 psMetadataRemoveIndex(contents, PS_LIST_TAIL);
             }
+
             psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iterator
             psMetadataItem *fpaItem;    // Item from iteration
@@ -252,14 +315,14 @@
                 }
 
-                psString content = NULL;    // Content of the chip
-                psStringAppend(&content, "%s:MosaickedCell:_mosaic", fpaItem->name);
-                psMetadataAddStr(contents, PS_LIST_TAIL, fpaItem->name, 0, NULL, content);
-                psFree(content);            // Drop reference
+                psMetadataAddStr(contents, PS_LIST_TAIL, fpaItem->name, 0, NULL, "_mosaicChip");
             }
             psFree(fpaIter);
-            break;
-        case PM_FPA_LEVEL_FPA:
-            psMetadataAddStr(format, PS_LIST_TAIL, "CONTENTS", PS_META_REPLACE, NULL,
-                             "MosaickedChip:MosaickedCell:_mosaic");
+
+            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:
@@ -268,5 +331,5 @@
 
         // Fix the cell type
-        psMetadata *cells = psMetadataLookupMetadata(&mdok, format, "CELLS"); // CELLS information
+        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);
@@ -316,5 +379,5 @@
         }
 
-        if (level == PM_FPA_LEVEL_FPA) {
+        if (mosaicLevel == PM_FPA_LEVEL_FPA) {
             removeChipConceptsSources(translation);
             removeChipConceptsSources(database);
@@ -347,5 +410,4 @@
 }
 
-
 // Generate the chip mosaicked version of a camera configuration
 bool pmConfigCameraMosaickedVersions(psMetadata *site, // The site configuration
